共用方式為


驅動程式安全性檢查清單

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

驅動程式安全性概觀

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

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

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

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

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

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

未標記的複選框,代表安全性檢查清單中的專案。使用驅動程序架構

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

未標記的複選框,代表安全性檢查清單中的專案。不要生產標誌測試驅動程式程式代碼

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

未標記的複選框,代表安全性檢查清單中的專案。遵循驅動程式安全編碼指導方針

未標記的複選框,代表安全性檢查清單中的專案。實作 HVCI 相容程式代碼

未標記的複選框,代表安全性檢查清單中的專案。遵循技術特定的程式代碼最佳做法

未標記的複選框,代表安全性檢查清單中的專案。執行對等程式代碼檢閱

未標記的複選框,代表安全性檢查清單中的專案。管理驅動程式訪問控制

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

未標記的複選框,代表安全性檢查清單中的專案。執行適當的發行驅動程序簽署

未標記的複選框,代表安全性檢查清單中的專案。使用 CodeQL 檢查驅動程式程式代碼

未標記的複選框,代表安全性檢查清單中的專案。將 SAL 批註新增至驅動程式程式代碼

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

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

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

未標記的複選框,代表安全性檢查清單中的專案。檢閱調試程式技術和擴充功能

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

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

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

確認需要核心驅動程式

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

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

如需使用背景工作的資訊,請參閱 使用背景工作支援您的應用程式。

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

使用驅動程序架構

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

使用 Windows Driver Framework 來減少程式代碼的大小,並增加其可靠性和安全性。 若要開始使用,請檢閱 使用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 簽章簽署之前,請先確定其符合建立可靠內核模式驅動程式指引。 此外,程式代碼不得包含任何危險行為,如下所述。 如需驅動程式簽署的詳細資訊,請參閱 本文稍後的發行驅動程序簽署

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

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

執行威脅分析

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

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

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

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

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

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

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

建立安全驅動程式的核心活動是識別程序代碼中需要變更的區域,以避免已知的軟體弱點。 其中許多已知的軟體弱點會處理嚴格追蹤記憶體的使用方式,以避免其他人覆寫或構成驅動程式使用的記憶體位置的問題。

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

記憶體緩衝區

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

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

IOCTL 緩衝區類型 摘要 如需相關資訊
METHOD_BUFFERED 建議用於大部分的情景設定 使用緩衝 I/O
METHOD_IN_DIRECT或METHOD_OUT_DIRECT 用於某些高速 HW I/O 使用直接 I/O
METHOD_NEITHER 盡可能避免 使用未緩衝處理或直接 I/O

一般而言,建議使用緩衝 I/O,因為它提供最安全的緩衝方法。 但是,即使使用緩衝 I/O 也有風險,例如必須減輕的內嵌指標。

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

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

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

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

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

  • 使用緩衝 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 要求中的指標。 如需詳細資訊,請參閱 參考用戶空間位址中的錯誤。

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

MSR 模型特定的緩存器讀取和寫入

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

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

TOCTOU 弱點

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

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

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

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

  • 設備驅動器必須正確處理各種使用者模式,以及核心 I/O 的核心要求。

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

處理

裝置物件

IRP

WDF 和 IRP

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

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

正確管理 IRP I/O 緩衝區

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

使用緩衝 I/O 的 DispatchReadWrite

緩衝 I/O 中的錯誤

使用直接 I/O 的 DispatchReadWrite

直接 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 之前標記 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。

使用安全函式

其他程式代碼弱點

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

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

管理驅動程式訪問控制

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

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

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

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

  • 保護裝置物件和介面的存取。

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

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

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

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

名稱、安全性描述元和裝置類別 - 讓裝置物件可供存取... 和 SAFE 從 2017 年 1 月起 OSR 發佈的 NT 測試人員通訊

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

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

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

控制裝置存取

控制裝置Namespace存取

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

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

下一節說明驅動程式程式代碼中使用的常見 SID 風險階層。 如需 SDDL 的一般資訊,請參閱 裝置物件的 SDDL、 SID 字串SDDL 字串語法

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

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

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

WDM 細微 IOCTL 安全性控制

