29_block_NtImpersonateAnonymousToken_before_LowerToken.patch (8072B)
1 # HG changeset patch 2 # User Bob Owen <bobowencode@gmail.com> 3 # Date 1687248452 -3600 4 # Tue Jun 20 09:07:32 2023 +0100 5 # Node ID a07e3be35d9e5558fb95a18e3b858d5f4654dce9 6 # Parent 5f4aecabd0376981a5f837f5de593c106c194712 7 Bug 1839463: Block NtImpersonateAnonymousToken before RevertToSelf. 8 9 Note this patch is slightly different from what landed for Bug 1839463, because 10 that also included the reversion of a different patch. 11 12 diff --git a/sandbox/win/src/interceptors.h b/sandbox/win/src/interceptors.h 13 --- a/sandbox/win/src/interceptors.h 14 +++ b/sandbox/win/src/interceptors.h 15 @@ -11,16 +11,17 @@ 16 17 namespace sandbox { 18 19 enum InterceptorId { 20 // Internal use: 21 MAP_VIEW_OF_SECTION_ID = 0, 22 UNMAP_VIEW_OF_SECTION_ID, 23 // Policy broker: 24 + IMPERSONATE_ANONYMOUS_TOKEN_ID, 25 SET_INFORMATION_THREAD_ID, 26 OPEN_THREAD_TOKEN_ID, 27 OPEN_THREAD_TOKEN_EX_ID, 28 OPEN_THREAD_ID, 29 OPEN_PROCESS_ID, 30 OPEN_PROCESS_TOKEN_ID, 31 OPEN_PROCESS_TOKEN_EX_ID, 32 // Filesystem dispatcher: 33 diff --git a/sandbox/win/src/interceptors_64.cc b/sandbox/win/src/interceptors_64.cc 34 --- a/sandbox/win/src/interceptors_64.cc 35 +++ b/sandbox/win/src/interceptors_64.cc 36 @@ -46,16 +46,24 @@ NTSTATUS WINAPI TargetNtUnmapViewOfSecti 37 reinterpret_cast<NtUnmapViewOfSectionFunction>( 38 g_originals.functions[UNMAP_VIEW_OF_SECTION_ID]); 39 return TargetNtUnmapViewOfSection(orig_fn, process, base); 40 } 41 42 // ----------------------------------------------------------------------- 43 44 NTSTATUS WINAPI 45 +TargetNtImpersonateAnonymousToken64(HANDLE thread) { 46 + NtImpersonateAnonymousTokenFunction orig_fn = 47 + reinterpret_cast<NtImpersonateAnonymousTokenFunction>( 48 + g_originals[IMPERSONATE_ANONYMOUS_TOKEN_ID]); 49 + return TargetNtImpersonateAnonymousToken(orig_fn, thread); 50 +} 51 + 52 +NTSTATUS WINAPI 53 TargetNtSetInformationThread64(HANDLE thread, 54 THREADINFOCLASS thread_info_class, 55 PVOID thread_information, 56 ULONG thread_information_bytes) { 57 NtSetInformationThreadFunction orig_fn = 58 reinterpret_cast<NtSetInformationThreadFunction>( 59 g_originals.functions[SET_INFORMATION_THREAD_ID]); 60 return TargetNtSetInformationThread(orig_fn, thread, thread_info_class, 61 diff --git a/sandbox/win/src/interceptors_64.h b/sandbox/win/src/interceptors_64.h 62 --- a/sandbox/win/src/interceptors_64.h 63 +++ b/sandbox/win/src/interceptors_64.h 64 @@ -31,16 +31,20 @@ TargetNtMapViewOfSection64(HANDLE sectio 65 // It should never be called directly. This function provides the means to 66 // detect dlls being unloaded, so we can clean up our interceptions. 67 SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtUnmapViewOfSection64(HANDLE process, 68 PVOID base); 69 70 // ----------------------------------------------------------------------- 71 // Interceptors without IPC. 72 73 +// Interception of NtImpersonateAnonymousToken on the child process. 74 +SANDBOX_INTERCEPT NTSTATUS WINAPI 75 +TargetNtImpersonateAnonymousToken64(HANDLE thread); 76 + 77 // Interception of NtSetInformationThread on the child process. 78 SANDBOX_INTERCEPT NTSTATUS WINAPI 79 TargetNtSetInformationThread64(HANDLE thread, 80 THREADINFOCLASS thread_info_class, 81 PVOID thread_information, 82 ULONG thread_information_bytes); 83 84 // Interception of NtOpenThreadToken on the child process. 85 diff --git a/sandbox/win/src/nt_internals.h b/sandbox/win/src/nt_internals.h 86 --- a/sandbox/win/src/nt_internals.h 87 +++ b/sandbox/win/src/nt_internals.h 88 @@ -145,16 +145,19 @@ typedef enum _NT_THREAD_INFORMATION_CLAS 89 IN ACCESS_MASK DesiredAccess, 90 IN POBJECT_ATTRIBUTES 91 ObjectAttributes, 92 IN PCLIENT_ID ClientId); 93 94 // Provide ThreadImpersonationToken which is not in THREADINFOCLASS. 95 constexpr auto ThreadImpersonationToken = static_cast<THREADINFOCLASS>(5); 96 97 +typedef NTSTATUS(WINAPI* NtImpersonateAnonymousTokenFunction)( 98 + IN HANDLE ThreadHandle); 99 + 100 typedef NTSTATUS(WINAPI* NtSetInformationThreadFunction)( 101 IN HANDLE ThreadHandle, 102 IN THREADINFOCLASS ThreadInformationClass, 103 IN PVOID ThreadInformation, 104 IN ULONG ThreadInformationLength); 105 106 // Partial definition only for values not in PROCESS_INFO_CLASS. 107 #pragma clang diagnostic push 108 diff --git a/sandbox/win/src/policy_broker.cc b/sandbox/win/src/policy_broker.cc 109 --- a/sandbox/win/src/policy_broker.cc 110 +++ b/sandbox/win/src/policy_broker.cc 111 @@ -95,16 +95,18 @@ bool SetupBasicInterceptions(Interceptio 112 if (!INTERCEPT_NT(manager, NtOpenThread, OPEN_THREAD_ID, 20) || 113 !INTERCEPT_NT(manager, NtOpenProcess, OPEN_PROCESS_ID, 20) || 114 !INTERCEPT_NT(manager, NtOpenProcessToken, OPEN_PROCESS_TOKEN_ID, 16)) 115 return false; 116 117 // Interceptions with neither policy nor IPC. 118 if (!INTERCEPT_NT(manager, NtSetInformationThread, SET_INFORMATION_THREAD_ID, 119 20) || 120 + !INTERCEPT_NT(manager, NtImpersonateAnonymousToken, 121 + IMPERSONATE_ANONYMOUS_TOKEN_ID, 8) || 122 !INTERCEPT_NT(manager, NtOpenThreadToken, OPEN_THREAD_TOKEN_ID, 20)) 123 return false; 124 125 // This one is also provided by process_thread_policy. 126 if (!INTERCEPT_NT(manager, NtOpenProcessTokenEx, OPEN_PROCESS_TOKEN_EX_ID, 127 20)) 128 return false; 129 130 diff --git a/sandbox/win/src/policy_target.cc b/sandbox/win/src/policy_target.cc 131 --- a/sandbox/win/src/policy_target.cc 132 +++ b/sandbox/win/src/policy_target.cc 133 @@ -67,16 +67,30 @@ bool QueryBroker(IpcTag ipc_id, CountedP 134 processor.Evaluate(kShortEval, params->parameters, params->count); 135 DCHECK_NT(POLICY_ERROR != result); 136 137 return POLICY_MATCH == result && ASK_BROKER == processor.GetAction(); 138 } 139 140 // ----------------------------------------------------------------------- 141 142 +// Hooks NtImpersonateAnonymousToken so we can block until call to LowerToken. 143 +// This means a non-retricted token behaves the same as restricted one before 144 +// LowerToken and prevents us from being left with an anonymous logon token 145 +// because we are blocking the RevertToSelf that would undo it. 146 +NTSTATUS WINAPI TargetNtImpersonateAnonymousToken( 147 + NtImpersonateAnonymousTokenFunction orig_ImpersonateAnonymousToken, 148 + HANDLE thread) { 149 + if (!SandboxFactory::GetTargetServices()->GetState()->RevertedToSelf()) { 150 + return STATUS_ACCESS_DENIED; 151 + } 152 + 153 + return orig_ImpersonateAnonymousToken(thread); 154 +} 155 + 156 // Hooks NtSetInformationThread to block RevertToSelf from being 157 // called before the actual call to LowerToken. 158 NTSTATUS WINAPI TargetNtSetInformationThread( 159 NtSetInformationThreadFunction orig_SetInformationThread, 160 HANDLE thread, 161 THREADINFOCLASS thread_info_class, 162 PVOID thread_information, 163 ULONG thread_information_bytes) { 164 diff --git a/sandbox/win/src/policy_target.h b/sandbox/win/src/policy_target.h 165 --- a/sandbox/win/src/policy_target.h 166 +++ b/sandbox/win/src/policy_target.h 167 @@ -14,16 +14,22 @@ namespace sandbox { 168 struct CountedParameterSetBase; 169 170 // Performs a policy lookup and returns true if the request should be passed to 171 // the broker process. 172 bool QueryBroker(IpcTag ipc_id, CountedParameterSetBase* params); 173 174 extern "C" { 175 176 +// Interception of NtImpersonateAnonymousToken on the child process. 177 +// It should never be called directly. 178 +SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtImpersonateAnonymousToken( 179 + NtImpersonateAnonymousTokenFunction orig_ImpersonateAnonymousToken, 180 + HANDLE thread); 181 + 182 // Interception of NtSetInformationThread on the child process. 183 // It should never be called directly. 184 SANDBOX_INTERCEPT NTSTATUS WINAPI TargetNtSetInformationThread( 185 NtSetInformationThreadFunction orig_SetInformationThread, 186 HANDLE thread, 187 THREADINFOCLASS thread_info_class, 188 PVOID thread_information, 189 ULONG thread_information_bytes);