When it comes to investigating security failures, three questions have to be answered:
- What privileges have been granted to the thread or process?
- What privileges are required to access the security object?
- What security objects are involved in the interaction?
lkd> !token -n
Thread is not impersonating. Using process token...
_EPROCESS 81c32020, _ETHREAD 81f6cda8, _TOKEN e7856380
TS Session ID: 0
User: S-1-5-21-527237240-926492609-839522115-1006 (User: BXIA\bing)
Groups:
00 S-1-5-21-527237240-926492609-839522115-513 (Group: BXIA\None)
Attributes - Mandatory Default Enabled
01 S-1-1-0 (Well Known Group: localhost\Everyone)
Attributes - Mandatory Default Enabled
02 S-1-5-21-527237240-926492609-839522115-1004 (Alias: BXIA\Debugger Users)
Attributes - Mandatory Default Enabled
03 S-1-5-32-544 (Alias: BUILTIN\Administrators)
Attributes - Mandatory Default Enabled Owner
04 S-1-5-32-545 (Alias: BUILTIN\Users)
Attributes - Mandatory Default Enabled
05 S-1-5-4 (Well Known Group: NT AUTHORITY\INTERACTIVE)
Attributes - Mandatory Default Enabled
06 S-1-5-11 (Well Known Group: NT AUTHORITY\Authenticated Users)
Attributes - Mandatory Default Enabled
07 S-1-5-5-0-1588032 (no name mapped)
Attributes - Mandatory Default Enabled LogonId
08 S-1-2-0 (Well Known Group: localhost\LOCAL)
Attributes - Mandatory Default Enabled
Primary Group: S-1-5-21-527237240-926492609-839522115-513 (Group: BXIA\None)
Privs:
00 0x000000017 SeChangeNotifyPrivilege Attributes - Enabled Default
01 0x000000008 SeSecurityPrivilege Attributes -
02 0x000000011 SeBackupPrivilege Attributes -
03 0x000000012 SeRestorePrivilege Attributes -
04 0x00000000c SeSystemtimePrivilege Attributes -
05 0x000000013 SeShutdownPrivilege Attributes -
06 0x000000018 SeRemoteShutdownPrivilege Attributes -
07 0x000000009 SeTakeOwnershipPrivilege Attributes -
08 0x000000014 SeDebugPrivilege Attributes - Enabled
09 0x000000016 SeSystemEnvironmentPrivilege Attributes -
10 0x00000000b SeSystemProfilePrivilege Attributes -
11 0x00000000d SeProfileSingleProcessPrivilege Attributes -
12 0x00000000e SeIncreaseBasePriorityPrivilege Attributes -
13 0x00000000a SeLoadDriverPrivilege Attributes - Enabled
14 0x00000000f SeCreatePagefilePrivilege Attributes -
15 0x000000005 SeIncreaseQuotaPrivilege Attributes -
16 0x000000019 SeUndockPrivilege Attributes - Enabled
17 0x00000001c SeManageVolumePrivilege Attributes -
18 0x00000001d SeImpersonatePrivilege Attributes - Enabled Default
19 0x00000001e SeCreateGlobalPrivilege Attributes - Enabled Default
Authentication ID: (0,185ddb)
Impersonation Level: Anonymous
TokenType: Primary
Source: User32 TokenFlags: 0x89 ( Token in use )
Token ID: 12a3e141 ParentToken ID: 0
Modified ID: (0, 12a45412)
RestrictedSidCount: 0 RestrictedSids: 00000000
The !sd extension command can be used to answer the second question. Since the security descriptor is protected by the kernel mode, !sd can only be run in the kernel mode. Thanks to local kernel debugging supported on XP and later versions of Windows, it becomes easier to check the security descriptor of a security object.
lkd> !object 81c32020
Object: 81c32020 Type: (833c8ca0) Process
ObjectHeader: 81c32008 (old version)
HandleCount: 5 PointerCount: 157
lkd> dt _OBJECT_HEADER 81c32008
nt!_OBJECT_HEADER
+0x000 PointerCount : 157
+0x004 HandleCount : 5
+0x004 NextToFree : 0x00000005
+0x008 Type : 0x833c8ca0 _OBJECT_TYPE
+0x00c NameInfoOffset : 0 ''
+0x00d HandleInfoOffset : 0 ''
+0x00e QuotaInfoOffset : 0 ''
+0x00f Flags : 0x20 ' '
+0x010 ObjectCreateInfo : 0x81f12da8 _OBJECT_CREATE_INFORMATION
+0x010 QuotaBlockCharged : 0x81f12da8
+0x014 SecurityDescriptor : 0xe6d77c33
+0x018 Body : _QUAD
lkd> !sd 0xe6d77c33 & FFFFFFF8
->Revision: 0x1
->Sbz1 : 0x0
->Control : 0x8004
SE_DACL_PRESENT
SE_SELF_RELATIVE
->Owner : S-1-5-21-527237240-926492609-839522115-1006
->Group : S-1-5-21-527237240-926492609-839522115-513
->Dacl :
->Dacl : ->AclRevision: 0x2
->Dacl : ->Sbz1 : 0x0
->Dacl : ->AclSize : 0x40
->Dacl : ->AceCount : 0x2
->Dacl : ->Sbz2 : 0x0
->Dacl : ->Ace[0]: ->AceType: ACCESS_ALLOWED_ACE_TYPE
->Dacl : ->Ace[0]: ->AceFlags: 0x0
->Dacl : ->Ace[0]: ->AceSize: 0x24
->Dacl : ->Ace[0]: ->Mask : 0x001f0fff
->Dacl : ->Ace[0]: ->SID: S-1-5-21-527237240-926492609-839522115-1006
->Dacl : ->Ace[1]: ->AceType: ACCESS_ALLOWED_ACE_TYPE
->Dacl : ->Ace[1]: ->AceFlags: 0x0
->Dacl : ->Ace[1]: ->AceSize: 0x14
->Dacl : ->Ace[1]: ->Mask : 0x001f0fff
->Dacl : ->Ace[1]: ->SID: S-1-5-18
->Sacl : is NULL
The corresponding shortcut for the above steps is as following:
lkd> !sd poi(81c32020-4) & FFFFFFF8
->Revision: 0x1
->Sbz1 : 0x0
->Control : 0x8004
SE_DACL_PRESENT
SE_SELF_RELATIVE
->Owner : S-1-5-21-527237240-926492609-839522115-1006
->Group : S-1-5-21-527237240-926492609-839522115-513
->Dacl :
->Dacl : ->AclRevision: 0x2
->Dacl : ->Sbz1 : 0x0
->Dacl : ->AclSize : 0x40
->Dacl : ->AceCount : 0x2
->Dacl : ->Sbz2 : 0x0
->Dacl : ->Ace[0]: ->AceType: ACCESS_ALLOWED_ACE_TYPE
->Dacl : ->Ace[0]: ->AceFlags: 0x0
->Dacl : ->Ace[0]: ->AceSize: 0x24
->Dacl : ->Ace[0]: ->Mask : 0x001f0fff
->Dacl : ->Ace[0]: ->SID: S-1-5-21-527237240-926492609-839522115-1006
->Dacl : ->Ace[1]: ->AceType: ACCESS_ALLOWED_ACE_TYPE
->Dacl : ->Ace[1]: ->AceFlags: 0x0
->Dacl : ->Ace[1]: ->AceSize: 0x14
->Dacl : ->Ace[1]: ->Mask : 0x001f0fff
->Dacl : ->Ace[1]: ->SID: S-1-5-18
->Sacl : is NULL
With first two questions answered, it is straightforward to check whether the principal identified by the token has enough privileges to access the object protected by the security descriptor.
What makes the investigation of a security issue challenging is the third question. For instance, in an invocation to ImpersonateSelf, more than one security objects are involved.
0:001> uf ADVAPI32!ImpersonateSelf
ADVAPI32!ImpersonateSelf:
77dfd203 8bff mov edi,edi
77dfd205 55 push ebp
77dfd206 8bec mov ebp,esp
77dfd208 ff7508 push dword ptr [ebp+8]
77dfd20b ff153012dd77 call dword ptr [ADVAPI32!_imp__RtlImpersonateSelf (77dd1230)]
77dfd211 85c0 test eax,eax
77dfd213 0f8c31210000 jl ADVAPI32!ImpersonateSelf+0x12 (77dff34a)
ADVAPI32!ImpersonateSelf+0x1c:
77dfd219 33c0 xor eax,eax
77dfd21b 40 inc eax
ADVAPI32!ImpersonateSelf+0x1f:
77dfd21c 5d pop ebp
77dfd21d c20400 ret 4
ADVAPI32!ImpersonateSelf+0x12:
77dff34a 50 push eax
77dff34b e8d479fdff call ADVAPI32!BaseSetLastNTError (77dd6d24)
77dff350 33c0 xor eax,eax
77dff352 e9c5deffff jmp ADVAPI32!ImpersonateSelf+0x1f (77dfd21c)
0:001> uf ntdll!RtlImpersonateSelf
ntdll!RtlImpersonateSelf:
7c92aa7d 8bff mov edi,edi
7c92aa7f 55 push ebp
7c92aa80 8bec mov ebp,esp
7c92aa82 83ec28 sub esp,28h
7c92aa85 8b4508 mov eax,dword ptr [ebp+8]
7c92aa88 53 push ebx
7c92aa89 8945f4 mov dword ptr [ebp-0Ch],eax
7c92aa8c 8d45f0 lea eax,[ebp-10h]
7c92aa8f 56 push esi
7c92aa90 8945ec mov dword ptr [ebp-14h],eax
7c92aa93 8d45fc lea eax,[ebp-4]
7c92aa96 50 push eax
7c92aa97 33db xor ebx,ebx
7c92aa99 6a02 push 2
7c92aa9b 6aff push 0FFFFFFFFh ; indicate current process handle
7c92aa9d c745d818000000 mov dword ptr [ebp-28h],18h
7c92aaa4 895ddc mov dword ptr [ebp-24h],ebx
7c92aaa7 895de4 mov dword ptr [ebp-1Ch],ebx
7c92aaaa 895de0 mov dword ptr [ebp-20h],ebx
7c92aaad 895de8 mov dword ptr [ebp-18h],ebx
7c92aab0 c745f00c000000 mov dword ptr [ebp-10h],0Ch
7c92aab7 c645f801 mov byte ptr [ebp-8],1
7c92aabb 885df9 mov byte ptr [ebp-7],bl
7c92aabe e8cd32feff call ntdll!ZwOpenProcessToken (7c90dd90) ; security descriptor of current process might be checked
7c92aac3 8bf0 mov esi,eax
7c92aac5 3bf3 cmp esi,ebx
7c92aac7 7c3c jl ntdll!RtlImpersonateSelf+0x88 (7c92ab05)
ntdll!RtlImpersonateSelf+0x4c:
7c92aac9 8d4508 lea eax,[ebp+8]
7c92aacc 50 push eax
7c92aacd 6a02 push 2
7c92aacf 53 push ebx
7c92aad0 8d45d8 lea eax,[ebp-28h]
7c92aad3 50 push eax
7c92aad4 6a04 push 4
7c92aad6 ff75fc push dword ptr [ebp-4]
7c92aad9 e8442efeff call ntdll!ZwDuplicateToken (7c90d922) ; security descriptor of primary token might be checked
7c92aade 8bf0 mov esi,eax
7c92aae0 3bf3 cmp esi,ebx
7c92aae2 7c19 jl ntdll!RtlImpersonateSelf+0x80 (7c92aafd)
ntdll!RtlImpersonateSelf+0x67:
7c92aae4 6a04 push 4
7c92aae6 8d4508 lea eax,[ebp+8]
7c92aae9 50 push eax
7c92aaea 6a05 push 5
7c92aaec 6afe push 0FFFFFFFEh ; indicate current thread handle
7c92aaee e84f3bfeff call ntdll!ZwSetInformationThread (7c90e642) ; security descriptor of current thread might be checked
7c92aaf3 ff7508 push dword ptr [ebp+8]
7c92aaf6 8bf0 mov esi,eax
7c92aaf8 e8892afeff call ntdll!NtClose (7c90d586) ; superseded by CloseHandle
ntdll!RtlImpersonateSelf+0x80:
7c92aafd ff75fc push dword ptr [ebp-4]
7c92ab00 e8812afeff call ntdll!NtClose (7c90d586) ; superseded by CloseHandle
ntdll!RtlImpersonateSelf+0x88:
7c92ab05 8bc6 mov eax,esi
7c92ab07 5e pop esi
7c92ab08 5b pop ebx
7c92ab09 c9 leave
7c92ab0a c20400 ret 4
From the above unassembled code, it is clear that there are three security objects involved in the invocation to ImpersonateSelf -- the current process, the primary token of current process, and the current thread. Their security descriptors will be checked and inadequate privileges on any of them will cause the error. Therefore, to answer the third question, we might have to dig deeper to see what happens behind the scene.
2 comments: