OAuth Token Theft Through Microsoft's Front Door | Huntress
Huntress researcher Andrew Schwartz demonstrates a novel OAuth token-theft technique: a sideloaded AppX package registered via Add-AppxPackage -Register (requiring only Developer Mode, no admin beyond that toggle) can set ContentUriRules WindowsRuntimeAccess="all" so attacker-controlled JavaScript rendered inside the Microsoft-signed WWAHost.exe process gets full WinRT access, including the legacy WebAuthenticationBroker OAuth API. Using Microsoft Office's own client ID and the oob redirect URI, the attacker triggers a genuine login.microsoftonline.com/MFA dialog with no browser chrome, captures the auth code, and exchanges it for an access token plus a long-lived refresh token carrying the full Office delegated Graph scope set (mail, files, Teams, directory, AuditLog.Create) — validated end-to-end against a live Entra ID tenant with MFA and default Conditional Access. The post frames it as a class of vulnerable signed AppX host binaries sharing the same WinRT activation layer, and provides a Sigma rule keyed on the MSAppHost/3.0 EdgeHTML user agent reaching non-Microsoft destinations, plus Sysmon/Event ID and GPO-based mitigations (restricting Developer Mode, Conditional Access, shorter refresh-token lifetimes, CAE).
What it is
Huntress researcher Andrew Schwartz's OAuth token-theft technique using WWAHost.exe. The catalog summary already has the core chain (sideloaded AppX + WindowsRuntimeAccess="all" → attacker JS in a Microsoft-signed host → real login.microsoftonline.com dialog → captured Office-scoped refresh token). What the summary omits and this page carries: the exact preconditions and error semantics, the mitigation commands, a broader WinRT abuse surface beyond OAuth, and a detection nuance that materially affects the Sigma rule.
Preconditions
- Registration fails closed without one of two gates; the error text
0x80073CFFnames both: Developer Mode or the enterpriseAllowAllTrustedAppssideloading policy. The policy path is the more likely way a managed fleet ends up vulnerable at scale. - Enabling Developer Mode requires admin (UAC-gated Settings toggle, or the HKLM registry write). Everything after the toggle runs as standard user — no UAC, no signature check.
- Common on dev machines, CI/CD runners, cloud VMs; can be pushed fleet-wide by GPO. Not on by default for end users.
- Office first-party client ID: the page cites
d590ed36-52b3-4102-aeff-aad2292ab01cin Step 2 butd3590ed6-52b3-4102-aeff-aad2292ab01cin Figure 8 (an internal inconsistency worth verifying before use). Redirect URIurn:ietf:wg:oauth:2.0:oob. - OAuth chain proven on Windows 11 24H2 (build 26100).
Beyond token theft (same WinRT surface, exercised on 22H2, not re-proven on 24H2)
- CredentialPicker — native OS credential dialog returning plaintext username/password.
- DataProtectionProvider (DPAPI) — encrypt/decrypt in the user's DPAPI context.
- Launcher.launchUriAsync — invoked
powershell:,cmd:,ms-msdt:,search-ms:,ms-officecmd:(some payloads Defender-blocked, launch mechanism succeeds). - WebAuthBroker
silentMode— expected to yield PRT-backed tokens with no UI on a domain-joined machine; author explicitly did not confirm this end-to-end.
Detection caveat that the summary hides
The Sigma rule keys on the exfil leg's user agent MSAppHost/3.0 (EdgeHTML) to non-Microsoft hosts. But the sign-in leg is rendered by a different host — Entra logs record ...Trident/7.0; MSAuthHost/1.0; rv:11.0. So the Entra sign-in record looks like a clean Office sign-in (App "Microsoft Office", "Mobile Apps and Desktop clients", credential type None, no CA failure) and the rule will not fire on identity telemetry — only on proxy/network egress. Fixing individual binaries or an EDR rule for wwahost.exe alone is futile; the flaw is in the shared WinRT activation layer, so block the network signature, not the host.
Allow-list tradeoff: broadening the Microsoft-owned domain list cuts false positives but opens evasion via an open redirect / abandoned tenant subdomain / attacker SharePoint site on a Microsoft-owned domain. High-security environments can run the narrow list (.microsoft.com, .microsoftonline.com, .windows.net) and eat the noise.
What to do
Disable the prerequisite via GPO: Computer Configuration > Administrative Templates > Windows Components > App Package Deployment > Allow all trusted apps to install > Disabled (closes both Developer Mode and the enterprise policy path).
Inventory Developer Mode across the fleet:
$devMode = Get-ItemProperty `
-Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock" `
-Name "AllowDevelopmentWithoutDevLicense" -ErrorAction SilentlyContinue
if ($devMode.AllowDevelopmentWithoutDevLicense -eq 1) {
Write-Host "DEVELOPER MODE ON: $env:COMPUTERNAME"
}Corroborating IOCs (validated in lab, native — no Sysmon required): AppXDeploymentServer/Operational Event 400 (register success) and 613 (timing only); PowerShell script-block 4104 captures the manifest; WFP Security Event 5156 records the AppX-host process image + destination IP on outbound connections.
Also: CA requiring compliant/managed devices for token issuance (limits refresh-token reuse from unmanaged machines), Token Protection, shorter refresh-token lifetimes, and CAE to shrink the persistence window.
Caveats
Delegated scopes mean effective power is the intersection of the token scope and the victim's own privilege — Directory.Read.All here reads only what that user could read; blast radius scales with the victim's role. Author is deliberate about "proven" (WWAHost token theft, end-to-end) vs merely "available" (namespace resolves) for the wider host class and the extra capabilities above.
Organisations named here
- AllowAllTrustedApps
- AuditLog.Create
- Continuous Access Evaluation
- Dirk-jan Mollema
- MSAppHost/3.0
- MSIX'd Up: Weaponizing the Modern Windows App Packaging Ecosystem
- Nick Powers
- Token Protection
Technologies named here
- Windows 11 24H2
- Add-AppxPackage
- Windows 11 22H2
- WebAuthenticationBroker.authenticateAsync
- WWAHost.exe
- kali_listener.py
- AppX web-host family
- register_appx.ps1
- WebAuthenticationBroker
- exchange_token.py
- Microsoft Entra ID
- ApiInformation.IsTypePresent
- Sysmon
- Microsoft Office
- Microsoft Graph API
- Windows Filtering Platform auditing / Security Event 5156
- AppXDeploymentServer/Operational Event Log
- PowerShell Script Block Logging
- Sigma
- CredentialPicker
- DataProtectionProvider / DPAPI
- Launcher.launchUriAsync
- askWAM
- Conditional Access / Continuous Access Evaluation
- Windows
- OAuth
- PowerShell
- Kali Linux
Techniques named here
- Signed-binary proxy execution via AppX web host
- OAuth token theft via WinRT WebAuthenticationBroker
- Sideloading of malicious AppX package
- Refresh token persistence / abuse
- Credential capture via fake-but-real system dialog
- Protocol handler abuse for code execution
- Silent/PRT-backed token acquisition
- Network detection via anomalous EdgeHTML user agent
Related in Identity & Access
Education Under Attack: The Pattern Behind Recent University Breaches
Next-Gen Phishing Tactics Users Aren’t Ready For | Huntress
.png)
Google API keys keep working after you delete them
