← Back to Feed CACHED · 2026-10-07 00:34:19 · CACHE_KEY CVE-2026-49176
CVE-2026-49176 · CWE-59 · Disclosed 2026-07-14

Windows WalletService Elevation of Privilege via ESE Persisted Callback Abuse

ASSESSED — NOISGATE
Vendor
—
—
—
Reassessed
—
—
—
Verdict: —
Do you agree?
01 · The Real Story

Like leaving a SYSTEM-signed blank check in every user's Documents folder

CVE-2026-49176 is a local privilege escalation in the Windows WalletService present on all supported Windows client and server editions with Desktop Experience. The root cause is an impersonation context switch bug: WalletService resolves FOLDERID_Documents while impersonating the *caller* (standard user), then reverts to LocalSystem before actually opening <Documents>\Wallet\wallet.db. Because a standard user can redirect their Documents folder via SHSetKnownFolderPath and pre-seed a crafted Extensible Storage Engine (ESE) database with a persisted callback column, the service loads an attacker-controlled DLL into its SYSTEM-privileged svchost.exe process. The result is deterministic, race-free code execution as NT AUTHORITY\SYSTEM. Affected builds span Windows 10 1607 through Windows 11 26H1, plus Windows Server 2016, 2019, 2022, and 2025. Microsoft patched it in the July 14, 2026 cumulative updates.

Microsoft rated this Important / HIGH (CVSS 7.8), and that score is well-calibrated. The AV:L prerequisite correctly captures the local-only attack surface, while AC:L and PR:L reflect the trivial exploitation complexity — no heap spray, no race condition, no user interaction. The public PoC from David Carliez and a separate Cobalt Strike Beacon Object File (777erp/CVE-2026-49176_BOF) have turned this into a push-button LPE for any operator with an existing Beacon session. Despite weaponization, the local-access gate prevents a CRITICAL rating. The vendor's 7.8 holds.

"Weaponized LPE: standard user to SYSTEM via WalletService ESE callback abuse, Cobalt Strike BOF available"
02 · The Attack Path

5 steps from start to impact.

STEP 01

Seed the malicious ESE database

The attacker creates a minimal ESE database (wallet.db) with the mandatory Cards table. A tagged column is added with the JET_bitColumnUserDefinedDefault flag, storing a persisted callback specification pointing to an attacker-controlled DLL (e.g., C:\Users\<user>\payload\callback.dll!DllMain). The callback DLL is placed in a sibling directory outside the Wallet subdirectory. This requires only standard user file-write permissions — no admin, no UAC prompt.
Conditions required:
  • Standard (non-admin) interactive or Beacon session on the target host
  • Ability to write files to user-profile directories
Where this breaks in practice:
  • Requires prior compromise — the attacker must already have code execution as a standard user on the machine
Detection/coverage: EDR telemetry for ESE database creation in non-standard paths; Sysmon FileCreate events for wallet.db outside %LOCALAPPDATA%
STEP 02

Redirect FOLDERID_Documents

The attacker calls SHSetKnownFolderPath to redirect their FOLDERID_Documents known folder to a controlled directory containing the seeded Wallet\wallet.db. This is a legitimate Win32 API available to any standard user — no privilege check beyond owning the user profile. The redirection is persisted in the registry under HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders.
Conditions required:
  • User-level access to Shell32 API or PowerShell equivalent
Where this breaks in practice:
  • Some EDR products flag known-folder redirection, though most don't treat it as high-severity
Detection/coverage: Registry modification monitoring on User Shell Folders\Personal; behavioral rule for Documents folder redirection immediately preceding WalletService activity
STEP 03

Trigger WalletService via WinRT API

The attacker invokes Windows.ApplicationModel.Wallet.WalletManager.RequestStoreAsync() followed by GetItemsAsync(). These are public, documented WinRT APIs accessible from any standard user token — no capability or permission gates. This causes WalletService to start (it runs as Manual by default), impersonate the caller to resolve Documents, then revert to LocalSystem before opening the database.
Conditions required:
  • WalletService must be registered and not disabled
  • WinRT Wallet namespace must be accessible (default on all Desktop Experience installs)
Where this breaks in practice:
  • WalletService can be disabled via GPO or registry — but this is not a common hardening step outside mature AD environments
  • Server Core installs do not include WalletService
Detection/coverage: Process creation telemetry showing svchost.exe -k WalletServiceGroup start correlated with prior Wallet API calls; ETW WinRT activation tracing
STEP 04

