Windows授權---Windows Authorization

授權

 

目的 Purpose

授權是指使用系統以及系統中的數據的權利的賦予。授權一般由系統管理員設置、並由計算機根據用戶的身份,比如代碼數字、密碼,來進行區分。

微軟的授權包括授權管理和授權API兩部分。

面向的開發者受衆 Developer audience

微軟的授權技術是爲那些基於Windows Server和控制訪問資源的操作系統開發應用程序的開發者設計的。開發者需要熟悉Windows編程,儘管沒有要求、但是對授權或者安全相關的主題的理解是有益的。

運行時要求 Run-time Requirements

這個可以學習參考文檔中的相關內容獲得詳細資料。

 

PS: MSDN裏面的文檔分的太細了,如果用縮進的方式分開章節,那麼有的章節就會縮到文本的一半距離,所以我想了用顏色來區分章節的辦法(黑、紅、藍按二級章節交替,Blue is my Favorite)。

 

1. 關於授權 About Authorization

1.1 訪問控制 Access Control

      訪問控制指的是控制誰可以訪問操作系統資源的安全特性,應用程序調用訪問控制函數來設置誰可以訪問指定的資源、或者控制對應用程序提供的資源的訪問。

 

      這個概覽描述了一個安全模型,即控制對例如文件等的Windows對象的訪問和控制用戶對一些功能例如設置系統時間的訪問、或者審覈用戶的行爲。訪問控制模型提供了一個關於訪問控制各部分的高級描述,還有它們之間如何相互影響。

 

1.1.1 C2級別安全 C2-level Security

      下面列舉了美國國防部定義的C2級別中一些最重要的安全要求:

  • 要可以控制賦予和否決個人用戶或者組用戶對資源的訪問
  • 要保護內存,以使進程釋放了內存之後它不能讀取它的內容;同樣的,一個安全的文件系統,比如NTFS,要保證正在讀取的文件不能被刪除。
  • 用戶登錄的時候必須可以用唯一的方式標識自己的身份,比如密碼。所有的審覈操作必須可以識別用戶作出的操作。
  • 系統管理員一定要可以審覈安全相關的事件,同時,訪問安全相關事件的審覈數據僅限於獲得授權的管理員。
  • 系統必須可以防止外部干擾和篡改,例如對運行中系統和磁盤上系統文件的修改。

1.1.2 訪問控制模型 Access Control Models

      訪問控制模型允許你控制進程訪問安全對象的能力以及完成不同系統管理員任務的能力,下面的這些主題提供了訪問控制模型的詳細描述,還有它們之間是如何相互影響的。

1.1.2.1 訪問控制模型的各部分 Parts of the Access Control Model

      訪問控制模型有兩個重要組成部分:

  • 訪問令牌(access token):包含了登錄用戶的信息
  • 安全描述符(security descriptors):包含了保護安全對象的安全信息

      一個用戶登錄時,系統會給用戶賬戶名字和密碼授權。如果登錄成功了,系統就創建一個訪問令牌。每一個代表該用戶執行的進程都有一份該訪問付符的副本。這個訪問令牌 包含了用來確認用戶賬戶和用戶屬於哪一個組賬戶的安全描述符。這個訪問令牌 還包含了用戶或者用戶所在組的一個特權列表。在一個進程嘗試訪問一個安全對象或者是執行要求特權的系統管理任務時,系統就通過該訪問令牌 來進行確認。

      當一個安全對象創建時,系統就賦予它一個安全描述符,其中包含了它的創建者指定的安全信息,或者,如果沒有指定用戶,就會是一個默認的安全信息。應用程序可以使用函數得到或者設置一個存在的對象的安全信息。

      一個安全描述符可以識別對象的擁有者、並且還可以包含下列訪問控制列表(ACLs):

  • 一個DACL(discretionary  access control list),用來識別用戶或組應該允許還是拒絕訪問指定對象。
  • 一個SACL(system access control list),控制系統如何審覈對指定對象的訪問嘗試。

      一個ACL包含了一個ACEs(access control entries)列表,每一個ACE包含了一組訪問權限和一個標識應該允許、拒絕、還是審覈某個受託對象(Trustee)的SID,所謂受託對象可以是一個用戶賬戶、組賬戶、或者是一個登陸會話。

      最好使用函數來操作安全描述符、SIDs、ACLs這些對象的內容,而不要直接訪問它們。因爲這樣可以保證這些對象的語法結構的準確性,並且在將來加強安全系統之後不影響已存在的代碼。

      以下8個小節講述訪問模型的部分知識點:

1.1.2.1.1 訪問令牌 Access Tokens

      訪問令牌 是一個用來描述進程或者線程的安全上下文的對象。訪問令牌 中的信息包含了與進程或者線程相關的用戶的ID和特權。當用戶登錄的時候,系統對用戶的密碼和保存在安全數據庫中的信息作比較,從而驗證用戶身份。如果密碼通過驗證,系統就生成一個訪問令牌 ,之後由該用戶運行起來的進程都有一份這個訪問令牌 的副本。

      當一個線程和一個安全對象進行交互,或者嘗試執行一個有特權要求的系統任務的時候,系統通過訪問令牌 來識別用戶的身份。訪問令牌 包含了以下信息:

  • 用戶賬戶的安全身份SID
  • 用戶所屬用戶組的安全身份SIDs
  • 標識當前登錄會話的登錄安全身份SID
  • 用戶或者用戶所在組的一個特權列表
  • 擁有者的SID
  • 主要用戶組的SID
  • 默認訪問控制列表DACLs,當用戶創建安全對象的時候未設置安全描述符,系統就會使用DACLs
  • 訪問令牌 的源
  • 該訪問令牌 是主要訪問令牌 還是模擬訪問令牌
  • 一個可選的限制安全身份SIDs
  • 當前模擬的級別Impersonation Level
  • 其他統計數據

      每一個進程都有一個主訪問令牌 用來描述和用戶相關的進程的安全上下文,默認情況下,當進程中的線程和安全對象交互的時候,系統要用到主訪問令牌 。另外,一個線程可以模擬一個客戶賬號,模擬操作允許線程使用這個客戶的安全上下文來和安全對象進行交互,這時候,模擬客戶賬號的線程同時擁有主訪問令牌 和模擬訪問令牌 。

      使用函數OpenProcessToken可以得到進程主訪問令牌 的句柄;使用函數OpenThreadToken可以得到線程的模擬訪問令牌 句柄。更多信息參考1.3.2客戶模擬。

      你可以使用下面的函數來控制訪問令牌 :

 

   
   
   
   
   
   
   
   
   
   
   
   
   

      上面的訪問令牌 操作函數使用下列結構體來描述訪問令牌 。

   
   
   
   
   
   
   
   
   
   

      訪問令牌 操作函數使用下面的枚舉類型

   
   
   

 

1.1.2.1.1.1 限制訪問令牌 Restrict Tokens

      一個限制訪問令牌是由函數CreateRestrictedToken函數修改的主要訪問令牌或者模擬訪問令牌。如果一個進程或者模擬線程運行在一個限制訪問令牌的安全上下文中的話,那麼這個進程/線程訪問安全對象或者使用特權的能力將有所限制。函數CreateRestrictedToken將通過下面的方式限制一個訪問令牌:

  • 去除訪問令牌中的特權
  • 將禁用屬性應用到訪問令牌中的安全身份SIDs中,以便它們不能訪問安全對象,關於禁用屬性的詳細信息參考 1.1.2.1.1.2 訪問令牌的SID屬性 小節
  • 指定一個限制SIDs列表,用來限制對安全對象的訪問

      當系統檢查令牌對一個安全對象的訪問權限的時候就會用到這個限制SIDs列表。當一個限制權限的進程/線程嘗試訪問安全對象的時候,系統執行兩次訪問檢查:一次是使用訪問令牌中開啓的SIDs,一次是使用限制SIDs列表。僅當兩次檢查的結果都允許請求的訪問權限時才賦予訪問權限,關於訪問檢查的詳情參考1.1.2.2 訪問檢查是如何工作的。

      你可以在CreateProcessAsUser函數調用中使用一個限制的主要訪問令牌,一般來說,調用CreateProcessAsUser函數的進程必須擁有SE_ASSIGNPRIMARYTOKEN_NAME特權,這個特權通常是由系統代碼或者運行在本地系統賬戶的服務擁有。但是,如果CreateProcessAsUser調用指定的是一個調用者的限制版本的主要訪問令牌,那麼是不需要這個特權的。這使得普通程序可以創建限制權限的進程(Restricted Processes)。

      你也可以在ImpersonatedLoggedOnUser函數中使用限制版本的主要訪問令牌和模擬訪問令牌。

      調用IsTokenRestricted函數,可以檢查一個訪問令牌是否包含一個限制SIDs列表。

註釋:使用限制訪問令牌的應用程序應該運行在限制程序的桌面,而不是默認的桌面。這樣做很有必要的,可以防止限制程序使用SendMessage、PostMessage對默認桌面上運行的非限制的應用程序進行攻擊。如果需要你應該根據需求在兩種桌面之間進行切換。

 

1.1.2.1.1.2 訪問令牌中的SID屬性 SID Attributes in an Access Token

      訪問令牌中的每一個用戶和組的安全身份SID都有一組屬性,它們可以控制系統如何在一次訪問檢查中使用SID,下面的表中列舉了控制訪問檢查的屬性。

   
   
   

      要設置或者清除一個組SID的SE_GROUP_ENABLED屬性,可以使用AdjustTokenGroups函數。你不能關閉一個帶有SE_GROUP_MANDATORY屬性的組SID,你不能使用AdjustTokenGroup來關閉訪問令牌的用戶SID。

      要想知道訪問令牌中的一個SID是否開啓,具體地說就是是否帶有SE_GROUP_ENALBED,可以調用CheckTokenMemberShip函數。

      當你調用CreateRestrictedToken的時候,要設置一個SID的SE_GROUP_USE_FOR_DENY_ONLY屬性,它是一個禁用SIDs列表中的一個SID。CreateRestrictedToken可以給任何SID設置SE_GROUP_USE_FOR_DENY_ONLY屬性,包括帶有SE_GROUP_MANDATORY屬性的用戶SID和組SIDs。但是你不能對一個SID移除禁用的屬性,也不能使用AdjustTokenGroups來對一個SID設置SE_GROUP_ENABLED屬性。

      要得到一個SID的屬性,可以調用帶有TokenGroups值的GetTokenInformation函數。這個函數返回一組標識了用戶組SIDs和他們的屬性值得SID_AND_ATTRIBUTES結構。

 

1.1.2.1.1.3 訪問令牌對象的訪問權限 Access Rights for Access Token Objects

      一個應用程序一般不能改變一個對象的訪問控制列表,除非它有這個權限。這些權限由訪問令牌中的安全描述符控制。關於安全的詳情參考1.1.2訪問控制模型。

      要設置或者得到一個訪問令牌中的安全描述符,可以調用GetKernelObjectSecurity和SetkernelObjectSecurity函數。

      當你調用OpenProcessToken或者OpenThreadToken得到一個訪問令牌的時候,系統檢查需要的訪問權限和在訪問令牌中安全描述符的DACL。

      下面是訪問令牌對象有效的訪問權限:

  • DELETE、READ_CONTROL、WRITE_DAC和WRITE_OWNER這些標準訪問權限,訪問令牌不支持SYNCRONIZE標準訪問權限
  • ACCESS_SYSTEM_SECURITY權限,得到或者設置一個對象的安全描述符中的SACL
  • 訪問令牌中特定的訪問權限,這些權限列於下表:
   
   
   
   
   
   
   
   
   
   
   
   
   
   

 

1.1.2.1.2 安全描述符 Security Descriptors

      安全描述符包含和安全對象相關的安全信息,一個安全描述符由SECURITY_DESCRIPTOR結構和相關的安全信息組成。一個安全描述符可以包含以下安全信息:

  • 一個對象的擁有者和所屬主要用戶組的安全身份SIDs
  • 一個DACL,這個DACL說明了允許還是禁止對特定用戶(組)的訪問權限
  • 一個SACL,這個SACL指定了爲對象生成的審覈記錄的訪問嘗試的類型
  • 一組控制bit位,這組bit位用來檢查一個安全描述符和它的私有成員所代表含義的資格

      應用程序不能直接操作安全描述符。Windows API提供了一組函數來設置和返回一個對象的安全描述符的安全信息。另外,還有一些函數用來創建和初始化一個新對象的安全描述符。

      操作活動目錄對象安全描述符的應用程序會使用Windows的安全函數或者由ADSI(活動目錄服務接口)提供的安全接口,關於ADSI的詳情可以參考對活動目錄域名服務的訪問控制是如何工作的

 

1.1.2.1.2.1 安全描述符的操作 Security Descriptor Operations

      Windows API提供了對安全對象的安全描述符進行設置和獲取操作的函數。使用GetSecurityInfo和GetNamedSecurityInfo函數可以得到一個對象的安全描述符。這些函數也可以返回安全描述符的私有部分:DACL、SACL、擁有者SID和主要用戶組SID。使用SetSecurityInfo和SetNamedSecurityInfo可以設置一個對象的安全描述符信息。

      一般來說,你可以使用GetSecurityInfo和SetSecurityInfo操作由句柄標識的對象,並通過SetSecurityInfo和SetNamedSecurityInfo來設置由一個名字標識的對象。關於對不同類型的對象使用哪些函數可以參考 1.1.6 安全對象。

      Windows API還提供了一些輔助函數用來操作一個安全描述符的子部分,關於如何處理訪問控制列表,可以參考 1.1.2.1.3.1 獲取ACL信息 和 創建和修改ACL。關於SID的詳情可以參考1.1.2.1.7 安全身份。

      要得到一個安全描述符的控制信息,調用GetSecurityDescriptorControl函數;要設置一個和自動繼承ACE相關的控制位bit,調用SetSecurityDescriptorControl函數;其他的控制位bit由不同的設置安全描述符子部分的函數操作。比如說如果你你調用SetSecurityInfo函數來改變一個對象的DACL,函數會設置或者清空相應的bit位來表示一個安全描述符是否有一個DACL,是否是一個默認的DACL等等,另一個例子是安全描述符中的資源管理器RM控制位,這些控制位bit根據資源管理管理器的實現分別有不同的用處,也可以用函數GetSecurityDescriptorRMControl和SetSecurityDescriptorRMControl來操作這些控制位bit。

 

1.1.2.1.2.2 新對象的安全描述符 Security Descriptors for New Objects

      當你創建一個新的安全對象的時候,你可以爲這個對象賦予一個安全描述符。比如說CreateFile、RegCreateKeyEx用來創建安全對象的函數,都有一個指向一個SECURITY_ATTRIBUTES結構的參數,這個參數可以包含這個新對象的安全描述符。有一個演示了創建一個安全描述符並調用RegCreateKeyEx賦給新註冊表鍵值的例子,用2.4.4.2 C++給新對象創建安全描述符。

      管理對象的系統組件或系統服務可以將對象特化的或默認的安全描述符保存下來永久化爲對象的屬性。如果對象的創建者沒有設定一個安全描述符,那麼系統將會使用繼承的或者是一個默認的安全描述符,你可以用函數來修改一個對象安全描述符中的數據。

      目錄服務對象,文件,目錄,註冊表鍵,以及桌面都是有父對象的安全對象。當你創建任何一個此類對象,系統就會檢查父對象的安全描述符中可繼承的ACEs。系統一般是將這些可繼承的ACEs合併到新對象的安全描述符的ACLs中,你可以通過在安全描述符的控制位bit上設置SE_DACL_PROTECTED和SE_SACL_PROTECTED來避免繼承ACEs的DACL和SACL。詳情參見1.1.2.1.4.4  ACE的繼承

 

1.1.2.1.2.2.1 新對象的DACL  DACL for a New Object

      系統使用下面的算法爲大多數安全對象創建DACL:

  1. 對象的DACL是由對象的創建者指定的安全描述符的DACL。系統合併所有可繼承的ACEs成爲DACL,除非在安全描述符的控制位中設置了SE_DACL_PROTECTED控制位。
  2. 如果創建者沒有指定一個安全描述符,系統會從繼承的ACEs中構建一個DACL。
  3. 如果沒有指定安全描述符、也沒有可繼承的ACEs,那麼新對象的DACL就是主訪問令牌或者是模擬訪問令牌的創建者的默認DACL。
  4. 如果沒有指定的、可繼承的、默認的DACL,那麼系統會創建一個沒有DACL的對象,它允許所有用戶訪問這個對象。

系統使用不同的算法來創建新活動目錄對象的DACL,更多信息參考如何設置新活動目錄對象的安全描述符

 

1.1.2.1.2.2.2 新對象的SACL   SACL for a New Object

      對於大多數對象,系統使用下面的算法來創建SACL:

  1. 對象的創建者設置了安全描述符的SACL,除非安全描述符中的控制位bit設置了SE_SACL_PROTECTED標記,否則系統會合並所有可繼承的ACEs到這個SACL中。即使設置了SE_SACL_PROTECTED標記,SYSTEM_RESOURCE_ATTRIBUTES_ACEs和SYSTEM_SCOPED_POLICY_ID_ACEs也會合併到新對象中。
  2. 如果對象的創建者沒有設置安全描述符,系統會從可繼承的ACEs中得到對象的SACL。
  3. 如果沒有指定的安全描述符、也沒有可繼承的SACL,對象就沒有SACL。

      要給新對象設置SACL,創建者必須有SE_SECURITY_NAME特權。如果爲新對象創建的SACL僅包含一個SYSTEM_ATTRIBUTE_ACEs,那麼SE_SECURITY_NAME特權就不是必需的了。如果對象的SCAL是從繼承的ACEs中構建出來的,那麼創建者也不需要有這個特權。

      系統使用一個不同的算法來創建活動目錄對象的SACL,詳情參考如何設置新活動目錄對象的安全描述符

 

