iT邦幫忙

2023 iThome 鐵人賽

DAY 14
2
Security

Windows Security 101系列 第 14

[Day14] Token & Object (Part 1): Introduction

  • 分享至 

  • xImage
  •  

今天要來介紹的是 Token & Object,我會盡量在這系列將 Windows 的權限管理模型解釋清楚。

我想藉由 James Forshaw 演講中常見到的這張圖來解釋在 Windows 中 Process 如何用自身的 Token 去取得 Resource 的存取權限。

https://ithelp.ithome.com.tw/upload/images/20230928/20120098Bty8SsunWy.png

(ref: James Forshaw - Social Engineering in Windows Kernel)

整個流程大致上分成以下步驟:

  1. Process 拿著 Token 向 Kernel 請求存取某個 Resource。
  2. 經過一系列的處理,最終 Kernel 執行 SeAccessCheck 確認是否該 Token 可以存取這個 Resource。
  3. 通過檢查後,就可以回傳 Resource 給該 Process。

接下來我要來介紹一些重要的物件!

Token (Access Token)

Token 就像是一張身分證,去超商取貨時,店員會以身分證來辨識取貨人的身分。Token 是一樣的概念,可以用來驗證持有者對於其他 Resource 的存取權限。

在 Windbg 可以下指令 dt nt!_token 看到 Token 的結構

nt!_TOKEN
   +0x000 TokenSource      : _TOKEN_SOURCE
   +0x010 TokenId          : _LUID
   +0x018 AuthenticationId : _LUID
   +0x020 ParentTokenId    : _LUID
   +0x028 ExpirationTime   : _LARGE_INTEGER
   +0x030 TokenLock        : Ptr64 _ERESOURCE
   +0x038 ModifiedId       : _LUID
   +0x040 Privileges       : _SEP_TOKEN_PRIVILEGES
   +0x058 AuditPolicy      : _SEP_AUDIT_POLICY
   +0x078 SessionId        : Uint4B
   +0x07c UserAndGroupCount : Uint4B
   +0x080 RestrictedSidCount : Uint4B
   +0x084 VariableLength   : Uint4B
   +0x088 DynamicCharged   : Uint4B
   +0x08c DynamicAvailable : Uint4B
   +0x090 DefaultOwnerIndex : Uint4B
   +0x098 UserAndGroups    : Ptr64 _SID_AND_ATTRIBUTES
   +0x0a0 RestrictedSids   : Ptr64 _SID_AND_ATTRIBUTES
   +0x0a8 PrimaryGroup     : Ptr64 Void
   +0x0b0 DynamicPart      : Ptr64 Uint4B
   +0x0b8 DefaultDacl      : Ptr64 _ACL
   +0x0c0 TokenType        : _TOKEN_TYPE
   +0x0c4 ImpersonationLevel : _SECURITY_IMPERSONATION_LEVEL
   +0x0c8 TokenFlags       : Uint4B
   +0x0cc TokenInUse       : UChar
   +0x0d0 IntegrityLevelIndex : Uint4B
   +0x0d4 MandatoryPolicy  : Uint4B
   +0x0d8 LogonSession     : Ptr64 _SEP_LOGON_SESSION_REFERENCES
   +0x0e0 OriginatingLogonSession : _LUID
   +0x0e8 SidHash          : _SID_AND_ATTRIBUTES_HASH
   +0x1f8 RestrictedSidHash : _SID_AND_ATTRIBUTES_HASH
   +0x308 pSecurityAttributes : Ptr64 _AUTHZBASEP_SECURITY_ATTRIBUTES_INFORMATION
   +0x310 Package          : Ptr64 Void
   +0x318 Capabilities     : Ptr64 _SID_AND_ATTRIBUTES
   +0x320 CapabilityCount  : Uint4B
   +0x328 CapabilitiesHash : _SID_AND_ATTRIBUTES_HASH
   +0x438 LowboxNumberEntry : Ptr64 _SEP_LOWBOX_NUMBER_ENTRY
   +0x440 LowboxHandlesEntry : Ptr64 _SEP_CACHED_HANDLES_ENTRY
   +0x448 pClaimAttributes : Ptr64 _AUTHZBASEP_CLAIM_ATTRIBUTES_COLLECTION
   +0x450 TrustLevelSid    : Ptr64 Void
   +0x458 TrustLinkedToken : Ptr64 _TOKEN
   +0x460 IntegrityLevelSidValue : Ptr64 Void
   +0x468 TokenSidValues   : Ptr64 _SEP_SID_VALUES_BLOCK
   +0x470 IndexEntry       : Ptr64 _SEP_LUID_TO_INDEX_MAP_ENTRY
   +0x478 DiagnosticInfo   : Ptr64 _SEP_TOKEN_DIAG_TRACK_ENTRY
   +0x480 BnoIsolationHandlesEntry : Ptr64 _SEP_CACHED_HANDLES_ENTRY
   +0x488 SessionObject    : Ptr64 Void
   +0x490 VariablePart     : Uint8B

