利用恶意页面攻击本地Xdebug

TL;DR
PHP开发者以及一些安全研究人员经常会在本地搭建一个基于Xdebug的PHP的调试服务,在大部分配置情况下,Xdebug采用HTTP请求头中的X-Forwarded-For字段作为DBGp协议的回连地址。受害者浏览攻击页面一段时间,攻击者可利用DNS Rebind技术向本地服务器发送带有恶意X-Forwarded-For的请求,即有可能在受害者电脑上执行任意代码。

前段时间看到VSCode修复了一个RCE的漏洞,讲的是VSCode在本地开放了一个Nodejs的调试端口,通过DNS Rebind的技术可以获取到调试用的WebSocket接口,即可执行任意代码实现RCE。这让我想起了PHP的调试工具Xdebug。

Xdebug是用于调试PHP的扩展,可以根据本地源码远程调试服务器上的PHP代码。很多开发者和安全研究人员通常会在本地搭建一套PHP的调试环境,用于日常的开发和调试。对于Xdebug的攻击,之前Ricter写了一篇文章介绍过。文章里提到了如果服务器开启了Xdebug的回连,并且攻击者能直接访问到服务器的话,可以直接造成RCE。

但是大部分情况下,这些服务器处于内网环境中,有些甚至监听在127.0.0.1上,攻击者很难直接访问到,导致无法利用。如果把开发人员当做代理,利用CSRF来攻击位于内网的Xdebug呢?

我们首先看一下Xdebug有关远程调试的文档
如果xdebug.remote_connect_back启用,xdebug.remote_host没有设置,Xdebug会主动连接发起HTTP请求的客户端。Xdebug会依次检测$_SERVER['HTTP_X_FORWARDED_FOR']$_SERVER['REMOTE_ADDR']来决定回连的IP地址。

即当Xdebug有类似如下的配置的时候,即有机会让Xdebug回连到请求头中X-Forwarded-For指向的ip地址。

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

一般来讲,在PHP开发人员的本地环境中会有index.phpconfig.php等文件。在受害者访问攻击者的恶意页面时,攻击者可以让受害者在浏览器里尝试向本地url如http://127.0.0.1/index.php?XDEBUG_SESSION_START或者http://127.0.0.1/config.php?XDEBUG_SESSION_START发起HTTP请求,并带有指向攻击者服务器的X-Forwarded-For请求头。这样攻击者就能在自己的服务器上收到来自受害者的DBGp协议的连接,在受害者的电脑上执行任意PHP代码。

我们都知道,在浏览器里发送带有非simple header的CORS请求的时候,需要先发送一个preflight request探测服务器是否允许发送这种请求头。此检测过程是由一个OPTIONS请求完成的。如果OPTIONS请求的响应头里有Access-Control-Allow-Headers: X-Forwarded-For这一项的话,才能发送带有X-Forwarded-For的GET或者POST请求。在受害者的本地环境中,几乎不会有这种响应头的。

不过,攻击者可以采用DNS Rebind的方式来绕过这个限制。攻击者首先自己搭建一个DNS解析服务器,让自己控制的域名在发生第一次DNS解析的时候指向攻击者的服务器,以后都解析到127.0.0.1。这样当受害者访问攻击者的页面(http://attacker-domain-with-dns-rebind/exp.html)的时候,会从攻击者的服务器上拉取攻击代码,使浏览器循环向http://attacker-domain-with-dns-rebind/index.php?XDEBUG_SESSION_START发送带有恶意X-Forwarded-For头的请求。因为攻击者存放攻击代码的页面和触发Xdebug回连请求的url在同一个域内,即可不用发送前面所说的preflight request。

由于DNS的解析结果也存在一定的缓存时间,在浏览器里大概需要1分钟的时间才会失效进行第二次解析。在发生第二次解析的时候,其指向的IP地址会变为127.0.0.1,即向受害者本地的服务器发送能触发Xdebug反弹的请求,这时候攻击者的服务器就能收到来自受害者Xdebug的连接了。攻击者可以通过DBGp协议中的eval命令在客户端执行任意php代码。

我们认为漏洞的成因是Xdebug从X-Forwarded-For头中取IP作为回连地址,而X-Forwarded-For头是不可信的。

我于2018年3月26日将此问题报告给PHP官方,PHP官方人员于2018年3月30日作出回应,不认为这是一个安全问题,并将报告转为bug使之处于公开状态。建议PHP开发人员和安全研究人员在Xdebug的配置文件中根据当前情况增加xdebug.remote_host配置项,来防止自己遭受此攻击。

参考文献
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

分享到 评论