1.1.2.1.2.2.3 新對象的擁有者 Owner for a New Object

      對象的擁有者擁有該對象的WRITE_DAC訪問權限,這意味可以修改對象的目錄訪問控制列表DACL,因此,也可以控制對象的訪問權限。

      新對象的擁有者是來自創建進程的主訪問令牌或者模擬訪問令牌中的安全描述符的默認的擁有者。要獲取/設置訪問令牌中的默認擁有者,可以調用帶TOKEN_OWNER結構的GetTokenInformation函數和SetTokenInformation函數,系統不允許你設置一個令牌的的默認擁有者到一個不可用的SID,比如說另一個用戶賬戶的SID。

      一個有SE_TAKE_OWNERSHIP特權的進程可以設置自身爲一個對象的擁有者。一個進程,若有SE_RESTOR_NAME特權或WRITE_OWNER對象訪問權限,那麼該進程可以設置一個對象的擁有者爲任何可用的用戶或組的SID。

 

1.1.2.1.2.2.4 新對象的主要用戶組 Primary Group of a New Object

      一個新對象的主要用戶組來源於對象創建者指定的安全描述符中的主要用戶組。如果一個對象的創建者沒有指定一個主要用戶組,那麼這個對象的主要用戶組就是創建者的主要訪問令牌或者模擬訪問令牌的主要用戶組。

 

1.1.2.1.2.3 安全描述符字符串 Security Descriptors Strings

      一個功能有效的安全描述符包含二進制格式的安全信息,Windows API提供了一些函數來讓二進制安全信息和文本字符串之間進行轉換。文本格式的安全描述符是不能使用的,但是它們在存儲和傳輸安全描述符方面是有用的。

      調用ConvertSecurityDescriptorToStringSecurityDescriptor可以將安全描述符轉化爲文本格式。調用ConvertStringSecurityDescriptorToSecurityDescriptor可以將一個文本格式的安全描述符轉換爲一個功能有效的安全描述符。

      更多信息,參考安全描述符定義語言

 

1.1.2.1.3 訪問控制列表 Access Control Lists

      訪問控制列表ACL是一個訪問控制項ACE的列表,ACL中的每一項ACE標識了一個受託者(用於ACE的用戶賬戶、用戶組賬號或者一個登錄會話)和指定是允許、拒絕、還是審覈這個受託者的訪問權限,一個安全對象的安全描述符可以包含兩種ACLs:DACLs和SACLs。

      用戶自定義的訪問控制列表DACL標識了允許或者拒絕受託者對安全對象的訪問。當一個進程訪問一個安全對象的時候,系統會通過檢查對象的DACL的ACE來決定是否賦予其訪問權限。如果該對象沒有DACL,系統就給所有用戶賦予完全訪問權限;如果這個對象的DACL沒有ACEs,系統就拒絕所有對該對象的訪問,因爲DACL不允許任何類型的訪問。系統將會按序檢查ACEs,直到所有被請求的權限被允許,或者是任何一個請求的權限被拒絕。更多信息參考1.1.2.2 DACLs如何控制對一個對象的訪問(實際是訪問檢查是如何工作的)。關於如何創建一個合適的DACL請參考創建一個DACL

      系統訪問控制列表(SACL)允許系統管理員將對安全對象的訪問記錄在日誌裏。每一個ACE標識了一個特定的受託者的一種訪問嘗試,這個受託者會令系統生成一條該安全對象事件的日誌記錄,當一次訪問嘗試失敗、成功或者二者都有的時候,SACL中的一個ACE會生成一條審覈記錄。關於SACL的詳情,請參考 1.1.5 審覈的生成和 1.1.2.1.5.4 SACL訪問權限。

      不要嘗試直接操作ACL,爲了保證ACLs語義上的正確性,要使用合適的函數創建和操作ACL,詳情參考 1.1.2.1.3.1 獲取ACL信息 和 1.1.2.1.3.2 創建或者修改ACL。

      ACLs也提供對微軟活動目錄服務對象的訪問控制,活動目錄服務接口包含了創建和修改ACLs內容的常規操作。詳情參考控制對活動目錄對象的訪問

 

1.1.2.1.3.1 獲取ACL信息 Getting Information From an ACL

      有好多函數用來獲得對訪問控制列表ACL的訪問控制信息,這些函數包括確定一個特定的受託者是否有ACL授權和審覈的訪問權限。其他函數可以抽取ACL中訪問控制項ACEs中的信息。

      GetExplicitEnteriesFromAcl函數可以得到一個EXPLICIT_ACCESS數組,這個EXPLICIT_ACCESS結構記錄了ACL中ACE的信息,這個在把一個ACL中的ACE信息拷貝到另一個ACL中時是很有用的。例如先用GetExplicitEnteriesFromAcl得到一個ACL中的ACE信息,然後將這個信息用SetEnteriesInAcl函數設置到一個新的ACL的ACEs中。

      GetEffectiveRightsFromAcl函數可以檢查一個DACL是否賦予一個受託者的有效權限,受託者的一個有效的權限是DACL賦予一個受託者或者受託者所在的任何用戶組的訪問權限。這個函數可以檢查指定DACL中所有允許和禁止訪問的ACE項。

      用下列方法檢查一個受託者是否有某個對象的訪問權限:

  1. 調用GetSecurityInfo或者GetNamedSecurityInfo函數得到一個對象的DACL指針
  2. 調用GetEffectiveRightsFromAcl函數獲得DACL賦予一個受託者的訪問權限

      GetAuditedPermissionsFromAcl函數可以檢查系統訪問控制列表SACL,以得到一個受託者或受託者所在組是否擁有經過審覈的訪問權限。經過審覈的訪問權限說明了訪問嘗試的類型,這種訪問引起系統在安全事件日誌中生成一條審覈記錄。這個函數返回兩個訪問掩碼,一個包含了監視過程中失敗的訪問請求權限,一個包含了監視過程中成功的訪問請求的權限。GetAuditedPermissionsFromAcl檢查ACL中所有系統審覈級別的ACE。

 

1.1.2.1.3.2 創建或者修改ACL Createing or Modifying an ACL

      Windows提供了一組函數,用來創建ACL或者修改一個已存在ACL中的ACEs。

      SetEnteriesInAcl函數創建一個ACL,這個函數也可以給一個ACL設置一個組新的ACE,或者將一個或多個新的ACE和一個已存在的ACL的ACEs。SetEnteriesInAcl使用一組EXPLICIT_ACCESS結構來指定新的ACE組的信息,每一個EXPLICIT_ACCESS結構包含了一個ACE的描述信息。這個信息包含訪問權限,ACE類型,控制ACE繼承的標記,和一個標記受託者的TRUSTEE結構。

      爲一個已經存在的ACL添加新的ACE:

  1. 使用GetSecurityInfo或者GetNamedSecurityInfo函數得到一個對象的安全描述符中的DACL或SACL。
  2. 爲每一個新的ACE調用BuildExplicitAccessWithName函數,來爲EXPLICIT_ACCESS結構填充上描述ACE的信息。
  3. 調用SetEnteriesInAcl,爲新的ACE組指定一個已存在的ACL或者一個EXPLICIT_ACCESS結構數組,這個函數會創建並初始化這個ACL和ACE數組。
  4. 調用SetSecurityInfo或SetNamedSecurityInfo函數,把新的ACL賦給對象的安全描述符。

      如果調用者指定了一個已存在的ACL,SetEntriesInAcl會把新的ACE和這個ACL中已存在的ACEs的信息合併起來。考慮一下這種情況,比如有一個已存在的ACL賦予了對一個受託者的訪問權限,而一個EXPLICIT_ACCESS結構拒絕對這個受託者的訪問,這時SetEntriesInAcl函數爲這個受託者添加一個新的拒絕訪問ACE並刪除或者是修改受託者的這個允許訪問的權限。

      有一個例子演示了把一個新的ACE合併到一個已有的ACL,參見2.4.4.1 用C++修改對象的ACLs。

 

1.1.2.1.4 訪問控制項 Access Control Entries

      訪問控制項ACE是訪問控制列表ACL中的元素,一個ACL中可以由0到多個ACEs。每一個ACE控制或者監視一個指定的受託者多一個對象的訪問,關於添加、刪除、修改一個對象的ACL中的ACEs,可參考2.4.4.1 用C++修改對象的ACLs。

      這裏有六種類型的ACEs。所有的安全對象都支持這三種;其他三種是 1.1.2.1.4.2 對象專屬的ACEs,只有目錄服務對象支持。

      所有的ACE都包含下面的訪問控制信息:

  • 一個安全身份SID,用來標識這個ACE用在哪個受託者上
  • 一個訪問掩碼,用來這個由ACE控制的訪問權限
  • 一個標記,標識ACE的類型
  • 一組bit標記,用來決定子容器或者對象能否繼承這個ACL附着的主對象的ACE。

      下面列出的ACE類型爲所有安全對象所支持:

   
   
   
   

      參考 1.1.2.1.4.2 對象專屬的ACEs,有一個對象專屬的ACE列表。

      注:現在不支持系統警告對象的ACE。

 

1.1.2.1.4.1 受託者 Trustees

      受託者是指使用了訪問控制項ACE的用戶賬戶、用戶組賬戶和登錄會話。ACL中每一個ACE都有一個用來標識受託者的安全身份SID。

      用戶賬戶包含真人用戶的賬戶,或者類似用來登錄本地計算機的Windows服務的賬戶。

      用戶組賬戶不能用於登錄一臺計算機,但是他們對於用來拒絕或者允許一個或多個用戶賬戶對一組權限的訪問。

      登錄SID標識了當前的登錄會話,這個對於在登錄期間允許或者是拒絕訪問權限是非常有用的。

      訪問控制函數使用TRUSTEE結構來標識一個受託者,TRUSTEE結構使用一個名字字符串或者一個SID來標識一個受託者。如果你使用了名字字符串的TRUSTEE結構來創建一個ACE,那麼這些函數將會申請一個SID緩存,然後搜索和賬戶名對應的SID。這裏有兩個函數可以幫助你用一個名字字符串和一個SID初始化一個TRUSTEE:BuildTrusteeWithSid和BuildTrusteeWithName,這兩個函數BuildTrusteeWithObjectAndSid和BuildTrusteeWithObjectAndName可以讓你用對象專屬的ACE初始化一個TRUSTEE結構,還有三個函數GetTrusteeForm、GetTrusteName和GetTrusteeName可以讓你獲得TRUSTEE結構的成員的值。

      TRUSTEE結構中的ptstrName成員可以是一個指向OBJECT_AND_NAME和OBJECT_AND_SID結構,這些結構指定了除了受託者對象名字和SID之外關於一個對象專屬的ACE的信息。這可以讓像SetEntriesInAcl和GetExplicitEntriesFromAcl這樣的函數在存儲特定對象的EXPLICIT_ACCESS中的Trustee成員的ACE的信息。

 

1.1.2.1.4.2 對象專屬的ACEs Object-Specific ACEs

      對象專屬的ACEs是爲了支持目錄服務對象的。一個對象專屬的ACE包含了一對GUIDs,這個用來擴展ACE保護對象的方法。

   
   
   

      系統支持三種類型的對象專屬的ACE類型。

      注:系統警告對象的ACEs目前不被支持。

   
   
   
   

      任何包含對象專屬的ACE的ACL都必須有ACL_REVERSION_DS的權限。

 

1.1.2.1.4.3 DACL中ACEs的順序 Order of ACEs in a DACL

      當一個進程訪問一個安全對象的時候,系統會逐步遍歷目錄訪問控制列表DACL中的控制入口ACEs,直至找到一個ACE允許或者拒絕這個請求的訪問。根據出現在不同的DACL中的ACEs的不同順序,一個DACL允許一個用戶的訪問權限有所不同。Windows XP爲安全對象的ACL提供了一個首選的ACEs順序,這個首選的ACEs順序提供了一個簡單的框架,它讓一個禁止訪問類型的ACE實際上也能拒絕訪問。關於系統檢查訪問權限的算法,參考 1.1.2.2 訪問檢查是如何工作的。

      對於Windows Server 2003和Windows XP來說,這個合適的順序被對象專屬的ACE和自動繼承的引入複雜化了。

      下面的步驟描述了這個首選順序:

  1. 用戶組中所有定義明確的ACEs位於可繼承的ACEs前面
  2. 用戶組中定義明確的ACEs中,禁止訪問類型的ACEs位於允許訪問的ACEs前面。
  3. 可繼承的ACEs按照它們被繼承的順序存儲。繼承自子對象的父對象的ACEs放在最前面,接下來是繼承自祖父對象的ACEs,接着向上沿着對象的繼承樹。
  4. 對每一個繼承層次中的ACEs,禁止訪問的ACEs位於允許訪問的ACEs前面

      當然ACL中並非有所有的需要的ACE類型。

      比如AddAccessAllowdAceEx和AddAccessAllowedObjectAce在ACL末尾添加一個ACE。確保ACEs以合適的順序添加到ACL中是函數調用者的責任。

 

1.1.2.1.4.4 ACE的繼承 ACE Inheritance

      一個對象的ACL可以包含了繼承自它的父對象容器的ACEs,例如,一個註冊表子鍵可以繼承來自注冊表上層結構的鍵的ACEs。類似地,在NTFS系統上的文件繼承包含它的文件夾的ACEs。

      一個ACE的ACE_HEADER結構包含一組繼承標記,這組標記控制了ACE的繼承和以及附加在這個對象上的ACE的效果。系統會解釋這個繼承標記,還有其他根據ACE繼承順序的繼承信息。

      下面這些規則可以用下列特性加強:

  • 對可繼承ACEs的自動傳播的支持
  • 區別繼承的ACEs和直接設置到對象的ACEs之間的不同的標記
  • 允許你指定子對象類型的對象專屬的ACEs,這種子對象可以繼承ACE
  • 通過設置安全描述符的控制位bit爲SE_DACL_PROTECTED或者SE_SACL_PROTECTED,不設置SYSTEM_RESOURCE_ATTRIBUTE_ACE和SYSTEM_SCOPED_POLICY_ID_ACE,來阻止DACL、SACL繼承ACEs。

1.1.2.1.4.5 可繼承ACEs的自動傳播 Automatic Propagation of Inheritable ACEs

      SetNamedSecurityInfo和SetSecurityInfo支持可繼承的ACEs的自動傳播,例如,如果你使用這兩個函數爲NTFS系統的一個目錄添加一個可繼承ACE,系統會把這個ACE應用到對應的子目錄和文件的ACL中。

      直接設置到對象的ACE比繼承的ACE擁有更高的優先級,系統爲了實現這種優先級別,把DACL中直接設置到對象的ACE放置於可繼承的ACEs前面,當你調用SetNamedSecurityInfo和SetSecurityInfo函數設置一個對象的安全信息的時候,系統會強制把當前的繼承模型應用到目標對象層次結構下的所有對象。那些轉換到當前繼承模型下的對象,其SE_DACL_AUTO_INHERITED和SE_SACL_AUTO_INHERITED位都被設置爲目標對象的安全描述符的控制域。

      當你創建一個反映當前繼承模型的安全描述符的時候,注意不要改變安全描述符的語意。比如,允許或者拒絕ACEs永遠不能在彼此之間移動。如果需要做此類動作(比如說把不可繼承的ACEs放置於ACL前面),ACL要標記爲被保護狀態避免語意的改變。

      當系統傳播可繼承ACEs到子對象時使用一下規則:

  • 當一個沒有DACL的子對象繼承了ACE時,該子對象的DACL只能包含可繼承的ACE。
  • 當一個含有空DACL的子對象繼承ACE時,該子對象的DACL也是隻能包含可繼承的ACE。
  • 當你從一個父對象中移除一個可繼承的ACE時,自動繼承機制會移除所有子對象中繼承的ACE的副本。
  • 如果自動繼承機制導致移除了子對象的DACL中所有ACE的時候,子對象將會擁有一個空的DACL,而不是沒有DACL。

      使用這些規則把一個沒有DACL的對象轉化爲擁有一個空DACL的對象的時候,會導致意想不到的錯誤。系統允許沒有DACL的對象擁有所有訪問權限,但是一個擁有空DACL的對象沒有任何訪問權限。下面舉例說明這些規則如何創建一個空DACL,假設你要給一個樹形對象組的根對象添加一個可繼承的ACE,自動繼承機制會傳遞該ACE到樹結構中所有的子對象中,一開始沒有DACL的子對象,現在有了一個包含單個可繼承ACE的DACL。如果你現在又把這個可繼承的ACE從根對象中移除,系統會自動地把這個改變傳遞到子對象中,那麼一開始沒有DACL的子對象(擁有所有訪問權限)現在擁有一個空DACL(沒有任何訪問權限)。

      爲了保護沒有DACL的子對象不受可繼承ACEs的影響,要給該對象的安全描述符中設置SE_DACL_PROTECTED標記。

      關於如何恰當地創建DACL的信息,請參考創建一個DACL

 

