在聽到術語“滲透測試”時,您可能會聯想到一個孤獨的天才正在對一些倒霉的軟件執行神奇的測試。在滲透測試復興之前,它或許是個真實的場景。現在,滲透測試的執行方式要系統化得多。這樣做是必要的,因為安全開發生命周期 (SDL) 以及前載式安全設計和開發重點降低了潛在缺陷的數量,從而使在測試過程中查找漏洞的任務變得更加困難。軟件安全測試非常重要,不能僅依靠一小組專家來完成。它必須是能夠傳授、系統化且可重復的過程,這樣才能將其應用到各種情況中。
這并不是說滲透測試是一門科學。所有測試均有值行研究的方面;測試人員應用輸入,而這些輸入會更改軟件內部的數據,從而導致其做出各種反應。由于復雜性很高,無法進行精確預測;但是,我們可事先做好各種規劃工作,本專欄將介紹我們在 Microsoft 是如何制定規劃的。
規劃
對于傳統測試而言,規范、用戶文檔、用例和其他設計文檔非常充足。可使用這些信息設計一組測試用例來確認指定的功能。但有關規劃的可用信息資源則非常有限。滲透測試并不是為了確認功能;其目的是確認不再存在不安全的功能。遺憾的是,沒有人定義過用于此類行為的軟件開發項目,因此測試人員不得不自行解決。
收集滲透測試信息的首個位置是軟件與外部環境之間的接口。用戶界面、網絡接口、API 和處理輸入的任意其他位置都是明顯的黑客攻擊目標。如果任意一個接口的設計或實現欠佳,它們可能會允許惡意偽造的輸入并帶來災難。可通過確定和記錄這些接口來開始執行滲透測試。
需要特別關注的第二個區域是錯誤消息和用戶警告對話框(它們將把來自軟件的信息傳遞給外部用戶)。由于某些用戶可能具有惡意企圖,因此必須了解會向其顯示哪些信息以及此類信息的傳遞方式。
最后,滲透測試人員通常會定義災難場景,以此指出成功的攻擊可能產生的后果。這些誤用案例(或者說濫用案例)通常起源于某種威脅模型或先前已知的攻擊。
對于滲透測試而言,從這三類資源中收集信息是至關重要的準備工作,并且有助于指導您完成實際的測試。
滲透測試類型
測試的對象是變化 — 找出軟件及環境中可能發生變化的部分,改變它們,然后觀察軟件的反應。測試目標是確保軟件在合理甚至不合理的生產環境中可靠且安全地運行。因此,測試人員可制定的最基本規劃是了解哪些部分可能發生變化以及在測試中需使用哪些方法來分階段實現這些變化。
從安全角度來看,環境、用戶輸入以及內部數據和邏輯是此類變化可能暴露出安全問題的主要位置。環境包括文件、應用程序、系統資源和應用程序使用的其他本地或網絡資源。所有這些都可能成為攻擊的入口點。用戶輸入是源自軟件分析和使用的外部(通常不受信任)實體的數據。內部數據和邏輯是內部存儲的變量和邏輯路徑(它們具有多種可能的枚舉)。
通過改變軟件環境、輸入域和數據/邏輯路徑中的信息,就可以執行攻擊。接下來我將更詳細地介紹這三類攻擊。
環境攻擊
軟件無法孤立地執行。它依賴于一些二進制和等效于代碼的模塊(如腳本和插件)。它還可能使用注冊表或文件系統中的配置信息以及可能位于任意位置的數據庫和服務。每個此類環境交互都可能成為安全漏洞的來源,因此必須對其進行測試。
對于應用程序在此類交互中所具有的信任程度,還有許多必須考慮的重要問題,其中包括:應用程序對于本地環境和遠程資源的信任程度如何?應用程序是否將敏感信息放在其他應用程序可讀取的資源(如注冊表)中?它是否信任自身加載的每個文件或庫,甚至無需確認內容?攻擊者是否能夠利用這種信任來強制應用程序服從其命令?
除信任問題外,滲透測試人員還應監視可能出現錯誤或已被攻擊者替換(或修改)的 DLL、二進制代碼或應用程序將與之進行交互并且未受到訪問控制列表 (ACL) 完全保護或者根本未受到保護的文件。測試人員還必須監視訪問共享內存資源或者在注冊表或臨時文件中存儲敏感數據的其他應用程序。最后,測試人員必須考慮造成系統壓力的因素(如網速較慢、內存不足等),并確定這些因素對安全功能的影響。
環境攻擊方式通常是侵入不安全的環境并隨后在該環境中執行應用程序來查看其反應。這是一種間接形式的測試;攻擊者對應用程序的運行環境發起攻擊。現在,我們來看直接測試。
輸入攻擊
在滲透測試中,來自不受信任來源的輸入最為重要。包括通信路徑(如網絡協議和套接字)、公開的遠程功能(如 DCOM、遠程過程調用 (RPC) 和 Web 服務)、數據文件(二進制文件或文本文件)、執行過程中創建的臨時文件以及控制文件(如腳本和 XML),所有這些內容都可能遭到篡改。最后,還必須檢查允許直接用戶輸入的 UI 控件(包括登錄屏幕、Web 前端及類似控件)。
具體來說,您需要確定是否已正確控制輸入:是否接收合格的輸入并拒絕不適當的輸入(如長字符串、格式不正確的數據包等)?適當的輸入檢查和文件分析至關重要。
需執行測試來查看能不能將危險的輸入項輸入到 UI 控件中,并了解此時會產生什么樣的后果。此類輸入包括特殊字符、編碼輸入、腳本段、格式字符串、轉義序列等。需確定嵌入到數據包字段或文件中且可能導致內存溢出的長字符串能否通過測試。協議流中損壞的數據包也是個問題。必須監視崩潰和掛起并檢查堆棧是否存在可利用的內存損壞。最后,必須確保當正確防御不適當的輸入時,驗證和出錯消息之類的信息會出現在正確的位置(客戶端而非服務器端)。
輸入攻擊實際上類似于向應用程序扔手榴彈。其中一些能正確躲避,而另一些則會導致軟件崩潰。滲透團隊將負責確定各種輸入攻擊,并啟動適當的修復措施。
數據和邏輯攻擊
一些錯誤深藏在應用程序的內部數據存儲機制和算法邏輯當中。在這種情況下,似乎存在設計和編碼錯誤,開發人員假定用戶始終會按照正確的方式執行操作或忽略了用戶可能用到的某些代碼路徑。
拒絕服務是此類攻擊的主要代表,但還不是最危險的攻擊。如果開發人員沒有針對大量用戶(或連接、文件或導致資源耗盡的任意輸入)做出計劃,拒絕服務攻擊就可能成功。然而,還有大量需要測試的更加隱匿的邏輯缺陷。例如,如果導致錯誤消息的輸入和其他生成的輸出向攻擊者顯示了可利用的信息,就可能發生信息泄漏。始終應刪除此類數據,其中一個實際的示例是硬編碼的測試帳戶或測試 API(通常包含在內部版本中以幫助實現測試自動化)。它們可能為攻擊者提供輕松的入侵點。還應執行另外兩個測試:輸入錯誤的憑據來確定內部身份驗證機制是否可靠,以及選擇代碼路徑不同的輸入。通常一個代碼路徑是安全的,但可使用另一方式訪問相同的功能(可能無意間忽略一些關鍵的檢查)。
不要膽怯
滲透測試與傳統的功能測試存在很大差異;滲透測試人員不僅缺乏適當的文檔,而且還必須能夠站在試圖進行破壞的用戶角度進行思考。這一點非常重要 — 開發人員往往假定用戶都非常守規矩并且不會執行特殊的操作,因而拒絕修復錯誤。但實際上,您不可能如此冒險。黑客們會深入發掘各種漏洞,任意技巧、欺騙或異常測試用例都不例外。對于滲透測試人員而言,也同樣適用。