多數作業系統——尤其是 Unix 系的系統——都內建一整套用途各異的實用工具。開發者有時會認為,執行某項任務(例如更新密碼)最省事的方式就是去執行一個外部應用程式或系統工具。
如果執行的命令列完全由開發者指定,這未必是問題。但實務上,常常會有來自網路用戶端的資料被插進命令列裡,才能完成想做的操作。
def update_password(string username)
{
string oldpassword = read_string();
string newpassword = read_string();
if(check_user_password(username, oldpassword))
{
// Invoke update_password command
system("/sbin/update_password -u " + username + " -p " + newpassword);
}
}這段程式在使用者知道原密碼的前提下更新密碼:它組出一行命令列,再呼叫 Unix 風格的 system 函式執行。我們無法控制 username 與 oldpassword(它們必須正確才能走到 system 呼叫),但對 newpassword 有完全的控制權。
由於完全沒有做淨化(sanitization),這段程式存在命令注入漏洞——
system函式是透過當前的 Unix shell 來執行命令列的。舉例來說,我們可以把newpassword指定為password; xcalc:shell 會先執行密碼更新命令,接著因為它把分號視為命令清單的分隔符,順帶執行xcalc。
分析時的重點是找出「應用程式資料 → 命令列字串 → shell」這條路徑。只要中間沒有嚴謹的淨化或跳脫(escaping),任何一個攻擊者可控的欄位都是注入點。