共用方式為


驅動程式安全性檢查清單

本文提供驅動程式安全性檢查清單,讓驅動程式開發人員協助降低驅動程式遭到入侵的風險。

驅動程式安全性概觀

安全性缺陷是任何缺陷,可讓攻擊者造成驅動程式故障,使系統當機或變成無法使用。 此外,驅動程式程式代碼中的弱點可讓攻擊者取得核心的存取權,進而造成危害整個OS的可能性。 當大多數開發人員都在處理其驅動程式時,其重點是讓驅動程式正常運作,而不是惡意攻擊者是否會嘗試在其程式代碼中惡意探索弱點。

不過,在驅動程式釋放之後,攻擊者可以嘗試探查及識別安全性缺陷。 開發人員必須在設計和實作階段考慮這些問題,才能將這類弱點的可能性降到最低。 目標是在驅動程序發行之前消除所有已知的安全性缺陷。

建立更安全的驅動程式需要系統架構設計人員的合作(有意識地思考對驅動程式的潛在威脅)、實作程式代碼的開發人員(以防禦性編碼常見作業可能是惡意探索的來源),以及測試小組(主動嘗試尋找弱點和弱點)。 通過適當協調所有這些活動,驅動程式的安全性會大幅增強。

除了避免與受到攻擊的驅動程式相關的問題之外,所描述的許多步驟,例如更精確的核心記憶體使用,也會增加驅動程式的可靠性。 這可降低支援成本,並提升您對產品的滿意度。 完成下列檢查清單中的工作將有助於達成所有這些目標。

安全性檢查清單:完成每個主題中所述的安全性工作。

[未標記] 複選框,代表安全性檢查清單中的專案。 確認需要核心驅動程式

未標記的核取方塊,代表安全檢查清單中的項目。 使用驅動程式架構

[未標記] 複選框,代表安全性檢查清單中的專案。 控制對僅限於軟體的驅動程式的存取

[未標記] 複選框,用於表示安全檢查清單中的項目。 不要在生產環境中簽署測試駕駛程式碼

未標記的複選框,代表安全檢查清單中的項目。 執行威脅分析

未勾選的複選框,代表安全檢查清單中的項目。 遵循驅動程式安全編碼指導方針

未標記的勾選框,表示安全性檢查清單中的項目。 實施 HVCI 相容程式代碼

[未標記] 核取方塊,代表安全檢查清單中的項目。 遵循特定技術的程式碼最佳實踐

[未標記] 的複選框,代表安全檢查清單中的一個項目。 進行程式碼同儕檢閱

[未勾選] 複選框,表示安全檢查清單中的一項。 管理驅動程式存取控制

[未標記] 複選框,代表安全性檢查清單中的專案。 增強裝置安裝安全性

[未標記] 核取方塊,代表安全性檢查清單中的項目。 執行正確的發行驅動程式簽署

未勾選的複選框,代表安全性檢查清單中的項目。 使用 CodeQL 檢查驅動程式代碼

未勾選的複選框,代表安全檢查表中的項目。 將 SAL 批註添加到驅動程式代碼中

[未標記] 複選框,代表安全性檢查清單中的專案。 使用驅動程式驗證器來檢查弱點

[未標記] 複選框,代表安全性檢查清單中的專案。 使用 BinSkim 二進位分析器檢查程式代碼

[未標記] 複選框,代表安全性檢查清單中的專案。 使用硬體相容性測試程式來檢查程式碼

[未標記] 複選框,代表安全性檢查清單中的專案。 瞭解如何使用Microsoft易受攻擊和惡意驅動程序報告中心 報告驅動程式

未勾選的複選框,表示安全性檢查清單中的專案。 檢閱安全編碼資源

[未標記] 複選框,代表安全性檢查清單中的專案。 檢閱 重點收穫摘要

確認需要核心驅動程式

安全性檢查清單專案 #1:確認需要核心驅動程式,且 Windows 服務或應用程式等風險較低的方法不是較佳的選項。

驅動程式位於 Windows 核心中,並在核心中執行時發生問題,會公開整個操作系統。 如果有任何其他選項可供使用,則其成本可能會較低,且與建立新核心驅動程序的風險較低。 如需使用內建 Windows 驅動程式的詳細資訊,請參閱 是否需要撰寫驅動程式?

如需了解使用背景工作的方法,請參閱 使用背景工作支援您的應用程式

如需使用 Windows 服務的資訊,請參閱 Services

使用驅動程序架構