ESE loads attacker DLL as SYSTEM

WalletService opens the attacker-seeded wallet.db with JET_paramEnablePersistedCallbacks enabled. When it accesses the Cards table, the ESE engine resolves the persisted callback metadata and calls LoadLibrary on the attacker-specified DLL path — now executing in the svchost.exe process running as NT AUTHORITY\SYSTEM. This is the privilege boundary crossing: a user-created artifact triggers SYSTEM-context code execution with zero race conditions.
Conditions required:
  • The seeded database must be well-formed ESE with valid callback metadata
  • The callback DLL must be accessible at the stored path
Where this breaks in practice:
  • Application whitelisting / WDAC policies that block DLL loads from user-writable paths will stop this step
  • Some EDR products detect unusual DLL loads into svchost.exe
Detection/coverage: Module load events showing svchost.exe (WalletService) loading a DLL from a user-profile path; CrowdStrike/Defender for Endpoint suspicious module injection alerts
STEP 05

SYSTEM shell delivery

The callback DLL verifies it holds WinLocalSystemSid, creates a temporary Windows service pointing to a shell broker executable, duplicates the SYSTEM token with the session ID adjusted to the active console session, and spawns cmd.exe on winsta0\default. The temporary service registration is deleted immediately afterward, minimizing forensic artifacts. The attacker now has an interactive SYSTEM shell.
Conditions required:
  • Successful DLL execution in SYSTEM context from step 4
Where this breaks in practice:
  • EDR behavioral detection for SYSTEM-context process creation on interactive desktops
  • Service creation/deletion auditing (Event ID 7045/7036)
Detection/coverage: Windows Event Log 7045 (new service installed) followed by 7036 (service stopped) within seconds; Defender for Endpoint alerts on SYSTEM-context cmd.exe on interactive desktop
03 · Compensating Control

1
HIGH 7.8→IGNORE 0.0
SEVERITY REDUCED
Disable WalletService via GPO or registry — Set HKLM\SYSTEM\CurrentControlSet\Services\WalletService\Start to 4 (Disabled) across your fleet via Group Policy Preferences or SCCM compliance baseline. This completely breaks the attack chain at step 3 — WalletService cannot be triggered if the service is disabled. Microsoft's own fix effectively neuters the service, so disabling it proactively has no operational impact on enterprise workstations or servers. WalletService is used only by the legacy Wallet app, which has no enterprise use case. Deploy within 30 days per the noisgate mitigation SLA for HIGH-severity findings.
2
HIGH 7.8→LOW 2.5
SEVERITY REDUCED
Enforce WDAC or AppLocker DLL rules blocking user-writable paths — Configure Windows Defender Application Control (WDAC) or AppLocker DLL enforcement rules to prevent svchost.exe from loading DLLs out of user-profile directories (C:\Users\*). This blocks step 4 of the chain — even if the attacker seeds the database and triggers WalletService, the ESE callback LoadLibrary call will fail against the WDAC policy. Deploy within 30 days. Note: WDAC DLL enforcement requires careful testing to avoid blocking legitimate user-installed applications.
3
HIGH 7.8→IGNORE 0.0
SEVERITY REDUCED
Deploy July 2026 cumulative updates — Apply KB patches from July 14, 2026 Patch Tuesday across all Windows endpoints. The patch introduces Feature_Servicing_WalletServiceRedirectionGuard which prevents WalletService from opening user-influenced database paths entirely. This is the definitive fix. Target completion within 180 days per the noisgate remediation SLA for HIGH-severity findings. Prioritize RDS/terminal servers and any Server Desktop Experience installs first.
4
HIGH 7.8→MEDIUM 5.5
SEVERITY REDUCED
Monitor for Documents folder redirection + WalletService activation — Deploy detection rules correlating registry writes to HKCU\...\User Shell Folders\Personal with subsequent WalletService (svchost.exe -k WalletServiceGroup) process creation within a 60-second window. Also alert on svchost.exe (WalletService) loading DLLs from user-writable paths. This does not prevent exploitation but provides high-fidelity detection for active exploitation attempts. Deploy within 30 days.
What doesn't work
  • UAC / Admin Approval Mode — the entire chain executes from a standard (medium-integrity) user context. UAC is never triggered because no admin-level operation is requested by the attacker; WalletService itself performs the privileged operations.
  • Network segmentation / firewall rules — this is a local privilege escalation with no network component. No amount of network-level controls affect the attack path.
  • Credential Guard / LSA Protection — these protect credential stores but do not prevent the WalletService impersonation context switch or ESE callback loading. The attacker gains SYSTEM independently of credential-theft defenses.
  • Removing the Wallet app — the vulnerability is in the WalletService *service*, not the UWP Wallet app. Uninstalling the app does not remove or disable the service.
