建置可靠且安全的 C++ 程式
美國政府出版物 NISTIR 8397:軟體開發人員驗證的最低標準指導方針 (英文) 包含有關如何以任何程式設計語言建置可靠且安全軟體的絕佳指引。
本文件遵循與 NISTIR 8397 相同的結構。 每個章節:
- 摘要說明如何使用 Microsoft 專為 C++ 和其他語言提供的開發人員產品符合該章節的安全性需求,以及
- 提供指引以從每個領域中獲得最大價值。
2.1 威脅模型化
摘要
威脅模型化是一項重要的程序,特別適用於為了符合您的開發需求進行擴展以及減少雜訊時。
建議
威脅模型化應該是您動態安全性開發生命週期 (SDL) 的一部分。 建議您針對整個產品、特定功能或是主要設計或實作變更:
- 擁有穩固且動態的 SDL,以便與開發人員小組及早接觸並精簡方法。
- 以標靶方式套用威脅模型化。 將威脅模型化套用至所有功能,但策略性地從公開、複雜或關鍵功能開始。 定期套用,而不是作為由上而下產品檢閱的一部分。
- 在還有機會變更設計時,及早套用威脅模型化 (如同所有安全性需求)。 此外,威脅模型可作為其他程序 (例如受攻擊面縮小或安全性設計) 的輸入。 稍後建立的威脅模型充其量是滲透測試的「調查」或需要安全性測試 (例如模糊測試) 的領域。 建立基準威脅模型之後,請規劃在受攻擊面變更時持續反覆運算。
- 使用資產清查與合規性來適當追蹤組成產品的內容,以及追蹤安全性成品 (包括威脅模型) 及其適用的資產。 此方法可讓您提升風險評定自動化,並將安全性工作聚焦於變更的特定元件或功能。
- 在 Azure 中,已於 2022 年更新 Microsoft Threat Modeling Tool 用於 Azure 開發。 如需詳細資訊,請參閱 Microsoft Threat Modeling Tool 概觀 - Azure
支援因素和做法
若要正確套用威脅模型化並避免未充分使用/過度使用,我們發現必須先解決下列核心概念。
開發方法
首先,了解小組的開發方法。 對於擁有每天將數十項變更推送至生產環境之敏捷開發工作流程的小組而言,每次變更功能都必須更新威脅模型既不實際也不合理。 相反地,請在一開始撰寫功能的功能需求時,就考慮包括安全性需求問卷。 該問卷應著重於功能的特定問題,以確定 SDL 適用的未來層面。 例如:
- 功能在設計時是否對如何在多租用戶環境中提供客戶隔離做出重大變更? 如果是,請考慮執行完整的威脅模型。
- 新功能是否允許檔案上傳? 如果是,也許 Web 應用程式安全性評定會更適當。
- 這項變更主要是功能性 UI 變更嗎? 如果是,也許除了傳統自動化工具之外,不需要其他任何方法。
安全性問卷結果會告知哪項 SDL 技術與哪個開發單位相關。 它也會通知開發合作夥伴功能的 SDL 時間表,以便他們能夠適時協作。
產品清查
其次,針對您負責評估的產品,維護強大的資產清查。 產品變得越來越複雜。 經常需要為具有下列項目的已連線裝置撰寫軟體:
- 感應器 (例如鐵路客運和車輛),
- 與車輛中其他元件通訊的公車網路 (例如 CANBUS 或 PROFIBUS),
- 用來與客戶裝置和雲端後端通訊的無線/行動數據/藍牙,
- 送回裝置或車隊管理應用程式的雲端機器學習,
- 還有更多。
在如此複雜的產品中,威脅模型化至關重要。 擁有強大的資產清查可讓您檢視整個產品堆疊以全面了解,並查看需要評估新功能或變更功能如何影響產品安全性的關鍵階段。
資料粒度與整合
建立系統,以使用明確的計量來衡量合規性。
- 定期衡量功能層級開發的合規性。 通常應該以較高的頻率和較小的資料粒度來衡量功能合規性,有時甚至是在開發人員的系統上或是在程式碼認可/合併時進行。
- 定期評估使用功能或元件之更廣泛產品的安全性。 通常會以較低的頻率和更廣泛的資料粒度來進行更廣泛的評估,例如在模組或系統測試時。
縮放比例
保持適當的資產清查系統,以擷取並保留安全性成品,以及威脅模型檢閱的輸出。 擁有清楚的清查可讓您評估檢閱輸出是否有模式,並針對如何定期精簡產品安全性計畫做出明智的決策。
嘗試結合需求階段安全性問卷、威脅模型化結果、安全性評定結果,以及自動化工具的結果。 結合這些項目可讓您自動呈現特定產品的相對風險觀點 (理想情況下為「儀表板」),以告知安全性小組需要專注的領域,從威脅模型化中獲得最大價值。
2.2 自動化測試
摘要
自動化測試是確保程式碼品質和安全的重要方法。 這是支援本文件中所提及其他領域不可或缺的一部分,例如威脅模型化。 搭配其他安全程式碼撰寫實務時,有助於防範程式碼基底中引進的 Bug 和弱點。
主要特性
測試應該可靠、一致且隔離。 這些測試應該盡可能涵蓋大部分的程式碼。 所有新功能和 Bug 修正都應該有對應的測試,以確保程式碼盡可能長期安全可靠。 定期執行自動化測試,並在盡可能多的環境中執行,以確保能夠執行並涵蓋所有領域:
- 第一個要執行的位置是在進行變更的電腦上。 這些測試最容易在用於編輯的 IDE 內執行,或在開發人員進行變更時作為命令列上的指令碼執行。
- 下一個要執行的位置是作為提取要求認可/合併程序的一部分。
- 最後一個執行測試的位置是作為持續整合與持續部署 (CI/CD) 管線的一部分,或作為候選版的一部分。
您應該在每個步驟增加測試的範圍,最後一個步驟會提供完整涵蓋範圍,以包含其他步驟可能遺漏的任何部分。
持續使用和維護
測試可靠性是維護測試套件有效性的重要部分。 測試失敗應指派給適當人員進行調查,其中潛在的安全性問題會優先處理,並在提示下於預先決定的時間範圍內更新。 您不應該經常忽略測試失敗,需要有強而有力的理由並經過核准才能這麼做。 由於測試套件本身問題的測試失敗應該與其他失敗一視同仁,以避免因遺漏產品問題而導致涵蓋範圍出現漏洞。
測試類型,特別是單元測試
自動化測試有幾種類型,雖然並非全部適用於所有應用程式,但良好的測試套件包含數種不同類型的選擇。 程式碼型測試案例 (例如單元測試) 是最常見且最不可或缺的,適用於所有應用程式,並刻意涵蓋盡可能多的程式碼路徑,以取得正確性。 這些測試應該規模很小、可快速完成且不會影響電腦的狀態,以便快速且經常地執行完整的測試套件。 可能的話,請在具有不同硬體設定的多部電腦上執行測試,以攔截單一類型電腦上無法重現的問題。
Visual Studio
Visual Studio 測試總管原生支援許多最熱門的 C++ 測試架構,並可選擇安裝延伸模組以取得更多架構。 這項彈性有助於執行涵蓋您所處理程式碼的測試子集,並讓您在測試失敗時輕鬆地進行偵錯。 Visual Studio 也可讓您輕鬆地為現有專案設定新的測試套件,並提供 CodeLens 等實用工具,讓您更輕鬆地管理這些測試。 如需使用 Visual Studio 撰寫、執行和管理 C/C++ 測試的詳細資訊,請參閱撰寫 C/C++ 的單元測試 - Visual Studio (Windows)。
在 Azure 和 GitHub CI/CD 中
執行更深入驗證且需要更長時間執行的測試 (例如靜態分析、元件偵測等),適合用於提取要求測試或持續整合測試。 Azure DevOps 和 GitHub Actions 可讓您輕鬆地在驗證失敗時自動執行驗證,並封鎖程式碼簽入。 自動化強制執行有助於確保所有正在簽入的程式碼根據正在執行的更嚴格檢查都是安全的。 以下說明 Azure Pipelines 和 Azure DevOps 組建驗證:
2.3 程式碼型 (或靜態) 分析
摘要 預設應啟用靜態程式碼/二進位檔分析,以確保預設安全。 靜態分析會分析程式在建置時所需的安全和安全性原則,而不是在客戶電腦上可能發生惡意探索的執行期間。 靜態分析可以分析原始程式碼格式或已編譯可執行檔格式的程式。
建議 Microsoft 建議您:
- 針對輸入原始程式碼 (編譯前) 和可執行二進位檔 (編譯後) 啟用所有 C++ 程式的靜態分析。 「啟用」可能表示在每個組建期間於開發人員的電腦上執行分析,或是作為個別組建執行以在稍後檢查程式碼,或作為簽入需求執行。
- 將靜態分析以測試形式納入 CI 管線。
- 靜態分析根據定義隨附誤判,並準備好將該事實納入您的品質意見反應迴圈。 快速預先啟用所有低誤判警告。 然後主動遞增規則數目,在定期新增更多規則時,讓程式碼基底編譯清理警告,以標幟重要的 Bug,但代價是誤判會越來越高 (一開始,也會針對這些規則清理程式碼基底)。
- 一律使用最新支援的 Visual Studio 版本,並設定您的工程環境,以在有最新修補程式版本可用時快速取用,而不會延遲到下一個開發階段/週期。
重要工具 請注意並利用下列資訊:
- 程式碼分析文件 - C++ 和 .NET
/analyze
- Visual C++ 編譯器/W4
和/WX
- Visual C++ 編譯器- 使用 C++ Core Guidelines 檢查工具
- CodeQL | GitHub (英文)
- Binskim 使用者指南 | GitHub (英文)
- 另請參閱 (僅限 Windows):SAL 註釋
注意:
/analyze
可在編譯時啟用 C++ 程式碼的靜態分析,以識別重大安全性和可靠性程式碼弱點。 應在 C++ 程式的整個開發期間啟用。 從預設至少啟用「Microsoft原生建議」作為最低基準開始。 然後,請參閱文件,以了解如何依照您工程原則的要求指定更多規則,特別是 C++ Core Guidelines 規則。 您可以在 Visual C++ IDE 和命令列建置工具中取得原始程式碼靜態分析功能。- 請盡可能啟用
/W4
和/WX
,以確保您在高警告層級 (W4
) 正常編譯程式碼,並將警告視為必須修正的錯誤 (WX
)。 這些選項可讓您尋找其他靜態分析工具無法檢查的非初始化資料錯誤,因為只有在後端編譯器執行程序間分析和內嵌之後才會顯示錯誤。 - BinSkim 二進位檔分析可確保專案能夠啟用廣泛的安全性功能。 BinSkim 會產生 PDB 和其他輸出,讓您更輕鬆地驗證監管鏈,並有效率地回應安全性問題。 Microsoft 建議執行 BinSkim 工具來分析程式所產生或使用的所有可執行二進位檔 (
.sys
、.dll
或.exe
)。 《BinSkim 使用者指南》包含支援的安全性標準清單。 Microsoft 建議您修正 BinSkim 工具回報為「錯誤」的所有問題。 回報為「警告」的問題應該選擇性地進行評估,因為解決這些問題可能會對效能造成影響,或可能沒有必要。
在 Azure 和 GitHub CI/CD 中 Microsoft建議一律在發行 CI/CD 案例中啟用原始程式碼和二進位檔靜態分析。 立即在本機開發人員的電腦上執行來源分析,或至少針對每個認可或提取要求執行來源分析,以儘早攔截來源 Bug,並將整體成本降到最低。 二進位檔層級 Bug 通常引進的速度較慢,因此在較不頻繁的發行前版本 CI/CD 案例 (例如夜間或每週組建) 中執行二進位檔分析可能就已足夠。
2.4 檢閱硬式編碼的祕密
摘要
請勿在軟體內硬式編碼祕密。 您可以使用可掃描整個原始程式碼基底的可靠工具,有效率地尋找並移除原始程式碼中的祕密。 找到祕密之後,請遵循安全儲存和使用祕密的指導方針,將其移至安全的地方。
問題
「祕密」是指建立身分識別並提供資源存取權的實體,或是用來簽署或加密敏感性資料的實體。 範例包括密碼、儲存體金鑰、連接字串和私密金鑰。 您可能很想在軟體產品中保留祕密,以便在軟體需要時隨時取得。 不過,由於這些硬式編碼的祕密很容易被發現,並可能被用來危害您的服務和資料,因此可能會導致嚴重或災難性的安全性事件。
預護
原始程式碼中硬式編碼的祕密 (作為純文字或加密的 Blob) 是安全性弱點。 以下是如何避免原始程式碼中祕密的一般指導方針:
- 使用預先檢查工具來掃描並攔截程式碼中潛在的硬式編碼祕密,再提交至原始檔控制。
- 請勿將純文字認證放在原始程式碼或設定檔中。
- 請勿將純文字認證儲存在 SharePoint、OneNote、檔案共用等。 或是透過電子郵件、IM 等方式共用。
- 請勿使用容易探索到的解密金鑰對祕密進行加密。 例如,請勿將 PFX 檔案與包含其密碼的檔案儲存在一起。
- 請勿使用弱式解密對祕密進行加密。 例如,請勿使用弱式或通用密碼加密 PFX 檔案。
- 避免將加密的認證放在原始程式碼中。 相反地,請在原始檔中使用預留位置,並讓您的部署系統將其取代為核准存放區中的祕密。
- 將相同的原則套用至測試、預備等環境中的祕密,就像您在生產部署中所做的一樣。 敵人通常會以非生產系統為目標 (因為其管理較不完善),再使用這些系統來轉向生產環境。
- 請勿在部署之間共用祕密 (例如在測試、預備、生產環境之間)。
雖然與硬式編碼的祕密不直接相關,但也記得保護測試、開發和生產環境的祕密:
- 定期並在祕密可能遭到公開時輪替祕密。 展示輪替/重新部署祕密的能力,以證明系統安全。 更值得注意的是,缺乏這項能力甚至成為無法避免弱點的更有力證明。
- 請勿屈服於「我的測試認證不會造成風險」的常見開發人員理由。實際上,他們幾乎總是會如此表示。
- 考慮不要使用祕密 (例如密碼、持有人金鑰),完全優先使用 RBAC/身分識別導向的解決方案作為良好的工程解決方案,以全面迴避祕密管理不善的情況。
偵測
您產品的舊版元件可能在其原始程式碼中包含隱藏的硬式編碼祕密。 有時候,開發人員桌上型電腦中的祕密可能會悄悄爬入遠端分支並合併到發行分支,而在無意中將祕密外洩。 若要探索原始程式碼中可能隱藏的祕密,您可以使用工具來掃描程式碼中硬式編碼的祕密:
補救
如果在您的原始程式碼中找到認證,您必須立即使公開的金鑰失效,並根據暴露風險執行風險分析。 即使您的系統需要持續執行,您也可以使用下列步驟啟用祕密管理員進行補救:
- 如果補救允許切換至受控識別,或要求存取 Azure Key Vault (AKV) 等祕密管理員,請先這麼做。 然後使用更新的身分識別或金鑰重新部署。
- 使公開的祕密失效。
- 執行稽核/風險評定,以評估因入侵所造成的潛在損害。
若要保護雲端應用程式和服務所使用的密碼編譯金鑰和其他祕密,請使用具有適當存取原則的 Azure Key Vault。
如果暴露風險洩漏特定客戶資料/PII,則可能需要其他合規性/報告需求。
從您的原始程式碼中移除現在無效的祕密,並將其取代為不會直接在原始程式碼中公開祕密的替代方法。 尋找機會,以使用 Azure AD 等工具盡可能消除祕密。 您可以更新驗證方法,以透過 Azure Active Directory 利用受控識別。 僅使用核准的存放區來儲存和管理祕密,例如 Azure Key Vault (AKV)。 如需詳細資訊,請參閱
Azure DevOps (AzDO)
AzDO 使用者可以透過適用於 Azure DevOps 的 GitHub Advanced Security (GHAzDO) 掃描其程式碼。 GHAzDO 也可讓使用者透過在存放庫上啟用推送保護來防止祕密暴露風險,並在外洩前攔截潛在暴露風險。 如需如何在 Azure DevOps 中偵測程式碼中硬式編碼祕密的詳細資訊,請參閱下列每個連結中的適用於 Azure DevOps 的 GitHub Advanced Security 中的密碼掃描:
- 適用於 Azure DevOps 的 GitHub Advanced Security
- 適用於 Azure DevOps 的 GitHub Advanced Security 中的祕密掃描
- 適用於 DevOps 的 Microsoft Defender 預覽
在 GitHub 中
祕密掃描以下列兩種形式在 GitHub.com 上提供:
- 適用於合作夥伴的祕密掃描警示。 在所有公用存放庫上自動執行。 任何符合祕密掃描合作夥伴所提供模式的字串,都會直接回報給相關合作夥伴。
- 適用於使用者的祕密掃描警示。 您可以針對使用 GitHub Enterprise Cloud 並具有 GitHub Advanced Security 授權之組織所擁有的存放庫,啟用和設定額外的掃描。 這些工具也支援私人和內部存放庫。
GitHub 為合作夥伴和使用者提供已知的祕密模式,可加以設定來符合您的需求。 如需詳細資訊,請參閱:
- 秘密掃描模式
- GitHub 中的關於祕密掃描 (英文)
注意
適用於 Azure DevOps 的 GitHub Advanced Security 提供相同的祕密掃描、相依性掃描和 CodeQL 程式碼掃描解決方案,這些解決方案已可供 GitHub 使用者使用,並原生整合於 Azure DevOps,以保護您的 Azure Repos 和 Pipelines。
其他資源
- 認證掃描 | Microsoft 使用工程劇本撰寫程式碼 (英文)。
- detect-secrets:認證掃描工具 | GitHub (英文) - 用於偵測程式碼基底內祕密的適當命名模組。
- 在 Azure Pipelines 中執行 detect-secrets (英文)。
- Git-secrets | GitHub awslabs (英文) - 防止您將密碼和其他敏感性資訊認可至 Git 存放庫。
- 祕密管理 | Microsoft 使用工程劇本撰寫程式碼 (英文) - 提供有關如何管理祕密的一般指導方針。
2.5 以語言和 OS 提供的檢查和保護方式執行
摘要
透過套用編譯時間安全性控制來進行二進位檔強化。 這包括下列風險降低功能:
- 防止程式碼中出現可惡意探索的弱點,
- 啟用執行階段偵測,以在惡意探索時觸發安全性防禦,以及
- 啟用資料產生和封存,以協助限制安全性事件所造成的損害。
二進位檔取用者必須加入 Windows 安全性功能,才能充分利用強化。
Microsoft 提供一組 C++ 專案特定工具,以協助開發人員撰寫和交付更安全且更受保護的程式碼。 C++ 開發人員也應該遵守產生可執行程式碼之語言通用的安全性標準。 Microsoft 維護 BinSkim,這是公用 OSS 二進位檔檢查程式,可協助強制使用本節中所述的許多保護。 如需 BinSkim 的詳細資訊,請參閱 Binskim 使用者指南 | GitHub (英文)
二進位檔層級控制會根據在工程程序中套用的位置而有所不同。 您應該區分下列編譯器和連結器選項:為嚴格編譯時間、在執行階段額外負荷下改變程式碼產生,以及改變程式碼產生以實現與 OS 保護的相容性。
開發人員設定應該優先啟用盡可能多的靜態分析、啟用私人資料產生以加速偵錯等。 發行組建應該調整為適當的安全性、效能和其他程式碼產生考量的組合。 發行程序必須設定為正確產生和管理公開與私下使用的組建資料 (例如公用與私人符號)。
保持最新狀態:一律使用最新的編譯器和工具
使用目前的工具組編譯所有程式碼,以受益於最新的語言支援、靜態分析、程式碼產生和安全性控制。 由於編譯器會影響每個產生的元件,因此工具更新的迴歸可能性相對較高。 使用過時的編譯器會在回應安全性事件時產生矯正措施的特定風險,因為小組可能沒有足夠的時間來升級編譯器。 Microsoft 建議小組開發工具,以定期更新編譯器並測試更新。
使用安全開發方法、語言版本、架構/API
程式碼應該利用開發方法、語言版本、架構、API 等促進 C++ 的安全性和簡單性,將風險降到最低,包括:
- 參閱 C++ Core Guidelines 的 Guideline Support Library (GSL) (英文),以取得撰寫遵循最佳做法並避免常見陷阱之現代、安全且一致 C++ 程式碼的指引。
- 參閱 Microsoft GSL 實作 (英文),以了解 C++ Core Guidelines 建議您使用的函式和類型。
- 資源安全 C++ 容器、C 執行階段程式庫 (CRT) 記憶體溢位保護:優先使用資源安全的
std::vector
和std::string
。 如果您必須使用 C 資料,請使用 CRT 函式的安全版本,其設計目的是為了協助防止由於緩衝區誤用和未定義的語言行為所造成的記憶體損毀。 - SafeInt 程式庫可防止數學和比較運算中的整數溢位。
使用安全相依性
二進位檔不應該連結至不安全的程式庫和相依性。 開發小組應該追蹤所有外部相依性,並在易受這些弱點攻擊時更新為更安全的版本,以解決這些元件中的 CVE/已識別的安全性弱點。
將程式碼來源保證和安全性回應效率提到最高
編譯應該啟用強式程式碼來源保證,以協助偵測及防止引進後門程式和其他惡意程式碼。 產生的資料對於偵錯和調查也至關重要,應該針對所有軟體版本封存,以便在遭洩漏時提高安全性回應效率。 下列編譯器參數會產生對於安全性回應至關重要的資訊:
- Visual C++ 中的
/ZH:SHA_SHA256
- 確保使用密碼編譯安全演算法來產生所有 PDB 來源檔案雜湊。 - Visual C++ 中的
/Zi
、/ZI
(偵錯資訊格式) - 除了發佈用於收集損毀資料和其他公開使用案例的刪減符號之外,請確保針對所有發行的二進位檔產生和封存私人 PDB。 二進位檔分析工具需要完整符號,才能驗證是否已在編譯時啟用許多安全性風險降低功能。 私人符號對於安全性回應至關重要,當工程師爭先評估並限制惡意探索的損毀時,其偵錯和調查成本較低。 - Visual C++ 連結器中的
/SOURCELINK
- 在 PDB 中包含 Sourcelink 檔案:來源連結是與語言和原始檔控制無關的系統,提供二進位檔的來源偵錯。 來源偵錯可大幅提升發行前版本安全性驗證和發行後事件回應的範圍。
啟用編譯器錯誤,以防止在程式碼撰寫時發生問題
編譯應該啟用安全性相關編譯器檢查作為中斷性錯誤,例如:
- Visual C++ 中的
/sdl
- 啟用額外的安全性檢查,將許多與安全性相關警告提升為錯誤,並啟用進階安全程式碼產生功能。 - BinSkim BA2007.EnableCriticalCompilerWarnings | GitHub 維護一份 Microsoft 建議的 C/C++ 編譯器警告清單,應該一律啟用並提升為錯誤。
將二進位檔標示為與 OS 執行階段安全性風險降低功能相容
編譯器和連結器設定應該加入程式碼產生功能,以偵測惡意程式碼執行並降低其風險,包括:
- 堆疊損毀防護
/SAFESEH
- 映像具有安全例外狀況處理常式 - 產生 x86 二進位檔映像的安全例外狀況處理常式表。/GS
- 緩衝區安全性檢查 - 偵測一些覆寫傳回位址、例外狀況處理常式位址或特定參數類型的緩衝區溢位。
- 位置獨立程式碼執行
/DYNAMICBASE
- 使用位址空間配置隨機載入 - 產生可在載入時隨機重訂基底的可執行檔映像。/HIGHENTROPVA
和/LARGEADDRESSAWARE
- 支援 64 位元 ASLR,並處理大型位址 - 可讓您使用整個 64 位元位址空間重訂映像基底。
- 程式碼流程完整性
/guard:cf
- 啟用控制流程防護 - 插入間接呼叫目標的執行階段驗證。/CETCOMPAT
- CET 陰影堆疊相容 - 將可執行檔映像標示為與 Microsoft 實作之 Intel 控制流程強制執行技術 (Control-flow Enforcement Technology,CET) 陰影堆疊功能相容。/guard:ehcont
- 啟用 EH 接續中繼資料 - 產生所有例外狀況處理接續目標的安全相對虛擬位址 (RVA) 清單。
- 資料執行防止
/NXCOMPAT
- 與資料執行防止相容 - 將 32 位可執行檔映像標示為與 Windows 資料執行防護 (DEP) 功能相容。 64 位元組建預設與 DEP 相容。
防止敏感性資訊洩漏
編譯器設定應該加入敏感性資訊探索防護。 近年來,研究人員發現了源自推測性執行等硬體功能的非預期資訊外洩。
在軟體層級,機密資料若意外遭到外洩,則可能會傳送給攻擊者。 無法零初始化緩衝區及其他緩衝區誤用,都可能會將私人機密資料外洩給呼叫受信任 API 的攻擊者。 此類問題的最佳處理方式,是透過啟用額外的靜態分析和使用安全資源容器 (如前所述)。
/Qspectre
- 降低推測性執行端通道攻擊風險 - 插入屏障指令,協助防止推測性執行所產生的敏感性資料遭到洩漏。 如有程式碼將敏感性資料儲存在記憶體中,並跨信任界限運作,則應該針對程式碼啟用這些風險降低功能。 Microsoft 一律建議您在啟用 Spectre 風險降低功能時,依據適當的基準衡量效能影響,因為有可能在效能關鍵區塊或迴圈中引進執行階段檢查。 這些程式碼路徑可以透過spectre(nomitigation)
declspec
修飾詞停用風險降低功能。 啟用/Qspectre
的專案也應該連結到也使用這些風險降低編譯的連結庫,包括Microsoft運行時間連結庫。
2.6 黑箱測試案例
摘要
黑箱測試不需要知道測試元件的內部運作。 黑箱測試旨在以任何層級,測試產品中功能的端對端功能性。 黑箱測試可以是功能測試、UI 測試、效能測試及整合測試。 黑箱測試對於衡量一般可靠性和功能正確性,以及確保產品如預期般運作,都很重要。
與其他章節的關聯
這些類型的需求型測試有助於驗證在威脅模型中所做的假設,並涵蓋該節中提出的潛在威脅。 這些測試有助於測試產品個別元件之間的整合,特別是跨信任界限的元件,如威脅模型中所述。 黑箱測試案例也有助於測試使用者輸入驗證的各種邊緣案例。 測試已知的邊緣案例和錯誤案例都很有用。 模糊測試也有助於測試較不明顯的案例。
自動化和迴歸
定期執行這些測試,並將結果與先前的執行進行比較,以攔截中斷性變更或效能迴歸。 此外,對許多不同的電腦和安裝設定執行這些測試,有助於涵蓋可能來自不同架構或設定變更的任何問題。
損毀傾印
這些測試有助於找出可靠性問題,能夠測試可能遇到損毀、停止回應、死結等許多不同案例。 藉由收集損毀傾印作為測試失敗的一部分,您可以將傾印直接匯入 Visual Studio,以進一步調查程式碼中哪些部分遇到這些問題。 如果您從 Visual Studio 內執行功能測試,只要在黑箱內查看測試失敗的實際位置,即可輕鬆地複寫和偵錯失敗,而且您可以快速測試修正。
若要開始偵錯測試,請參閱使用測試總管進行偵錯單元測試 - Visual Studio (Windows)
在 Azure 中
Azure DevOps 也可以使用 Test Plans 來協助管理和驗證這些測試。 這些測試可用來確保手動驗證核准,並執行與產品需求相關聯的自動化測試。 如需 Azure Test Plans 及其如何用來執行自動化測試的詳細資訊,請參閱:
2.7 程式碼型測試案例
摘要
程式碼型測試案例是維護產品安全性和可靠性不可或缺的一部分。 這些測試應該規模很小並可快速完成,而且不應該對彼此造成影響,以便能夠平行執行。 開發人員可以在每次對程式碼進行變更時,輕鬆地在開發電腦本機執行程式碼型測試,而不必擔心開發週期變慢。
類型,以及與其他章節的關聯
程式碼型測試案例的常見類型包括:
- 單元測試,
- 參數化測試,以涵蓋具有多個輸入類型的函式,
- 元件測試,讓每個測試元件保持分開,以及
- 模擬測試,以驗證與其他服務通訊的程式碼部分,而不需要擴大測試範圍以包含這些服務本身。
這些測試是以撰寫的內部程式碼為基礎,而黑箱測試則是以產品的外部功能需求為基礎。
目標
透過這些測試,目標是要實現程式碼的高階測試涵蓋範圍。 您應該主動追蹤此涵蓋範圍,以及存在漏洞的位置。 隨著您新增更多測試來練習更多程式碼路徑,對您程式碼安全性和可靠性的整體信賴度將會提高。
Visual Studio
Visual Studio 中的測試總管工具可讓您輕鬆地經常執行這些測試,並快速取得成功/失敗率和失敗位置的意見反應。 許多測試架構也支援 CodeLens 功能,可在測試本身位置查看測試狀態,讓新增和維護測試套件變得更容易。 測試總管也可讓您輕鬆管理這些測試,允許測試群組、自訂測試播放清單、篩選、排序、搜尋等。
如需詳細資訊,請參閱
- 單元測試基本概念 - Visual Studio (Windows) - 簡介和概觀
- 使用測試總管執行單元測試 - Visual Studio (Windows) - 更深入了解所提供的功能,以協助使用測試總管來管理可能很龐大的單元測試集
Visual Studio 也隨附用來追蹤程式碼涵蓋範圍的工具。 這些工具可讓您確保現有測試涵蓋您所做的程式碼變更,或新增測試以涵蓋新的和未經測試的程式碼路徑。 這些工具也會顯示程式碼涵蓋範圍百分比,以確保其維持在目標層級以上,從而提高對整體程式碼品質的信賴度。
如需這些工具的資訊,請參閱程式碼涵蓋範圍測試 - Visual Studio (Windows)
在 Azure 中
Azure DevOps 也可協助在建置管線過程中追蹤整個產品的程式碼涵蓋範圍結果。 如需詳細資訊,請參閱檢閱程式碼涵蓋範圍 - Azure Pipelines。
2.8 歷史測試案例
摘要
歷史測試案例 (也稱為迴歸測試案例) 可防止舊問題再次出現,並增加產品的整體測試涵蓋範圍。 您應該確保修正 Bug 時,專案也會新增對應的測試案例。 在一段時間後,隨著修正的進行,測試套件的整體健全性將持續改善,為可靠性和安全性提供更好的保證。
主要特性,以及與其他章節的關聯
由於這些測試會測試 Bug 迴歸,執行起來應該很快且很容易,因此可以與 [程式碼型測試案例] 一起執行,並有助於產品的整體程式碼涵蓋範圍。 此外,使用客戶的真實範例來激發新的測試案例,是改善測試涵蓋範圍和品質的絕佳方式。
Visual Studio
Visual Studio 可讓您輕鬆地將測試新增至套件,同時進行變更以修正 Bug,並快速執行測試和程式碼涵蓋範圍,以確保考慮到所有新的案例。 在撰寫測試的程式碼中參考問題追蹤系統中的 Bug 識別碼,有助於將迴歸測試連接到對應的問題。 請優先搭配 Visual Studio 使用 Azure Boards 和測試計劃,以便:
- 建立測試、測試案例和問題的關聯;以及
- 追蹤問題及其對應測試的所有層面。
如需詳細資訊,請參閱
最後,將這些測試整合到本應涵蓋程式碼區段的單元測試區域,有助於讓測試套件井然有序且更容易管理。 您可以使用測試總管的測試群組,有效地追蹤屬於一起的測試。 如需詳細資訊,請參閱使用測試總管執行單元測試 - Visual Studio (Windows)
2.9 模糊測試
摘要 模糊測試是自動化軟體測試技術,涉及提供無效、非預期或隨機資料作為程式的輸入。 接著會監視程式是否有例外狀況,例如損毀、內建或編譯器插入的程式碼判斷提示失敗,以及潛在的記憶體流失。
指引
請對所有可能處理攻擊者可控制之不受信任輸入的所有軟體使用模糊測試。 如果您要建置新的應用程式及其相關聯的測試套件,請儘早包含關鍵模組的模糊測試。 第一次在軟體上執行模糊測試,幾乎一律會發現先前未知的實際弱點。 一旦您開始模糊測試,則絕不停止。
與其他章節的關聯
當模糊測試報告失敗時,自然而然一律會提供可重現的測試案例來示範 Bug。 您可以重現此測試案例、加以解決,然後將其新增至歷史測試案例。
同時使用清理程式 (例如AddressSanitizer (ASan)) 和模糊測試時:
- 請先執行已啟用清理程式的一般測試來查看是否有問題,一旦程式碼清理乾淨,便可開始模糊測試。
- 對於 C 或 C++,有自動插入執行階段判斷提示的編譯器,以及啟用 ASan 的中繼資料。 針對 ASan 編譯時,產生的二進位檔會與執行階段程式庫連結,以便精確地診斷 15 種以上具有零誤判的記憶體安全錯誤類別。 對於 C 或 C++,當您有來源時,請使用 LibFuzzer,這需要先啟用 ASan。
- 對於以 Java、C#、Python、Rust 等撰寫的程式庫,請使用 AFL++ 架構。
主要特性
- 模糊測試會尋找靜態程式分析、詳盡的功能測試和手動程式碼檢查經常遺漏的弱點。
- 模糊測試是尋找軟體中安全性和可靠性 Bug 的有效方法,因此 Microsoft 安全性開發生命週期需要在每個產品的每個不受信任介面上執行模糊測試 (另請參閱威脅模型化)。
- 一律針對可能處理不受信任輸入的軟體使用模糊測試。
- 模糊測試對於具有大型資料剖析器的獨立應用程式而言很有效。
Azure 和 GitHub CI/CD
修改您的組建,以支援持續建立使用 LibFuzzer 或 AFL++ 的可執行檔。 您可以新增對 OSS-Fuzz 或 OneFuzz 等服務執行模糊測試所需的額外運算資源。
2.10 Web 應用程式掃描
摘要
在 Windows 版 Microsoft Visual C++ 的範圍內,Microsoft 建議:
- 優先使用適用於 Web 應用程式的 TypeScript、JavaScript 和 ASP.NET。
- 請勿以 C++ 撰寫 Web 延伸模組。 Microsoft 已停用 ActiveX。
- 當程式碼編譯為 Emscripten/WASM 時,則不再適用 C++ 和其他工具。
- Microsoft 提供 RESTler,這是具狀態的 REST API 模糊工具。
概觀和主要特性
Web 應用程式掃描器會對 Web 應用程式的網頁進行編目來探索 Web 應用程式,並檢查其是否有安全性弱點。 此編目涉及自動產生惡意輸入和評估應用程式的回應。 嚴格來說,Web 應用程式掃描必須涵蓋/支援下列作業:
- 對您網路中的所有 Web 應用程式進行編目 (包括新的和未知的應用程式),並從幾個應用程式擴充到數千個。
- 對行動裝置所使用的軟體版本、SOAP 和 REST API 服務以及 API 進行深入掃描。
- 將安全性基本類型插入 DevOps 環境中的應用程式開發和部署。 這些基本類型可與編目程式搭配使用。
- 惡意程式碼偵測。
2.11 檢查包含的軟體元件
摘要
以與使用其他程式設計語言撰寫的程式碼相同的方式來處理您的 C++ 程式碼,並將貴公司採用的任何軟體組成分析 (SCA) 和來源分析 (OA) 工具套用至您的 C++ 程式碼。 工作流程和安全性掃描應設計為 CI/CD (持續整合與持續傳遞) 系統的一部分。
上游防禦
若要降低上游相依性攻擊的風險,第三方來源/元件應該儲存在企業控制的資產上,以針對該資產執行 SCA 和 OA 工具。
- 當發現弱點時 (包括公用資料庫),工具應掃描並發出警示,例如:首頁 | CVE
- 對應用程式/存放庫中包含的所有軟體元件執行靜態分析,以識別易受攻擊的程式碼模式。
相依性防禦
執行並維護相依性的稽核,以驗證 SCA 和 OA 工具考慮並涵蓋所有這類項目。
- 您應該定期稽核元件,並將其更新為最新驗證的版本。
- 套件摘要相依性。
- SCA/OA 工具涵蓋並稽核來自單一摘要的所有套件相依性。
SBOM
產生您產品的 SBOM (軟體物料清單),以列出所有相依性,例如:
- 來源 (例如 URL (統一資源定位器))
- version
- 一致性 (例如 SHA-256 來源雜湊),以及用於驗證一致性的其他方法 (例如具決定性的組建)。
- 要求並稽核軟體相依性中的 SBOM 檔案,或作為組建一部分產生的檔案,包括 OSS (開放原始碼軟體)。
- Microsoft 將標準化,並建議使用 SPDX (Software Package Data Exchange) 2.2 版或更新版本 | Linux Foundation 作為 SBOM 文件格式。
- 組建決定性可用來獨立產生位元相同的二進位檔,並提供完整性的獨立驗證:
- 第一方或第三方重現證明
- 其他技術 (例如透過受信任的憑證來源進行二進位檔簽署) 也可提供二進位檔完整性的一些保證。
其他資源
Microsoft 解決方案包含下列指引和產品:
- Microsoft Supply Chain Platform | Microsoft
- 保護您的軟體供應鏈 | GitHub 安全性 (英文)
- vcpkg - vcpkg 私人登錄可將 OSS 採購重新導向至企業控制的資源,以取得相依性的來源,將上游或無線攻擊的風險降到最低。