安全性檢查清單專案 #2:使用驅動程式架構來減少程式代碼的大小,並增加其可靠性和安全性。

使用 Windows Driver Frameworks 來減少程式代碼的大小,並增加其可靠性和安全性。 若要開始,請檢閱 使用 WDF 開發驅動程式。 如需使用較低風險的使用者模式架構驅動程式 (UMDF)的資訊,請參閱 選擇驅動程式模型

撰寫舊式 Windows 驅動程式模型 (WDM) 驅動程式更耗時、成本高昂,而且幾乎一律牽涉到重新建立驅動程式架構中可用的程式代碼。

Windows Driver Framework 原始碼是開放原始碼,可在 GitHub 上使用。 這是與隨 Windows 10 附帶的 WDF 執行階段庫相同的原始程式碼。 當您能追蹤驅動程式與 WDF 的互動時,您可以更有效地偵錯驅動程式。 從 https://github.com/Microsoft/Windows-Driver-Frameworks下載它。

控制僅軟體驅動程式的存取

安全性檢查清單專案 #3:如果要建立僅限軟體的驅動程式,則必須實作額外的訪問控制。

僅限軟體的核心驅動程式不會使用即插即用 (PnP) 來與特定硬體識別碼相關聯,而且可以在任何電腦上執行。 這類驅動程式可用於原本預期以外的用途,以建立攻擊向量。

由於僅限軟體的核心驅動程式包含額外的風險,因此它們必須受限於在特定硬體上執行(例如,使用唯一的 PnP 標識符來啟用建立 PnP 驅動程式,或檢查 SMBIOS 數據表中是否有特定硬體)。

例如,假設 OEM Fabrikam 想要散發驅動程式來為其系統啟用超頻工具。 如果這個僅為軟體的驅動程式在不同 OEM 的系統上執行,可能會導致系統不穩定或損毀。 Fabrikam 的系統應該包含唯一的 PnP 識別碼,以便建立也可透過 Windows Update 更新的 PnP 驅動程式。 如果無法這樣做,Fabrikam 會撰寫舊版驅動程式,該驅動程式應該找到另一種方法來確認它正在 Fabrikam 系統上執行(例如,在啟用任何功能之前先檢查 SMBIOS 數據表)。

不要將測試程式碼用於生產環境

安全性檢查清單專案 #4:不要生產程式代碼簽署開發、測試和製造核心驅動程式程序代碼。

用於開發、測試或製造的核心驅動程式程式代碼可能包含構成安全性風險的危險功能。 此危險程式代碼絕不應以 Windows 信任的憑證簽署。 執行危險驅動程式程式代碼的正確機制是停用 UEFI 安全開機、啟用 BCD “TESTSIGNING”,並使用不受信任的憑證簽署開發、測試和製造程式代碼(例如,makecert.exe所產生的憑證)。

由信任的軟體發行者憑證 (SPC) 或 Windows 硬體質量實驗室 (WHQL) 簽章簽署的程式代碼不得有助於略過 Windows 程式代碼完整性和安全性技術。 在程式代碼由信任的 SPC 或 WHQL 簽章簽署之前,請先確定其符合 建立可靠 Kernel-Mode 驅動程式的指引。 此外,程式代碼不得包含任何危險行為,如下所述。 如需有關驅動程式簽署的詳細資訊,請參閱本文後續的 發行驅動程式簽署

危險行為的範例包括下列各項:

  • 提供將任意核心、實體或裝置記憶體對應至使用者模式的能力。
  • 提供讀取或寫入任意核心、實體或裝置記憶體的能力,包括埠輸入/輸出(I/O)。
  • 提供存取繞過 Windows 存取控制的儲存空間。
  • 提供修改驅動程式未設計來管理的硬體或韌體的能力。

執行威脅分析

安全性檢查清單專案 #5:修改現有的驅動程序威脅模型,或為您的驅動程式建立自定義威脅模型。

在考慮安全性時,常見的方法是建立特定的威脅模型,以嘗試描述可能的攻擊類型。 這項技術在設計驅動程式時很有用,因為它會強制開發人員事先考慮針對驅動程式的潛在攻擊媒介。 識別出潛在威脅之後,驅動程式開發人員就可以考慮防禦這些威脅的方法,以增強驅動程式元件的整體安全性。

本文提供特定於驅動程式的輕量型威脅模型建立指引:驅動程式的威脅模型化。 本文提供可用來作為驅動程式起點的範例驅動程序威脅模型圖表。

範例數據流程圖,說明假設的核心模式驅動程式。