04 · Intelligence Metadata

The supporting signals.

In-the-Wild StatusWeaponized — Cobalt Strike BOF available (777erp/CVE-2026-49176_BOF); Feedly threat intel tags Cobalt Strike as a malware family actively using this. No confirmed mass exploitation campaigns or CISA KEV listing.
Proof-of-ConceptPublic, multiple implementations. Original PoC by DavidCarliez/CVE-2026-49176_LPE_POC (57 ★, 19 forks, released Aug 10 2026) — includes trigger.ps1, build.ps1, and source. Separate Cobalt Strike BOF by 777erp with standalone and BOF modes. Exploit is deterministic and fully automated.
ResearchersDiscovered by Chen Le Qi and Mochi Nishimiya of STAR Labs SG (credited in MSRC advisory). Independent exploit development and PoC by David Carliez (blog writeup).
EPSS0.328% probability of exploitation in next 30 days (15.2nd percentile). Low EPSS likely reflects the local-access prerequisite rather than exploitability.
CVSS VectorCVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H — Local access, low complexity, low privilege required, no user interaction, unchanged scope. Full CIA impact on the host.
Affected VersionsWindows 10 (1607, 1809, 21H2, 22H2), Windows 11 (24H2, 25H2, 26H1), Windows Server 2016/2019/2022/2025. Essentially all supported Windows with Desktop Experience. Server Core is not affected.
Fixed VersionsWin 10 1607: 14393.9339, Win 10 1809: 17763.9020, Win 10 21H2/22H2: 19044.7548/19045.7548, Win 11 24H2: 26100.8875, Win 11 25H2: 26200.8875, Server 2016: 14393.9339, Server 2019: 17763.9020, Server 2022: 20348.5386, Server 2025: 26100.33158. 0patch micropatches available for legacy builds (Win 10 1803–22H2, Win 11 21H2–22H2, Server 2008 R2–2012 R2).
Scanning / ExposureNot remotely exploitable — no Shodan/GreyNoise/Censys exposure surface. This is a local-only vulnerability. Vulnerability scanners (Qualys, Tenable, Rapid7) detect via missing KB/build-number checks.
Disclosure TimelineJuly 14, 2026 — Microsoft advisory and patch release (Patch Tuesday). Aug 10, 2026 — David Carliez public PoC. Oct 2, 2026 — 0patch micropatches for legacy Windows.

Sources.

  1. NVD Detail — CVE-2026-49176
  2. David Carliez — WalletService to SYSTEM exploit writeup
  3. DavidCarliez/CVE-2026-49176_LPE_POC (GitHub)
  4. 777erp/CVE-2026-49176_BOF — Cobalt Strike BOF (GitHub)
  5. CyberSecurityNews — WalletService Vulnerability PoC Released
  6. GBHackers — WalletService Flaw Lets Standard Users Gain SYSTEM Privileges
  7. Strix.ai — CVE-2026-49176 affected versions
  8. AD Hardening — Disable WalletService on DCs
05 · The Call

Final Verdict
= UNCHANGED to HIGH (7.8/10)

Why this verdict

  • Weaponized with public PoC and Cobalt Strike BOF — exploitation is deterministic, race-free, and fully automated. Any operator with a standard-user Beacon session can escalate to SYSTEM in seconds. This keeps the score at or above the vendor baseline.
  • Local access prerequisite is real friction — the attacker must already have code execution as a standard user on the target host. This is a post-initial-access primitive, not an entry vector. It bounds the score below CRITICAL.
  • Wide affected surface with no configuration prerequisite — WalletService is registered and set to Manual start on every Desktop Experience install across all supported Windows versions. The attacker triggers it on demand via public WinRT APIs. No exotic feature flag or optional role required.
  • Role multiplier: Workstations (>80% of Windows installs) — the chain succeeds trivially. Blast radius is host-level (standard user → SYSTEM). Valuable for lateral movement, credential harvesting, EDR tampering, and persistence. Outcome: host compromise. This supports HIGH.
  • Role multiplier: Domain Controllers (~2-3% of Windows Server installs) — WalletService is present on DCs with Desktop Experience (common for Server 2016/2019/2022). The chain technically succeeds if an attacker has any code execution context on the DC. However, standard users do not have interactive logon rights to DCs in properly configured environments, adding significant friction. IF reached, outcome is domain takeover (SYSTEM on a DC = full AD control). This sets the floor at HIGH per the blast-radius rule.
  • Role multiplier: RDS/Terminal Servers and VDI hosts — multi-user environments where a compromised standard user can escalate to SYSTEM and access all user sessions, cached credentials, and security tooling. Blast radius: multi-tenant host compromise. Supports HIGH.
  • No confirmed mass exploitation or KEV listing — despite weaponization, there are no documented campaigns using this at scale. EPSS at 0.328% reflects low observed exploitation probability. This prevents a bump above the baseline.

