Go 開發人員可能需要在各種場景中使用系統命令,例如映像處理,他們需要處理或調整映像大小或執行系統命令來管理資源或收集指標或日誌。
有時,您可能正在用 Go 建立一個新系統,需要與現有的遺留系統進行互動。此介面依賴執行系統命令並處理其輸出。
無論哪種情況,在產生系統命令時都必須遵循安全編碼約定,因為這可能會導致稱為命令注入的安全漏洞。
當應用程式將不安全的使用者提供的資料(例如來自 Web 表單的輸入)傳遞到系統 shell 時,命令注入是一個安全漏洞。此漏洞允許攻擊者在同一應用程式使用者下的主機作業系統上執行任意命令。
在 Go 中,命令注入通常涉及使用 os/exec 套件來產生系統命令。
考慮以下 Go 程式碼範例:
func handler(req *http.Request) { cmdName := req.URL.Query()["cmd"][0] cmd := exec.Command(cmdName) cmd.Run() }
在此程式碼片段中,cmdName 直接從請求查詢參數中提取,並用於建構在伺服器上執行的命令。這是命令注入漏洞的典型範例,因為攻擊者可以操縱 cmd 查詢字串值來執行他們選擇的任何命令,從而可能危及伺服器。
攻擊者可以使用惡意指令製作請求,例如:
http://example.com/execute?cmd=rm%20-rf%20/
為什麼命令注入很危險?命令注入是危險的,因為它允許攻擊者在伺服器上執行任意命令,這可能導致嚴重後果,包括:
成功的命令注入攻擊的影響可能是毀滅性的,不僅會影響受感染的系統,還會影響組織的聲譽和客戶信任。
以偏好簡單性和效能而聞名的 Go 開發人員可能會選擇整合系統命令來利用這些實用程式的功能。這種方法使他們能夠專注於建立強大的應用程序,而無需重新發明輪子。然而,這種整合也帶來了一系列挑戰,特別是在安全性方面。
為了說明更現實的場景,請考慮一個使用諸如 Convert 之類的命令列實用程式處理映像檔的 Go 應用程式。
我們探索了一個旨在處理圖像大小調整請求的 Go 應用程式。該應用程式使用 Gin Web 框架定義 POST 端點 /cloudpawnery/image,它根據使用者輸入處理圖片大小調整。此端點接受來自查詢字串的參數,例如tenantID、fileID和fileSize。 fileSize 參數是可選的,如果未提供,則預設為「200」。
以下程式碼片段示範了 Go 中存在漏洞的實作。
func handler(req *http.Request) { cmdName := req.URL.Query()["cmd"][0] cmd := exec.Command(cmdName) cmd.Run() }
downloadAndResize函數使用convert建構指令字串來調整圖片大小,並使用exec.CommandContext執行它。
downloadAndResize函數如何建構指令字串?它使用用戶提供的檔案大小來獲取此輸入。然後執行該字串,可能允許攻擊者註入惡意命令。為了減輕這種風險,Go 開發人員應該驗證和清理所有使用者輸入,使用參數化命令,並利用安全實踐來安全處理命令執行。
在 Go 開發中,就像在任何其他語言中一樣,確保您的程式碼免受命令注入漏洞的影響至關重要。當攻擊者可以在主機上執行任意命令時,就會發生命令注入,這可能會導致未經授權的存取、資料外洩和其他嚴重的安全問題。
讓我們來探索一些減輕這些風險的最佳實踐。
防止命令注入的基本步驟之一是嚴格的輸入驗證和衛生。在提供的範例中,downloadAndResize 函數使用使用者提供的輸入(如 fileSize)建構指令字串。如果這些輸入未正確驗證,攻擊者可能會注入惡意命令。
以下是改進輸入驗證的方法:
以下是如何實作這些實務的範例:
func handler(req *http.Request) { cmdName := req.URL.Query()["cmd"][0] cmd := exec.Command(cmdName) cmd.Run() }
即便如此,我們仍然可以做得更好,以保護 Go 程式碼免於指令注入。繼續閱讀!
另一個有效的策略是盡可能避免直接執行系統指令。相反,請利用安全的 API 或程式庫來提供所需的功能,而不會讓您的應用程式面臨命令注入風險。
例如,如果您的應用程式需要操作映像,請考慮使用 Go 函式庫(如 github.com/disintegration/imaging),而不是呼叫外部命令(例如從 ImageMagick 軟體庫進行轉換)。這種方法將功能封裝在 Go 的型別安全環境中,減少了攻擊面。
http://example.com/execute?cmd=rm%20-rf%20/
透過在 Go 中使用 images 等函式庫,您無需建置和執行 shell 指令,從而降低指令注入的風險。儘管如此,在某些程式庫和語言生態系統中,第三方套件可能是命令執行的簡單包裝器,因此必須檢查此類敏感操作的程式碼。
在前面的範例中,我們示範了一個可能存在漏洞的 Go 應用程序,該應用程式使用 exec.CommandContext 函數執行 shell 命令。正如我們所指出的,這種方法可能會導致命令注入漏洞。
讓我們嘗試重構 downloadAndResize 函數,以確保使用者輸入不會導致任意指令執行。
防止命令注入的一種有效方法是避免直接從使用者輸入建構 shell 命令字串。相反,我們可以使用帶有單獨參數的 exec.Command 函數,這有助於安全地將使用者輸入作為參數傳遞給命令,而無需呼叫 shell,也不允許使用者控制實際命令。
這是 downloadAndResize 函數的重構版本,可解決指令注入漏洞:
func handler(req *http.Request) { cmdName := req.URL.Query()["cmd"][0] cmd := exec.Command(cmdName) cmd.Run() }
在此重構中,我們將指令與其參數分開。透過使用具有單獨參數的 exec.CommandContext,我們無需建構 shell 命令字串。這種方法確保使用者輸入被視為資料而不是可執行程式碼,從而顯著降低命令注入的風險。
我們也消除了對 shell 呼叫的需要。重構的程式碼不會呼叫 shell (sh -c),這是命令注入的常見向量。相反,它直接使用指定的參數呼叫轉換實用程式。
Snyk Code 是一款強大的靜態分析工具,可協助開發人員識別並修復程式碼庫中的漏洞。它無縫整合到您的 IDE 和開發工作流程中,提供有關潛在安全問題的即時回饋。
在提供的 Go 範例中,downloadAndResize 函數使用使用者提供的輸入建構一個 shell 指令:
http://example.com/execute?cmd=rm%20-rf%20/
此程式碼容易受到命令注入的攻擊,因為它直接將使用者輸入合併到命令字串中。
如果您的團隊中有開發人員不知道命令注入漏洞怎麼辦?
您是否能夠在程式碼審查中輕鬆定位文件間靜態分析呼叫流程以發現此命令注入漏洞?
這就是 Snyk 的用武之地。
了解如何透過 Snyk Code 擴充功能在 VS Code 編輯器中突出顯示即時易受攻擊的程式碼來輕鬆確保應用程式安全:
Snyk 可以透過掃描 Go 程式碼並標記在 shell 命令中不安全使用使用者輸入的實例來幫助識別此類漏洞。 Snyk 向您展示了其他開源專案所做的緩解此特定漏洞的真實提交,因此您可以獲得多個程式碼參考作為「良好外觀」的範例。
更重要的是,如果您按一下「問題概述」選項卡,您可以深入了解更多詳細資訊和防止命令注入的最佳實踐。此標籤提供了有關如何減輕這些風險的詳細見解和建議,並且在您編碼時可以直接在 IDE 視圖中使用,並且可以遵循這些操作,而無需進行昂貴的上下文切換:
若要進一步了解如何保護您的程式碼免受此類漏洞的影響,請考慮安裝 Snyk Code IDE 擴充功能並連接您的 Git 項目,以識別和修復 Go 應用程式中的安全性問題。您可以透過註冊並開始掃描您的程式碼是否有漏洞來輕鬆且免費地完成此操作。
以上是了解 Go 中的命令注入漏洞的詳細內容。更多資訊請關注PHP中文網其他相關文章!