IHV 和 OEM 可以使用安全性開發生命週期 (SDL) 最佳做法和相關聯的工具,以改善其產品的安全性。 如需詳細資訊,請參閱 SDL 建議給 OEM

遵循驅動程式安全編碼指導方針

安全性檢查清單專案 #6:檢閱您的程序代碼,並移除任何已知的程式代碼弱點。

建立安全驅動程式的核心活動是識別程序代碼中需要變更的區域,以避免已知的軟體弱點。 眾所周知的許多軟體漏洞涉及嚴格控制記憶體的使用情況,以避免其他人覆寫或影響驅動程式所用記憶體位置的問題。

程式代碼掃描工具,例如 CodeQL 和驅動程式特定測試,可用來協助找出這些弱點的一些,但並非全部。 本主題稍後會說明這些工具和測試。

記憶體緩衝區

使用適當的方法來存取具有IOCTLs的數據緩衝區

Windows 驅動程式的主要責任之一是在使用者模式應用程式與系統裝置之間傳輸數據。 下表顯示存取數據緩衝區的三種方法。

IOCTL 緩衝區類型 總結 如需詳細資訊
METHOD_BUFFERED 建議用於大多數情況 使用緩衝輸入/輸出
METHOD_IN_DIRECT或METHOD_OUT_DIRECT 用於某些高速硬體 I/O 使用直接 I/O
方法_兩者皆非 盡可能避免 未使用緩衝處理或直接 I/O

一般而言,建議使用緩衝 I/O,因為它提供最安全的緩衝方法。 但是,即使使用緩衝 I/O 也存在風險,例如需要應對的嵌入指標。

如需在 IOCTLs 中使用緩衝區的詳細資訊,請參閱 存取數據緩衝區的方法

使用IOCTL緩衝I/O時發生錯誤

  • 檢查 IOCTL 相關緩衝區的大小。 如需詳細資訊,請參閱 無法檢查緩衝區的大小

  • 正確初始化輸出緩衝區。 如需詳細資訊,請參閱 無法初始化輸出緩衝區

  • 正確驗證可變長度緩衝區。 如需詳細資訊,請參閱 無法驗證 Variable-Length 緩衝區

  • 使用緩衝的 I/O 時,請確定並傳回 [IO_STATUS_BLOCK 結構資訊] 欄位中 OutputBuffer 的適當長度。 不要只是直接從 READ 要求中直接傳回長度。 例如,假設用戶空間傳回的數據顯示出現 4K 緩衝區。 如果驅動程式實際上只應該傳回 200 個字節,但只會在 [資訊] 字段中傳回 4K,就會發生資訊洩漏弱點。 發生此問題的原因是,在舊版 Windows 中,I/O 管理員用於緩衝 I/O 的緩衝區不會為零。 因此,使用者應用程式會傳回原始的 200 位元組數據,加上緩衝區中任何內容的 4K-200 位元組(非分頁集區內容)。 此情況可能發生在所有緩衝 I/O 的使用中,而不僅限於使用 IOCTL。

IOCTL 直接 I/O 中的錯誤

正確處理長度為零的緩衝區。 如需詳細資訊,請參閱直接 I/O中的 錯誤。

參考使用者空間位址時發生錯誤

  • 驗證內嵌在緩衝 I/O 要求中的指標。 如需詳細資訊,請參閱參考 User-Space 位址中的 錯誤。

  • 在嘗試使用它之前,請先驗證用戶空間中的任何位址,並在適當時使用如 ProbeForReadProbeForWrite 等 API。

MSR 模型專用暫存器讀取和寫入

編譯程式內部函數,例如 __readmsr__writemsr 可用來存取模型特定的緩存器。 如果需要此存取權,驅動程式必須一律檢查要讀取或寫入的緩存器是否受限於預期的索引或範圍。

如需更多資訊和程式代碼範例,請參閱 Windows 驅動程式開發人員開發安全性最佳做法提供讀取/寫入 MSR 的能力。

TOCTOU 弱點

使用直接 I/O 或讀取/寫入時,有 檢查使用時間 (TOCTOU) 弱點的時間。 請注意,驅動程式正在存取用戶數據緩衝區,用戶可以同時存取它。

若要管理此風險,請將需要從用戶數據緩衝區驗證的任何參數複製到只能從核心模式存取的記憶體(例如堆棧或集區)。 然後,一旦使用者應用程式無法存取數據,請驗證並操作傳入的數據。

