# CVE-2025-59511 — WLAN AutoConfig `wlansvc.dll` Registry-Symlink EoP: User Data Handled Under SYSTEM Without Impersonation in `CdsTriggerSync*`

---

## Summary

| | |
|---|---|
| **Product** | Windows — `wlansvc.dll` (WLAN AutoConfig service, runs as SYSTEM) |
| **CVE ID** | CVE-2025-59511 |
| **Impact** | Elevation of Privilege |
| **CWE** | CWE-59: Improper Link Resolution Before File Operation / External Control of File Name or Path |
| **CVSS** | 7.8 — `CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H` |
| **Patch Date** | November 11, 2025 |
| **Pre-patch binary** | `wlansvc.dll` 10.0.26100.7019 (Oct 28 2025) — SHA256 `187597802e4e45fba6df36cad00bb420bcea66842eda9dd45c79c67db25df48b` |
| **Post-patch binary** | `wlansvc.dll` 10.0.26100.7171 (Nov 11 2025) — SHA256 `f8ccb40338fe7bdbee24c5b1d62dd54523efec79922822c28c736c7a6660d874` |
| **Fix gating** | None — impersonation added directly |

---

## Product Description

The **WLAN AutoConfig service (`wlansvc`)** configures, discovers and connects
Wi-Fi networks and runs as **NT AUTHORITY\SYSTEM**. It maintains per-user Wi-Fi
profile-sync state under
`HKLM\SOFTWARE\Microsoft\WlanSvc\ProfileSync\<Current User SID>`.

---

## Vulnerability Summary

The profile-sync trigger functions (`CdsTriggerSync*`) retrieve the **session
user's token** via `UMgrQueryUserToken`, then call
`Windows::Internal::WiFiCloudStore::IsSyncNeededForUser` with that token **but
without impersonating it** — so the registry work runs under **SYSTEM**:

```c
// CdsTriggerSyncIfNeededForLoggedInUsers (10.0.26100.7019) — PRE-PATCH, from our decompilation
v11 = UMgrQueryUserToken(*(v16 + 16*v10), &hObject);   // session user's token
...
IsSyncNeededForUser = WiFiCloudStore::IsSyncNeededForUser(hObject, &v21, v12);  // *** runs as SYSTEM, no impersonation ***
```

Inside `IsSyncNeededForUser`, keys are opened by name under the per-user
`ProfileSync` tree — `OpenGenericSyncBaseKeyForUser(&hKey, L"Profiles")` and
`...L"Cost"`, and the `WlanSvcTaskBootstrapped` DWORD is read to decide whether to
proceed. Because a standard user has write access under
`ProfileSync\<SID>`, they can replace the `Profiles` / `Cost` / `NLM` path
components with **registry symbolic links** pointing into sensitive system hives.
The SYSTEM service then opens/creates/reads those targets **with SYSTEM
authority**, letting the attacker direct privileged registry operations at
protected locations (CWE-59 / external control of path).

---

## Prerequisites and Constraints

- Local, low-privileged (`PR:L`).
- The user sets `WlanSvcTaskBootstrapped = 1` under
  `HKLM\SOFTWARE\Microsoft\WlanSvc\ProfileSync\<SID>` (they own that subtree),
  then plants registry symlinks for the `Profiles` / `Cost` / `NLM` path segments
  pointing at a protected hive.
- Triggering a profile sync (service restart / natural trigger) makes SYSTEM
  follow the symlink and act on the target — EoP.

---

## Vulnerability Details

### Call Chain

```
Local user (owns HKLM\...\WlanSvc\ProfileSync\<SID>):
  sets WlanSvcTaskBootstrapped=1 and plants registry symlinks (Profiles/Cost/NLM)
        ↓  (service trigger; SYSTEM)
  wlansvc!CdsTriggerSyncIfNeededForLoggedInUsers  (also …WithProfileDeletion / …IfProfileEligible)
    UMgrQueryUserToken(session user) -> hObject
    WiFiCloudStore::IsSyncNeededForUser(hObject)          // *** no impersonation -> SYSTEM ***
      OpenGenericSyncBaseKeyForUser("Profiles"/"Cost")     // opens attacker-symlinked keys as SYSTEM
```

### Root Cause

The service holds the user's token but performs the registry work in its own
**SYSTEM** security context (no impersonation). User-controlled registry path
components are therefore resolved with SYSTEM authority, so attacker-planted
symbolic links redirect privileged operations (CWE-59).

### The patch (confirmed — decompilation diff, .7019 → .7171)

The three `CdsTriggerSync*` functions are changed to **switch the thread's
security context to the target user before the operation**: they `DuplicateToken`
the queried user token and `wil::impersonate_token_nothrow` it, perform the
`IsSyncNeededForUser` work **impersonated**, then `RevertImpersonateToken`; if
token acquisition/impersonation fails, the operation is halted:

```c
// CdsTriggerSyncIfNeededForLoggedInUsers (10.0.26100.7171) — PATCHED, from our decompilation
if (!DuplicateToken(hObject, SecurityImpersonation, &DuplicateTokenHandle)) { ...fail-safe halt... }
v16 = wil::impersonate_token_nothrow(DuplicateTokenHandle, &v27);   // *** impersonate the user ***
if (v16 < 0) { ...halt... }
v21 = WiFiCloudStore::IsSyncNeededForUser(hObject, &v34, v17);      // now runs as the user
...
wil::details::RevertImpersonateToken(v27, ...);                     // revert
```

Under impersonation, registry access is evaluated with the **user's** rights, so a
symlink into a system hive fails with access-denied instead of being honoured —
closing the redirection. Our decompilation shows PRE = 0 and POST = 22
impersonation-related calls across these functions. Unconditional fix (no feature
flag).

---

## Detection Guidance

**Behavioural.** Standard users writing `WlanSvcTaskBootstrapped=1` and creating
registry symbolic links for the `Profiles` / `Cost` / `NLM` segments under
`HKLM\SOFTWARE\Microsoft\WlanSvc\ProfileSync\<SID>`, followed by SYSTEM
(`wlansvc`) registry operations against protected hives.

**Registry.** Auditing on the `WlanSvc\ProfileSync` subtree for
`REG_OPTION_CREATE_LINK` and for cross-hive redirection during Wi-Fi profile sync.

---

## References

- MSRC advisory — CVE-2025-59511
- Full decompilation diff: `/data/patch_diffs/wlansvc_dll-cve-2025-59511-ghidriff.md`
- Related registry-symlink / missing-impersonation EoPs: CVE-2025-59512, CVE-2025-59514, CVE-2022-30225