也可以使用 James Forshaw 開發的 TokenViewer.exe 觀察各個 token 的細節

https://ithelp.ithome.com.tw/upload/images/20230928/20120098iw7Lb3gJYr.png

https://ithelp.ithome.com.tw/upload/images/20230928/20120098YHb1OKpRqE.png

Classification by Token Type

根據 0xcsandker 的文章,實際上只會有兩種 Token Type:Primary Token 和 Impersonation Token。

  • Primary token
    • 在 Windows 中,process 持有的 token 就是 Primary token。
  • Impersonation Token
    • 在 Windows 中,thread 持有的 token 就是 Impersonation token。
    • Windows 中設計了一套機制在 Cross-Process 的情境下,可以讓其中一端的 process 模擬另一端 process 持有的 token。在本系列的第三篇會探討。

Classification by Elevation Type, Restricted, AppContainer

根據 James Forshaw 的演講 Token 也可以依照功能分成 Normal Token、Linked Token、Filter Token、LowBox Token 等(應該還有更多種以功能命名的 token),但這只是為了方便區分功能,在此的 token 都是 Impersonate Token,除了 Normal Token 有可能是 Primary Token。

https://ithelp.ithome.com.tw/upload/images/20230928/20120098E78R8QYEsW.png
(ref: James Forshaw - Social Engineering in Windows Kernel)

[TODO] 這邊會出現一堆 token,但我目前還沒整理好,沒辦法有條理地寫出來@@

Object

Windows 是由各式各樣 Object Types 的 Object 為基礎所建構。所有的 Object 都是可以被取得的 Resources,連 Token 本身都是 Object。而在 Windows 10 中,可以在 Windbg 中統計 nt!ObTypeIndexTable 的 entry,會發現有多達 70 種左右的 Object Types。

https://ithelp.ithome.com.tw/upload/images/20230928/20120098jNAPWfiVaE.png

在 SysInternal Suite 的 winobj64.exe 也可以看到各式各樣的 Object Type

https://ithelp.ithome.com.tw/upload/images/20230928/20120098bXMulRmcWD.png

在 User mode 中,不能直接操控 Object,必須透過建立 Handle 的方式,透過 Handle 來操控 Object。Kernel mode 中也會維護一張 Handle Table,用來管理該 Object 建立的多個 Handle。

https://ithelp.ithome.com.tw/upload/images/20230928/20120098YXFmBJjJbT.png

Object 本身除了代表可以被取得的資源外,也會包含 Security Descriptor 決定該 Object 可以被誰存取,唯有符合條件的 Token 才能存取。 另外,Handle Table 中也會記錄每個 Handle 當初被開啟時賦予的權限。

根據 Rayanfam 的 blog,OpenProcess 會有以下流程:

user-mode      |  OpenProcess
               |  NtOpenProcess
---------------------------------
kernel-mode    |  NtOpenProcess 
               |  PsOpenProcess
               |  ObOpenObjectByPointer
               |  ObpCreateHandle

最終回傳 Process Handle

Security Descriptor

在正式開始介紹 Security Descriptor 前,需要先介紹 Security Identifier 和 Access Mask。

Security Identifier

我們先來認識 Security Identifier 的組成

https://ithelp.ithome.com.tw/upload/images/20230928/20120098ch1T5cZTkO.png
(ref: James Forshaw - Introduction to Local Privilege Escalation on Windows)

根據 James Forshaw 的投影片,其實 SID 和 Linux 中的 UID/GID 類似,但是在結構上有所不同。記得一些常見的 SIDs 也對滲透測試蠻有幫助的。

Access Mask

https://ithelp.ithome.com.tw/upload/images/20230928/20120098kheMG89UDQ.png
(ref: James Forshaw - Introduction to Local Privilege Escalation on Windows)

在許多 Windows APIs 都可以看到需要填入想要取得的權限 (e.g., CreateFile) ,之後才能對這個 Object 開啟 Handle,原理就是在 Kernel Mode 中會檢查 DesiredAccess 是不是允許的

根據 MSDN

至於 Security Descripter 就是檢查存取權限的清單,上面會記載這些資訊:

  • Owner SID
  • Group SID
  • System Access Control List (SACL)
    • 一個 SACL 中會有零個或多個 Access Control Entries (ACEs),標示是否要對不同的 access 種類生成 auditing log。
  • Discretionary Access Control List (DACL)
    • 一個 DACL 中會有零個或多個 Access Control Entries (ACEs),標示可以存取該 Object 的 Users 和 Group。

Security Descriptor 可以在 _OBJECT_HEADER→SecurityDescriptor 中找到