驅動程式程式代碼必須正確使用記憶體

  • 所有驅動程式集區配置都必須位於非可執行的 (NX) 集區中。 使用 NX 記憶體集區原本就比使用可執行的非分頁集區(NP) 集區更安全,並提供更好的保護來防範溢位攻擊。

  • 裝置驅動程式必須正確處理各種使用者模式和核心與核心之間的 I/O 要求。

若要允許驅動程式支援 HVCI 虛擬化,有額外的記憶體需求。 如需詳細資訊,請參閱本文稍後部分中的 實作與 HVCI 相容的程式碼

把手

裝置物件

IRPs

WDF 和 IRP

使用 WDF 的優點之一是 WDF 驅動程式通常不會直接存取 IRP。 例如,架構會將代表讀取、寫入和裝置 I/O 控制作業的 WDM IRP 轉換為 KMDF/UMDF 在 I/O 佇列中接收的架構要求物件。

如果您要撰寫 WDM 驅動程式,請檢閱下列指引。

正確管理 IRP I/O 緩衝區

下列文章提供驗證 IRP 輸入值的相關信息:

DispatchReadWrite 使用緩衝 I/O

在緩衝 I/O 中 錯誤

DispatchReadWrite 使用 Direct I/O

直接 I/O 中的錯誤

I/O 控制碼的安全性問題

請考慮驗證與 IRP 相關聯的值,例如緩衝區地址和長度。

如果您選擇使用 「非 I/O」,請注意,與「讀取和寫入」不同,而且與緩衝 I/O 和直接 I/O 不同,使用 「非 I/O IOCTL」時,緩衝區指標和長度不會由 I/O 管理員驗證。

正確處理 IRP 完成作業

除非驅動程式實際支援並處理 IRP,否則驅動程式絕對不能完成狀態值為 STATUS_SUCCESS 的 IRP。 如需正確處理 IRP 完成作業的方法的相關資訊,請參閱 完成 IRP

管理驅動程式 IRP 擱置狀態

驅動程式應該在儲存 IRP 之前標記其為擱置中,並考慮在相互鎖定的序列中同時包含呼叫 IoMarkIrpPending 和指派。 如需詳細資訊,請參閱 驅動程式狀態檢測失敗裝置暫停時保留傳入 IRP

正確處理 IRP 取消作業

取消作業可能很難正確撰寫程式代碼,因為它們通常以異步方式執行。 處理取消作業的程式代碼問題可能會長時間被忽視,因為此程式代碼通常不會在執行中的系統中經常執行。 請務必閱讀並瞭解 取消 IRP下提供的所有資訊。 請特別注意 同步處理 IRP 取消取消 IRP 時的注意事項

若要將與取消作業相關聯的同步處理問題降到最低,其中一個建議方式是實作 取消安全 IRP 佇列

正確處理 IRP 清除和關閉作業

請務必瞭解 IRP_MJ_CLEANUPIRP_MJ_CLOSE 要求之間的差異。 清理請求會在應用程式關閉檔案物件上的所有檔案句柄之後到達,但有時在所有 I/O 請求都完成之前。 關閉要求會在檔案物件的所有 I/O 操作要求都完成或取消後抵達。 如需詳細資訊,請參閱下列文章:

DispatchCreate、DispatchClose 和 DispatchCreateClose 例程

DispatchCleanup 清理例程

處理清除和關閉作業 錯誤

如需正確處理 IRP 的詳細資訊,請參閱 處理 IRP中的其他錯誤。

其他安全性問題

  • 使用鎖定或連鎖序列來防止競爭狀況。 如需詳細資訊,請參閱多處理器環境中的 錯誤

  • 請確保設備驅動程式能正確處理各種用戶模式以及核心對核心的 I/O 請求。

  • 請確定驅動程式或相關聯的軟體套件在安裝或使用期間未安裝任何 TDI 篩選器或 LSP。

使用安全功能

  • 使用安全字串函式。 如需詳細資訊,請參閱使用安全字串函式

  • 使用安全的算術函式。 如需詳細資訊,請參閱 安全整數庫例程

  • 使用安全轉換函式。

其他程式代碼弱點

除了此處所涵蓋的可能弱點之外,本文還提供增強核心模式驅動程式程式代碼安全性的其他資訊:建立可靠的 Kernel-Mode 驅動程式

如需 C 和 C++ 安全編碼的詳細資訊,請參閱本文結尾 安全編碼資源。

管理驅動程式訪問控制

安全性檢查清單專案 #7:檢閱驅動程式,以確定您已正確控制存取權。

管理驅動程式存取控制 - WDF

