skip to content

An account in the local Administrators group runs a script that writes into C:\Program Files and gets Access Denied. Why, and what changes when the same script is started with 'Run as administrator'?

level: seniorimportance: should knowfreq 55%

answer

  1. being in the group is not being elevated
  2. two tokens are built at logon
  3. the group SID is present but deny-only
  4. a second check runs before the DACL
  5. elevation makes a new process

basics

~20 s

User Account Control gives an administrator two tokens at logon. Ordinary processes get the filtered one, where the Administrators SID is deny-only and the integrity level is Medium, so ACEs granting Administrators do not apply. Elevation starts a new process with the full token.

solid answer

~50 s

Being in Administrators is not the same as running elevated. At interactive logon Windows builds two tokens for such an account: a full token with the admin group SIDs enabled, admin privileges, and High integrity; and a *filtered* token where the Administrators SID is marked **deny-only**, most privileges are stripped, and the integrity level is Medium. Your desktop, your shell and everything they launch run with the filtered token. Deny-only means that SID still matches Deny ACEs but is ignored for Allow ACEs — so the `Administrators: Full control` entry on `C:\Program Files` grants you nothing, and the write fails. "Run as administrator" does not change the running process; it asks the Application Information service to launch a *new* process with the full token after a consent prompt. Mandatory Integrity Control adds a second gate: a Medium-integrity process cannot write to a High-integrity object regardless of the DACL.

go deeper

for a junior

Know that being a member of Administrators does not mean your programs run with administrative rights, and that starting a program with Run as administrator is what actually gives it those rights.

for a middle

Explain the split token: a filtered token with the Administrators SID deny-only and Medium integrity for ordinary processes, a full token at High integrity after elevation, and that elevation launches a new process rather than upgrading one.

for a senior

Diagnose from the symptom — distinguish an integrity-level block from a DACL denial, know that scheduled tasks need highest privileges configured, that remote connections with local accounts are filtered too, and that mapped drives differ across the two contexts.

for a principal

Argue where the real privilege boundary sits: UAC is not one, so decide between separate administrative accounts, privileged access workstations or just-in-time elevation, and weigh the lateral-movement cost of relaxing remote token filtering for convenience.

