命令列注入

問題

與 SQL 注入允許攻擊者在資料庫上執行任意查詢的方式類似,命令列注入允許某人在 Web 伺服器上執行不受信任的系統命令。使用不正確安全的伺服器,這將使攻擊者完全控制系統。

例如,假設指令碼允許使用者在 Web 伺服器上列出目錄內容。

<pre>
<?php system('ls ' . $_GET['path']); ?>
</pre>

(在實際應用程式中,可以使用 PHP 的內建函式或物件來獲取路徑內容。此示例用於簡單的安全演示。)

人們希望得到一個類似於/tmppath 引數。但是,如果允許任何輸入,path 可能是 ; rm -fr /。然後,Web 伺服器將執行該命令

ls; rm -fr /

並嘗試從伺服器的根目錄中刪除所有檔案。

必須使用 escapeshellarg()escapeshellcmd() 轉義所有命令引數。這使得引數不可執行。對於每個引數,還應驗證輸入值。

在最簡單的情況下,我們可以保證我們的例子

<pre>
<?php system('ls ' . escapeshellarg($_GET['path'])); ?>
</pre>

在上一個嘗試刪除檔案的示例之後,執行的命令變為

ls '; rm -fr /'

字串只是作為引數傳遞給 ls,而不是終止 ls 命令並執行 rm

應該注意的是,上面的示例現在對命令注入是安全的,但不是來自目錄遍歷。要解決此問題,應檢查規範化路徑是否以所需的子目錄開頭。

PHP 提供了各種執行系統命令的功能,包括 execpassthruproc_openshell_execsystem。所有人都必須仔細驗證和轉移他們的輸入。