若要在使用者模式呼叫者傳送 IOCTLs 時進一步管理安全性,驅動程式程式代碼可以包含 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 保護的程式代碼完整性(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 驅動程式開發的詳細資訊,請參閱 SAL 2.0 Windows 驅動程式 的註釋和使用 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 使用者指南

請遵循下列步驟來驗證您寄送的程式代碼中是否已正確設定安全性編譯選項。

  1. 下載並安裝跨平臺 .NET Core SDK

  2. 確認已安裝Visual Studio。 如需下載和安裝 Visual Studio 的相關信息,請參閱 安裝 Visual Studio

  3. 有許多選項可以下載 BinSkim,例如 NuGet 套件。 在此範例中,我們將使用 git clone 選項從這裡下載: https://github.com/microsoft/binskim 並將它安裝在 64 位 Windows 計算機上。

  4. 開啟 Visual Studio 開發人員命令提示字元視窗並建立目錄,例如 C:\binskim-master

    C:\> Md \binskim-master
    
  5. 移至您剛才建立的目錄。

    C:\> Cd \binskim-master
    
  6. 使用 git clone 命令下載所有必要的檔案。

    C:\binskim-master> git clone --recurse-submodules https://github.com/microsoft/binskim.git
    
  7. 移至複製命令所建立的新 binskim dirctory。

    C:\> Cd \binskim-master\binskim
    
  8. 執行 BuildAndTest.cmd 以確保發行組建成功,且所有測試都通過。

    C:\binskim-master\binskim> BuildAndTest.cmd
    
    Welcome to .NET Core 3.1!
    ---------------------
    SDK Version: 3.1.101
    
    ...
    
    C:\binskim-master\binskim\bld\bin\AnyCPU_Release\Publish\netcoreapp2.0\win-x64\BinSkim.Sdk.dll
    1 File(s) copied
    C:\binskim-master\binskim\bld\bin\AnyCPU_Release\Publish\netcoreapp2.0\linux-x64\BinSkim.Sdk.dll
    1 File(s) copied
    
    ...
    
    
  9. 建置程式會使用 BinSkim 可執行檔建立一組目錄。 移至 win-x64 組建輸出目錄。

    C:\binskim-master\binskim> Cd \binskim-master\bld\bin\AnyCPU_Release\Publish\netcoreapp2.0\win-x64>
    
  10. 顯示分析選項的說明。

C:\binskim-master\binskim\bld\bin\AnyCPU_Release\Publish\netcoreapp2.0\win-x64> BinSkim help analyze

BinSkim PE/MSIL Analysis Driver 1.6.0.0

--sympath                      Symbols path value, e.g., SRV*http://msdl.microsoft.com/download/symbols or Cache*d:\symbols;Srv*http://symweb. See
                              https://learn.microsoft.com/windows-hardware/drivers/debugger/advanced-symsrv-use for syntax information. Note that BinSkim will clear the
                              _NT_SYMBOL_PATH environment variable at runtime. Use this argument for symbol information instead.

--local-symbol-directories     A set of semicolon-delimited local directory paths that will be examined when attempting to locate PDBs.

-o, --output                   File path to which analysis output will be written.

--verbose                      Emit verbose output. The resulting comprehensive report is designed to provide appropriate evidence for compliance scenarios.

...

設定符號路徑

如果您要建置您在執行 BinSkim 的相同電腦上分析的所有程式碼,您通常不需要設定符號路徑。 這是因為您的符號檔可在您編譯的本機方塊上使用。 如果您使用更複雜的建置系統,或將符號重新導向至不同的位置(而非編譯的二進位檔),請使用 --local-symbol-directories 將這些位置新增至符號檔搜尋。 如果您的程式代碼參考不是程序代碼一部分的已編譯二進位檔,則可以使用 Window 調試程式同情來擷取符號,以驗證這些程式代碼相依性的安全性。 如果您在這些相依性中發現問題,可能無法加以修正。 但是,透過採用這些相依性,瞭解您接受的任何可能安全性風險會很有用。

提示

新增符號路徑 (參考網路符號伺服器)時,請新增本機快取位置以指定本機路徑來快取符號。 這樣做可能會大幅損害 BinSkim 的效能。 下列範例會指定位於 d:\symbols 的本機快取。 --sympath Cache*d:\symbols;Srv*http://symweb 如需同情的詳細資訊,請參閱 Windows 調試程式的符號路徑。

  1. 執行下列命令來分析已編譯的驅動程式二進位檔。 更新目標路徑,以指向您符合的驅動程式.sys檔案。

    C:\binskim-master\binskim\bld\bin\AnyCPU_Release\Publish\netcoreapp2.0\win-x64> BinSkim analyze "C:\Samples\KMDF_Echo_Driver\echo.sys"
    
  2. 如需詳細資訊,請新增如下的詳細信息選項。

    C:\binskim-master\binskim\bld\bin\AnyCPU_Release\Publish\netcoreapp2.0\win-x64> BinSkim analyze "C:\Samples\KMDF_Echo_Driver\osrusbfx2.sys" --verbose
    

    注意

    --verbose 選項會產生每個檢查的明確傳遞/失敗結果。 如果您沒有提供詳細資訊,您只會看到 BinSkim 偵測到的瑕疵。 --verbose 選項通常不建議用於實際自動化系統,因為記錄檔的大小增加,而且因為當記錄檔發生時,較難以挑選個別失敗,因為它們會內嵌在大量「傳遞」結果中。

  3. 檢閱命令輸出以尋找可能的問題。 此範例輸出會顯示三個通過的測試。 BinSkim 使用者指南提供規則的其他資訊,例如 BA2002。

    Analyzing...
    Analyzing 'osrusbfx2.sys'...
    ...
    
    C:\Samples\KMDF_Echo_Driver\osrusbfx2.sys\Debug\osrusbfx2.sys: pass BA2002: 'osrusbfx2.sys' does not incorporate any known vulnerable dependencies, as configured by current policy.
    C:\Samples\KMDF_Echo_Driver\Debug\osrusbfx2.sys: pass BA2005: 'osrusbfx2.sys' is not known to be an obsolete binary that is vulnerable to one or more security problems.
    C:\Samples\KMDF_Echo_Driver\osrusbfx2.sys: pass BA2006: All linked modules of 'osrusbfx2.sys' generated by the Microsoft front-end satisfy configured policy (compiler minimum version 17.0.65501.17013).
    
  4. 此輸出顯示測試BA3001未執行,因為工具指出驅動程式不是ELF二進位檔。

    ...
    C:\Samples\KMDF_Echo_Driver\Debug\osrusbfx2.sys: notapplicable BA3001: 'osrusbfx2.sys' was not evaluated for check 'EnablePositionIndependentExecutable' as the analysis is not relevant based on observed metadata: image is not an ELF binary.
    
  5. 此輸出會顯示測試BA2007的錯誤。

    ...
    
    C:\Samples\KMDF_Echo_Driver\Debug\osrusbfx2.sys: error BA2007: 'osrusbfx2.sys' disables compiler warning(s) which are required by policy.
    A compiler warning is typically required if it has a high likelihood of flagging memory corruption, information disclosure, or double-free vulnerabilities.
    To resolve this issue, enable the indicated warning(s) by removing /Wxxxx switches (where xxxx is a warning id indicated here) from your command line, and resolve any warnings subsequently raised during compilation.
    

若要在 Visual Studio 中啟用這些警告,請在專案屬性頁的 C/C++下,移除您不想在 [停用特定警告] 中排除的值。

在 Visual Studio 2019 中停用特定警告的對話框螢幕快照。

Visual Studio for 驅動程式專案中的預設編譯選項可以停用警告,例如下列專案。 BinSkim 會報告這些警告。

C4603 - 'name': 在先行編譯標頭使用之後,宏未定義或定義不同

C4627 - 'description': 在尋找先行編譯標頭使用時略過

C4986 - 'declaration': 例外狀況規格不符合先前的宣告

如需編譯程式警告的詳細資訊,請參閱 編譯程式版本的編譯程式警告。

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

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

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

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

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

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

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

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

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

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

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

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

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

自訂和網域特定的測試工具

請考慮開發自定義網域特定的安全性測試。 若要開發其他測試,請收集軟體原始設計工具的輸入,以及熟悉所開發特定驅動程式類型的不相關開發資源,以及一或多個熟悉安全性入侵分析和預防的人員。

檢閱調試程式技術和擴充功能

安全性檢查清單專案 #18:檢閱這些調試程式工具,並考慮其在開發偵錯工作流程中的用法。

!acl 延伸模組會格式化並顯示訪問控制清單的內容(ACL)。 如需詳細資訊,請參閱判斷物件的 ACL 和 !acl

!token 延伸模組會顯示安全性令牌物件的格式化檢視。 如需詳細資訊,請參閱 !token

!tokenfields 延伸模組會顯示存取令牌物件中欄位的名稱和位移(TOKEN 結構)。 如需詳細資訊,請參閱 !tokenfields

!sid 延伸模組會顯示位於指定位址的安全性識別碼 (SID)。 如需詳細資訊,請參閱 !sid

!sd 延伸模組會顯示指定位址的安全性描述元。 如需詳細資訊,請參閱 !sd

Microsoft易受攻擊和惡意驅動程序報告中心

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

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

檢閱安全編碼資源

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

檢閱這些資源以深入瞭解驅動程序安全性

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

建立可靠的內核模式驅動程式

安全編碼組織

卡內基梅隆大學 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

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

鎖定驅動程式 - 技術調查

融化和幽靈:司機呢?

案例研究

從警示到驅動程式弱點:Microsoft Defender ATP 調查發掘許可權提升缺陷

書籍

24 個軟體安全性的致命罪:程序設計缺陷以及如何由 Michael Howard、David LeBlanc 和 John Viega 修復它們

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

撰寫安全軟體第二版,邁克爾·霍華德和大衛·萊布蘭克

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

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

設計Microsoft Windows 驅動程式模型(第 2 版)、沃爾特·Oney

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

訓練

Windows 驅動程式教室訓練可從廠商取得,如下所示:

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

識別 C/C++ 程式設計中的安全性弱點。

SAFECode 也提供免費訓練:

SAFECode.org/training

專業認證

CERT 提供 安全編碼專業認證

重要外賣摘要

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

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

  • 套用最低許可權原則:

    a. 使用嚴格的 SDDL 字串來限制驅動程式的存取

    b. 進一步限制個別的IOCTL

  • 建立威脅模型來識別攻擊媒介,並考慮是否有任何專案可以進一步限制。

  • 請小心從 usermode 傳入的內嵌指標。 除非擷取並比較緩衝區的值,否則它們必須在 try 內進行探查、存取,而且容易發生使用時間檢查時間 (ToCToU) 問題。

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

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

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

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