## Two tokens, one account When a member of the Administrators group logs on interactively on a system with UAC enabled, the logon process builds **two** access tokens: - the **full (elevated) token** — all group SIDs enabled including Administrators, the full set of administrative privileges present and mostly enabled, integrity level **High** (`S-1-16-12288`); - the **filtered (limited) token** — the Administrators SID and other powerful group SIDs marked *deny-only*, nearly all administrative privileges removed, integrity level **Medium** (`S-1-16-8192`). The user's shell and desktop are started with the filtered token, and every process they launch inherits it. So the everyday session of an administrator is, for access-check purposes, a standard user session that happens to be one consent prompt away from more. ## What deny-only actually means A deny-only group SID is not removed from the token — removing it would change behaviour in the wrong direction. Instead it is flagged so that during an access check it is **considered for Deny ACEs but skipped for Allow ACEs**. The reasoning is conservative: dropping the SID entirely would let an administrator sneak past a Deny entry aimed at administrators, so the SID stays and only its granting power is switched off. Apply that to `C:\Program Files`, whose DACL is roughly "Administrators and SYSTEM: Full control; Users: read and execute": - Under the filtered token, the Administrators ACE is skipped for granting, the Users ACE grants read and execute, and the requested write is never granted → Access Denied. - Under the full token, the Administrators ACE grants everything → the write succeeds. The file was never the problem; the token was. This is exactly why an interviewer likes the question: it separates people who think "admin means root" from people who know Windows splits identity from elevation. ## Mandatory Integrity Control: the second gate Before the DACL is even consulted, Windows performs an integrity check. Every process token carries an integrity level SID, and securable objects may carry a **mandatory label ACE** in their SACL. The ladder is Untrusted (`S-1-16-0`), Low (`S-1-16-4096`), Medium (`S-1-16-8192`), High (`S-1-16-12288`) and System (`S-1-16-16384`). The default policy is *no-write-up*: a subject at a lower integrity level cannot obtain write access to an object at a higher one, even if the DACL would allow it. Sandboxed processes run at Low precisely so that a compromise cannot modify the user's own Medium-integrity files. Integrity levels also gate window messaging between processes at different levels — the mechanism known as User Interface Privilege Isolation — which is why an unelevated tool cannot automate an elevated window. So a write can fail for two independent reasons, and "check the ACL" only addresses one of them. ## What elevation actually does Elevation is **per process, not per session, and not retroactive**. There is no operation that promotes a running process. "Run as administrator", or launching a binary whose manifest declares `requestedExecutionLevel` as `requireAdministrator`, hands the request to the Application Information service, which displays the consent prompt on the secure desktop and then creates a *new* process with the full token at High integrity. Several practical consequences follow: - A script that discovers it needs elevation cannot acquire it in place; it has to relaunch itself. - Drive letters mapped in the unelevated session are not visible to the elevated one, because the two tokens have separate logon-session namespaces (`EnableLinkedConnections` exists to paper over this). - Environment differences between the two contexts cause a lot of "works when I right-click, fails from the scheduler" confusion. - A scheduled task must be configured to run with highest privileges to get the full token; Windows services running as LocalSystem or another service account never see a UAC prompt at all, because UAC applies to interactive logons. ## Remote access is filtered too For local (non-domain) accounts connecting over the network, remote UAC filtering hands out the filtered token as well, so an administrative share or remote management call can fail even though the account is in Administrators. The `LocalAccountTokenFilterPolicy` setting is the documented knob that changes this, and loosening it is a real lateral-movement consideration, not a convenience tweak. Domain accounts in the target's Administrators group are treated differently. ## UAC is not a security boundary Microsoft states this explicitly: UAC is a convenience mechanism that keeps administrators out of full privilege by default and makes privilege escalation visible, but the elevated and unelevated processes share a desktop session and a user profile, and auto-elevating system binaries have repeatedly been abused to bypass the prompt. Treat it as a guardrail against accidental damage, not as an isolation boundary — the real boundary is a separate account or a separate machine. ## The answer in one breath The script ran with the filtered token, so the Administrators ACE on `C:\Program Files` was deny-only and granted nothing, and the Medium integrity level would have blocked the write to a High-integrity location anyway. Elevation starts a *new* process with the full token at High integrity, which satisfies both checks.

  • Why does UAC mark the Administrators SID deny-only instead of removing it from the filtered token?
    Because removing it would let the filtered process slip past Deny ACEs aimed at administrators, weakening security rather than strengthening it. Keeping the SID present but deny-only means it still matches Deny entries while contributing nothing to Allow entries — restrictive in both directions.
  • Can a running unelevated process elevate itself?
    No. Elevation is a property of a token, and a process's token is fixed at creation. The process must relaunch itself — typically via the shell's runas verb — so that the Application Information service creates a new process with the full token after the consent prompt.
  • Do Windows services prompt for UAC consent?
    No. UAC filtering applies to interactive logons. A service running as LocalSystem, LocalService or NetworkService is started by the service control manager with the appropriate token already, so there is no prompt and no filtered token — which is also why service accounts need careful scoping.
  • Why can an elevated command prompt not see the drives you mapped in your normal session?
    The filtered and full tokens belong to different logon sessions, and drive-letter mappings are per logon session. The elevated context therefore starts with none of them. The documented workaround links the two sessions' mappings, but the cleaner fix is to use UNC paths from elevated contexts.

An administrator carries two keyrings. The one in their pocket has had the master key deliberately filed off; the full ring is in a locked drawer, and asking for it opens a new door rather than upgrading the one you already walked through.

saying these in an interview costs you the question

  • Says membership in Administrators means you always have full access
  • Thinks a running process can be elevated in place
  • Believes Access Denied always means the file's ACL is wrong
  • Treats UAC as a security boundary against a local attacker
  • Assumes services show a UAC prompt like desktop applications

context