驅動程式必須能夠運作,以防止使用者不當存取計算機的裝置和檔案。 若要防止未經授權存取裝置和檔案,您必須:

  • 僅在必要時命名裝置物件。 具名裝置物件通常是基於舊版原因才必要的,例如,如果您有應用程式預期使用特定名稱開啟裝置,或如果您使用非 PNP 裝置/控制裝置。 請注意,WDF 驅動程式不需要命名其 PnP 裝置 FDO,才能使用 WdfDeviceCreateSymbolicLink建立符號連結。

  • 安全存取裝置物件和介面。

若要允許應用程式或其他 WDF 驅動程式存取您的 PnP 裝置 PDO,您應該使用裝置介面。 如需詳細資訊,請參閱 使用裝置介面。 裝置介面可作為裝置堆疊 PDO 的符號連結。

控制 PDO 存取權的其中一個更好方法是在 INF 中指定 SDDL 字串。 如果 SDDL 字串不在 INF 檔案中,Windows 會套用預設的安全性描述元。 如需詳細資訊,請參閱 保護裝置物件裝置物件的 SDDL

如需控制存取的詳細資訊,請參閱下列文章:

在 KMDF 驅動程式中控制裝置存取

名稱、安全性描述元和裝置類別 - 讓裝置物件可供存取... 和 SAFE2017 年 1 月到 2 月的 NT Insider 通訊OSR發行。

管理驅動程式存取控制 - WDM

如果您正在使用 WDM 驅動程式,而且您用了具名的裝置物件,您可以使用 IoCreateDeviceSecure 並指定 SDDL 來確保其安全性。 當您實作 IoCreateDeviceSecure 時,始終指定 DeviceClassGuid 的自定義類別 GUID。 您不應該在這裡指定現有的類別 GUID。 這樣做可能會中斷屬於該類別的其他裝置的安全性設定或相容性。 如需詳細資訊,請參閱 WdmlibIoCreateDeviceSecure

如需詳細資訊,請參閱下列文章:

控制裝置存取

控制裝置命名空間存取

適用於驅動程式開發人員的 Windows 安全性模型

安全性標識碼 (SID) 風險階層

下一節說明驅動程式程式代碼中使用的常見 SID 風險階層。 如需 SDDL 的一般資訊,請參閱 SDDL for Device ObjectsSID StringsSDDL String Syntax

請務必瞭解,如果允許較低的許可權呼叫端存取核心,程式代碼風險就會增加。 在此摘要圖表中,當您允許較低許可權的 SID 存取驅動程式功能時,風險就會增加。

SY (System)
\/
BA (Built-in Administrators)
\/
LS (Local Service)
\/
BU (Built-in User)
\/
AC (Application Container)

遵循一般最低許可權安全性原則,只設定驅動程序運作所需的最低存取層級。

WDM 細粒度 IOCTL 安全性控制

若要在使用者模式呼叫者傳送 IOCTL 時進一步強化安全性,驅動程式代碼可以包括 IoValidateDeviceIoControlAccess 函式。 此函式可讓驅動程式檢查訪問許可權。 收到 IOCTL 時,驅動程式可以呼叫 IoValidateDeviceIoControlAccess,並指定 FILE_READ_ACCESS、FILE_WRITE_ACCESS 或兩者。

實作細微的IOCTL安全性控制,並不會取代使用上述技術來管理驅動程式存取的需求。

如需詳細資訊,請參閱下列文章:

定義 I/O 控制碼

實作 HVCI 相容程式代碼

安全性檢查清單專案 #8:驗證驅動程式是否使用記憶體,使其與 HVCI 相容。

記憶體使用量和 HVCI 相容性

HVCI 使用硬體技術和虛擬化,將程式代碼完整性 (CI) 決策函式與操作系統的其餘部分隔離。 使用虛擬化型安全性來隔離 CI 時,核心記憶體可能成為可執行檔的唯一方式是透過 CI 驗證。 這表示核心記憶體頁面永遠無法既可寫入又可執行(W+X),且可執行程式碼無法直接被修改。

若要實作 HVCI 相容程式代碼,請確定您的驅動程式程式代碼會執行下列動作:

  • 根據預設,選擇加入 NX
  • 使用 NX API/旗標進行記憶體設定 (NonPagedPoolNx)
  • 不使用可寫入和可執行的區段
  • 不會嘗試直接修改可執行的系統記憶體
  • 在核心中不使用動態程序代碼
  • 不會將資料檔載入為可執行檔
  • 區段對齊是0x1000的倍數(PAGE_SIZE)。 例如,DRIVER_ALIGNMENT=0x1000

