Command Injection(命令注入)java
執行不可信賴資源中的命令,或在不可信賴的環境中執行命令,都會致使程序以攻擊者的名義執行惡意命令。git
Command Injection 漏洞主要表現爲如下兩種形式:
- 攻擊者可以篡改程序執行的命令: 攻擊者直接控制了所執行的命令。
- 攻擊者可以篡改命令的執行環境: 攻擊者間接地控制了所執行的命令。
在這種狀況下,咱們着重關注第一種狀況,即攻擊者控制所執行命令的可能性。 這種形式的 Command Injection 漏洞在如下狀況下發生:shell
... String home = System.getProperty("APPHOME"); String cmd = home + INITCMD; java.lang.Runtime.getRuntime().exec(cmd); ...
例 1 中的代碼使得攻擊者可經過修改系統屬性 APPHOME 而指向一個包含惡意版本 INITCMD 的其餘路徑,從而提升本身在應用程序中的權限,繼而爲所欲爲地執行命令。 因爲程序不會驗證從環境中讀取的值,因此若是攻擊者可以控制系統屬性 APPHOME 的值,他們就能欺騙應用程序去運行惡意代碼從而取得系統控制權。例 2: 如下代碼來自一個管理 Web 應用程序,該程序旨在容許用戶經過使用圍繞 rman 實用程序的批處理文件包啓動 Oracle 數據庫備份,而後運行 cleanup.bat 腳本刪除一些臨時文件。 腳本文件 rmanDB.bat 接受一個命令行參數,其中指明瞭須要執行的備份類型。 因爲訪問數據庫受限,因此應用程序執行備份須要具備較高權限的用戶。數據庫
... String btype = request.getParameter("backuptype"); String cmd = new String("cmd.exe /K \"c:\\util\\rmanDB.bat "+btype+"&&c:\\utl\\cleanup.bat\"") System.Runtime.getRuntime().exec(cmd); ...
這裏的問題是:程序沒有對讀取自用戶的 backuptype 參數作任何驗證。 一般狀況下,一次調用Runtime.exec() 函數並不會執行多條命令,可是在本例中,程序首先運行了 cmd.exe 指令,進而在一次
調用 Runtime.exec() 後即可以運行多條命令了。 一旦調用了該 shell,它即會心甘情願地執行用兩個與號分隔的多條命令。 若是攻擊者傳遞了一個形式爲 "&& del c:\dbms\." 的字符串,那麼應用程序將會在執行其餘程序指定的命令時執行這些命令。 因爲該應用程序的特性,運行該應用程序須要具有與數據庫進行交互所需的權限,這就意味着攻擊者注入的任何命令都將經過這些權限得以運行。 例 3: 如下代碼來自一個 Web 應用程序。經過該應用程序,用戶能夠訪問可以更新其系統密碼的接口。 在特定的網絡環境中更新密碼時,其中的一個步驟就是在 /var/yp 目錄中運行 make 命令,下面顯示了此步驟的代碼。安全
... System.Runtime.getRuntime().exec("make"); ...
這裏的問題在於程序沒有在它的構造中指定一個絕對路徑,而且沒能在執行Runtime.exec() 調用前清除它的環境變量。 若是攻擊者可以修改 $PATH 變量,把它指向名爲 make 惡意二進制代碼,程序就會在其指定的環境下執行,而後加載該惡意二進制代碼,而非本來指望的代碼。 因爲應用程序自身的特性,運行該應用程序須要具有執行系統操做所需的權限,這意味着攻擊者會利用這些權限執行本身的 make,從而可能致使攻擊者徹底控制系統。 此種類來源於 Cigital Java Rulepack。 http://www.cigital.com/securitypack/網絡
應當禁止用戶直接控制由程序執行的命令。 在用戶的輸入會影響命令執行的狀況下,應將用戶輸入限制爲從預約的安全命令集合中進行選擇。 若是輸入中出現了惡意的內容,傳遞到命令執行函數的值將默認從安全命令集合中選擇,或者程序將拒絕執行任何命令。 在須要將用戶的輸入用做程序命令中的參數時,因爲合法的參數集合實在很大,或是難以跟蹤,使得這個方法一般都不切實際。 開發者一般的作法是使用黑名單。 在輸入以前,黑名單會有選擇地拒絕或避免潛在的危險字符。 可是,任何一個定義不安全內容的列表都極可能是不完整的,而且會嚴重地依賴於執行命令的環境。 較好的方法是建立一份白名單,容許其中的字符出如今輸入中,而且只接受徹底由這些經承認的字符組成的輸入。 攻擊者能夠經過修改程序運行命令的環境來間接控制這些命令的執行。 咱們不該當徹底信賴環境,還需採起預防措施,防止攻擊者利用某些控制環境的手段進行攻擊。 不管什麼時候,只要有可能,都應由應用程序來控制命令,並使用絕對路徑執行命令。 若是編譯時尚不瞭解路徑(如在跨平臺應用程序中),應該在執行過程當中利用可信賴的值構建一個絕對路徑。 應對照一系列定義有效值的常量,仔細地檢查從配置文件或者環境中讀取的命令值和路徑。 有時還能夠執行其餘檢驗,以檢查這些來源是否已被惡意篡改。 例如,若是一個配置文件爲可寫,程序可能會拒絕運行。 若是可以預先得知有關要執行的二進制代碼的信息,程序就會進行檢測,以檢驗這個二進制代碼的合法性。 若是一個二進制代碼始終屬於某個特定的用戶,或者被指定了一組特定的訪問權限,這些屬性就會在執行二進制代碼前經過程序進行檢驗。 儘管可能沒法徹底阻止強大的攻擊者爲了控制程序執行的命令而對系統進行的攻擊,但只要程序執行外部命令,就務必使用最小受權原則: 不給予超過執行該命令所必需的權限。函數