Why not higher?

The vulnerability requires local authenticated access — it is not remotely exploitable and cannot be used for initial access. The CVSS Scope is Unchanged (S:U), meaning compromise is contained to the target host. While the DC scenario theoretically enables domain takeover, standard users lack interactive logon rights to DCs in any reasonably hardened environment, and the attacker would need a prior compromise of the DC itself. The absence of KEV listing, mass exploitation campaigns, and the low EPSS score all argue against CRITICAL.

Why not lower?

The exploitation chain is trivially reliable — no race condition, no memory corruption, no heap spray, no user interaction. A public Cobalt Strike BOF means this is now standard post-exploitation tradecraft. WalletService is present on every Desktop Experience install with no opt-in required. On RDS/terminal servers, the blast radius extends beyond a single user. The weaponization into CS BOF format means threat actors with initial access *will* use this. Downgrading below HIGH would understate the real-world risk to any fleet running unpatched Windows.

06 · Verification

Crowdsourced verification payload.

Run this script on each target Windows host as any user (no admin required). Execute via powershell.exe -ExecutionPolicy Bypass -File .\Check-CVE-2026-49176.ps1 or paste into a remote PowerShell session. The script checks both the OS build/UBR against fixed versions AND whether WalletService is disabled (compensating control).

noisgate-verify.ps1
POWERSHELLREAD-ONLYSAFE
#Requires -Version 3.0
<#
  Check-CVE-2026-49176.ps1
  Checks whether the host is vulnerable to CVE-2026-49176
  (Windows WalletService LPE via ESE persisted callbacks).
  Exit codes: 1 = VULNERABLE, 0 = PATCHED, 2 = UNKNOWN
#>

$ErrorActionPreference = 'Stop'

try {
    $build = [int](Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' -Name CurrentBuildNumber).CurrentBuildNumber
    $ubr   = [int](Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' -Name UBR).UBR

    # Map build families to fixed UBR thresholds
    $fixedUBR = switch ($build) {
        14393  { 9339  }   # Win 10 1607 / Server 2016
        17763  { 9020  }   # Win 10 1809 / Server 2019
        19044  { 7548  }   # Win 10 21H2
        19045  { 7548  }   # Win 10 22H2
        20348  { 5386  }   # Server 2022
        26100  { 8875  }   # Win 11 24H2 / Server 2025 (client branch)
        26200  { 8875  }   # Win 11 25H2
        28000  { 2269  }   # Win 11 26H1
        default { $null }
    }

    # Check WalletService state
    $svcDisabled = $false
    try {
        $svc = Get-Service -Name WalletService -ErrorAction Stop
        if ($svc.StartType -eq 'Disabled') { $svcDisabled = $true }
    } catch {
        # Service not found (Server Core or removed) - not vulnerable
        Write-Host 'PATCHED - WalletService not present (Server Core or removed).'
        exit 0
    }

    if ($null -eq $fixedUBR) {
        if ($svcDisabled) {
            Write-Host "PATCHED - Build $build.$ubr is not in the known affected range, and WalletService is disabled."
            exit 0
        }
        Write-Host "UNKNOWN - Build $build.$ubr is not in the known affected build family list. Manual review required."
        exit 2
    }

    $patched = $ubr -ge $fixedUBR

    if ($patched) {
        Write-Host "PATCHED - Build $build.$ubr meets or exceeds fixed UBR $fixedUBR."
        exit 0
    } elseif ($svcDisabled) {
        Write-Host "VULNERABLE (MITIGATED) - Build $build.$ubr is below fixed UBR $fixedUBR, but WalletService is disabled."
        exit 0
    } else {
        Write-Host "VULNERABLE - Build $build.$ubr is below fixed UBR $fixedUBR and WalletService is enabled."
        exit 1
    }
} catch {
    Write-Host "UNKNOWN - Error during check: $_"
    exit 2
}