如需使用工具和不相容記憶體呼叫清單的詳細資訊,請參閱 實作 HVCI 相容程式代碼

如需相關系統基本概念安全性測試的詳細資訊,請參閱 HyperVisor 程式代碼完整性整備測試Hypervisor-Protected 程式代碼完整性 (HVCI)

遵循特定技術的程式碼最佳實踐

安全性檢查清單專案 #9:檢閱驅動程式的下列技術特定指引。

檔案系統

如需檔案系統驅動程式安全性的詳細資訊,請參閱下列文章:

檔案系統安全性簡介

檔案系統安全性問題

檔案系統的安全性功能

與其他文件系統篩選驅動程式共存

NDIS - 網路

如需 NDIS 驅動程式安全性的相關信息,請參閱網路驅動程式安全性問題。

顯示

如需顯示驅動程式安全性的相關資訊,請參閱 <內容擱置>。

印表機

如需印表機驅動程式安全性的相關信息,請參閱 V4 印表機驅動程式安全性考慮

Windows 映射擷取 (WIA) 驅動程式的安全性問題

如需 WIA 安全性的相關信息,請參閱 Windows 映射擷取 (WIA) 驅動程式的安全性問題

增強裝置安裝安全性

安全性檢查清單專案 #10:檢閱驅動程式建立和安裝指引,以確定您遵循最佳做法。

當您建立安裝驅動程式的程式代碼時,您必須確定裝置的安裝一律會以安全的方式執行。 安全的裝置安裝是執行下列動作的裝置:

  • 限制對裝置及其裝置介面類別的存取
  • 限制存取為裝置建立的驅動程序服務
  • 保護驅動程式檔案不受修改或刪除
  • 限制存取裝置的註冊表項目
  • 限制對裝置 WMI 類別的存取
  • 正確地使用 SetupAPI 函式

如需詳細資訊,請參閱下列文章:

創建安全裝置安裝

使用 SetupAPI 的指導方針

使用裝置安裝函式

裝置和驅動程式安裝進階主題

執行同儕程式碼審查

安全性檢查清單項目 #11:執行同儕程式碼檢閱,以檢查其他工具和流程未發現的問題

尋找知識淵博的程式代碼檢閱者,尋找您可能錯過的問題。 第二組眼睛通常會看到您可能忽略的問題。

如果您沒有適當的人員在內部檢閱程式代碼,請考慮針對此目的參與外部協助。

執行適當的版本驅動程式簽署

安全性檢查清單項目 #12:使用 Windows 合作夥伴入口網站正確簽署您的驅動程式以分發。

將驅動程式套件發行至公用之前,建議您提交套件以進行認證。 如需詳細資訊,請參閱 測試效能和相容性開始使用硬體程式硬體儀錶板服務,以及 證明簽署公開發行核心驅動程式。

使用 CodeQL 檢查驅動程式程式代碼

安全性檢查清單專案 #13:使用 CodeQL 檢查驅動程式程式代碼中的弱點。

由 GitHub 撰寫的 CodeQL 是語意程式代碼分析引擎,以及廣泛的安全性查詢套件組合,以及強固的平臺,使其成為保護驅動程式程式代碼的寶貴工具。 如需詳細資訊,請參閱 CodeQL 和靜態工具標誌測試

將 SAL 批註新增至驅動程式程式代碼

安全性檢查清單項目 #14:在驅動程式程式碼中新增 SAL 註記。

原始程式碼批注語言 (SAL) 提供一組批注,可用來描述函式如何使用其參數、它對其做出的假設,以及它在完成時所做的保證。 批注定義於頭檔 sal.h中。 C++的 Visual Studio 程式代碼分析會使用 SAL 註釋來修改其函式分析。 如需有關 SAL 2.0 for Windows 驅動程式開發的詳細資訊,請參閱 適用於 Windows 驅動程式的 SAL 2.0 註釋和使用 SAL 註釋來減少 C/C++程式代碼瑕疵

如需 SAL 的一般資訊,請參閱 OSR 提供的這篇文章。 https://www.osr.com/blog/2015/02/23/sal-annotations-dont-hate-im-beautiful/

使用驅動程式驗證器來檢查弱點

安全性檢查清單專案 #15:使用驅動程序驗證器檢查驅動程式程序代碼中的弱點。