1.1.2.1.4.6 ACE繼承規則 ACE Inheritance Rules

      系統把可繼承的ACEs傳播到子對象,會依據一組繼承規則。系統根據1.1.2.1.4.3DACLs中ACE的順序把可繼承的ACEs放入DACL中。系統在所有的可繼承ACEs中設置INHERITED_ACE標記。

      容器子對象和非容器子對象繼承ACEs是有區別的,這要看繼承標記的組合情況而定。這些繼承規則對DACLs和SACLs都是一樣的。

      

   
   
   
   
   

 

      如果一個繼承的ACE對子對象是有效的,系統會爲子對象把所有通用權限映射到特定權限。類似地,系統會把例如CREATOR_OWNER這樣的通用安全身份SID映射到適當的SID,如果一個繼承來的ACE是一個僅被繼承的ACE,所有的通用權限和通用SID都不變,以便在映射的時候這些ACE在下一代子對象被正確地繼承。

      對於容器對象繼承一個ACE的情況,該容器對象將得到一個有效的ACE,並且其後代對象也可以繼承該ACE,容器對象可能繼承兩個ACE。這種情況在可繼承的ACE包含通用信息的時候就會發生。容器繼承一個僅可被繼承的ACE,該ACE中包含了通用信息和一個僅在通用信息被映射的時候纔有效的ACE。

      一個對象專屬的ACE有一個InheritedObjectType成員,它可以包含一個GUID來標識一個可以繼承ACE的對象的類型。

      如果沒有指定InheritedObjectType GUID,對象專屬的ACE的繼承規則和標準ACE是相同的。

      如果指定了InheritedObjectType GUID,那麼如果設置了OBJECT_INHERIT_ACE標記,匹配該GUID的對象可以繼承該ACE;如果設置了CONTAINER_INHERIT_ACE標記,匹配該GUID的容器也可以繼承該ACE。注意,當前僅有DS對象支持對象專屬的ACE,並且DS(Directory Service)對象把所有對象類型都視看作容器。

 

1.1.2.1.4.7 對象屬性控制訪問的ACEs ACEs to Control Access to an Object's Properties

      目錄服務對象的DACL可以包含一個ACEs層次結構,如下所述:

  1. 保護對象的ACEs
  2. 保護對象指定屬性集的對象專屬的ACEs
  3. 保護對象指定屬性的對象專屬的ACEs

      在這個層次結構中,權限可以在更高層次上賦予和拒絕,也可以在更低層次上。例如,一個屬性集中的一個對象專屬的ACE允許一個受託者擁有ADS_RIGHT_DS_READ_PROP權限,受託者隱式地有了讀取那個屬性集中所有屬性的訪問權。類似地,允許ADS_RIGHT_DS_READ_PROP訪問的對象中的一個ACE會賦予受託者對該對象所有屬性的讀取訪問權。

      下圖示意了一個假設的DS對象的和它的屬性集。

 

      

 

      假設你想要獲得下以下對DS對象屬性的訪問權:

  • 組A對該DS對象所有屬性進行讀/寫
  • 其他對象(除組A之外)對除屬性D之外的屬性進行讀寫

      爲此,可按照下表對對象的DACL中的ACEs進行設置。

 

       
       
       
       

 

      組A的ACE沒有對象GUID,這意味着它有對所有對象屬性的訪問權,屬性集1的對象專屬ACE可讓組A獲得屬性A和屬性B所有訪問權。其他對象專屬ACE可讓組A獲得屬性C的所有訪問權。注意,雖然這個DACL沒有任何拒絕訪問的ACE,但是它隱式地拒絕了除組A之外的對象對屬性D的訪問。

      當一個用戶嘗試訪問對象的屬性,系統會按一定順序檢查該對象的ACEs,直到請求的訪問被明確地接受、拒絕,或者沒有ACEs(也就是說該訪問被隱式地拒絕)。

      系統的算法是:

  • 應用到該對象的ACEs
  • 應用到包含要被訪問屬性的屬性集的對象專屬ACEs
  • 應用到將要被訪問的屬性的對象專屬ACEs

      系統忽略應用到其他屬性集和屬性的對象專屬ACEs。

 

1.1.2.1.5 訪問權限和訪問掩碼 Access Rights and Access Masks

      所謂訪問權是一個位標記,它對應於一組特殊的操作,這個操作是一個線程可能對一個安全對象做的操作。比如,一個註冊表鍵有一個KEY_SET_VALUE訪問權,這對應於一個線程可以對這個鍵設置值。如果一個線程要對一個對象進行操作,但是沒有必要的操作權限,系統就不會執行該操作。

      所謂訪問掩碼是一個32位的值,每一位對應於對象支持的訪問權。所有Windows安全對象都使用一個包含下列類型訪問權的位:

  • 通用訪問權 (1.1.2.1.5.2)
  • 標準訪問權 (1.1.2.1.5.3)
  • SACL訪問權 (1.1.2.1.5.4)
  • 目錄服務訪問權 (1.1.2.1.5.5)

      當一個線程嘗試打開一個對象的句柄時,線程通常會指定一個訪問掩碼以請求一組訪問權。比如一個應用程序需要設置和查詢註冊表的鍵,則可以使用請求KEY_SET_VALUE和KEY_QUERY_VALUE訪問權的訪問掩碼打開該鍵。

      下表給出了操作各種安全對象的安全信息的函數:

 

   
   
   
   
   
   
   
   
   
   
   
   
   
   

 

1.1.2.1.5.1 訪問控制掩碼格式 Access Mask Format

      所有安全對象使用訪問掩碼來整理訪問權,如下表所示:

 

      

 

      在這個格式中,低16位是對象專屬訪問權,接着的8位是標準訪問權(使用的對象類型最多),高4位用來標識通用訪問權(每種對象可以映射到一組標準和對象專屬權限)。ACCESS_SYSTEM_SECURITY位對應於訪問對象的SACL的權限。

      

1.1.2.1.5.2 通用訪問權限 Generic Access Rights

      安全對象使用的訪問掩碼格式中高4位指定了通用訪問權限。每種類型的安全對象會映射這些位到一組自身的標準訪問權限以及對象專屬的訪問權,比如,一個Windows文件對象的GENERIC_READ位會映射到標準訪問權限READ_CONTROL和SYNCHRONIZE,以及對象專屬訪問權FILE_READ_DATA、FILE_READ_EA和FILE_READ_ATTRIBUTE。其他類型對象會把GENERIC_READ位映射到那種類型對象適當的訪問權。

      你可以使用通用訪問權指定你想打開一個對象的句柄時需要的訪問類型。這比專門指定對應的標準的和對象專屬訪問權要簡單得多。

      下表給出了爲通用訪問權定義的常量:

 

   
   
   
   
   

 

      定義了私有安全對象的應用程序同樣使用通用訪問權限。

 

1.1.2.1.5.3 標準訪問權限 Standard Access Rights

      每種安全對象都有一組對應於對象特有操作的訪問權。對於對象專屬的訪問權,還有一組對應於所有安全對象標準訪問權。

      訪問掩碼格式包含了一組bit位來標識標準訪問權。在winnt.h中有下列爲標準訪問權定義的Windows常量:

 

   
   
   
   
   
   

 

      winnt.h中還定義了下面的標準訪問權限組合的常量:

 

   
   
   
   
   
   

 

1.1.2.1.5.4 SACL訪問權限 SACL Access Right

      訪問權ACCESS_SYSTEM_SECURITY標記控制獲取和設置一個對象中安全描述符的SACL的資格。僅當請求線程中訪問令牌中有SE_SECURITY_NAME特權,系統纔會賦予這些訪問權。

      爲了訪問對象的SACL:

  1. 調用AdjustTokenPrivilege函數,得到SE_SECURITY_NAME特權
  2. 當你打開一個對象的時候,請求ACCESS_SYSTEM_SECURITY訪問權
  3. 使用諸如GetSecurityInfo或SetSecurityInfo函數獲得或設置對象的SACL
  4. 調用AdjustTokenPrivilege函數,禁用SE_SYSTEM_SECURITY特權

      用GetNamedSecurityInfo或SetNamedSecurityInfo函數訪問SACL啓用SE_SECURITY_NAME標記。這個函數間接地請求訪問權。

      DACL中的ACCESS_SYSTEM_SECURITY訪問權不可用,因爲DACLs不能控制對SACL的訪問權。但是,你可以在一個SACL中使用ACCESS_SYSTEM_SECURITY訪問權來審覈使用訪問權的嘗試。

 

1.1.2.1.5.5 目錄服務訪問權限 Directory Services Access Rights

      每一個活動目錄對象都有一個被賦予的安全描述符。爲受託者指定一組權限可以設置在這些安全描述符中。這些權限列在下表中,詳細信息參考控制訪問權

 

   
   
   
   
   
   
   
   
   
   
   

 

1.1.2.1.5.6 向一個對象的請求訪問權限 Requesting Access Rights to an Object

      當你打卡一個對象句柄,返回的句柄含有一些訪問權限的組合,有些函數(比如說CreateSemaphore)並不會要求指定一組的需要的訪問權,這些函數通常會嘗試爲得到全部訪問權而打開句柄。其它函數(比如CreateFile、OpenProcess)會讓你指定一組你想要的訪問權。你應該僅指定你需要的權限,而不是爲了得到全部訪問權而打開一個句柄。如果對象的DACL僅支持有限的訪問權,這會阻止你用一種意想不到的方法是用句柄,同時增大成功請求的機率。

      打開一個對象的句柄時,使用通用訪問權指定必要的訪問權。這通常比指定標準訪問權和對象專屬訪問權要簡單。另外,使用MAXIMUM_ALLOWED常量來得到被打開的對象的對調用者來說全部有效權限。

      注意: MAXIMUM_ALLOWED不能用於ACE。

      打開一個對象的句柄時,要求有ACCESS_SYSTEM_SECURITY訪問權,來得到或者設置對象安全描述符中的SACL。

 

1.1.2.1.6 統一授權策略 Centralized Authorization Policy

      動態訪問控制(DAC)方案可以幫助扶着企業文件服務的統一訪問控制管理員。多數組織有多個想要進行訪問控制的區域。

      例如:

  • 對敏感信息的控制,其中標記爲敏感的文件有特殊的許可。
  • 對隱私信息的文件訪問控制。
  • 對基於組織保留政策的文檔要限制訪問權限。

      有許多新的授權政策概念允許管理員來統一定義這些政策,通過允許定義和維護(但是單獨使用)這些訪問請求作爲一個政策,並簡化定義流程。

      Windows8中有兩個新的活動目錄政策對象,一個是統一授權政策(CAP),一個是統一授權政策規則(CAPR),這兩個對象是基於需求和資源的屬性的表達。具體使用時,管理員把CAPR定義爲特定的授權政策,這些政策可以應用到具有特定屬性或者滿足一定應用條件的資源中。比如標記爲“高商業影響”的文檔,在一個可表達的組織中或者一個要使用政策的可標識資源中,用Windows 8 DAC的方式,CAPEs可能定義爲每一個想要的訪問控制政策。一個CAP是一個可一起應用到資源的CAPRs集合,下圖顯示了CAP和CAPEs的關係,以及在定義和使用這些對象到文件資源中的概念性步驟。

 

      

 

1.1.2.1.6.1 統一授權策略 Central Authorization Policies

      統一授權策略(CAP)把一組特定的CAPRs集合在一起成爲一個授權策略。把特定的CAPRs組合爲一個組織的整體性的策略,CAPRs可以引用在一起,並應用於一組資源。可以通過引用的方式把多個集合到一個CAP中。一旦定義好一個CAP之後,就可以用資源管理器把它部署到組織授權策略的資源上。

      一個CAP有以下屬性:

  • 一個CAPR的集合,一個CAPR對象的引用列表
  • 一個身份SID
  • 描述
  • 名字

      一個CAP在對由管理員允許的文件和文件夾訪問審覈的時候進行計算。在一個AccessCheck調用中,一個CAP審查邏輯上由任意的ACL審查組成,這意味着爲了訪問一個應用了CAP的文件,用戶需要同時根據CAP策略(內含的CAPRs)和應用在文件上的ACL規則來審查。

      CAP例子:

 

      CAP定義:

      可以用ADAC中的一個UX在活動目錄中創建和修改一個CAP。這個ADAC要允許管理員創建一個CAP並指定一組構建CAP的CAPRs。

 

另外

 

1.1.2.1.6.2 統一授權策略規則 Central Authorization Policy Rule

      統一授權規則CAPR的目的是爲了提供一個域名範圍的、關於組織授權策略的獨立定義。管理員可以通過定義CAPR類加強某些授權需求。因爲CAPR定義的僅是某一個方面的授權策略需求,如果所有這些組織授權策略需求編寫爲一個單獨的策略定義,它還可以更加簡單易懂。

      CAPR還有下列屬性:

  • 名字 - 對管理員區分CAPR的身份
  • 描述 - 定義CAPR的目的,客戶需要的關於CAPR的任何說明
  • 適用性說明 - 定義在那種資源或情形下可以使用該策略
  • ID - 審覈CAPR修改時的身份
  • 有效訪問控制策略 - 一個Windows安全描述符
  • 異常表述 - 一個或多個表達式,該表達式提供了改寫策略並根據表達式計算結果授權訪問一個對象的方法
  • 階段性策略 - 一個可選的Windows安全描述符,包含一個定義了建議性授權策略的DACL,該策略是獨立於有效策略進行測試但是不強制的。如果在有效策略和該策略之間有任何差別,這些差別將會被記錄在審查時間日誌中。
    • 因爲階段性的審查可能會對系統性能有意想不到的效果,組策略管理員必須可以選擇指定的可以使用該策略的機器。這使得階段性審查發生在這些機器的一個子集的時候,已有的策略在大多數OU機器上是適當的,
    • P2 - 一些機器上的本地管理員應該擁有禁用階段性審查,如果那些機器上的階段性審查造成了過多的性能降級。
  • CAP的反向鏈接 - 一個反向鏈接到該CAPs的反向鏈接列表,該CAP可能被引用到CAPR

      在訪問審查中,系統根據適用性表達式計算適當的CAPR。如果一個CAPR是適用的,系統就會計算是否可以爲請求的用戶提供指定的資源。這個CAPE計算結果邏輯上是相關資源DACL的結果與任何其他適當的有效CAPRs的交集(AND計算)。

      CAPRs的例子:

 

      CAPEs中否定ACEs

      在Windows 8中,將不支持在ACPRs中否定ACEs,CAPR授權UX將不支持創建一個否定ACE。另外,當LSA從活動目錄的時候檢索CAP,LSA將會檢查沒有包含否定ACE的CAPR。如果發現一個CAPR中含有否定ACE,那麼這個ACPR將被視爲無效,並且不會拷貝到註冊表或者SRM中。

      注意,如果沒有發現ACE,將不會強制進行訪問審查。這時候會使用CAPR中的否定ACE。正如所料,授權工具將會阻止這個發生。

      CAPE定義

      活動目錄管理中心(ADAC)的一個新UX創建CAPR。ADAC中,創建CAPR會有一個新的任務選項,選擇任務的時候,ADAC會用一個彈出框提示用戶,並詢問用戶對CAPR的名字和描述。當用戶提供這些之後,任何已有的CAPR元素的控制定義也將生效。對於每一個已有的CAPR元素,UX將會調出ACL-UI來允許表達式和/或ACLs的定義。

      相關主題

      AccessCheck函數

      動態訪問控制情景

 

1.1.2.1.7 安全身份 Security Identifiers

      一個安全身份(SID)是一個用來識別受託者的獨特的變長值。每一個賬號都有一個獨特的SID,由另一個權威賬戶賦予,比如說Windows域管理者,並存儲在安全數據庫中。每次用戶登錄的時候,系統就爲用戶從安全數據庫中取出這個SID,並把它放置在這個用戶的訪問令牌中。在隨後與系統的交互中,系統使用訪問令牌中的這個SID來區分用戶。當一個SID用來作爲一個用戶或組的唯一身份的時候,是不能用來標識另一個用戶或組身份的。

      Windows安全在一下安全元素中使用SID:

  • 在安全描述符中,用來標識一個對象或者主要組的所有者
  • 在訪問控制項ACE中,爲受託者標識哪一個訪問是允許的,拒絕的,或者審查的
  • 在訪問令牌中,標識一個用戶屬於哪一個用戶或組

      另外,對於爲用戶或組特別創建的、域範圍內的SID,有一些公開的SID用來標識通用組和用戶。例如這個SID,Everyone and World,標識了所有用戶。

      大多數應用程序是不需要用到SID的。因爲這些公開的SID的名字彼此不同,你應該使用函數從預定義的常量上創建SID,而不是使用這些公開SID的名字。例如,美國英語版本的Windows操作系統中有一個命名爲"BUILTIN\Administrator"公開的SID,可能在不同的國際系統版本中有不同的名字。創建公開SID的例子,可以參考 用C++在一個訪問令牌中搜索一個SID。

      如果你真的需要使用SID,不要直接操作它們,應該使用下列函數。

 

   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   

 

1.1.2.1.7.1 SID的結構 SID Component

      一個SID值包含提供了SID結構信息的部分,和唯一標識了受託者的部分。一個SID包含下列部分:

  • 一個SID結構的修訂級別
  • 一個48bit的標識符權限,用來標識賦予該SID的權限
  • 若干數量的子權限或相對標識符(RID)值,該RID值唯一地標識了相關的賦予了SID權限的受託者。

      標識符權限值和和子權限值的組合保證了沒有兩個SID會相同,即使兩個不同的SID分配權威分配了相同的RID值的組合。一個SID分配權威分配一個特定RID,僅一次。

      SID以二進制的方式存儲於一個SID結構中。爲了演示一個SID,你可以調用ConvertSidToStringSid函數來把一個二進制的SID轉爲字符串格式。可以調用ConvertStringSidToSid函數,把轉換一個SID字符串格式到有效的、可用的SID。

      這些函數使用下列SID標準字符串符號,這使得它們的結構可視化變得更簡單:

S-R-I-S...

      在這個符號中,字符S表示數字序列是一個SID,R表示修訂級別,I是標識符權限值,S...是一個或多個子權限值。

      下面的例子 使用這個格式演示了本地管理員組的公開相對域SID:

S-1-5-32-544

      在這個例子中,SID有下列組成部分,括號中的常量是定義在Winnt.h中公開的標識符權限和RID值。

  • 修訂級別爲1
  • 標示符權限值爲5(SECURITY_NT_AUTHORITY)
  • 第一個子權限是32(SECURITY_BUILTIN_RID)
  • 第二個子權限是544(DOMAIN_ALIAS_RID_ADMINS)

 

1.1.2.1.7.2 公開的SIDs Well-Known SIDs

      公開的安全描述符(SID)定義了通用組、用戶。比如區分下列組合用戶的公開SID:

  • Everyone or World, 包含所有用戶的組
  • CREATOR_OWNER,在可繼承ACE中用作一個佔位符。當一個ACE是繼承來的,系統就把該SID替換爲創建對象的SID
  • 本地計算機上內置域的管理員組

      還有些國際通用的SID,可用於所有基於這個安全模型的安全系統上,甚至是非Windows系統。另外,還有一些公開的SID僅能用於Windows系統。

      Windows API爲公開標識符權限和相關標示符(RID)值定義了一組常量。你可以用這些常量來創建公開的SID。下面的例子組合了SECURITY_WORLD_SID_AUTHORITY和SECURITY_WORLD_RID來演示爲所有用戶使用的國際通用SID。

S-1-1-0

      這裏例子使用SID字符串符號,其中S網i標識SID的字符串,第一個1是SID的修訂級別,剩餘的兩個數字是SECURITY_WORLD_SID_AUTHORITY和SECURITY_WORLD_RID常量。

      你可以使用AllcateAndInitializeSid函數,結合標識符權限值和多大8個子權限值的組合,來創建一個SID。例如,確定一個登錄用戶是否是一個公開組的成員,使用AllocateAndInitializeSid函數來爲公開組創建一個SID,使用EqualSid函數來比較該SID和用戶訪問令牌中的組SID。要看參考示例的話,請看 用C++在訪問令牌中搜索一個SID。你必須使用FreeSid函數來釋放由AllocatedAndinitializeSid函數申請的SID。

      本節剩餘部分包含了公開SID的表格,標識符權限表格和子權限常量表格,你可用它們來創建SID。

      下面是部分國際通用SID:

     
     
     
     
     
     

 

      下表列出了預定義的標識符權限常量。前4個值用於國際通用SID,最後一個用於Windows公開SID中。

 

     
     
     
     
     
     

 

      下列RID值和國際通用SID一起使用。標識符權限列展示了標識符權限的前綴,使用這個你可以和RID組合來創建國際通用SID。

 

     
     
     
     
     
     
     

 

      SECURITY_NT_AUTHORITY(S-1-5)預定義了標識符權限生成SID,這些SID不是國際通用SID,僅在Windows安裝上有意義。你可以使用下列RID值和SECURITY_NT_AUTHORITY來創建公開SID。

 

 

     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     

 

      下面域相關的RID:

 

   
   
   
   
   
   
   
   
   
   
   
   
   
   
   

 

      以下RID用於指定受託者誠信水平:

 

     
     
     
     
     
     
     
     

 

      下表是你可以用來爲本地組(別名)構造公開SID的域相關的RID。關於本地組合全局組的詳細信息請參考本地組函數組函數

 

 

 

     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     

 

      枚舉值WELL_KNOWN_SID_TYPE定義了一個常用的SID的列表。另外,安全描述符定義語言(SDDL)使用SID字符串來引用有某種字符格式的公開SID。

 

1.1.2.2 訪問檢查是如何工作的 How Access Check Works

      當一個線程嘗試訪問安全對象的時候,系統會允許或拒絕該訪問。如果一個該對象沒有DACL,那麼系統會允許該訪問;反之,系統會搜索線程中使用的對象的DACL中的ACE。對象的DACL中的每一個ACE都指定了訪問權限允許或拒絕一個受託者對象,這個受託者可能是一個用戶賬號,一個組賬號,或者一個登錄會話

      DACLs

      系統會比較每個ACE中的受託者和線程訪問令牌中指定的受託者。一個訪問令牌包含一個安全描述符,指定用戶屬於哪個一個用戶賬號或組賬號。一個訪問令牌也包含一個登錄ID用來標識當前登錄會話。在一個訪問審查中,系統忽略未激活的組安全描述符(SID)。關於激活、取消、以及僅限拒絕的SID,參考 訪問令牌中的SID屬性。

      一般地說,系統使用請求訪問線程的第一訪問令牌。但是如果一個線程模擬令一個用戶,系統使用線程的模擬令牌。

      系統檢查按序檢查每一個ACE,直到下列事件中的某一個發生:

  • 一個訪問拒絕(Access-denied)ACE明確否定列在線程訪問令牌中的受託者請求的任何訪問權限。
  • 一個或多個列在線程訪問令牌中的受託者的允許訪問(access-allowed)ACE明確地允許所有訪問權限。
  • 所有ACE都經過了審查,但是還有至少一個請求的訪問權限沒有被明確地允許,這種情況下,訪問隱式地被拒絕。

      下圖展示了一個對象的DACL是如何允許一個線程,而拒絕另一個線程的。

 

 

      對於線程A,系統讀到ACE 1就立即拒絕了訪問,因爲該線程訪問令牌中的用戶位於訪問拒絕ACE 1中。這種情況下系統不會檢查ACE 2和3。對於線程B,ACE 1沒有使用到,所以系統直接處理ACE 2, ACE 2允許寫訪問,而ACE 3允許讀和執行權限。

      因爲當請求的訪問明確地被允許或拒絕時,系統會停止審查ACE,所以DACL中的ACE的順序是很重要的。注意如果在例子中ACE的順序是不同的話,系統是可能會賦予線程A的訪問。對於系統對象,操作系統定義了優先選擇的DACL中的ACE順序

 

1.1.2.3 線程和安全對象之間的交互 Interaction between Threads and Securable Objects

      當一個線程嘗試訪問一個安全對象時,系統會在允許線程執行之前執行訪問審查操作。在訪問審查中,系統會對線程訪問令牌中的安全信息和該對象安全描述符中的安全信息作比較。

  • 訪問令牌包含一個安全描述符(SID),其定義了與線程相關的用戶。
  • 安全描述符定義了一個對象的擁有者,包含了一個用戶自定義訪問控制列表(DACL)。這個DACL包含了一組訪問控制項(ACEs)每一個ACE指定了允許或拒絕特定用戶或組的訪問權限。

      系統檢查對象的DACL,會搜索來自線程訪問令牌、同時又定義了用戶或組SID的ACE。系統會檢查每一個ACE,直到訪問被允許或拒絕,或者沒有ACE。不難想象,一個訪問列表ACL可以擁有多個用於訪問令牌SID的ACE。若此,每個ACE賦予的訪問權限就會累積。例如,如果一個ACE賦予了一個組的讀權限,同時另一個ACE賦予了該組中一個用戶以寫權限,那麼這個用戶可以同時擁有讀和寫對象的權限。

 

 

1.1.2.4 DACLs和ACEs DACLs and ACEs

      如果一個Windows對象沒有自定義訪問控制列表(DACL),系統就會賦予其全部訪問權。如果對象擁有一個DACL,系統僅在其DACL中的某個ACE明確允許該訪問時方可訪問。如果該DACL中沒有ACE,系統不允許訪問任何對象。類似地,如果一個DACL有一組ACE,允許一個受限的用戶和組,系統隱式地拒絕不在ACE中的所有受託者的訪問。

      大多數時候,你可以使用允許訪問ACE來控制對一個對象的訪問,你不需要明確地拒絕對某個對象的訪問。例外的情況是,當一個ACE允許一個組的訪問請求,但是你想要拒絕該組中的某個用戶。爲此,在該用戶的DACL中對這個組的所有允許訪問ACE之前放置一個訪問拒絕ACE。注意ACE的順序是很重要的,因爲系統會按序讀取ACE直到訪問被允許或被拒絕。用戶的訪問拒絕ACE必須出現在前面,否則,系統會讀到組的允許訪問ACE,這會賦予受限制的用戶的訪問權。

      下圖展示了一個DACL拒絕一個用戶的訪問,但是允許賦予另外兩個組訪問權。組A中的用戶通過累積被允許的組A的權限和所有用戶的權限而得到了讀、寫、執行訪問權限。例外是Andrew,他被訪問拒絕ACE拒絕,儘管他屬於所有用戶組的一員。

 

 

1.1.2.5 空的DACLs和DACLs爲空 Null DACLs and Empty DACLs

      如果一個對象的安全描述符的DACL被設置爲NULL,那麼一個null DACL就被創建了。一個null DACL賦予所有請求它的用戶以所有權限,普通的安全檢查就不會執行了。一個null DACL不能和一個空DACL混淆。一個空DACL是一個被正確地創建和初始化的DACL,它不包含ACE。一個空DACL不會賦予所屬對象任何權限。

      關於如何創建一個DACL的例子,參考創建DACL

 

1.1.2.6 允許匿名訪問 Allowing Anonymous Access

      默認的安全策略限制匿名本地訪問擁有任何權限。管理員可以根據情況添加或刪除權限。

      一個本地訪問組可以像所有用戶的訪問權限一樣。管理員可以適當地增減那個組的用戶數量,這個組名就是Pre-Windows 2000-Compatible Access Group。

      更多詳情,參考本地組函數主題表中函數參考頁。

 

1.1.3 安全描述符定義語言 Security Descriptor Definition Language 

      安全描述符定義語言(SDDL)定義了字符串格式,函數ConvertSecurityDescriptorToStringSecurityDescripto和ConvertStringSecurityDescriptor使用該格式來把一個安全描述符SID描述爲一個文本字符串。該字符串還定義了描述安全描述符中組成部分的信息的字符串元素。

      注意 有條件的ACE有不同的SDDL格式,這一點不同於其他ACE類型。對於ACE的詳情,參考ACE字符串。對於有條件的ACE,參考條件ACE的安全描述符定義語言。

 

相關主題

安全描述符字符串格式

條件ACE的安全描述符定義語言

ACE字符串

SID字符串

[MS-DTYP]:安全描述符定義語言

 

1.1.3.1 安全描述符字符格式 Security Descriptor String Format

      安全描述符字符串格式是安全描述符中存儲或交換信息的一種文本格式,函數ConvertSecurityDescriptorToStringSecurityDescripto和ConvertStringSecurityDescriptor使用了改格式。

      格式是帶有標識安全描述符四個主要組件的null終止字符串:擁有者(O:),主要用戶組(G:),DACL(D:),和SACL(S:)。

      注意:ACE和條件ACE有不同的格式,對於ACE的詳情,參考ACE字符串。對於有條件的ACE,參考條件ACE的安全描述符定義語言。

 

 

 

      owner_sid

            定義了對象的擁有者的SID字符串。

      group_sid

            定義了對象的主要用戶組的字符串

      dacl_flags

            DACL用到的安全描述符控制標記。關於這些控制標記的詳細介紹,請參考SetSecurityDescriptorControl函數。dacl_flags可以是下列字符串中的零個或多個級聯:

 

     
     
     
     
     

 

      sacl_flags

            SACL用到的安全描述符控制標記。sacl_flags字符串用到的控制位字符串和dacl_falgs相同。

      string_ace

            描述安全描述符中DACL和SACL的ACE的字符串。關於ACE字符串格式的詳情,請參考1.1.3.3 ACE字符串。每一個ACE字符串都用圓括號括起來了。

      不需要的部分可能會從安全描述符字符串中省略。例如SE_DACL_PRESENT標記不會設置到輸入安全描述符中,輸出字符串ConvertSecurityDescriptorToStringSecurityDescriptor不會包含D:部分。你仍然可以使用SECURITY_INFORMATION位標記來指示組成部分來包含一個安全描述符字符串。

      安全描述符字符串格式不支持NULL ACL。

      爲了表示空ACL,安全描述符字符串包含D:或者S:標記,但是沒有任何其他的字符串信息。

      安全描述符字符串會以不同的方式存儲SECURITY_DESCRIPTOR_CONTROL位。在字符串中SE_DACL_PRESENT和SE_SACL_PRESENT位使用D:和S:來標記。DACL和SACL中使用的其他位存儲在dacl_flags和sacl_flags中。SE_OWNER_DEFAULTED、SE_GROUP_DEFAULTED、SE_DACL_DEFAULTED和SE_SACL_DEFUALTED位不會在安全描述符中存儲。SE_SELF_RELATIVE位不會存儲在字符串中,但是ConvertStringSecurityDescriptorToSecurityDescriptor總是會設置到輸出安全描述符中。

      下面的例子展示了相關的安全描述符中安全描述符字符串和信息。

      字符串1:

 

      安全描述符1:

 

 

      字符串2:

 

 

      安全描述符2:

 

 

      相關主題

      1.1.3.3 ACE字符串

      1.1.3.2 條件ACE的安全描述符定義語言

 

1.1.3.2 條件ACE的安全描述定義語言 Security Descriptor Definition Language  for Conditional ACEs

      當執行訪問審查時條件訪問控制項(ACE)允許一個訪問條件執行計算。安全描述符定義語言SDDL提供了一種定義條件ACE的字符串語法。

      條件ACE的SDDL和所有ACE都一樣,只是語法上是在ACE字符串的末尾加上了條件聲明。更多關於SDDL信息參考安全描述符定義語言

      在資源屬性中“#”符號和“0”是同義詞。例如, D:AI(XA;OICI;FA;;;WD;(OctetStringType==#1#2#3##))等同於(並解釋爲)D:AI(XA;OICI;FA;;;WD;(OctetStringType==#01020300)).

  • 條件ACE字符串格式
  • 條件表達式
  • 屬性
  • 操作符
  • 操作符優先級
  • 未知數值
  • 條件ACE計算
  • 示例
  • 相關主題

      條件ACE字符串格式

      安全描述符中的每個ACE都用圓括號包圍起來。下面是按序排列,並用分號分割的ACE的域。

AceType;AceFlags;Rights;ObjectGuid;InheritObjectGuid;AccountSid;(ConditionalExpression)

      在ACE字符串中描述的域,有下面的例外。

  •       AceType域可以是下面字符串的其中之一:

 

     
     
     
  • ACE字符串包含一個或多個條件表達式,在每個字符串的結尾使用圓括號包圍起來。

      條件表達式

      一個條件表達式可以包含下列元素中的任何一個。

 

   
   
   
   
   
   
   
   

 

      屬性

      在客戶端上下文中,一個屬性表示AUTHZ_SECURITY_ATTRIBUTES_INFOMATION中的一個元素。一個屬性名可以包含任何字母數字和符號":", "/", ".", 和 "_"。

      一個屬性值可以由下列值:

 

   
   
   
   
   

 

      操作符

      下面定義的操作符是在條件表達式中測試屬性值的。所有這些都是二元操作符,並以AttributeName Operator Value的形式。

 

   
   
   
   
   
   
   
   
   

 

      另外,對於一元操作符,Member_Of、和取反操作符(!),正如條件表達式表中所描述的。

      “Contains”操作符必須執行並且後面跟一個空白符,“Any_of”操作符後面必須跟一個空白符。

      操作符優先級

      操作符按照下面的優先級順序,相同優先級的按照從左向右的順序進行計算。

  1. Exists, Member_of
  2. Contains, Any_of
  3. ==, !=, <, <=, >, >=
  4. !
  5. &&
  6. ||

      另外,一個條件表達式的任何部分都可以用圓括號包圍起來。帶圓括號的表達式首先計算。

      未知值

      有時候條件表達式的結果返回一個Unknown。例如,當指定的屬性不存在的時候,任何關係操作符都返回Unknown。

      下表中描述了兩個條件表達式之間進行邏輯與(AND)計算的結果,ConditionalExpression1 and ConditionalExpression2.

 

     
     
     
     
     
     
     
     
     
     

 

      下表中描述了兩個條件表達式進行邏輯或(OR)操作符計算的結果,ConditionalExpression1 orConditionalExpression2.

 

     
     
     
     
     
     
     
     
     
     

      

      Unknown條件表達式的否定操作還是Unknown。

 

      條件ACE計算

      下表描述了根據條件表達式最終計算結果的條件ACE結果的訪問審查。

 

       
       
       

 

      示例

      下面的例子顯示了使用SDDL定義的條件ACE如何代表指定的訪問策略。

      Policy

            如果滿足同時滿足以下條件,就允許Everyone執行。

      SDDL

            D:(XA; ;FX;;;S-1-1-0; (@User.Title=="PM" && (@User.Division=="Finance" || @User.Division ==" Sales")))

 

      Policy

            如果所有用戶的任務都和文件的任務相交的話,可以執行。

      SDDL

            D:(XA; ;FX;;;S-1-1-0; (@User.Project Any_of @Resource.Project))

 

      Policy

            如果用戶使用一個智能卡登陸那麼允許其讀訪問,這是一個備份操作,並且連接到一個啓用了Bitlocker的機器上。

      SDDL

            D:(XA; ;FR;;;S-1-1-0; (Member_of {SID(Smartcard_SID), SID(BO)} && @Device.Bitlocker))

      相關主題

      [MS-DTYP]: Security Descriptor Description Language

 

