Pwning PHP developers

TL;DR
A php programmer who use xdebug’s remote debugging feature may affects RCE when he just access to attacker’s website in modern browsers.

Xdebug is an extension for PHP to assist with debugging and development. PHP programmers or web security researchers always setup a local PHP debugging environments for convenience. If the debugging server can be directly accessed by an attacker, there is a Remote Code Execution vulnerability.

But usually, these servers are in Intranet and some even bind on 127.0.0.1, which makes it hard to be accessed. What if attacking Xdebug using CSRF?

Let’s read the Xdebug’s document first. As in the doc, if xdebug.remote_connect_back is enabled, the xdebug.remote_host setting is ignored and Xdebug will try to connect to the client that made the HTTP request. It checks the $_SERVER['HTTP_X_FORWARDED_FOR'] and $_SERVER['REMOTE_ADDR'] variables to find out which IP address to use.

If xdebug is configured as follows, we can use $_SERVER['HTTP_X_FORWARDED_FOR'] as the connect back ip.

xdebug.remote_connect_back = 1
xdebug.remote_enable = 1
xdebug.remote_log =  /tmp/test.log

For php programmers, there are always index.php or config.php in there local debugging environment. If the attatcker can send a http request with X-Forwarded-For header(which points to attacker’s server) to local url just like http://127.0.0.1/index.php?XDEBUG_SESSION_START or http://127.0.0.1/config.php?XDEBUG_SESSION_START, the attacker can get a Xdebug’s connect back and then use DBGp commands to execute any php code.

As we all know, sending CORS request headers other than simple headers in browsers, a preflight request is required to check whether the CORS request is allowed. To bypass this check, there is a tech called DNS Rebind(remember the challenge Monkey I made in 0CTF 2016 ?). Attacker can setup a private dns server and make a domain first resolved to attacker’s ip and then 127.0.0.1. When victim accesses the malicious web page, for example http://attacker-domain-with-dns-rebind/exp.html, the browser pulls payload, sending requests to http://attacker-domain-with-dns-rebind/index.php?XDEBUG_SESSION_START with X-Forwarded-For header repeatedly. There is no preflight request because the exploit page and the requested page are same origin.

It needs some time when the DNS record changes to 127.0.0.1 because of cache mechanism in the browser. When the domain resolves to 127.0.0.1, the Xdebug on victim’s machine will connect to attacker’s ip and eval any php code the attacker provided through DBGp.

The cause of this attack is that Xdebug uses a untrusted value as connect back IP from X-Forwarded-For header.

Tencent’s Xuanwu Lab reported this to PHP on March 26, but PHP don’t think it is a security issue and they made the report public on March 30.

Tencent’s Xuanwu Lab suggests PHP programmers and security researchers who use Xdebug set xdebug.remote_host to a proper value to keep safety.

Timeline:
2018-03-26: Report to PHP
2018-03-30: They think it is not a security issue and change the report from security to bug, everyone can see the report.

Reference:
https://bugs.php.net/bug.php?id=76149
https://ricterz.me/posts/Xdebug%3A%20A%20Tiny%20Attack%20Surface
https://medium.com/0xcc/visual-studio-code-silently-fixed-a-remote-code-execution-vulnerability-8189e85b486b
http://bluec0re.blogspot.ch/2018/03/cve-2018-7160-pwning-nodejs-developers.html