驅動程式驗證器會使用一組介面規則和操作系統模型來判斷驅動程式是否與 Windows 作業系統正確互動。 DV 會在驅動程式代碼中找到可能指向驅動程式中潛在 Bug 的缺陷。

驅動程式驗證器允許對驅動程式進行實時測試。 驅動程式驗證器會監視 Windows 內核模式驅動程式和圖形驅動程式,以偵測可能損毀系統的非法函式呼叫或動作。 驅動程式驗證器可以對 Windows 驅動程式施加各種壓力和測試,以找出不當的行為。 如需詳細資訊,請參閱 驅動程式驗證器

請注意,DV 僅支援特定類型的驅動程式。 如需 DV 可以驗證之驅動程式的詳細資訊,請參閱 支援的驅動程式。 如需您正在使用之驅動程序類型的 DV 測試相關信息,請參閱下列頁面。

若要熟悉 DV,您可以使用其中一個範例驅動程式(例如,展示的烤麵包機範例:https://github.com/Microsoft/Windows-driver-samples/tree/main/general/toaster/toastDrv/kmdf/func/featured)。

使用 BinSkim 二進位分析器檢查程式代碼

安全性檢查清單專案 #16:遵循下列步驟,使用 BinSkim 來仔細檢查編譯和建置選項是否已設定為將已知安全性問題降到最低。

使用 BinSkim 來檢查二進位檔,以識別可能會使二進位易受攻擊的程式代碼撰寫和建置做法。

BinSkim 會檢查:

  • 使用過期的編譯程式工具組 - 二進位檔應該針對最新的編譯程式工具集進行編譯,盡可能最大化使用目前編譯程式層級和 OS 提供的安全性風險降低功能。
  • 不安全的編譯設定 - 二進位檔應該使用最安全的設定進行編譯,以啟用操作系統提供的安全性防護功能、將編譯程式錯誤和可採取動作的警告報告最大化等。
  • 簽署問題 - 簽署的二進位檔應該使用密碼編譯強式演算法進行簽署。

BinSkim 是開放原始碼工具,會產生使用靜態分析結果交換格式的輸出檔案(SARIF) 格式。 BinSkim 會取代先前的 BinScope 工具。

如需 BinSkim 的詳細資訊,請參閱 使用 BinSkim 檢查二進位檔BinSkim 使用者指南

使用硬體相容性程式測試檢查程序代碼

安全性檢查清單專案 #17:使用安全性相關的硬體相容性程序測試來檢查安全性問題。

硬體相容性程式包含安全性相關測試,可用來尋找程式碼弱點。 Windows 硬體相容性計劃會利用 Windows 硬體實驗室套件 (HLK) 中的測試。 HLK 裝置基本概念測試可在命令行上使用,以練習驅動程式程式代碼和探查弱點。 如需裝置基本概念測試和硬體相容性程式的一般資訊,請參閱 Windows Hardware Lab Kit

下列測試是測試範例,這些測試對於檢查驅動程式程式代碼是否有與程式代碼弱點相關聯的某些行為很有用:

DF - 模糊隨機 IOCTL 測試 (可靠性)

DF - 模糊子開啟測試 (可靠性)

DF - 模糊零長度緩衝區 FSCTL 測試 (可靠性)

DF - 模糊隨機 FSCTL 測試 (可靠性)

DF - 模糊 Misc API 測試 (可靠性)

您也可以使用驅動程式驗證器隨附的 核心同步處理延遲模糊測試

CHAOS(並行硬體和作業系統)測試會同時執行各種 PnP 驅動程式測試、裝置驅動程式模糊測試和電源系統測試。 如需詳細資訊,請參閱 CHAOS 測試(裝置基本概念)

裝置基本概念滲透測試會執行各種形式的輸入攻擊,這是安全性測試的重要元件。 攻擊和滲透測試可協助識別軟體介面中的弱點。 如需詳細資訊,請參閱 滲透測試(裝置基本概念)

使用 Device Guard - 合規性測試,以及本文所述的其他工具,以確認您的驅動程式與 HVCI 相容。

自定義和領域特定的測試工具

請考慮設計自定義領域專屬的安全性測試。 若要開發其他測試,請收集來自原始軟體設計者的意見,以及不涉及這個專案但熟悉所開發特定驅動程式類型的開發資源,還有一位或多位熟悉安全性入侵分析和預防的人員的建議。

瞭解如何使用Microsoft易受攻擊和惡意驅動程序報告中心回報驅動程式

安全性檢查清單專案 #18: 瞭解如何使用Microsoft易受攻擊和惡意驅動程序報告中心回報驅動程式

任何人都可以使用Microsoft易受攻擊和惡意驅動程序報告中心提交可疑的驅動程式。 請參閱此部落格文章,以瞭解如何提交驅動程序進行分析 - 使用新的Microsoft易受攻擊和惡意驅動程序報告中心 改善核心安全性

Reporting Center 可以掃描和分析針對 x86 和 x64 架構所建置的 Windows 驅動程式。 易受攻擊和惡意的驅動程式會被標註,供 Microsoft 的易受攻擊驅動程式小組進行分析和調查。 確認易受攻擊的驅動程序之後,就會發生適當的通知,它們會新增至易受攻擊的驅動程序封鎖清單。 如需詳細資訊,請參閱 Microsoft建議的驅動程式區塊規則。 根據預設,這些規則會套用至已啟用受虛擬化技術保護的程式碼完整性(HVCI)的裝置和 S 模式中的 Windows 10 作業系統。

檢閱安全編碼資源

安全性檢查清單專案 #19:檢閱這些資源,以進一步瞭解適用於驅動程序開發人員的安全編碼最佳做法。

安全內核模式驅動程式程式代碼撰寫指導方針

建立可靠的 Kernel-Mode 驅動程式

安全編碼組織

卡內基梅隆大學 SEI CERT

Carnegie Mellon University SEI CERT C 編碼標準:開發安全、可靠和安全系統的規則 (2016 版)。

MITRE - CERT C 安全編碼標準 解決的 弱點

在成熟度模型中建置安全性 (BSIMM) - https://www.bsimm.com/

SAFECode - https://safecode.org/

CISA 資源

OSR

OSR 提供驅動程式開發訓練和諮詢服務。 OSR 電子報中的這些文章重點指出驅動程式安全性問題。

名稱、安全性描述元和裝置類別 - 讓裝置物件可供存取... 和 SAFE

您已使用保護 -- 驅動程式內部 & 裝置安全性

鎖住驅動程式 - 技術方法調查

Meltdown 與 Spectre:驅動程式怎麼辦?

個案研究

從警報到驅動漏洞:Microsoft Defender ATP 調查揭示權限提升漏洞

書籍

24個軟體安全性的致命罪:程序設計缺陷以及如何修復它們 邁克爾·霍華德、大衛·勒布蘭克和約翰·維加

軟體安全性評估的藝術:識別和防止軟體弱點、馬克·道德、約翰·麥當勞和賈斯汀·舒赫

撰寫安全軟體第二版、Michael Howard 和 David LeBlanc

軟體安全性評估的藝術:識別和防止軟體弱點、馬克·道德和約翰·麥克唐納

C 與 C++ 安全編碼 (SEI 系列於軟體工程) 第 2 版,Robert C. Seacord

程式設計 Microsoft Windows 驅動程式模型(第 2 版),沃爾特·奧尼

使用 Windows Driver Foundation 開發驅動程式(開發人員參考)、Penny Orwick 和 Guy Smith

訓練

Windows 驅動程式課程訓練由以下廠商提供,如下所示:

從各種來源提供安全的在線程式代碼訓練。 例如,此課程可從 coursera 取得:

識別 C/C++ 程式設計中的安全漏洞

SAFECode 也提供免費訓練:

SAFECode.org/training

專業認證

CERT 提供 安全編碼專業認證

關鍵要點摘要

驅動程式安全性是包含許多元素的複雜工作,但以下是一些需要考慮的重要要點:

  • 驅動程式位於 Windows 核心中,並在核心中執行時發生問題,會公開整個操作系統。 因此,請密切關注驅動程式安全性和設計,並考慮到安全性。

  • 套用最低權限原則:

    一個。 使用嚴格的 SDDL 字串來限制驅動程式的存取

    b. 進一步限制個別的IOCTL

  • 建立威脅模型來識別攻擊向量,並考慮是否有任何措施可以進一步限制。

  • 請小心處理從用戶模式傳入的嵌入式指標。 在 try except 模塊中,它們需要被探查和存取,且除非擷取並比較緩衝區的值,否則容易產生檢查使用時間(ToCToU)問題。

  • 如果您不確定,請使用 METHOD_BUFFERED 作為IOCTL緩衝方法。

  • 使用程式代碼掃描公用程式來尋找已知的程式代碼弱點,並補救任何已識別的問題。

  • 尋找知識淵博的程式代碼檢閱者,尋找您可能錯過的問題。

  • 使用驅動程式驗證器,並使用多個輸入來測試您的驅動程式,包括邊角案例。