1.1.3.3 ACE字符串 ACE String

      安全描述符定義語言(SDDL)使用了安全描述符字符串的組成部分DACL和SACL中的ACE字符串。

      正如1.1.3.1 安全描述符字符串格式 中描述的那樣,每一個在安全描述符字符串中的ACE都用圓括號包圍起來。ACE的域按照下面的順序用分號分割的。

      注意:條件ACE和其他類型的ACE的格式是不同的。對於條件ACE請參考1.1.3.2 條件ACE的安全描述符定義語言。

 

      域

      ace_type

      一個字符串,描述ACE_HEADER成員AceType的值。ACE類型字符串可以是下面定義在sddl.h中的字符串之一。

 

     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     

 

      注意:如果一個ace_type是ACCESS_ALLOWED_OBJECT_ACE_TYPE,並且object_guid或inherit_object_guid指定了一個GUID,那麼函數ConvertStringSecurityDescriptorToSecurityDescriptor轉化ace_type爲ACCESS_ALLOWED_OBJECT_ACE_TYPE。

      ace_flags

      一個字符串,指定ACE_HEADER結構AceFlags成員的值。ACE標識字符串可以是下面定義在sddl.h中的字符串的級聯。

 

     
     
     
     
     
     
     
     

 

      rights

      一個字符串,指定由ACE控制的訪問權限。這個字符串可以是代表訪問權限的十六進制的字符串,比如“0x7800003F”,或者是下面字符串的組合。

 

 

     
 
     
     
     
     
 
     
     
     
     
 
     
     
     
     
     
     
     
     
     
 
     
     
     
     
 
     
     
     
     
 
     
     
     

 

      object_guid

      一個表示GUID的字符串,指定了特定對象的ACE結構的ObjectType成員的值,比如說ACCESS_ALLOWED_OBJECT_ACE。GUID字符串使用UuidToString函數返回的格式。

     下表列出了常用的對象GUID。

   
   
   

 

      inherit_object_guid

      一個標識GUID的字符串,指定了特定對象ACE結構的InheritedObjectType成員的值。這個GUID字符串使用UuidToString的格式。

      account_sid

      SID字符串代表了一個ACE的受託者。

      resource_attribute

      [可選的] resource_attribute僅針對資源ACE,並且是可選的。代表了數據類型資源屬性ACE數據類型可以是下面定義在sddl.h中的數據類型之一。

      在資源屬性中“#”跟“0”是同義詞。比如,D:AI(XA;OICI;FA;;;WD;(OctetStringType==#1#2#3##)) 等同於(並翻譯爲) D:AI(XA;OICI;FA;;;WD;(OctetStringType==#01020300)).

      Windows Server 2008 R2, Windows 7, Windows Server 2008, Windows Vista, and Windows Server 2003:  資源屬性是不可用的。

 

     
     
     
     
     
     
     

 

      下面的例子顯示了一個允許訪問ACE的ACE字符串,這不是一個特定對象的ACE,所以在object_guid和inherit_object_guid域中沒有信息。ace_flags域也是空的,這說明沒有設置任何ACE標記。

 

 

 

      上面的ACE字符串描述了下面的ACE信息。

 

 

 

      下面的例子演示了按照Windows和爲具有高度商業影響的帶保密SQL要求的資源劃分的文件。

 

 

 

      上面給出的ACE字符串描述了下面的ACE信息。

 

 

 

      更多信息,參考1.1.3.1 安全描述符字符串格式和SID字符串。對於條件ACE,參考1.1.3.2 條件ACE的安全描述符定義語言。

      相關主題

      [MS-DTYP]: Security Descriptor Description Language

 

1.1.3.4  SID字符串 SID String

      在1.1.3 安全描述符定義語言(SDDL)中,安全描述符字符串爲安全描述符的下列組成部分使用SID字符串。

  • 擁有者
  • 主要用戶組
  • ACE中的受託者

      安全描述符中的一個SID字符串可以使用標準字符串表示一個SID(S-R-I-S-S...),也可以使用定義在Sddl.h中的字符串常量。關於標準SID字符串符號的更多信息請參考,1.1.2.1.7.1 SID的結構。

      下列SID字符串常量是定義在sddl.h中的公開SID。關於對應相對IDs(RIDs)的更多信息,請參考公開SIDs。

      

     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     

 

      ConvertSidToStringSid和ConvertStringSidToSid函數通常只使用標準SID字符串符號,而不支持SDDL SID字符串常量。

      關於公開SID的更多信息,參考1.1.2.1.7.2 公開的SIDs。

 

1.1.4 特權 Privilege

      特權是一個賬戶的權限,比如一個用戶或組的賬號,可以在本地計算機上執行不同的系統相關的操作,比如說關閉系統,加載設備驅動,或者修改系統時間,特權會以兩種方式區分訪問權:

  • 特權控制對系統資源以及系統相關任務的訪問,而訪問權限控制對安全對象的控制訪問。
  • 一個系統管理員爲用戶和組賬戶賦予特權,而系統根據安全對象的DACL中ACE賦予的訪問權限,對該對象進行訪問權限的賦予或拒絕。

      每個系統都有一個賬號數據庫,存儲了用戶和組用戶擁有的特權,當一個用戶登錄的時候,系統生成一個訪問令牌,其中包含了一個用戶特權的列表,其中包含了用戶或用戶所屬組的特權。注意,特權僅僅用在本地計算機中,一個域賬號可以在不同的計算機中有不同的特權。

      當用戶嘗試執行一個特權操作的時候,系統檢查用戶的訪問令牌來確定用戶是否擁有必需的特權,如果有,將會檢查該特權是否處於開啓。如果這些測試失敗了,系統將不執行該操作。

      爲了得到訪問令牌中的特權,調用GetTokenInformation函數,同時也指出對應的特權將被開啓。大多數特權默認關閉。

      Windows API定義了一組字符串常量,比如SE_ASSIGNPRIARYTOKEN_NAME,用來區別不同的特權。這些常量在所有系統中都是一樣的,並且定義在winnt.h中。關於Windows定義的特權的列表,參考特權常量。得到和調整一個訪問令牌中的特權的函數使用LUID來區分特權。不同計算機,同一個計算機上的不同啓動的特權的LUID是不同的。使用LookupPrivilegeValue函數,要得到當前的LUID(與字符串常量之一相關聯)。使用LookupPrivilegeName函數把一個LUID轉化爲與之相關的字符常量。

      系統提供一組可顯示的字符串來描述每一個特權,這在你需要給用戶提供關於特權的描述的時候非常有用,使用LookupPrivilegeDisplayName函數返回一個關於特權的描述字符常量。例如,在英語操作系統上,顯示SE_SYSTEMTIME_NAME特權的名字就是“Change the system time”。

      你可以使用PrivilegeCheck函數來得到一個訪問令牌是否有一組指定的特權。這主要是對於模擬成一個客戶的服務應用程序非常有用。

      一個系統管理員可以使用管理工具,比如用戶管理,來添加、刪除用戶和組用戶的特權。管理員可以使用局部安全性權限(LSA)函數來操作特權。LsaAddAccountRightLsaRemoveAccountRight函數添加和刪除一個賬號的特權。LsaEnumerateAccountWithUserRight函數可以枚舉擁有特享特權的賬號。

      相關主題

      授權常量

      用C++打開和關閉特權

 

1.1.5 審查的生成 Audit Generation

      C2級別安全要求系統管理員必須可以審查系統相關的事件,並且對於審查數據的訪問僅限於授權管理員。Windows API提供用來監控安全相關的事件的函數。

      一個安全對象的安全描述符可以有一個系統訪問控制列表(SACL),一個SACL包含了一組訪問控制項(ACE),其指定了生成審查報告的訪問嘗試的類型。每一個ACE對應一個受託者,一個組訪問權限,和一組標記,這個標記指定系統是否要對失敗、成功,或者二者皆有的訪問嘗試生成審查消息。

      系統把審查消息寫到安全事件日記中,關於訪問安全事件日記中的記錄的信息,參考事件日誌

      爲了讀或寫一個對象的SACL,線程首先必須打開SE_SECURITY_NAME特權,更多信息參考1.1.2.1.5.4 SACL訪問權限。

      Windows API也提供了這樣的支持,當一個客戶端嘗試訪問一個私有對象,服務應用程序會生成審查事件。更多信息,參考1.3.6.3 審查對私有對象的訪問。

 

1.1.6 安全對象 Securable Objects

      安全對象是一個可以擁有安全描述符的對象。所有命名的Windows對象都是對象安全,一些未命名的對象,比如說進程和線程對象,也可以擁有安全描述符。對於大多數安全對象,你可以在創建這個對象的函數中指定一個對象的安全描述符。比如,你可以在CreateFile和CreateProcess函數中指定一個安全描述符。

      另外,Windows安全函數可以讓你得到和設置在操作系統上創建的安全對象的安全信息,且不止在Windows操作系統上。Windows安全函數也提供了對使用帶私有的、應用程序定義的對象的安全描述符的支持,更多關於私有安全對象的信息,參考1.3 客戶端/服務器訪問控制。

      每種類型的安全對象定義了它自己的特定的訪問權限,以及通用訪問權限的映射。關於各種類型安全對象的特定和通用訪問權限的信息,參考對應對象類型的總覽。

      下表展示了一些普通安全對象用於管理安全信息的函數。

   
   
   
   
   
   
   
   
   
   
   
   
   
   

 

1.1.7 低層訪問控制 Low-level Access Control 

      低層安全函數可以幫助你操作安全描述符、訪問控制列表(ACLs),和訪問控制項(ACEs)。

      關於這個模型的描述,參考訪問控制模型

 

   
   
   
   
   

 

1.1.7.1 低層安全描述符的函數 Low-level Security Descriptor Function

      有若干對低層函數來設置和返回對象的安全描述符。每對函數僅能操作一組有限的Windows對象。例如,一對操作文件對象,另一對操作註冊表鍵。下表列出了用於不同類型安全對象的低層函數。

 

   
   
   
   
   
   
   
   
   

 

1.1.7.2 低層安全描述符的創建 Low-level Security Descriptor Creation

      底層訪問控制提供了一組函數來創建安全描述符,並且可以設置和得到安全描述符組成部分。用於初始化和設置安全描述符組成部分的底層函數僅能操作絕對格式的安全描述符。獲取安全描述符組成部分的底層函數可以操作絕對和自相對格式的安全描述符InitializeSecurityDescriptor函數初始化一個SECURITY_DESCRIPTOR緩存。這個初始化了的安全描述符是絕對格式的,並且沒有擁有者,沒有主要用戶組,沒有用戶自定義訪問控制列表(DACL),沒有系統訪問控制列表(SACL)。你可以使用下面的函數來得到和設置指定安全描述符的指定組成部分。

 

   
   
   
   
   
   
   
   
   
   
   

 

      要檢查修訂層級和結構化一個安全描述符的整合度,調用IsValidSecurityDescriptor函數。

 

1.1.7.3 絕對的和自相相對的安全描述符 Absolute and self-Relative Security Descriptors

      安全描述符既可以用絕對格式,也可以用自相對格式。用絕對格式的話,一個安全描述符包含一個指向它的信息的指針,而不是包含它的信息。用自相對格式的話,一個安全描述符在一段連續內存中存儲一個SECURITY_DESCRIPTOR結構,以及相關的安全信息。要確定一個安全描述符是自相對的還是絕對的,可以調用函數GetSecurityDescriptor函數,並檢查SECURITY_DESCRIPTOR_CONTROL參數中的SE_SELF_RELATIVE標記。你還可以使用MakeSelfRelativeSD函數和MakeAbsoluteSD函數在這兩種格式之間進行轉換。

      當你要創建一個安全描述符,並且擁有其所有組件指針的時候,絕對格式是非常有用的,比如,擁有者、用戶組、和用戶自定義ACL默認是可用的。這種情況下,你可以調用InitializeSecurityDescriptor函數初始化一個SECURITY_DESCRIPTOR結構,並調用諸如SetSecurityDescriptorDacl之類的函數來爲安全描述符的ACL和SID指針賦值。

      使用自相對格式,一個安全描述符經常以一個SECURITY_DESCRIPTOR結構開始,但是其他安全描述符的組件可以按任何順序跟在這個結構之後。安全描述符的組件使用相對描述符開始的偏移來定位,而不是內存地址。當安全描述符必須存放在硬盤上,並且使用協議來交互,或者在內存中拷貝的時候,這種格式是非常有用的。

      除了MakeAbsoluteSD,所有返回安全描述符的函數都適用自相對格式。用作參數傳遞給函數的安全描述符既可以是絕對,也可以是自相對的。詳情請參考相應函數的說明。

 

1.1.7.4 低層ACL和ACE函數 Low-level ACL and ACE Functions

      要創建一個訪問控制列表(ACL),可以使用底層函數,爲ACL申請內存,然後使用InitializeAcl函數初始化之。要添加訪問控制項(ACE)到用戶自定義訪問控制列表(DACL)的末尾,可以使用AddAccessAllowedAce和AddAccessDeniedAce函數。AddAuditAccessAce函數在系統訪問控制列表(SACL)末尾添加一個ACE。AddAce函數允許你添加一個可繼承的ACE到ACL中。DeleteAce函數從指定的ACL中移除一個ACE。GetAce函數從一個ACL中指定位置上得到一個ACE。FindFirstFreeAce函數返回一個ACL中第一個未使用字節的指針。

      要修改一個對象的安全描述符中已存在的ACL,可以使用GetSecurityDescriptorDacl或者GetSecurityDescriptorSacl函數得到這個已存在的ACL。你可以使用GetAce函數從一個ACL中拷貝ACE。申請並初始化一個新的ACL之後,使用諸如AddAccessAllowedAce和AddAce函數添加ACE。當你完成創建一個新的ACL之後,使用SetSecurityDescriptorDacl和SetSecurityDescriptorSacl函數來添加新的ACL到對象的安全描述符中。

      你可以使用AddAccessAllowedObjectAce,AddAccessDeniedObjectAce,或者AdAuditAccessObjectAce函數把一個指定對象的ACE添加到一個ACL末尾。

 

1.2 訪問控制編輯器 Access Control Editor

      訪問控制編輯器是一組屬性表(Sheet)和屬性頁(page),它允許用戶查看和修改對象安全描述符的組成部分。編輯器由兩個主要部分組成:

  • 一個基本安全屬性頁,提供了一個簡單的接口來編輯一個對象的自定義訪問控制列表(DACL)中的訪問控制項(ACE)。這頁能包含一個展示高級安全屬性頁的可選的高級按鈕。
  • 一個帶有屬性頁的高級安全屬性,可以讓用戶編輯對象的系統訪問控制列表(DACL),修改對象的擁有者,執行對象DACL的高級編輯。

      CreateSecurityPage函數創建基本安全屬性頁。你可以使用PropertySheet函數或者PSM_MESSAGE消息添加這個屬性頁到一個屬性表。

      另外,你可以使用EditSecurity函數來顯示一個包含基本安全屬性頁的屬性表。

      對於CreateSecurityPage和EditSecurity,調用者必須傳遞一個ISecurityInformation的實現的指針。訪問控制編輯器調用這個接口的方法來返回被編輯的對象的訪問控制信息,並把用戶的輸入傳遞返回給你的應用程序。ISecurityInformation有一下目的:

  • 初始化屬性頁。

      你實現的GetobjectInformation方法傳遞一個SI_OBJECT_INFO結構給編輯器。這個結構指定了你想要編輯器顯示的屬性頁。以及其他一些判斷是否對用戶可用的編輯選項。

  • 提供被編輯對象的安全信息。

      你對GetSecurity的實現會傳遞對象的初始安全描述符給編輯器。GetAccessRights和MapGeneric方法提供了對象訪問權限的信息。GetInheritTypes方法提供了對象的ACE如何被子對象繼承的信息。

  • 給你的應用程序傳遞用戶的輸入。

      當用戶點擊Okay或者Cancel的時候,編輯器調用你的SetSecurity方法來傳遞迴一個包含用戶改變的安全描述符。

 

1.2.1 基本安全屬性頁 Basic Security Property Page

      基本安全屬性頁是由EditSecurity函數展示的第一個屬性頁。你也可以通過CreateSecurityPage函數創建一個基本屬性頁來插入到你自己的屬性表。

      屬性頁展示了在對象自定義訪問控制列表(DACL)中一個命名的訪問控制項(ACE)的受託者列表。這個頁面也包含一個由對象支持的訪問權限列表。當用戶從受託者中選中一個名字之後,每個訪問權限旁邊的複選框表示的是該權限對於受託者而言是允許還是拒絕。用戶可以選擇或者清空複選框來修改受託者的訪問權限。用戶也可以從列表中添加或刪除受託者。

      基本安全屬性頁不能顯示覆雜的ACE,比如對象專屬的ACE,或者ACE繼承信息。要讓用戶查看或者編輯此類信息,你需要在基本安全頁包含一個高級按鈕。用戶可以點擊高級按鈕顯示一個高級安全屬性表。這個屬性表中的屬性頁允許用戶編輯對象的系統訪問列表(SACL),改變對象的擁有者,執行對象的DACL的高級編輯。要顯示該高級按鈕,就要在你的ISecurityInformation::GetObjectInformation實現返回的SI_OBJECT_INFO結構中的設置SI_ADVANCED標誌。

      你可以使用SI_OBJECT_INFO結構的pszPageTitle成員指定基本安全屬性頁的標題,默認的標題是安全。

 

