2

Let me start by saying I know next to zero about Windows. My understanding is that processes in Windows get their privileges from a process-level token, which normally would identify the user started the process, but may differ as is common for system tasks, correct? This is somewhat akin to Linux processes having real and effective user and group IDs (it may not be appropriate to make analogies to Linux, but it's all I know). Also, as far as I know, a user can run a process as another user using runas.exe (similar to sudo in Linux). And of course they'll be prompted for the credentials of the user they want to run the process as, and as long as they know the credentials no special permissions are needed, correct?

Now, there is a user right called "Replace a process level token", which according to the docs:

Users with the Replace a process level token user right can start processes as another user if they know the user’s credentials.

Emphasis above is mine. So my question is: if someone knows the credentials for a given user, they can always run a process as them (either using runas.exe or just by logging in as them). What's the purpose of the "Replace a process level token" user right, and what's the security impact of it?

Aayla Secura
  • 271
  • 4
  • 12
  • 1
    You're exactly correct. Windows `CreateProcessAsUser()` is analogous to Linux [su](https://man7.org/linux/man-pages/man1/su.1.html). As the [CreateProcessAsUser() documentation](https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessasusera) says: "CreateProcessAsUser must be able to open the primary token of the calling process with the TOKEN_DUPLICATE and TOKEN_IMPERSONATE access rights." – FoggyDay Jul 22 '20 at 20:40
  • You may wish to read about the `wheel` group and `sudoers` on Linux, where it is definitely not true that "as long as they know the credentials no special permissions are needed" – Ben Voigt Jul 22 '20 at 20:46
  • @BenVoigt ah, yes, on Linux, it's true that they need to be in the `wheel` group by default to use `su` and there needs to be a `sudoers` rule for them to use `sudo`. However, I was talking about windows `runas`. Does `runas` need extra permissions? My test shows "no" – Aayla Secura Jul 22 '20 at 20:59
  • runas.exe usually calls `CreateProcessWithLogonW`, which is implemented as a remote procedure call to the Secondary Logon service, which runs in a SYSTEM process in terminal session 0 (non-interactive services). The Secondary Logon service logs the user on via `LsaLogonUser`, to which it passes the caller's logon session SID to be set in the groups of the new access token, which grants the created process access to the caller's window station and desktop. It sets the token's terminal session ID to that of the caller instead of session 0, and then calls `CreateProcessAsUserW`. – Eryk Sun Jul 22 '20 at 22:08
  • @ErykSun thanks for the detailed info. However, I don't understand how that shows whether or not special permissions are required. Am I right that any user by default can use `runas`? – Aayla Secura Jul 22 '20 at 22:11
  • 1
    Any user has the right to execute runas.exe since `CreateProcessWithLogonW` requires no special privileges. But it's making an RPC call to a privileged service, the Secondary Logon service, which acts on behalf of the user. I don't know what level of protection is implemented in the Secondary Logon service against bad actors, but at least it's a point of system-controlled code that gets to decide what will and will not be allowed. – Eryk Sun Jul 22 '20 at 22:16
  • 1
    As to the wording "*replace* a process level token" for SeAssignPrimaryTokenPrivilege, this is misleading nowadays (NT 6+). Programs aren't allowed to replace the token of a process while it's running. This privilege is strictly about the right for initially *assigning* the token. It used to be -- a long time ago -- that `CreateProcessAsUserW` created a suspended process via `CreateProcessW` and replaced its access token and reset its quota limits before resuming it, but nowadays there's a common `NtCreateUserProcess` system call that handles *all* of this in the process manager in the kernel. – Eryk Sun Jul 22 '20 at 22:19
  • Back to `CreateProcessWithLogonW`, note that the Secondary Logon service does not elevate. When an administrator (except for RID 500) is logged on under UAC, LSA returns a hande to the standard-access token, and that is all that the Secondary Logon service will use. The only privileged access that `CreateProcessWithLogonW` can grant access to, per default UAC policy, is the system's "Administrator" account (RID 500), and by default that account is disabled in NT 6+ systems. – Eryk Sun Jul 22 '20 at 22:26
  • @ErykSun: I don't know what your last comment even means, but what matters is what kind of token the `LogonUser` function returns: restricted or unfiltered. And it can be either one, depending on the flags passed in: https://stackoverflow.com/a/39403260/103167 – Ben Voigt Jul 23 '20 at 14:51
  • @BenVoigt, the standard access token of an administrator is the filtered or limited token (i.e. `TokenElevationTypeLimited`). Limited is the best term. It can also be called "restricted" because it definitely has restrictions (i.e. removed privileges, administrators group set to deny only), but it doesn't have restricting SIDs, and a restricted token from `CreateRestrictedToken` is the same elevation type as the source token, whereas the UAC standard-access token is limited (i.e. `TokenElevationTypeLimited`) at medium integrity level (S-1-16-8192). – Eryk Sun Jul 23 '20 at 15:21
  • @BenVoigt, hope the part about the default UAC policy for the "Administrator" user (RID 500) was understood. As to what the Secondary Logon service could do to get a privileged access token, that is entirely beside the point. If it wanted to elevate, it would not use a batch logon, which is entirely the wrong type (wrong logon-type SID in the access token groups), but instead simply request the linked token, as the Appinfo service does to support elevation. – Eryk Sun Jul 23 '20 at 15:24
  • Also, the Secondary Logon service doesn't use the messy approach of modifying the DACLs of the caller's window station and desktop. I know the documentation for `CreateProcessAsUserW` recommends this, but it's a dirty approach that would grow the DACLs if the service didn't track the logon and remove the ACEs from the DACLs when the logon session is no longer referenced. It takes the much simpler approach of setting the logon-session SID (i.e. flagged `SE_GROUP_LOGON_ID`) in the access token to that of the caller, which grants access to the caller's window station and desktop. – Eryk Sun Jul 23 '20 at 15:35
  • @ErykSun: Ok, my confusion is because you were describing `CreateProcessWithLogonW` (which acquires the token itself, always non-elevated) and I was thinking of `CreateProcessAsUserW` (to which you can pass either a limited or unfiltered token). – Ben Voigt Jul 23 '20 at 16:02

0 Answers0