Windows.Detection.Impersonation

An access token is an object that describes the security context of a process or thread. The information in a token includes the identity and privileges of the user account associated with the process or thread. When a user logs on, the system verifies the user’s password by comparing it with information stored in a security database.

Every process has a primary token that describes the security context of the user account associated with the process. By default, the system uses the primary token when a thread of the process interacts with a securable object. Moreover, a thread can impersonate a client account. Impersonation allows the thread to interact with securable objects using the client’s security context. A thread that is impersonating a client has both a primary token and an impersonation token.

This artfiact enumerates all threads on the system which have an impersonation token. I.e. they are operating with a different token then the token the entire process has. For example mimikatz has a command called token::elevate to do just such a thing:

mimikatz # privilege::debug
Privilege '20' OK

mimikatz # token::elevate
Token Id  : 0
User name :
SID name  : NT AUTHORITY\SYSTEM

688     {0;000003e7} 1 D 42171          NT AUTHORITY\SYSTEM     S-1-5-18        (04g,21p)       Primary
-> Impersonated !
* Process Token : {0;000195ad} 1 F 757658339   DESKTOP-NHNHT65\mic     S-1-5-21-2310288903-2791442386-3035081252-1001  (15g,24p)       Primary
* Thread Token  : {0;000003e7} 1 D 759094260   NT AUTHORITY\SYSTEM     S-1-5-18        (04g,21p)       Impersonation (Delegation)

name: Windows.Detection.Impersonation
description: |
  An access token is an object that describes the security context of
  a process or thread. The information in a token includes the
  identity and privileges of the user account associated with the
  process or thread. When a user logs on, the system verifies the
  user's password by comparing it with information stored in a
  security database.

  Every process has a primary token that describes the security
  context of the user account associated with the process. By default,
  the system uses the primary token when a thread of the process
  interacts with a securable object. Moreover, a thread can
  impersonate a client account. Impersonation allows the thread to
  interact with securable objects using the client's security
  context. A thread that is impersonating a client has both a primary
  token and an impersonation token.

  This artfiact enumerates all threads on the system which have an
  impersonation token. I.e. they are operating with a different token
  then the token the entire process has. For example mimikatz has a
  command called `token::elevate` to do just such a thing:

  ```
  mimikatz # privilege::debug
  Privilege '20' OK

  mimikatz # token::elevate
  Token Id  : 0
  User name :
  SID name  : NT AUTHORITY\SYSTEM

  688     {0;000003e7} 1 D 42171          NT AUTHORITY\SYSTEM     S-1-5-18        (04g,21p)       Primary
  -> Impersonated !
  * Process Token : {0;000195ad} 1 F 757658339   DESKTOP-NHNHT65\mic     S-1-5-21-2310288903-2791442386-3035081252-1001  (15g,24p)       Primary
  * Thread Token  : {0;000003e7} 1 D 759094260   NT AUTHORITY\SYSTEM     S-1-5-18        (04g,21p)       Impersonation (Delegation)
  ```
reference:
  - https://github.com/kslgroup/TokenImp-Token_Impersonation_Detection/blob/master/TokenImp%20documentation.pdf


precondition: SELECT OS From info() where OS = 'windows'

sources:
  - query: |
      LET processes = SELECT Pid AS ProcPid, Name AS ProcName,
               Username, OwnerSid, TokenIsElevated,
               CommandLine, Exe
        FROM pslist()
        WHERE log(message=format(format="Inspecting %s (%v)", args=[ProcName, Pid]))

      SELECT * FROM foreach(row=processes,
          query={
             // List all the threads and check that their tokens are the
             // same as the process token.
             SELECT ProcPid, ProcName, Username, OwnerSid, TokenIsElevated,
               CommandLine, Exe, ThreadInfo.TokenInfo AS ImpersonationToken
             FROM handles(pid=ProcPid, types='Thread')
             WHERE ImpersonationToken.User AND ImpersonationToken.User != OwnerSid
          })