1.2.2 高級安全屬性頁 Advanced Security Property Sheet

      高級安全屬性表允許用戶對一個訪問控制編輯器執行在基本安全屬性頁中沒有的編輯操作。屬性表可以包含下面的屬性頁:

  • 權限屬性頁,可以對對象的自定義訪問控制列表(DACL)進行高級編輯,比如編輯對象專屬的ACE或者控制ACE的繼承。
  • 審覈屬性頁,查看和編輯對象的系統系統訪問控制列表(SACL)。
  • 擁有者屬性頁,修改對象的擁有者。

      用戶可以點擊基本安全屬性頁中的高級按鈕顯示高級安全屬性。要顯示高級按鈕,就要在你的ISecurityInformation::GetObjectInformation實現返回的SI_OBJECT_INFO結構中的設置SI_ADVANCED標誌。

 

1.2.3 許可屬性頁 Permission Property Page

      權限屬性頁包含對一個對象的DACL的高級編輯控制項。這頁允許用戶查看和編輯DACL中的所有信息,包括基本安全屬性頁中不可用的信息。高級信息包括對象專屬ACE和ACE繼承性的信息。

      當用戶點擊基本安全屬性頁中的高級按鈕時,權限屬性頁通常包含在高級安全屬性表中,

 

1.2.4 審查屬性頁 Audit Property Page

      訪問控制編輯器可以包含一個審覈屬性頁,允許用戶查看和編輯對象的系統訪問控制列表(SACL)中的訪問控制項(ACE)。更多關於SACL的信息,參考 1.1.2.1.3訪問控制列表(ACL)。

  • 在基本安全屬性頁中,點擊高級按鈕,審覈屬性頁就在高級安全屬性表中。

      要包含審覈屬性頁,就要在你的ISecurityInformation::GetObjectInformation實現返回的SI_OBJECT_INFO結構中的設置SI_ADVANCED和SI_EDIT_AUDITS標誌。

 

1.2.5 擁有者屬性頁 Owner Property Page

      訪問控制編輯器可以包含一個擁有者屬性頁,允許用戶修改一個對象的擁有者。更多關於對象的擁有者的信息,參考 1.1.2.1.2.2.3 新對象的擁有者和 2.4.8 使用C++獲取對象的擁有者。

      當用戶點擊基本安全屬性頁中的高級按鈕時,高級安全屬性表中的擁有者屬性頁就會顯示。要包含擁有者屬性頁,就要在你的ISecurityInformation::GetObjectInformation實現返回的SI_OBJECT_INFO結構中的設置SI_ADVANCED和SI_EDIT_OWNER標誌。

 

1.3 C/S訪問控制 Client/Server Access Control

      服務程序爲客戶端提供服務,比如一個服務可能代表一個客戶端執行下面的服務:

  • 在一個私有數據庫中保存和返回數據。
  • 訪問網絡資源
  • 在服務器計算機的客戶端安全上下文中開啓進程

      受保護的服務控制者對其服務的訪問,Windows提供了讓一個服務做以下服務的安全支持。

  • 實現一個客戶端安全上下文,這使得系統可以根據客戶端的訪問令牌而不是服務器的訪問令牌來執行大多數訪問和特權檢查。
  • 把一個客戶端登陸到服務器計算機上
  • 使用客戶端安全上下文連接網絡資源
  • 創建一個安全描述符來保護私有對象
  • 確定一個安全描述符是否允許訪問一個客戶端
  • 確定一個客戶端的訪問令牌中的一組特權是否被激活
  • 在安全事件日誌中生成審覈消息,記錄客戶端訪問對象的嘗試,或者使用的特權。

 

1.3.1 客戶端安全上下文 The Client Security Context

      跟所有進程類似,一個受保護的服務有一個描述其安全上下文的主要訪問令牌。當一個客戶端連接到受保護服務的時候,服務可能想要使用客戶端的安全上下文而不是服務的。比如一個動態數據交換(DDE)從一個DDE服務轉換請求的信息,服務需要確定客戶端是被允許訪問這個信息的。

      一個服務可以根據客戶端的安全上下文用兩種方式進行模擬:

  • 服務進程的一個線程可以模擬客戶端。在這種情況下,服務的線程有一個模擬訪問令牌來標識客戶端、客戶端的組和客戶端的特權。更多信息參考 1.3.2 客戶端模擬。
  • 服務可以獲得客戶端的證書,並把客戶端登陸到服務所在的計算機上。這會創建一個新的登錄會話,併爲客戶端生成一個主要訪問令牌。然後服務可以使用客戶端的訪問令牌來模擬客戶端,開啓一個新進程,並使用客戶端的安全上下文。更多信息參考 1.3.3 客戶端登錄會話。

      大多數情況下,模擬客戶端是足夠的。模擬動作可以讓服務檢查客戶端對安全對象的訪問,檢查客戶端的特權,並生成審覈足跡項來標識客戶端。一般地,一個服務僅在它需要使用客戶端的安全上下文訪問網絡的時候才需要開啓一個客戶端登錄會話。

 

1.3.2 客戶端模擬 Client Impersonation

      模擬是一個線程使用不同的安全信息運行的一種能力,而非使用線程所屬進程的安全信息。一般地,一個服務應用中的線程模擬一個客戶端。這使得服務線程代表客戶端訪問服務中的對象,或者驗證客戶端的擁有對象的訪問。

      微軟的Windows API提供了一下函數來開始一個模擬操作:

  • 一個動態數據交換(DDE)服務應用可以調用DdeImpersionateClient函數來模擬一個客戶端。
  • 一個命名管道服務可以調用ImpersonateNamedPipeClient函數。
  • 你可以調用ImpersonateLoggedOnUser函數來模擬一個登錄用戶的訪問令牌的安全上下文。
  • ImpersonateSelf函數允許一個線程生成自身訪問令牌的一個拷貝。當一個應用需要修改一個單線程的安全上下文的時候是非常有用的。比如,有時候進程中僅有一個線程需要擁有一個特權。
  • 你可以使用SetThreadToken函數在指定的模擬令牌安全上下文中啓動目標線程。
  • 一個微軟遠程過程調用(RPC)服務應用可以調用RpcImpersonateClient函數來模擬一個客戶端。
  • 一個安全包或者應用服務可以調用ImpersonateSecurityContent函數來模擬一個客戶端

      對於大多數模擬,模擬線程可以通過調用RevertToSelf函數來反轉自己的安全上下文。例外是RPC的模擬,這種情況下RPC應用調用RpcRevertToSelf或者RpcRevertToSelfEx函數來反轉它自己的安全上下文。

 

1.3.2.1 模擬級別 Impersonation Levels

      枚舉類型SECURITY_IMPERSONATION_LEVEL定義了四個模擬級別,這些級別決定了一個服務可以在客戶端上做的操作。

 

   
   
   
   
   

 

      命名管道、RPC、或者DDE連接上下文可以控制模擬級別。例如,一個命名管道客戶端可以調用CreateFile函數來打開一個命名管道的句柄,並制定服務的模擬級別。

      當命名管道、RPC、或者DDE連接是遠程的傳遞給CreateFile設置模擬級別的標記將會被忽略。這種情況下,客戶端的模擬級別由服務激活的模擬級別決定,而這個級別由目錄服務上的服務賬號設置。例如,服務是爲代理激活的,即便傳遞給CreateFile的標記指定了模擬級別身份,客戶端的模擬級別也會被設置爲代理。

      DDE客戶端使用DdeSetQualityOfService函數,並用SECURITY_QUALITY_OF_SERVICE結構指定模擬級別。命名管道、RPC、和DDE服務的默認級別是SecurityImpersonation。ImpersonnateSelfDuplicateTokenDuplicateTokenEx函數允許調用者指定模擬級別。使用GetTokenInformation函數來獲得訪問令牌的模擬級別。

      在SecurityImpersonation級別上,多數線程的動作發生在線程的模擬令牌的安全上下文中,而不是線程所在進程的主要令牌中。例如,如果一個模擬線程打開了一個安全對象,系統使用模擬令牌來檢查線程的訪問。同樣地,如果一個模擬線程創建了一個新對象,比如說,用CreateFile函數,這個新對象的擁有者就是客戶端的訪問令牌的默認擁有者。

      然而,在以下情形中,系統使用進程的主要令牌而不是調用線程的模擬令牌:

  • 如果一個模擬線程調用CreateProcess函數,新的進程常常繼承了進程的主要令牌。
  • 對於需要SE_TCB_NAME特權的函數,比如LogonUser函數,系統總是檢查進程的主要令牌。
  • 對於需要SE_AUDIT_NAME特權的函數,比如ObjectOpenAuditAlarm函數,系統總是檢查進程主要令牌的特權。
  • 調用OpenThreadToken時,線程可以指定是使用模擬令牌還是主要令牌從而決定是否授予請求 的訪問。

 

1.3.2.2 模擬令牌 Impersonation Token

      一個模擬令牌有兩訪問令牌:

  • 一個主要訪問令牌,描述了服務的安全上下文。要得到這個令牌的句柄,調用OpenProcessToken函數。
  • 一個模擬訪問令牌,描述了要模擬的客戶端的安全上下文。要得到這個令牌的句柄,調用OpenThreadToken函數。

      一個服務在以前情形中可以使用模擬令牌:

  • 用函數AccessCheck、AccessCheckByByte和AccessCheckByTypeResultList判斷一個安全上下文是否允許客戶端一組訪問權利時。
  • 用函數AdjustTokenPrivilege激活或禁用客戶端的特權時。
  • 用PrivilegeCheck函數確定一組特權是否在客戶端令牌中激活時。
  • 用生成安全事件日誌中的項的函數,比如ObjectOpenAuditAlarm或PrivilegeServiceAuditAlarm。這些函數使用模擬令牌來得到關於客戶端的日誌項的信息。

 

1.3.3 客戶端登陸會話 Client Logon Sessions

      帶有SE_TCB_NAME特權的服務,比如一個運行在本地系統賬號上的Windows服務,可以調用LogonUser函數向一個運行服務的計算機授權。LogonUser函數啓動一個新會話,並返回一個包含了客戶端安全信息的主要訪問令牌。你可以在ImpersonateLoggedOnUser函數中使用這個主要訪問令牌來模擬客戶端,或者調用CreateProcessAsUser函數來創建一個運行在客戶端的安全上下文中的進程。

 

      以這種方式授權客戶端的優點是,服務模擬授權客戶端,或者模擬在授權客戶端中創建的一個進程,可以以客戶端身份連接遠程網絡資源。如果這個授權不能執行,服務僅當獲得客戶端傳遞給WNetAddConnection2函數的賬戶名和密碼才能連接網絡資源。

      以這種方式授權客戶端的缺點是,服務必須得到客戶端的憑證(域名,用戶名,和密碼)。如果一個遠程客戶端爲服務器提供這些的憑證,那麼客戶端和服務就有責任保證這些憑證以一種安全的方式傳輸。

 

1.3.4 客戶端安全上下文中的進程 Processes in the Client Security Context

      服務應用可以調用CreateProcessAsUser函數來創建一個在用戶端上下文中運行的新進程。調用時使用客戶端的訪問令牌,CreateProcessAsUser要求SE_ASSIGNPRIMARYTOKEN_NAME和SE_INCREASE_QUOTA_NAME特權,這些特權由在本地系統賬戶中運行的Windows服務管理着。

      CreateProcessAsUser函數同樣需要一個主要訪問令牌。一個服務可以通過爲客戶端啓動一個登錄會話、或者模擬一個客戶端並複製模擬訪問令牌來得到客戶端的主要訪問令牌。

      下面的過程描述了創建一個客戶端進程的兩種方法:

      通過登錄到客戶端創建一個客戶端進程

  1. 在對LogonUser的調用中使用客戶端的證書把客戶端登錄到本地系統。LogonUser爲客戶端的登錄會話產生一個主要訪問令牌。
  2. 如果服務需要使用客戶端的安全上下文,就需要通過使用主要訪問令牌調用ImpersonateLogonedOnUser函數來得到客戶端進程的可執行文件的訪問權。
  3. 調用CreateProcessAsUser時使用主要訪問令牌在客戶端上下文中創建一個進程。

      注意 使用下述技術創建的進程可能不能訪問網絡資源,除非它有客戶端的證書。

      通過模擬客戶端創建客戶端進程

  1. 通過使用模擬函數開始一個模擬操作,比如ImpersonateNamedPipeClient。
  2. 調用OpenThreadToken函數來得到一個含有客戶端安全上下文的模擬訪問令牌。
  3. 調用DuplicateTokenEx函數來把模擬訪問令牌轉換爲主要訪問令牌。
  4. 在CreateProcessAsUser中使用主要訪問令牌在一個客戶端安全上下文中創建一個進程。

      默認情況下,CreateProcessAsUser在一個非交互的工作站或桌面上創建一個客戶端進程。要創建一個交互程序,服務必須首先要設置交互工作站或桌面的用戶自定義訪問列表(DACL),以保證客戶端可以訪問這些資源。較好的辦法是讓登錄客戶端,得到客戶端的登錄會話的安全身份(SID),然後在交互式Windows工作站和桌面上允許訪問的ACE中使用這個SID。服務可以調用CreateProcessAsUser,指定默認的交互Windows工作站和桌面。關於這個過程的示例,參考使用C++開啓一個交互客戶端進程

 

1.3.5 客戶端訪問網絡資源 Client Access to Network Resources

      服務可以使用下面的策略訪問網絡資源:

  • 如果服務有客戶端的賬戶名和密碼,服務可以使用客戶端的證書調用函數WNetAddConnection2來映射本地驅動字母到網絡共享。
  • 在使用客戶端證書調用LogonUser之後,服務可以調用CreateProcessAsUser函數來爲客戶端創建一個進程。這個新的客戶端進程可以使用客戶端的安全上下文來訪問網絡資源。例如,這個進程可以調用CreateFile函數打開一個遠程電腦的文件。系統使用客戶端的主要訪問令牌來檢查客戶端進程的訪問嘗試。
  • 服務可以使用一個空的證書調用WNetAddConnection2,來建立一個到帶服務訪問網絡資源的連接或者默認連接。如果服務作爲本地系統賬戶運行,它會授權給域服務安全上下文下的網絡資源。如果服務在服務賬戶下運行,那麼服務就會授權爲這個賬戶。更多信息參考本地系統賬戶。

      關於保護密碼的更多信息,參考管理密碼。關於獲得證書的更多信息,參考請求用戶證書

 

1.3.6 基於ACL的訪問控制  ACL-based Access Control

      正如系統使用安全描述符來控制對安全對象的控制一樣,一個服務可以使用安全描述符來控制對它的私有對象的訪問。關於Windows安全模型的更多信息,參考訪問 1.1.2控制模型。

      一個受保護的服務可以使用一個指定了各種受託者可訪問類型的DACL創建一個安全描述符。在一個簡單案例中,服務可以創建一個單安全描述符來控制對服務的數據和功能的訪問。想要一個更好粒度的保護,服務可以爲它的每一個私有對象、或者不同的功能創建安全描述符,

      例如,當一個客戶端請求服務在數據庫中創建一個新對象,服務可以爲這個新對象創建一個新的安全描述符。之後,服務可以把這個安全描述符和私有對象一起存儲在數據庫中。當一個客戶端嘗試訪問這個對象時,服務返回這個安全描述符來檢查這個客戶端的訪問權。這裏要注意,這個安全描述符中沒有任何與受保護的對象或功能相關的東西。取而代之的是,這取決於受保護服務如何維護這些相關項。

      訪問這些私有對象,也可以被審查。參考 1.3.6.3 審查私有對象的訪問 得到更多描述。

 

1.3.6.1 私有對象的安全訪問描述符 Security Descriptors for Private Objects

      要創建安全描述符,受保護服務可以使用和應用程序爲安全對象創建安全描述符相同的流程。示例代碼,參考 2.4.4.2 用C++爲一個新對象創建安全描述符。另外,一個受保護服務應用可以調用BuildSecurityDescriptor函數來完成這個工作。如果爲BuildSecurityDescriptor提供一個指向一個存在的自相關安全描述符的指針,函數會使用這個安全描述符的信息創建一個新的安全描述符,這時候的安全描述符信息合併了函數調用時傳遞給參數的控制信息。擁有者和組由傳遞給函數的TRUSTEE結構指定,這個是可選的。由BuildSecurityDescriptor創建的安全描述符是自相關格式的。

      另外,Windows API提供了一組函數用於合併客戶端安全信息和繼承自父對象或者一個默認安全描述符的信息。CreatePrivateObjectSecurityGetPrivateObjectSecuritySetPrivateObjectSecurityDestroyPrivateObjectSecurity函數提供了從一個訪問令牌中獲取默認信息的能力,支持繼承、和管理安全描述符中的特定部分。這當客戶端在安全對象架構中創建一個私有對象的時候是很有用的。比如,你可以使用CreatePrivateObjectSecurity函數創建一個安全描述符,讓它包含由客戶端指定的ACE,從父對象繼承的ACE,來自創建客戶端訪問令牌的默認擁有者。當BuildSecurityDescriptor創建安全描述符時使用的訪問控制信息,或者來自傳遞到函數調用的訪問控制信息,或者來自一個已存在的安全描述符,CreatePrivateObjectSecurity創建一個安全描述符僅僅來自一個已存在的安全描述符中的信息。

      LookupSecurityDescriptorParts函數獲得安全描述符信息來自一個已存在的自相關安全描述符。這個信息包括指定的擁有者和組,SACL或DACL中ACE的數量,以及SACL或DACL中的列表。

 

