Process TokenWhenever a process is created, its process access token is also created in the kernel. This process token is used when access permission check is required. Roughly speaking, process token is the user identity of the process. For example, if the process tries to access system resources such as registry or file, the process shows its process token and the operating system checks access permission by using security descriptor (SD) of the system resources. SD contains the complete list of who is allowed and who is denied. Generally, all threads in the process inherit the process token, “unless” thread is impersonating.
Let’s take an example. I ran SQL Configuration Manager, attached the debugger and picked one of threads (thread#1). To inspect the thread token, switch to the thread#1 and run !token –n.
0:000> ~1s 0:001> !token -n Thread is not impersonating. Using process token... TS Session ID: 0x1 User: S-1-5-21-2127521184-1604012920-1887927527-570548 (User: TDomain\yongslee) Groups: 00 S-1-5-21-2127521184-1604012920-1887927527-513 (Group: TDomain\Domain Users) Attributes - Mandatory Default Enabled 01 S-1-1-0 Attributes - Mandatory Default Enabled ..... ..... Impersonation Level: Anonymous TokenType: Primary Is restricted token: no.As bold-face text says, the thread is not impersonating any and using primary access token which is the process token.
Impersonation and Thread TokenSometimes thread might need to impersonate other user. This basically means that the thread does not use process access token and rather uses different user token. This scenario often occurs when client is accessing server resources. To access server resources, the server code impersonates (and acts as) the client identity and performs resource access with it. If the client user doesn’t have permission to access server resource, it throws access denied.
To see how it works, let’s run SQL Configuration Manager and invoke SQL WMI provider. SQL WMI provider is run as Network Service account in the wmiprvse.exe process and thus its process token is representing Network Service. WMI providers are typically using impersonation so we expect that worker thread in WMI provider is using client account, not Network Service. If worker thread uses Network Service, it might be a big security hole.
(1) Run SQL Configuration Manager (SQLCM)
=> Whenever SQLCM is launched, new SQL WMI provider process (wmiprvse) will be created (if already doesn’t exist)
=> Run tlist.exe to find SQL WMI provider
C> tlist –m sqlmgmprovider.dll
(2) Attach to SQL WMI provider by using windbg
C> windbg –p 2202 (ex: 2202 = pid of wmiprvse.exe)
(3) Set breakpoint in one of SQL WMI classes. Let’s try SqlServiceAdvancedProperty.
To break in when Advanced properties is clicked, set bp against this method and keep debugger going.
0:011> bp sqlmgmprovider!SqlServiceAdvancedProperty::EnumerateInstances 0:011> g(4) In SQLCM, select SQL Server Services -> doubleclick SQL Server (MSSQLSERVER) to bring up the Properties page -> Click Advanced tab to display advanced properties. (This will call SqlServiceAdvancedProperty:: EnumerateInstances method in SQL WMI provider)
Now, breakpoint will be hit and we can check thread token by using !token command.
Breakpoint 0 hit eax=541c1d58 ebx=80041024 ecx=54214588 edx=6d599bc9 esi=54214588 edi=0095e3c8 eip=541def70 esp=00deefb8 ebp=00deefc8 iopl=0 nv up ei pl zr na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246 sqlmgmprovider!SqlServiceAdvancedProperty::EnumerateInstances: 541def70 8bff mov edi,edi 0:007> !token -n TS Session ID: 0x1 User: S-1-5-21-2127521184-1604012920-1887927527-570548 (User: TDomain\yongslee) Groups: 00 S-1-5-21-2127521184-1604012920-1887927527-513 (Group: TDomain\Domain Users) Attributes - Mandatory Default Enabled .... Primary Group: S-1-5-21-2127521184-1604012920-1887927527-513 (Group: TDomain\Domain Users) Privs: … 15 0x000000017 SeChangeNotifyPrivilege Attributes - Enabled Default 19 0x00000001d SeImpersonatePrivilege Attributes - Enabled Default 20 0x00000001e SeCreateGlobalPrivilege Attributes - Enabled Default Auth ID: 0:5eeba Impersonation Level: Impersonation TokenType: Impersonation Is restricted token: no.The thread token here is impersonating and acts as TDomain\yongslee, not using Network Service. Please note this user is the same one that invoked SQLCM process. So even if the SQL WMI provider process is run as Network Service, actual worker thread is using the client user principal that makes WMI request. If the client application is run in low privilege account and the account cannot access system resource such as registry, the WMI request accessing registry resource won’t be successful.
Impersonation in SQL WMIThen how can the worker thread in SQL WMI provider impersonate the client principal? It is using internally WbemCoImpersonateClient method in WMI framework API. Before this method is called, the worker thread is using process token (Network Service). Once the WbemCoImpersonateClient is executed, the thread acquires impersonation token.
0:010> bp framedyn!WbemCoImpersonateClient 0:010> g framedyn!WbemCoImpersonateClient: 0:007> !token –n //Check token before impersonation Thread is not impersonating. Using process token... TS Session ID: 0 User: S-1-5-20 (Well Known Group: NT AUTHORITY\NETWORK SERVICE) ..... Impersonation Level: Anonymous TokenType: Primary Is restricted token: no. 0:007> gu // Execute WbemCoImpersonateClient() framedyn!CWbemProviderGlue::CheckImpersonationLevel+0x39: 0:007> !token –n // Check token after impersonation TS Session ID: 0x1 User: S-1-5-21-2127521184-1604012920-1887927527-570548 (User: TDomain\yongslee) ..... Impersonation Level: Impersonation TokenType: Impersonation