tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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);