1.3.6.2 檢查私有對象的訪問 Checking Access to Private Objects

      受保護服務應用必須在允許客戶端訪問受保護私有對象之前檢查一個客戶端的訪問權限。爲此,服務要傳遞一個模擬訪問令牌,一個安全描述符,和一組AccessCheck要求的訪問權限。安全描述符的DACL中的ACEs指定了對於不同受託者允許訪問或者拒絕訪問。函數AccessCheck對比ACE中的每個受託者和定義在模擬訪問令牌中的受託者。關於賦予和拒絕訪問的算法描述,參考 1.1.2.2 訪問檢查是如何工作的

      AccessCheckAndAuditAlarm函數執行一個類似的訪問檢查。另外,它還根據安全描述符中的SACL在安全事件日誌中生成一個審查記錄。

      函數AccessCheckByTypeAccessCheckByTypeAndAuditAlarmAccessCheckAccessCheckAndAuditAlarm,除了還允許你檢查對一個對象的子對象的訪問,比如屬性子集或者是屬性。AccessCheckByTypeResultListAccessCheckByTypeResultListAndAuditAlarm函數同AccessCheck類似,除了它們按照對象的屬性和屬性集合層次爲每個子對象提供一個訪問檢查結果。這些函數使用OBJECT_TYPE_LIST結構來描述對象的訪問檢查的層次結構。生成審查消息的函數使用AUDIT_EVENT_TYPE枚舉類型來指示正在審查的這個對象是否是一個目錄服務對象。關於對象和它的子對象的層次的信息,參考 1.1.2.1.4.7 對象屬性控制訪問的ACEs

      傳遞給AccessCheck和AccessCheckAndAuditAlarm函數要求的訪問權限一定不能包含任何通用訪問權限。服務能夠使用MapGenericMask函數根據GENRIC_MAPPING結構體中指定的映射把任何通用訪問權限轉化到對應的特定的和標準的權限。

      AreAllAccessesGrantedAreAnyAccessesGranted函數會比較請求的訪問掩碼和授權的訪問掩碼。

      使用AccessCheck函數的代碼示例,參考 2.4.6 用C++區分帶ACLs的客戶訪問。

      ConvertToAutoInheritPrivateObjectSecurity函數會以允許自動傳播可繼承的ACEs的形式創建並返回一個安全描述符。這個安全描述符以自相關的形式包含所有的ACE,包括已繼承的和不可繼承。ConvertToAutoInheritPrivateObjectSecurity函數通過對比當前安全描述符中的所有ACEs和它的父安全描述符中的所有ACEs來決定某個ACE是可繼承的還是不可繼承的。在兩組ACEs之間不一定是一對一的相關。比如,一個允許讀/寫許可的ACE可以等於兩個ACE:一個允許讀的ACE,和一個允許寫的ACE。一個父安全描述符。如果當前的安全描述符就是父安全描述符的話,那麼它可能就沒有父安全描述符。

 

1.3.6.3 審查私有對象的訪問 Auditing Access to Private Objects

      一個受保護的服務可以通過下列函數在安全事件日誌中生成審查報告。

 

   
   
   
   
   
   
   
   
   
   

 

1.4 應用程序資源訪問控制 Access Control for Application Resources

      授權管理API和Windows Server 2003中可用的的MMC管理單元提供了帶有一個靈活的、基於角色的控制框架的程序。這個框架包含一組對於web和商業應用程序線而言是可剝離的COM對象。

      下面的兩個章節提供了關於控制訪問應用程序資源的信息。

 

1.4.1 基於角色的訪問控制 Role-based Access Control

      授權管理API和MMC管理單元提供一個基於角色的訪問控制框架的應用程序。授權管理API,也被稱爲AzMan,提供了一個簡化了的開發模型,該模型管理靈活的組和商業規則,並存放授權策略。詳情參考下面的話題:

      Windows XP:授權管理API和MMC管理單元可以從http://www.microsoft.com/downloads下載。這個鏈接下載提供授權管理策略管理和開發:不支持使用了授權管理控制訪問的應用程序的部署。

      相關主題

授權接口

授權對象

使用C++授權

使用腳本授權

 

1.4.1.1 基於角色訪問的優勢 Advantage of Role-based Authorization

      授權管理API提供一個授權模型,該模型在底層(基於ACL)授權上有很多優勢:

  • 簡化訪問控制管理
  • 使授權對於腳本和使用Microsoft Visual Basic開發系統開發的應用是可用的
  • 提供一個機制,當檢查訪問的時候應商業邏輯

 

1.4.1.2 授權管理模型 Authorization Manager Model

      授權管理提供一個靈活的框架,爲了整合基於模型訪問控制到應用程序。它可以讓使用那些應用程序的管理員通過賦予用戶與任務功能相關的角色來提供訪問。

      授權管理應用以存儲在活動目錄或XML文件和授權貯存格式存儲授權策略,並在運行時應用授權。

      應用程序然後調用一個運行時訪問檢查方法,該方法根據授權貯存中的策略信息檢查訪問。

      授權策略包含下列部分:

  • 策略存儲,應用程序,和範圍
  • 用戶和組
  • 操作和任務
  • 角色
  • 商業規則
  • 集合

 

1.4.1.2.1 策略存儲、應用程序、和範圍 Policy Stores、Applications、and Scopes

      授權策略的存儲,應用程序和範圍代表了授權管理策略的不同組織層次。一個策略的存儲可以包含一個或多個應用程序,一個應用程序可以包含一個或多個範圍。

授權策略存儲

      在授權管理API中,一個授權策略用一個IAzAuthorizationStroe對象表示。授權策略存儲包含應用程序、範圍、操作、任務、角色、和用戶組的定義和賦值。

      一個授權策略存儲可以存儲在XML文件或者活動目錄中。

      一個應用程序在修改存儲的信息、或者使用儲存策略檢查客戶端對資源的訪問前,必須初始化一個授權策略存儲。

      一個授權策略可以包含一個或多個IAzApplication對象,這些對象代表了指定應用的授權策略。

應用程序

      在授權管理API中,一個應用程序使用一個IAzApplication對象來表示。一個授權策略存儲可以包含多個應用程序的授權策略信息。使用IAzApplication對象可以讓你用一種策略存儲來爲不同的應用程序存儲不同的授權策略。

      一個授權策略存儲必須包含至少一個應用程序。

範圍

      在授權管理API中,一個範圍使用一個IAzScope對象表示。範圍爲授權策略提供了附加的、可選管理層次。一個應用程序可以包含一個或多個範圍,但不必包含任何(授權管理提供一個默認的、應用程序級別範圍)。

      範圍是一個程序內的細分,而這個程序是區分其他程序使用的資源的。如果你有授權管理組,角色定義,或者你不想應用到某個應用程序的任務定義,你可以在範圍這一級別創建它們。

託管

      存儲在活動目錄的授權策略貯存支持管理託管。可以託管這個管理到這個貯存、應用程序、或者範圍級別中的用戶和組。每一層級都爲這個層級的策略定義了管理角色。要給某個用戶或組託管控制,可以賦予他們管理員角色;要允許用戶或組讀取策略,可以賦予他們讀者角色。

      一個貯存、應用程序、範圍的管理員可以讀取和修改那個託管層級的策略存儲。讀者可以在託管層級讀取這個策略存儲,但是不能修改存儲。

相關主題

2.4.1.1 用C++創建授權策略存儲對象

2.4.1.2 用C++創建應用程序對象

2.3 用C++託管許可的定義

 

1.4.1.2.2 用戶和組 Users and Groups

      在授權管理中,授權策略的接受者用下面的組表示:

  • Windows用戶和組

      這些組包含用戶,計算機,和滿足安全原則的內置組。

  • LDAP查詢組

      這些用戶組中的成員根據輕量目錄訪問協議(LDAP)查詢需求動態計算得到。一個LDAP查詢組是一種應用程序組。

  • 基本應用程序組

      這些組由LDAP查詢組、Windows用戶和組、和其他基本應用程序組構成。

Windows用戶和組

      這些組類似於Windows操作系統中的用戶和組。

LDACP查詢組

      在授權管理中,你可以使用LDAP查詢來匹配用戶的屬性和那些活動目錄中用戶的對象。

      比如,下面的查詢會找到所有用戶,但是除了Andy。

 

      下面的查詢會找到所有www.fabrikam.com的成員。

 
  • 基本應用程序組

      在授權管理API中,一個應用程序組使用IAzApplicationGroup對象來表示。一個基本應用程序組是應用程序組類型的。

      要定義基本應用程序組成員,要定義誰是成員,誰不是成員。這兩步都以同樣的方式執行。在指定零個或多個Windows用戶和組之前,要先定義基本應用程序組,或者LDAP查詢組。這個基本應用程序組的成員會在移除該組任何非成員的時候計算。授權管理會在運行時自動計算。

      基本應用程序組中的非成員會優先於成員執行。

      閉環成員關係定義是非法的,這回導致以下錯誤信息:“不能添加組名。發生下面的問題:檢測到一個循環。”

相關主題

2.4.1.6 用C++定義用戶組

 

1.4.1.2.3 操作和任務 Operations and Tasks

      一個操作是一個底層的動作。在授權管理API中,一個操作用一個IAzOperation對象來表示。一般來說,操作由於過於繁多並且過於底層,對於管理是不方便的。任務相關的組操作可以簡化授權策略管理。

      一個任務使用一個IAzTask對象表示,可以包含一個或多個IAzOperation對象。一個IAzTask對象可以包含其他的IAzTask對象,以便任務可以嵌套。爲了簡化管理,一個IAzTask對象應該代表一個用戶真的想要執行的任務。

      訪問一個任務包含的操作可以在運行時通過一個與代表這個任務的IAzTask對象相關的商業規則腳本來進行授權。關於商業規則腳本,詳情參考商業規則

      通過設置IsRoleDefinition爲TRUE,一個IAzTask對象也可以代表一個角色定義。授權管理MMC管理單元用戶接口然後展示IAzTask對象爲一個角色。更多關於角色的信息參考角色

相關主題

2.4.1.3 用C++定義操作

2.4.1.4 用C++把操作打包到任務中

2.4.1.5 用C++把任務打包到角色中

1.4.1.2.2 用戶和組

 

1.4.1.2.4 角色 Roles

      在授權管理中角色服務於兩種目的。一個角色是某種分類用戶請求訪問的一組任務或操作,同時也是符合這種分類的一組用戶和組。

作爲任務組集合的角色

      一個授權策略把一個IAzTask對象賦值給一個IAzRole對象,來創建任務組。所有用戶和組賦值到那個IAzRole對象之後,就可以房屋內由那些IAzTask對象包含的所有操作。

      因爲一個IAzRole對象代表一組任務和可以訪問那些任務的一組用戶和組。授權管理提供了一種方法來創建可以賦值給多於一個IAzRole對象的角色定義。一個IAzTask對象可以包含其他IAzTask對象。你可以使用這個IAzTask對象作爲一個角色定義賦值給一個或多個IAzRole對象。設置IAzTask對象的IsRoleDefinition屬性爲TRUE使授權管理MMC管理單元用戶接口顯示IAzTask爲一個角色。

所謂用戶和組集合的角色

      調用AddMember和AddMemberName方法,爲用戶和組賦予IAzRole對象來授權,使得這些用戶和組可以訪問賦值給IAzRole對象的任務。調用AddAppMember方法,可以爲由IAzApplicationGroup對象代表的已有應用程序組賦值。所有賦予IAzRole的用戶和組可以訪問賦予那個角色的任務和操作。關於應用程序組的更多信息參考1.4.1.2.2 用戶和組。

相關主題

2.4.1.5 用C++把任務打包到角色

2.4.1.6 用C++定義用戶組

2.4.1.7 用C++添加用戶到應用程序組

 

1.4.1.2.5 商業規則 Business Rules

      一個商業規則可以讓一個程序在運行時使用邏輯驗證賦予客戶端的資格。

      一個商業規則是一個用VBScript編程語言或者與IAzTask對象有關的微軟JScript開發軟件寫成的腳本。當應用程序檢查對一個操作的訪問時,授權管理首先檢查當前的客戶端是否訪問了任何包含這個操作但是沒有關聯商業規則的任務。如果這個訪問沒有這樣授權,授權管理會運行包含這個操作的所有任務相關的商業規則腳本。

      一個應用程序用一對錶示名字和值的數組參數傳遞給商業規則腳本。

      一個商業規則腳本不能賦值給一個包含在託管範圍中的任務。

相關主題

2.4.3 用C++寫的商業邏輯驗證訪問

 

1.4.1.2.6 集合 Collections

      授權管理API提供表示其他對象集合的接口。例如IAzRole接口表示一個IAzRole對象的集合。

      其他代表集合的接口是IAzApplication、IAzApplicationGroups、IAzOperations、IAzScopes和IAzTasks。每一個接口都提供了簡化枚舉集合中對象的屬性。

 

1.5 強制誠信控制 Mandatory Integrity Control

      強制誠信控制(MIC)提供了一種對安全對象訪問的控制機制。這種機制是隨意訪問控制和計算訪問的補充,發生在對一個對象的用戶自定義訪問控制列表的計算訪問檢查之前。

      MIC使用誠信層級和強制策略來計算訪問。賦值給安全原則和安全對象的誠信層級決定了它們的保護和訪問層級。比如,一個擁有低誠信的原則不能對一個擁有中等誠信層級的對象寫操作,即使是這個對象的DACL允許原則的寫訪問。

      Windows定義了四種誠信層級:低級、中級、高級、系統級。標準用戶對應中級,提升用戶對應高級。你啓動的進程、創建的對象對應的是你的誠信級別(中級或者高級),如果可執行文件是低級那麼也是低級;系統服務對應的是系統級別的誠信。缺少一個誠信標籤的對象會被操作系統當做中級;這樣可以防止低級別代碼修改無標籤的對象。另外,Windows保證運行在低級誠信上的進程不能獲得訪問一個與app容器相關的進程的權限。

誠信標籤

      誠信標籤指定了安全對象和安全原則的誠信級別。誠信標籤由誠信SID表示。安全對象的誠信SID存儲在系統訪問控制列表(SACL)中。SACL包含一個SYSTEM_MANDATORY_LABLE_ACE的ACE,這個ACE反過來又包含了這個誠信SID。任何沒有誠信SID的對象都會被當做擁有中級誠信。

      安全原則的誠信SID存放在它的訪問令牌中。一個訪問令牌可以包含一個或多個誠信SID。

      關於誠信SID的定義,詳情參考 1.1.2.1.7.2 公開的SID。

進程的創建

      當一個用戶嘗試加載一個可執行文件,一個使用最低的用戶整合性層級和文件整合性層級的進程就被創建了。這意味着新的進程的執行層級永遠不會比可執行文件誠信層級高。如果管理員用戶執行一個低層級的程序,相應的新進程的訪問令牌就是低層級的。這可以幫助加載不可信代碼的用戶免受惡意行爲的影響。用戶數據(典型的用戶誠信層級)是對新進程寫保護的。

強制策略

      安全對象的SACL中的SYSTEM_MANDATORY_LABEL_ACE包含一個訪問掩碼,這個掩碼指定主要的誠信層級訪問權限低於賦予對象的訪問權限。爲這個訪問掩碼定義的值有SYSTEM_MANDATORY_LABEL_NO_WRITE_UP、SYSTEM_MANDATORY_LABEL_NO_READ_UP、和SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP。默認情況下,系統創建的每個對象都是使用訪問掩碼SYSTEM_MANDATORY_LABEL_NO_READ_UP。

      每一個訪問令牌也會指定一個強制策略,這個在創建令牌的時候由本地安全授權(LSA)設置。這個策略由一個與令牌相關的TOKEN_MANDATORY_POLICY結構指定。調用GetTokenInformation函數並給TokenMandatoryPolicy設置TokenInformationClass參數值來查詢這個結構。

 

1.6 用戶賬戶控制 User Account Control

      用戶賬戶控制(UAC)可以讓用戶以非管理員身份執行普通任務,調用標準用戶,不需要切換用戶、註銷、或者使用Run As就切換到管理員身份。UAC行爲中的“從不通知”設置不再禁用UAC。設置“從不通知”使你一個分離令牌,並一直允許自動提升請求的特權。這些微妙的變化可能會給你的app帶來兼容性上的問題。你也可以使用組策略或者手動設置註冊表禁用UAC。

      Windows Server 2008 R2,Windows 7,Windows Server 2008,和Windows Vista:設置“從不通知”會禁用UAC。

      例如,如果你通過以下步驟修改“從不通知”設置,你就會在要求提升權限的文件夾中創建文件時得到不同的結果。Windows 8會拒絕訪問。Windows 7允許你創建愛你File.txt文件。

  1. 打開“開始“菜單,在搜索框中鍵入”更改用戶賬戶控制設置“。
  2. 點擊”更改用戶賬戶控制設置“打開。
  3. 移動滑塊到”從不通知“。
  4. 點擊”確認“。
  5. 重啓操作系統。
  6. 打開運行對話框,輸入”cmd.exe“。注意窗口標題不再包含”管理員“字符串。
  7. 鍵入"echo > %windir%\system32\File.txt"。

 

      UAC在Windows Server 2008和Windows Vista的時候加入。一個標準用戶賬戶和Windows XP中的一個用戶賬戶是同義詞。本地管理員組的成員用戶賬戶以標準用戶身份運行大多數應用程序。

      關於UAC的信息,參考下列主題:

 

   
   
   
   

 