在 Windbg,可以下指令 !sd address 0 就可以看到 Security Descriptor 中的 Owner SID, Group SID, DACL, SACL

(其中 address 的部分要注意後3個bit為0,e.g., _OBJECT_HEADER→SecurityDescriptor & ~0xf == address)

lkd> !sd 0xffffce04`250f7c20  0
->Revision: 0x1
->Sbz1    : 0x0
->Control : 0x8814
            SE_DACL_PRESENT
            SE_SACL_PRESENT
            SE_SACL_AUTO_INHERITED
            SE_SELF_RELATIVE
->Owner   : S-1-5-32-544
->Group   : S-1-5-21-2232672516-4162811975-572094402-513
->Dacl    : 
->Dacl    : ->AclRevision: 0x2
->Dacl    : ->Sbz1       : 0x0
->Dacl    : ->AclSize    : 0x50
->Dacl    : ->AceCount   : 0x3
->Dacl    : ->Sbz2       : 0x0
->Dacl    : ->Ace[0]: ->AceType: ACCESS_ALLOWED_ACE_TYPE
->Dacl    : ->Ace[0]: ->AceFlags: 0x0
->Dacl    : ->Ace[0]: ->AceSize: 0x18
->Dacl    : ->Ace[0]: ->Mask : 0x000f01ff
->Dacl    : ->Ace[0]: ->SID: S-1-5-32-544

->Dacl    : ->Ace[1]: ->AceType: ACCESS_ALLOWED_ACE_TYPE
->Dacl    : ->Ace[1]: ->AceFlags: 0x0
->Dacl    : ->Ace[1]: ->AceSize: 0x14
->Dacl    : ->Ace[1]: ->Mask : 0x000f01ff
->Dacl    : ->Ace[1]: ->SID: S-1-5-18

->Dacl    : ->Ace[2]: ->AceType: ACCESS_ALLOWED_ACE_TYPE
->Dacl    : ->Ace[2]: ->AceFlags: 0x0
->Dacl    : ->Ace[2]: ->AceSize: 0x1c
->Dacl    : ->Ace[2]: ->Mask : 0x0002001f
->Dacl    : ->Ace[2]: ->SID: S-1-5-5-0-1516497

->Sacl    : 
->Sacl    : ->AclRevision: 0x2
->Sacl    : ->Sbz1       : 0x0
->Sacl    : ->AclSize    : 0x1c
->Sacl    : ->AceCount   : 0x1
->Sacl    : ->Sbz2       : 0x0
->Sacl    : ->Ace[0]: ->AceType: SYSTEM_MANDATORY_LABEL_ACE_TYPE
->Sacl    : ->Ace[0]: ->AceFlags: 0x0
->Sacl    : ->Ace[0]: ->AceSize: 0x14
->Sacl    : ->Ace[0]: ->Mask : 0x00000001
->Sacl    : ->Ace[0]: ->SID: S-1-16-12288

Integrity Level

Integrity Level 是定義 SID 被記錄在 _TOKEN→IntegrityLevelIndex

根據 Yarden Shafir 的 Exploit Writeup,可以照著 SepLocateTokenIntegrity 的邏輯在 Token 裡面找到 Integrity Level

https://ithelp.ithome.com.tw/upload/images/20230928/20120098TzKjarkGoG.png
(ref: https://windows-internals.com/exploiting-a-simple-vulnerability-part-2-what-if-we-made-exploitation-harder/)

找到的 Integrity Level 會是一組 SID,還需要去查表才可以確認是哪種 Integrity Level。Integrity Level 的 SID 會是 S-1-16-xxxx,xxxx 的部分會填入以下的 RID。

https://ithelp.ithome.com.tw/upload/images/20230928/20120098Qxxzwae64S.png
(ref: https://learn.microsoft.com/en-us/windows/win32/secauthz/well-known-sids)

Yarden Shafir 的 Exploit Writeup 為例

https://ithelp.ithome.com.tw/upload/images/20230928/20120098lPWZp4HJ5K.png
(ref: https://windows-internals.com/exploiting-a-simple-vulnerability-part-2-what-if-we-made-exploitation-harder/)

根據 _TOKEN→IntegrityLevelIndex 是 0xe,以此為 index 可以在 _TOKEN→UserAndrGroups 中找到 S-1-16-8192,很明顯的這是 Mandatory Label (Integrity Level),並且 8192 == 0x2000 == Medium Integrity Level。

在 windbg 中可以下指令 !token address 就可以看到所有 SIDs。

其實,最簡單方式是直接用 Process Explorer 就可以看到全部的 SIDs。

https://ithelp.ithome.com.tw/upload/images/20230928/20120098aFu5ZHjfLc.png

Privileges

Privilege 會存在 _TOKEN→Privileges 中,並且有以下結構

lkd> dt _sep_token_privileges
nt!_SEP_TOKEN_PRIVILEGES
   +0x000 Present          : Uint8B
   +0x008 Enabled          : Uint8B
   +0x010 EnabledByDefault : Uint8B

Present 表示 token 能夠啟用的 privilege,沒有的 bit flag 也就無法啟用。

Enabled 表示 token 現在啟用的 privilege

此外,結構中的每個成員都是 8 bytes 的 bitmask,每個 bit flag 的定義可以參考 ReactOS 的程式碼

/* If the first isn't defined, assume none is */
#ifndef SE_MIN_WELL_KNOWN_PRIVILEGE
#define SE_MIN_WELL_KNOWN_PRIVILEGE       2L
#define SE_CREATE_TOKEN_PRIVILEGE         2L
#define SE_ASSIGNPRIMARYTOKEN_PRIVILEGE   3L
#define SE_LOCK_MEMORY_PRIVILEGE          4L
#define SE_INCREASE_QUOTA_PRIVILEGE       5L
#define SE_MACHINE_ACCOUNT_PRIVILEGE      6L
#define SE_TCB_PRIVILEGE                  7L
#define SE_SECURITY_PRIVILEGE             8L
#define SE_TAKE_OWNERSHIP_PRIVILEGE       9L
#define SE_LOAD_DRIVER_PRIVILEGE         10L
#define SE_SYSTEM_PROFILE_PRIVILEGE      11L
#define SE_SYSTEMTIME_PRIVILEGE          12L
#define SE_PROF_SINGLE_PROCESS_PRIVILEGE 13L
#define SE_INC_BASE_PRIORITY_PRIVILEGE   14L
#define SE_CREATE_PAGEFILE_PRIVILEGE     15L
#define SE_CREATE_PERMANENT_PRIVILEGE    16L
#define SE_BACKUP_PRIVILEGE              17L
#define SE_RESTORE_PRIVILEGE             18L
#define SE_SHUTDOWN_PRIVILEGE            19L
#define SE_DEBUG_PRIVILEGE               20L
#define SE_AUDIT_PRIVILEGE               21L
#define SE_SYSTEM_ENVIRONMENT_PRIVILEGE  22L
#define SE_CHANGE_NOTIFY_PRIVILEGE       23L
#define SE_REMOTE_SHUTDOWN_PRIVILEGE     24L
#define SE_UNDOCK_PRIVILEGE              25L
#define SE_SYNC_AGENT_PRIVILEGE          26L
#define SE_ENABLE_DELEGATION_PRIVILEGE   27L
#define SE_MANAGE_VOLUME_PRIVILEGE       28L
#define SE_IMPERSONATE_PRIVILEGE         29L
#define SE_CREATE_GLOBAL_PRIVILEGE       30L
#define SE_MAX_WELL_KNOWN_PRIVILEGE      SE_CREATE_GLOBAL_PRIVILEGE
#endif /* ndef SE_MIN_WELL_KNOWN_PRIVILEGE */

各個 bit flag 掌握的 privilege 都不太一樣,這篇文章 有寫到各個 Privilege 的作用:

  • SeImpersonatePrivilege
    • 可以 impersonate 任何 token,像是 NTLM relay 類型的攻擊都需要 (e.g., Potatoes)
  • SeAssignPrimaryPrivilege
    • 可以指派 primary token
  • SeTcbPrivilege
    • 可以用 KERB_S4U_LOGON (Kerberos S4U logon) 取得 impersonation token
    • 將任意 group 加入自身 token
    • 將 integrity level 設成 medium (AppContainer Escape?)
    • 將 token 指派給其他 thread
  • SeBackupPrivilege
    • 允許系統所有 read access,可以用在 pass the hass (PTH),像是 psexec 和 winexec 都可以以 PTH 過認證。(在 Local Administrator 未啟用時無效)
  • SeRestorePrivilege
    • 允許系統所有 write access (無視 ACL)
  • SeCreateTokenPrivilege
    • 在可以 impersonate token 的條件下,可以建立 impersonation token 並加入 privileged group SID
  • SeLoadDriverPrivilege
    • Load / unload driver
  • SeTakeOwnershipPrivilege
    • 跟 SeRestorePrivilege 很像,允許更換 object 的 owner
  • SeDebugPrivilege
    • 允許對其他 process 進行操作。像是 read/write process memory

可以用 whoami /priv 檢視所有的 privileges

https://ithelp.ithome.com.tw/upload/images/20230928/20120098jiqLveTNJn.png

最後,在這篇文章發布前我覺得還有還是有許多物件的細節不夠完整,因此我在之後還是會陸續編輯這篇文章。

下一篇,我要介紹的是本系列的第二篇 Access Check!

References


上一篇
[Day13] Dark LoadLibrary
下一篇
[Day15] Token & Object (Part 2): Access Check
系列文
Windows Security 10130
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言