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

Windows 安全性模型是以安全性實體對象為基礎。 操作系統的每個元件都必須確保其負責的物件安全性。 因此,驅動程式必須保護其裝置和裝置對象的安全性。

本主題摘要說明 Windows 安全性模型如何套用至內核模式驅動程式。

Windows 安全性模型

Windows 安全性模型主要以個別物件許可權為基礎,具有少量的系統範圍許可權。 可以保護的物件包括但不限於進程、線程、事件和其他同步處理物件,以及檔案、目錄和裝置。

針對每種類型的物件,泛型讀取、寫入和執行許可權對應會對應到詳細的物件特定許可權。 例如,對於檔案和目錄,可能的許可權包括讀取或寫入檔案或目錄的許可權、讀取或寫入擴充檔案屬性的許可權、周遊目錄的許可權,以及寫入物件安全性描述元的許可權。

安全性模型包含下列概念:

  • ) (SID 的安全性識別碼
  • 存取權杖
  • 安全性描述元
  • 存取控制清單 (ACL)
  • 權限

安全性識別碼 (SID)

安全性標識子 (SID,也稱為 主體) 識別使用者、群組或登入會話。 每個使用者都有唯一的 SID,這是由操作系統在登入時擷取的。

SID 是由作業系統或網域伺服器等授權單位所發出。 有些 SID 是已知的,而且具有名稱和識別碼。 例如,SID S-1-1-0 會識別所有人 (或 World) 。

存取權杖

每個進程都有存取令牌。 存取令牌描述進程的完整安全性內容。 它包含使用者的 SID、使用者所屬群組的 SID,以及登入工作階段的 SID,以及授與使用者的全系統許可權清單。

根據預設,每當進程的線程與安全性實體對象互動時,系統就會針對進程使用主要存取令牌。 不過,線程可以模擬客戶端帳戶。 當線程模擬時,除了自己的主要令牌之外,還有模擬令牌。 模擬令牌描述線程正在模擬之用戶帳戶的安全性內容。 模擬在遠端過程調用 (RPC) 處理中特別常見。

描述線程或進程的受限制安全性內容的存取令牌稱為受限制的令牌。 限制令牌中的 SID 只能設定為拒絕存取,而不允許存取安全物件。 此外,令牌可以描述一組有限的全系統許可權。 使用者的 SID 和身分識別維持不變,但在程式使用受限制的令牌時,使用者的訪問許可權會受到限制。 CreateRestrictedToken 函式會建立受限制的令牌。

安全性描述元

每個具名 Windows 物件都有安全性描述元;有些未命名的物件也一樣。 安全性描述項描述物件及其 ACL 的擁有者和群組 SID。

對象的安全性描述元通常是由建立物件的函式所建立。 當驅動程式呼叫 IoCreateDeviceIoCreateDeviceSecure 例程來建立裝置物件時,系統會將安全性描述元套用至已建立的裝置物件,並設定物件的 ACL。 針對大部分裝置,ACL 會在裝置資訊 (INF) 檔案中指定。

如需核心驅動程式檔中 的安全性描述項 詳細資訊。

存取控制清單

存取控制 清單 (ACL) 啟用對物件存取的精細控制。 ACL 是每個物件之安全性描述元的一部分。

每個 ACL 都包含零個或多個 存取控制 專案, (ACE) 。 每個 ACE 接著都包含單一 SID,可識別使用者、群組或計算機,以及拒絕或允許該 SID 的許可權清單。

裝置物件的 ACL

裝置物件的 ACL 可以透過下列三種方式之一來設定:

  • 在裝置類型的預設安全性描述項目中設定 。
  • 以程序設計方式由 RtlCreateSecurityDescriptor 函式建立,並由 RtlSetDaclSecurityDescriptor 函式設定。
  • 在裝置 INF 檔案或 IoCreateDeviceSecure 例程的呼叫中,於安全描述符定義語言 (SDDL) 中指定。

所有驅動程式都應該在 INF 檔案中使用 SDDL 來指定其裝置物件的 ACL。

SDDL 是可延伸的描述語言,可讓元件以字串格式建立 ACL。 使用者模式和內核模式程式代碼都會使用 SDDL。 下圖顯示裝置物件的SDDL字串格式。

此圖顯示裝置物件的SDDL字串格式。

Access 值會指定允許的存取類型。 SID 值會指定安全性識別碼,以決定 Access 值套用至哪些使用者或群組 (,例如使用者或群組) 。

例如,下列 SDDL 字串允許系統 (SY) 存取所有專案,並允許其他人只 (WD) 只讀存取:

“D:P(A;;GA;;;SY)(A;;GR;;;WD)”

頭檔 wdmsec.h 也包含一組適用於裝置物件的預先定義 SDDL 字串。 例如,頭檔會定義SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_RWX_RES_RWX,如下所示:

"D:P(A;;GA;;;SY)(A;;GRGWGX;;;BA)(A;;GRGWGX;;;WD)(A;;GRGWGX;;;RC)"

此字串的第一個區段允許核心和操作系統 (SY) 完全控制裝置。 第二個區段可讓內建 Administrators 群組中的任何人 (BA) 存取整個裝置,但無法變更 ACL。 第三個區段可讓每個人都 (WD) 讀取或寫入裝置,而第四個區段會將相同的許可權授與不受信任的程式代碼 (RC) 。 驅動程式可以使用預先定義的字串,如同原樣或裝置物件特定字串的模型。

堆疊中的所有裝置物件都應該具有相同的 ACL。 變更堆疊中某個裝置物件上的 ACL 會變更整個裝置堆疊上的 ACL。

不過,將新的裝置物件新增至堆疊並不會變更任何 ACL,如果新的裝置物件有 ACL) 或堆疊中任何現有裝置物件的 ACL, (這些 ACL。 當驅動程式建立新的裝置物件並將它附加至堆疊頂端時,驅動程式應該將堆疊的 ACL 複製到新的裝置物件,方法是從下一個較低的驅動程式複製 DeviceObject.Characteristics 字段。

IoCreateDeviceSecure 例程支援使用 WD 和 SY 等預先定義 SD 的 SDDL 字串子集。 使用者模式 API 和 INF 檔案支援完整的 SDDL 語法。

使用 ACL 的安全性檢查

當進程要求存取物件時,安全性檢查會將物件的 ACL 與呼叫端存取令牌中的 SID 進行比較。

系統會以嚴格的由上而下的順序比較 ACE,並在第一個相關比對時停止。 因此,建立 ACL 時,您應該一律將拒絕 ACE 放在對應的授與 ACE 上方。 下列範例顯示比較的繼續方式。

範例 1:比較 ACL 與存取令牌

範例 1 顯示系統如何比較 ACL 與呼叫端進程的存取令牌。 假設呼叫端想要開啟具有下表所示 ACL 的檔案。

範例檔案 ACL

權限 SID Access
Allow 會計 寫入、刪除
Allow Sales 附加
拒絕 法務 附加、寫入、刪除
Allow 所有人 讀取

此 ACL 有四個 ACE,特別適用於會計、銷售、法律及所有人群組。

接下來,假設要求程式的存取令牌包含一個使用者和三個群組的 SID,順序如下:

User Jim (S-1-5-21...)

群組會計 (S-1-5-22...)

群組法律 (S-1-5-23...)

群組所有人 (S-1-1-0)

比較檔案 ACL 與存取令牌時,系統會先在檔案的 ACL 中尋找 ACE 的使用者 Jim。 [無] 隨即出現,因此接下來它會尋找會計群組的 ACE。 如上表所示,會計群組的 ACE 會顯示為檔案 ACL 中的第一個專案,因此 Jim 的程式被授與寫入或刪除檔案和比較停止的許可權。 如果法律群組的 ACE 改為在 ACL 中會計群組的 ACE 之前,進程將會遭到拒絕寫入、附加和刪除檔案的存取權。

範例 2:比較 ACL 與受限制的令牌

系統會比較 ACL 與受限制令牌的方式,與比較令牌中不受限制的令牌相同。 不過,受限制令牌中的拒絕 SID 只能比對 ACL 中的拒絕 ACE。

範例 2 顯示系統如何比較檔案的 ACL 與受限制的令牌。 假設檔案具有上表所示的相同 ACL。 不過,在此範例中,進程具有包含下列 SID 的受限制令牌:

User Jim (S-1-5-21...) 拒絕

群組會計 (S-1-5-22...) 拒絕

群組法律 (S-1-5-23...) 拒絕

群組所有人 (S-1-1-0)

檔案的 ACL 不會列出 Jim 的 SID,因此系統會繼續進行會計群組 SID。 雖然檔案的 ACL 具有會計群組的 ACE,但此 ACE 允許存取;因此,它不符合進程受限制令牌中的 SID,而拒絕存取。 因此,系統會繼續進行法律群組 SID。 檔案的 ACL 包含拒絕存取之法律群組的 ACE,因此進程無法寫入、附加或刪除檔案。

權限

許可權是使用者在本機計算機上執行系統相關作業的許可權,例如載入驅動程式、變更時間或關閉系統。

許可權與訪問許可權不同,因為它們會套用至系統相關的工作和資源,而不是物件,而且會由系統管理員指派給使用者或群組,而不是由操作系統指派。

每個進程的存取令牌都包含授與進程的許可權清單。 必須先特別啟用許可權,才能使用。 如需有關許可權的詳細資訊 ,請參閱核心 驅動程式檔中的許可權。

Windows 安全性模型案例:建立檔案

每當進程建立檔案或物件的句柄時,系統就會使用 Windows 安全性模型中所述的安全性建構。

下圖顯示使用者模式進程嘗試建立檔案時所觸發的安全性相關動作。

當使用者模式進程嘗試建立檔案時,說明安全性相關動作的流程圖。

上圖顯示當使用者模式應用程式呼叫 CreateFile 函式時,系統如何回應。 下列附註是指圖中的圓圈數位:

  1. 使用者模式應用程式會呼叫 CreateFile 函式,並傳遞有效的 Microsoft Win32 檔名。
  2. 使用者模式 Kernel32.dll 將要求傳遞至 Ntdll.dll,這會將 Win32 名稱轉換成 Microsoft Windows NT 檔名。
  3. Ntdll.dll 使用 Windows 檔名呼叫 NtCreateFile 函式。 在 Ntoskrnl.exe 內,I/O 管理員會處理 NtCreateFile
  4. I/O 管理員會將要求重新封裝至物件管理員呼叫。
  5. 物件管理員會解析符號連結,並確保使用者具有檔案建立所在路徑的周遊許可權。 如需詳細資訊,請參閱 物件管理員中的安全性檢查
  6. 物件管理員會呼叫擁有與要求相關聯之基礎物件類型的系統元件。 針對檔案建立要求,此元件是擁有裝置物件的 I/O 管理員。
  7. I/O 管理員會根據用戶進程的存取令牌,檢查裝置對象的安全性描述元,以確保使用者具有裝置的必要存取權。 如需詳細資訊,請參閱 I/O 管理員中的安全性檢查
  8. 如果用戶進程具有必要的存取權,I/O 管理員會建立句柄,並將IRP_MJ_CREATE要求傳送給裝置或文件系統的驅動程式。
  9. 驅動程式會視需要執行其他安全性檢查。 例如,如果要求在裝置的命名空間中指定物件,驅動程式必須確定呼叫端具有必要的訪問許可權。 如需詳細資訊,請參閱 驅動程式的安全性檢查

物件管理員中的安全性檢查

檢查訪問許可權的責任屬於可執行這類檢查的最高層級元件。 如果物件管理員可以驗證呼叫者的訪問許可權,則會這麼做。 如果沒有,物件管理員會將要求傳遞至負責基礎物件類型的元件。 該元件接著會驗證存取權,如果可以,則為 ;如果無法,它會將要求傳遞至仍然較低的元件,例如驅動程式。

物件管理員會檢查 ACL 是否有簡單的物件類型,例如事件和 Mutex 鎖定。 對於具有命名空間的物件,類型擁有者會執行安全性檢查。 例如,I/O 管理員會被視為裝置對象和檔案對象的類型擁有者。 如果物件管理員在剖析名稱時發現裝置物件或檔案對象的名稱,它會將名稱交出給 I/O 管理員,如同上述檔案建立案例所示。 然後,I/O 管理員會檢查其是否可存取權。 如果名稱指定裝置命名空間內的物件,I/O 管理員會關閉名稱給裝置 (或文件系統) 驅動程式,而該驅動程式負責驗證要求的存取權。

I/O 管理員中的安全性檢查

當 I/O 管理員建立句柄時,它會根據進程存取令牌檢查對象的許可權,然後儲存授與用戶的許可權以及句柄。 當稍後的 I/O 要求送達時,I/O 管理員會檢查與句柄相關聯的許可權,以確保進程有權執行要求的 I/O 作業。 例如,如果進程稍後要求寫入作業,I/O 管理員會檢查與句柄相關聯的許可權,以確保呼叫端具有物件的寫入許可權。

如果句柄重複,則可以從複本中移除許可權,但無法新增至該複本。

當 I/O 管理員建立物件時,它會將一般 Win32 存取模式轉換為特定物件的許可權。 例如,下列許可權適用於檔案和目錄:

Win32 存取模式 物件特定許可權
GENERIC_READ ReadData
GENERIC_WRITE WriteData
GENERIC_EXECUTE ReadAttributes
GENERIC_ALL 全部

若要建立檔案,進程必須具有目標路徑中父目錄的周遊許可權。 例如,若要建立 \Device\CDROM0\Directory\File.txt,進程必須有周遊 \Device、\Device\CDROM0 和 \Device\CDROM0\Directory 的權利。 I/O 管理員只會檢查這些目錄的周遊許可權。

I/O 管理員會在剖析檔名時檢查周遊許可權。 如果檔名是符號連結,則 I/O 管理員會將它解析為完整路徑,然後從根目錄開始檢查周遊許可權。 例如,假設符號連結 \DosDevices\D 對應至 Windows NT 裝置名稱 \Device\CDROM0。 此程式必須具有 \Device 目錄的周游許可權。

如需詳細資訊,請參閱 物件句柄物件安全性

驅動程式中的安全性檢查

操作系統核心會將每個驅動程式視為具有本身命名空間的檔案系統。 因此,當呼叫端嘗試在裝置命名空間中建立物件時,I/O 管理員會檢查進程是否具有路徑中目錄的周遊許可權。

使用 WDM 驅動程式時,除非已建立指定FILE_DEVICE_SECURE_OPEN的 Device Object,否則 I/O 管理員不會對命名空間執行安全性檢查。 未設定FILE_DEVICE_SECURE_OPEN時,驅動程式會負責確保其命名空間的安全性。 如需詳細資訊,請參閱 控制裝置命名空間存取 和保護 裝置物件

對於WDF驅動程式,一律會設定FILE_DEVICE_SECURE_OPEN旗標,以便先檢查裝置的安全性描述元,再允許應用程式存取裝置命名空間內的任何名稱。 如需詳細資訊,請參閱 在 KMDF 驅動程式中控制裝置存取

Windows 安全性界限

驅動程式會彼此通訊,以及不同許可權等級的使用者模式呼叫者,可視為跨越信任界限。 信任界限是任何從較低特殊許可權進程跨到較高特殊許可權進程的程式代碼執行路徑。

許可權等級的差異愈高,界限對於想要對目標驅動程式或進程執行許可權提升攻擊等攻擊的攻擊者而言愈有趣。

建立威脅模型的一部分是檢查安全性界限,並尋找非預期的路徑。 如需詳細資訊,請參閱 驅動程序的威脅模型化。

跨越信任界限的任何數據都不受信任,而且必須經過驗證。

下圖顯示三個核心驅動程式,以及兩個應用程式,一個在應用程式容器中,一個是使用系統管理員許可權執行的應用程式。 紅色線條表示範例信任界限。

此圖描述具有三個核心驅動程式的驅動程式攻擊面、應用程式容器中的應用程式,以及具有系統管理員許可權的應用程式。

由於應用程式容器可以提供額外的條件約束,而且未在系統管理層級執行,因此路徑 (1) 是提升攻擊的風險較高的路徑,因為信任界限是在應用程式容器之間, ( 非常低的許可權進程) 和核心驅動程式。

路徑 (2) 是較低的風險路徑,因為應用程式是以系統管理員許可權執行,並直接呼叫核心驅動程式。 管理員 已經是系統上相當高的許可權,因此從系統管理員到核心的攻擊面對攻擊者而言較不有趣,但仍是值得注意的信任界限。

路徑 (3) 是程式代碼執行路徑的範例,其跨越多個信任界限,如果未建立威脅模型,可能會遺漏這些界限。 在此範例中,驅動程式 1 與驅動程式 3 之間有信任界限,因為驅動程式 1 會從使用者模式應用程式取得輸入,並將它直接傳遞至驅動程式 3。

來自使用者模式之驅動程式的所有輸入都是不受信任的,而且應該經過驗證。 來自其他驅動程式的輸入也可能不受信任,視先前的驅動程式是否只是簡單的傳遞 (例如,驅動程式 1 從應用程式 1 收到數據,驅動程式 1 不會對數據進行任何驗證,而只是將它轉送到驅動程式 3) 。 建立完整的威脅模型,請務必識別所有受攻擊面和信任界限,並驗證跨越這些攻擊面的所有數據。

Windows 安全性 模型建議

  • IoCreateDeviceSecure 例程的呼叫中設定強預設 ACL。
  • 為每個裝置在 INF 檔案中指定 ACL。 如有必要,這些 ACL 可能會鬆散緊密的預設 ACL。
  • 設定FILE_DEVICE_SECURE_OPEN特性,將裝置物件安全性設定套用至裝置命名空間。
  • 請勿定義允許FILE_ANY_ACCESS的IOCTL,除非這類存取無法惡意入侵。
  • 使用 IoValidateDeviceIoControlAccess 例程來強化允許FILE_ANY_ACCESS的現有 IOCTLS 安全性。
  • 建立威脅模型來檢查安全性界限,並尋找非預期的路徑。 如需詳細資訊,請參閱 驅動程序的威脅模型化。
  • 如需其他驅動程式安全性建議 ,請參閱驅動程式安全性檢查清單

另請參閱

保護裝置物件

驅動程式安全性檢查清單