1.6.1 開發需要管理員特權的應用程序 Developing Application that Require Administrator Privilege

      開發一個應用程序,使它以運行標準用戶身份運行,但是執行要求管理員特權的操作是可能的。

      有幾個模型可以實現這一點。

 

   
   
   
   
   

 

1.6.1.1 管理員代理模型 Administrator Broker Model

      在管理員代理模型中,應用程序被一分爲二。一個程序以標準用戶身份運行,另一個以管理員身份運行。

      使用一個應用程序清單(manifest),標記標準用戶程序的asInvoke爲requestedExecutionLevel,標記管理員程序的reqireAdministrator爲requestedExecutionLevel。用戶首先加載標準用戶程序。當用戶嘗試執行一個要求完整管理員權限的訪問令牌時,標準用戶程序調用ShellExecute函數加載那個管理員身份運行的程序。ShelExecute函數會在以用戶的完整管理員訪問令牌運行應用程序之前提示用戶提升權限。在此之後,管理員程序纔可以執行要求管理員特權的任務。

      管理員程序並不是完全獨立於標準用戶程序的。管理員程序可以允許和標準用戶程序做進程間通信。然而,這樣的通信受限於默認的強制誠信策略。關於強制誠信考慮的信息,參考設計運行在低誠信層級的應用程序

      下面的資料對管理員代理模型可能有用:

  • 開發嚮導。當一個硬件嚮導判斷一個要求的驅動沒有在計算機上安裝,或者位於在企業的允許範圍之外,它會調用一個提升權限能力的應用程序把驅動移動到計算機商店。
  • Autorun.exe調用Setup.exe。當一個用戶從CD運行軟件,作爲標準用戶運行的Autorun.exe啓動Setup.exe安裝軟件到計算機上,而這個Setup.exe是以管理員身份運行的。

      下面是使用管理員代理模型的弊端:

  • 在應用程序之間轉換會讓用戶感到迷惑。很難讓用戶明白爲什麼一個新的應用程序出現在它的屏幕上。
  • 很難在兩個程序之間傳遞狀態信息。比如,你不使用這個模型在標準用戶控制面板(CPL)和它的管理員對應部分之間傳遞狀態,而允許同樣的CPL擁有管理員和標準用戶的功能。標準用戶CPL就需要把它的狀態存放在某個地方。
  • 在兩個程序之間分割功能會有很多複製代碼。

相關主題

1.6.1 開發需要管理員特權的應用程序

1.6.1.2 操作系統服務模型

1.6.1.3 提升任務模型

1.6.1.4 管理員COM對象模型

 

1.6.1.2 操作系統服務模型 Operating System Service Model

      在操作系統服務模型中,一個以標準用戶身份運行的應用程序通過遠程過程調用RPC方式與以系統級別運行的服務進行通信。

      標準用戶應用程序在其程序清單中的asInvoker被標記爲requestedExecuteLevel。要執行需要管理員特權的操作,標準用戶應用程序標記請求爲某個服務。

      使用操作系統服務模型的程序是要管理影響操作系統的應用程序的,比如反病毒軟件或者其他有缺點的軟件和間諜軟件。標準用戶程序允許登錄用戶控制服務的某些方面。服務程序負責分辨哪些操作是標準用戶程序的。例如,反病毒服務可能允許標準用戶啓動對系統的掃描,但是可能不允許標準用戶禁用實時病毒檢查。

      使用操作系統服務模型的主要好處是不需要提升權限請求。

      使用操作系統服務模型的一個缺點是運行在系統上的服務會比一個任務佔用更多的資源,並且普通用戶不能停用服務。那樣的話,可以考慮使用 1.6.1.3 提升任務模型。

      要實現操作系統服務模型,要創建一個標準用戶客戶端程序,和一個操作系統服務程序。並在安裝應用程序的時候在操作系統中安裝這個服務。

相關主題

1.6.1 開發需要管理員特權的應用程序

1.6.1.1 管理員代理模型

1.6.1.3 提升任務模型

1.6.1.4 管理員COM對象模型

1.6.1.3 提升任務模型 Elevated Task Model

      在提升任務模型中,通過啓動一個計劃任務,可以讓一個以標準用戶身份運行的程序執行要求管理員權限的操作。

      Windows Server 2003和Windows XP:不支持提升任務模型。

      任務不會像服務那樣消耗操作系統資源,並且任務在執行完之後會自動關閉。除非必須考慮到向下兼容早期的操作系統,否則可以考慮用這個代替操作系統服務模型

      要使用任務來爲標準用戶執行管理員特權操作,需要滿足一下幾點條件:

  • 任務必須設置爲以系統級別運行。
  • 與該任務相關的安全描述符必須確認允許標準用戶啓動任務。
  • 必須運行任務計劃服務

      關於如何創建和啓動任務的信息,參考任務計劃

相關主題

1.6.1 開發需要管理員特權的應用程序

1.6.1.1 管理員代理模型

1.6.1.2 操作系統服務模型

1.6.1.4 管理員COM對象模型

1.6.1.4 管理員COM對象模型 Administrator COM Object Model

      在管理員COM對象模型中,通過創建一個提升權限的組合對象模型對象,使得一個標準用戶可以執行要求管理員特權的操作。關於創建一個提升權限的COM對象,參考COM提升標識

      使用管理員COM對象模型的缺點是每次一個特權呢操作執行的時候都會提醒用戶。

      任何用戶可以控制的COM接口都必須由COM對象自身暴露。否則,一個沒有特權的進程可能導致提升的COM對象在未經提示的情況下執行特權操作。

相關主題

1.6.1 開發需要管理員特權的應用程序

1.6.1.1 管理員代理模型

1.6.1.2 操作系統服務模型

1.6.1.3 提升任務模型

 

 

2. 使用C++授權  Using Authorization in C++

 

      你可以使用授權管理API來控制對程序資源的訪問。

      如果你有一個基於訪問控制列表ACL的訪問控制解決方案,並且想避免把這種解決方案轉換爲授權管理,你可以繼續使用ACLs來控制對資源的訪問。關於使用ACLs控制對資源的訪問詳情,參考 2.4.4 用C++定義ACLs的許可,2.4.5 用C++根據一個SID創建一個客戶上下文和2.4.6 用C++區分帶ACLs的客戶訪問

      注意 對於大型企業,會在行政管理費用和性能之間做出平衡。隨着安全資源和用戶的增加,ACL的管理會變得很複雜。因爲所有要求的關於訪問權限的信息會被分配到安全資源上,所有性能不會受影響。授權管理的性能受規模的影響。

      關於其他授權任務的信息,參考 2.4用C++支持授權任務。

      

   
   
   
   

 

2.1 用C++定義許可 Defining Permission in C++

      在授權管理中,你可以通過創建一個授權策略存儲來定義哪一個用戶可以訪問哪些應用程序資源。

      關於使用ACL定義許可的詳情,可以參考2.4.4 用C++定義ACLs的許可

      爲定義訪問許可:

1. 創建定義的授權策略的存儲:2.4.1 使用C++創建授權策略存儲

2. 爲指定的應用程序在授權策略存儲中創建段:2.4.1.2 用C++創建應用程序對象

3. 定義應用程序對訪問和修改資源的實現的操作:2.4.1.3 用C++定義操作

4. 把操作打包到用戶想要執行的高級任務中:2.4.1.4 用C++把操作打包到任務

5. 定義由組構成的任務的角色:2.4.1.5 用C++把任務打包到角色中

      一個賦予角色的用戶擁有執行那個角色中任何任務的許可。

6. 創建腳本在運行時驗證對任務的訪問:2.4.3 用C++寫的商業邏輯驗證訪問

      這一步是可選的。

7. 定義用戶組:2.4.1.6 用C++定義用戶組

      可以把這些組設置給角色以判斷它們可以執行哪些任務。

8. 爲用戶組添加用戶:2.4.1.7 用C++把用戶添加到應用程序組

 

2.2 使用C++檢查客戶端對請求資源的訪問  Verifying Client Access to a Requested Resource in C++

      調用IAzClientContext接口中的AccessCheck方法,檢查客戶端是否擁有對一個或多個操作的訪問權。一個客戶端可能擁有一個或多個角色成員,一個操作可能被賦值給一個或多個任務,所以授權管理會檢查所有的角色和任務。如果客戶端中的任何角色包含了任何一個操作的任務,那麼對這個操作的訪問就是允許的。

      爲了檢查屬於客戶端的單個角色,要設置IAzClientContext接口中的RoleForAccessCheck屬性。

      當你爲訪問檢查初始化授權策略的時候,你必須設置IAzAuthorizationStore::Initilize方法的lFlag參數爲0。

      下面的例子演示瞭如何檢查一個客戶端對一個操作的訪問權限。這個例子假定了C盤根目錄下有一個名爲MyStore.xml的XML策略存儲,這個策略存儲包含了一個名爲Expense的應用程序和一個名爲UseFormControl的操作,變量hToken包含了一個可用的客戶端令牌。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2.3 用C++授權許可定義  Delegating the Defining of Permissions in C++

      存放在活動目錄中的授權策略存儲支持管理託管。可以託管管理到存儲中的用戶和組,或者範圍層級。

      在每一個層級,都有一個管理員和讀者列表。存儲、應用程序、或者範圍的管理員可以在託管層級讀取和修改策略存儲。讀者可以在託管層級讀取策略存儲但是不能修改存儲。

      必須作爲包含那個應用的策略存儲的授權用戶添加這個應用的用戶或者組(就是說或者是應用的管理員,或者是應用的讀者)。同樣地,必須作爲包含那個範圍的應用的授權用戶包含這個範圍內的用戶和組(也就是管理員或者讀者)。

      例如,要授權某個範圍的管理,首先,調用IAzAuthorizatoinStore::AddDelegatedPolicyUser方法把用戶和組添加到包含那個範圍的存儲的授權用戶列表。然後,調用IAzScope::AddDelegatedPolicyUser添加用戶和組到包含這個範圍的應用的授權用戶。最後,調用IAzScope::AddPolicyAdministrator方法添加用戶和組到這個範圍的管理員列表。

      基於XML策略存儲不支持任何層級的授權。

      如果某個範圍包含了任務定義,而這個定義又包含授權規則或者包含授權規則的角色定義,那麼不能授權存儲在活動目錄中的授權存儲中的這個範圍。

      下面的例子說明了如何授權一個應用的管理。這個例子假定在指定的位置有一個活動目錄授權策略存儲,這個策略存儲包含一個名叫Expense的應用,這個應用沒有包含商業規則腳本的任務。

 

 

 

 

 

 

 

 

 

 

 

 

 

2.4 用C++支持授權任務  Supporting Tasks for Authorization in C++

      下列任務支持列於2 使用C++授權中的主要任務。

   
   
   
   
   
   
   
   
   

 

2.4.1 使用C++創建授權策略存儲 Creating an Authorization Policy Store in C++

      在安裝一個應用之前或過程中創建一個授權策略。

      當你使用授權管理API創建授權策略時,參考下面的主題中提供的指令。

   
   
   
   
   
   
   
   

 

2.4.1.1 用C++創建授權策略存儲對象 Creating an Authorization Policy Store Object in C++

      一個授權策略存儲包含關於一個應用的安全策略或者應用程序組的信息。這些信息包括應用程序、操作、任務、用戶、和存儲相關的用戶組。當一個使用了授權管理的應用初始化時,它會從存儲中加載這些信息。授權策略存儲必須存放在可信任的系統上,因爲這個系統上的管理員對這個存儲擁有高度訪問權限。

      授權管理支持把授權管理策略存儲在活動目錄中或者是如下所示的一個XML文件中。在授權管理API中,一個授權策略存儲使用一個AzAuthorizationStore對象來表示。下面這個例子演示瞭如何爲活動目錄存儲和XML文件存儲創建一個AzAuthorizationStroe對象。

創建一個活動目錄存儲

      爲了使用活動目錄存儲授權策略,這個域必須位於Windows Server 2003 域功能層。授權策略存儲不能位於非域名上下文(也叫應用程序分區)。推薦把這個存儲放在專門爲授權策略存儲創建的新組織單元下的Program Data容器中。也推薦把這個存儲放在同應用服務相同的局域網內,這個服務運行使用這個存儲的應用程序。

      下面的例子演示瞭如何創建一個AzAuthorizationStore對象,這個對象代表在活動目錄中的一個授權策略存儲。這個例子假設在名爲authmanager.com的域中有一個名爲Program Data的活動目錄組織單元。

 

 

 

 

 

 

 

 

 

 

 

創建一個SQL服務存儲

      授權管理支持創建一個基於Microsoft SQL Server的組織策略存儲。要創建一個基於SQL Server的組織存儲,可以使用一個MSSQL://開頭的URL。這個URL必須包含一個有效的SQL連接字符串,一個數據庫名,和授權策略存儲的名字:MSSQL://ConnectionString/DatabaseName/PolicyStoreName.

      如果這個SQL Server實例不包含指定的授權管理數據庫,授權管理會使用那個名字創建一個新的數據庫。

      注意 連接SQL Server是不加密的,除非你明確地爲連接安裝SQL加密或者安裝使用英特網協議安全性(IPsec)的網絡流量加密工具。

      下面的例子演示瞭如何在SQL Server數據庫中創建一個代表授權策略存儲的AzAuthorizationStore對象。

 

 

 

 

 

 

 

 

 

 

創建一個XML存儲

      授權管理支持用XML格式創建一個授權策略。XML存儲可以位於應用程序運行的同一個計算機上,或者存儲在遠程計算機上。不支持直接編輯XML文件。使用授權管理MMC管理單元或者授權管理API來編輯策略存儲。

      授權管理不支持授權一個XML策略存儲的管理員。關於授權的更多信息,參考2.3 用C++授權許可定義。

      下面的例子演示瞭如何創建一個AzAuthorizationStore對象來表示XML文件中的一個授權策略。

      

 

 

 

 

 

 

 

 

 

 

2.4.1.2 用C++創建應用程序對象  Creating an Application Object in C++

      一個授權策略存儲包含一個或多個應用的授權策略信息。對於每一個使用這個策略存儲的應用程序,你必須創建一個IAzApplication對象並把它存儲到策略存儲中。

      下面的例子演示瞭如何創建一個代表應用程序的IAzApplication對象,以及如何添加這個IAzApplication對象到這個應用使用的授權策略存儲中。這裏例子假設在C盤根目錄有一個名爲MyStore.xml的XML策略存儲。

 

 

 

 

 

 

 

 

 

 

 

2.4.1.3 用C++定義操作 Defining Operations in C++

      

 

2.4.1.4 用C++把操作打包到任務 Grouping Operations into Tasks in C++

      

 

2.4.1.5 用C++把任務打包到角色 Grouping Tasks into Roles in C++

      

 

2.4.1.6 用C++定義用戶組 Defining Groups of Users in C++

      

 

2.4.1.7 用C++把用戶添加到應用程序組 Adding Users to an Application Group in C++

      

 

2.4.2 用C++建立一個帶有授權管理的客戶上下文 Establishing a Client Context with Authorization Manager in C++

      

 

2.4.3 用C++寫的商業邏輯驗證訪問 Qualifying Access with Business Logic in C++

 

2.4.4 用C++定義ACLs的許可 Defining Permissions with ACLs in C++

      

 

2.4.4.1 用C++修改一個對象的ACLs Modifying the ACLs of an Object in C++

      

 

2.4.4.2 用C++創建一個新對象的安全描述符 

      

 

2.4.4.3 用C++控制子對象的創建 

      

 

2.4.4.4 用C++打開和關閉特權

      

 

2.4.5 用C++根據一個SID創建一個客戶上下文 Establishing a Client Context from a SID in C++

      

 

2.4.5.1 用C++在一個訪問標記裏搜索SID 

      

 

2.4.5.2 用C++把一個二進制的SID轉爲字符串類型

      

 

2.4.6 用C++區分帶ACLs的客戶訪問  Verifying Client Access with ACLs in C++

      

 

2.4.7 用C++尋找一個文件對象的擁有者 Finding the Owner of a File Object in C++

      

 

2.4.8 用C++獲取對象擁有者 Taking Object Ownership in C++

      

 

3. 用腳本使用授權

3.1 用腳本定義許可

3.2 用腳本區分對一個請求資源的客戶訪問

3.3 用腳本委任許可定義

 

3.4 用腳本支持授權任務

3.4.1 用腳本創建授權策略存儲

3.4.1.1 用腳本創建授權策略存儲對象

3.4.1.2 用腳本創建應用程序對象

3.4.1.3 用腳本定義操作集

3.4.1.4 用腳本把操作打包到任務

3.4.1.5 用腳本把任務打包到角色

3.4.1.6 用腳本定義用戶組

 

3.4.1.7 用腳本添加用戶到一個應用程序組

3.4.2 用腳本創建客戶上下文

 

3.4.3 用腳本賦予“用戶”商業邏輯的訪問

 

4. 使用授權API

4.1 初始化一個客戶上下文

4.2 查詢客戶上下文

4.3 添加一個SID到客戶上下文

4.4 使用授權API檢查訪問

 

4.5 緩存訪問檢查

 

5. 授權參考文檔(detail從略)

5.1 授權常量

5.2 授權數據類型

5.3 授權枚舉

5.4 授權函數 (這個很重要,要學會查)

5.5 授權接口

5.6 授權對象

 

5.7 授權結構體

 

6. Microsoft.Interop.Security.AzRoles (detail從略)

 

 

附錄

Security Glossary

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章