PoC, IOCs, and detection logic for the SharePoint /_trust WS-Federation BinaryFormatter deserialization chain. Lab reconstruction covering unauthenticated RCE, in-process machine key theft, and the artifacts each variant leaves behind. SharePoint 2016, 2019, and Subscription Edition. CVE-2026-50522, CVE-2026-45659, CVE-2026-56164, CVE-2026-58644.
/_trust WS-Federation Deserialization: PoC & Detection NotesLive writeup (GitHub Pages): https://sp-poc.wismansec.com/ (HTML rendering of this document).
Affected: SharePoint Server 2016, 2019, and Subscription Edition.
Reconstruction of a SharePoint Server (Subscription Edition) intrusion in an isolated lab, built to (a) understand the full attacker capability, (b) determine what a defender should hunt for, including stealthy persistence, and (c) share a PoC to aid other investigators.
Authorized research only. Everything here was performed on isolated, personally-owned lab hardware and accounts, against a build deliberately left unpatched for the test. The underlying issue is fixed by the vendor; apply the current updates. Do not run this against systems you do not own and have explicit authorization to test. Machine-key values, internal hostnames/IPs, and callback domains are redacted in the text and example artifacts. The SIEM screenshots are unmodified and carry the lab's real names; see the note in §4.
/_trust SecurityContextToken BinaryFormatter deserialization familyPOST /_trust/default.aspx (WS-Federation sign-in) carrying a malicious SecurityContextToken triggers BinaryFormatter deserialization in the SharePoint worker (w3wp.exe), yielding remote code execution as the web-app pool identity./_trust detects and blocks it; see §5). Those keys let an attacker forge __VIEWSTATE/auth tokens that survive patching./_trust request signature, which is the one artifact present in every variant.SharePoint exposes a WS-Federation passive sign-in endpoint at /_trust/default.aspx. A crafted sign-in response (wa=wsignin1.0 + wresult=<RequestSecurityTokenResponse>) embeds a SecurityContextToken whose <Cookie> element is a base64, DEFLATE-compressed BinaryFormatter stream. Server-side, that cookie is decompressed and deserialized without type restriction, so a gadget chain (via ysoserial.net) executes attacker-controlled code inside w3wp.exe.
Request skeleton (unauthenticated):
POST /_trust/default.aspx HTTP/1.1
Content-Type: application/x-www-form-urlencoded
wa=wsignin1.0&wctx=<url>&wresult=<RequestSecurityTokenResponse>...
<SecurityContextToken><Cookie>BASE64(DEFLATE(BinaryFormatter payload))</Cookie>...
| Chain | Gadget | Effect | Output channel |
|---|---|---|---|
| OOB RCE | TypeConfuseDelegate → -EncodedCommand PowerShell | code execution as pool identity | out-of-band (HTTP/DNS beacon) |
| Machine-key disclosure | ActivitySurrogateDisableTypeCheck → ActivitySurrogateSelectorFromFile (compiles KeyDump.cs in-proc) | dumps ValidationKey/DecryptionKey | inline in the HTTP response |
Scripts (sanitized) in scripts/: a parameterized OOB RCE and the two-stage key-dump. Payload delivery uses PowerShell -EncodedCommand so multi-statement payloads survive the cmd.exe/transport layers intact (no ;/&& quoting breakage).
Single SharePoint SE farm (build pinned pre-fix), app-pool identity LAB\sp_pool, PowerShell 5.1, Microsoft Defender on with cloud protection. Telemetry (Windows Event Log, SharePoint logs, Defender for Endpoint) shipped to nano, a lightweight open-source SIEM; attacker host ran ysoserial.net; an interactsh client provided the OOB listener. Addresses and domains are redacted in the text; see the screenshot note in §4.
Every row is one real detonation; artifacts pulled from the SIEM + OOB listener per run.
Screenshots are unmodified. They carry the lab's real host and NetBIOS names, which are crude and differ from the sanitized
SHAREPOINT01/LABused throughout the text. Same runs, same events, nothing staged. Work-safe equivalents inartifacts/.
| Invocation | Process tree (as LAB\sp_pool, High) | Defender | OOB beacon | Primary artifacts |
|---|---|---|---|---|
| OOB RCE, default | w3wp.exe → cmd.exe → powershell.exe → conhost.exe | Behavior:Win32/WebshellLauncher.A (EID 1116 detect / 1117 Remove) | landed (race) | 4688 tree; Defender 1116/1117; /_trust POST |
OOB RCE, -RawCmd | w3wp.exe → powershell.exe → conhost.exe (no cmd) | none | landed (DNS+HTTP) | 4688 tree; /_trust POST; beacon |
OOB RCE, -DropFile | w3wp.exe → powershell.exe | none | landed | file write to …\TEMPLATE\LAYOUTS\ (not in object-access-audited log) |
OOB RCE, -Diag | w3wp.exe → powershell.exe → whoami.exe | none | landed | env disclosure exfil: {host, whoami, PSver, LanguageMode} |
| Machine-key dump | (none, in-process) | none | (none) | only the /_trust POST + anomalous response carrying the keys |
These outcomes are for the default AMSI configuration (Balanced mode, /_trust not scanned). With AMSI request-body scanning of /_trust enabled (Full mode or targeted), every row is instead blocked at the request layer: HTTP 400, Exploit:Script/SpCookieExec.A, before execution (see §5).

All four documented detonations, 15:01 to 15:18 UTC, every child of w3wp.exe running as the pool identity. Three of the four are powershell.exe spawned directly. Only the 15:03:34 run goes through cmd.exe, and only that run was detected. Widen the window past this one and earlier development iterations from the same morning enter the result set, so the claim is scoped to these four runs.

Default invocation: w3wp.exe → cmd.exe → powershell.exe, with conhost.exe alongside. This is the shape Behavior:Win32/WebshellLauncher.A keys on.

-RawCmd invocation, same primitive and same payload, with the cmd.exe hop removed. Defender produced nothing for this run. A detection built on w3wp → cmd misses it entirely.

Every Defender event in the same 25-minute window that contained four detonations. All three belong to the single cmd.exe run: two malware_detected at Severe, then malware_action_taken with action Remove. Remediation did not beat the beacon, which completed first.
Key command line recovered verbatim from Security 4688 (encoding ≠ evasion):