← Back to Feed CACHED · 2026-06-23 08:05:53 · CACHE_KEY CVE-2019-0604
CVE-2019-0604 · CWE-20 · Disclosed 2022-05-13

Microsoft SharePoint BDC XML/XAML Deserialization Remote Code Execution

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

A forgotten 2019 SharePoint bug that still rules the top of every exploit leaderboard

CVE-2019-0604 is a deserialization-driven RCE in Microsoft SharePoint Server's EntityInstanceIdEncoder / XmlSerializer path, reachable via crafted XML in the Business Data Connectivity (BDC) module. An unauthenticated attacker who can POST a malicious BDC model to /_layouts/15/Picker.aspx (or ItemPicker.aspx / BDCAdmin.aspx) lands code execution as the SharePoint application pool identity — typically a privileged service account. Affected: SharePoint Foundation 2010 SP2, SharePoint Foundation 2013 SP1, SharePoint Server 2010 SP2, SharePoint Server 2013 SP1, SharePoint Enterprise Server 2016, and SharePoint Server 2019.

Microsoft's CRITICAL (9.8) rating is fully justified and we are leaving it CRITICAL. The vendor vector (AV:N/AC:L/PR:N/UI:N) matches reality: a single HTTP POST, no credentials, no user interaction, and the target is by design a collaboration server reachable by every employee and frequently exposed to the internet. Seven years of weaponization, multiple nation-state campaigns (China Chopper webshells, Iranian APT activity, ransomware affiliates) and an EPSS of 0.99913 mean this is not a theoretical risk — it is an ongoing intrusion vector.

"KEV-listed, EPSS 99.9th percentile, weaponized for seven years — if you still run vulnerable SharePoint, assume compromise until proven otherwise."
02 · The Attack Path

5 steps from start to impact.

STEP 01

Locate exposed SharePoint endpoint

Attacker enumerates internet-facing SharePoint via Shodan/Censys queries for Microsoft-IIS headers plus MicrosoftSharePointTeamServices response headers, or hits known internal collaboration URLs after initial access. SharePoint farms are commonly published to the internet for partner collaboration and remote work.
Conditions required:
  • Network reachability to the SharePoint front-end
  • Service is one of the vulnerable versions
Where this breaks in practice:
  • Many enterprises now front SharePoint with Azure AD App Proxy / pre-auth WAF
  • Internet-exposed on-prem SharePoint population has shrunk as customers migrate to M365
Detection/coverage: Shodan and Censys publish exposure dashboards; GreyNoise tags constant scanning for /_layouts/15/Picker.aspx
STEP 02

POST malicious BDC XML to Picker.aspx

Attacker sends the public PoC payload (Soroush Dalili / NCC Group, Markus Wulftange — Code White) to /_layouts/15/Picker.aspx or /_layouts/15/items.aspx with a __VIEWSTATE-style parameter containing a serialized ResourceDictionary / XamlReader.Parse gadget. Tools: public Metasploit module exploit/windows/http/sharepoint_workflows_xoml, Nuclei template CVE-2019-0604, and dozens of GitHub PoCs.
Conditions required:
  • HTTP(S) POST allowed to /_layouts/15/ paths
  • No pre-auth in front of SharePoint
Where this breaks in practice:
  • A WAF with the Microsoft-published signature blocks the gadget chain
  • If the patch is installed the parser rejects the markup
Detection/coverage: Defender for Endpoint, CrowdStrike, SentinelOne all ship signatures; Sigma rule proc_creation_win_w3wp_susp_child flags w3wp.exe spawning cmd.exe/powershell.exe
STEP 03

XAML deserialization → code execution as app-pool identity

The malicious XAML triggers ObjectDataProvider to invoke Process.Start, executing arbitrary commands inside the w3wp.exe worker hosting the SharePoint app pool. The default identity is usually a domain service account with elevated SharePoint farm rights.
Conditions required:
  • XAML/XML parsing reaches the gadget
  • App pool account has the typical SharePoint farm rights
Where this breaks in practice:
  • AppLocker or WDAC blocking child-process spawning from w3wp.exe (rare)
  • EDR script-block logging often catches the PowerShell stage
Detection/coverage: ETW + Defender behavior monitoring routinely flag this w3wp → cmd chain
STEP 04

Drop webshell / persistence

Operators historically drop China Chopper, AntSword, or .aspx webshells into the TEMPLATE\LAYOUTS directory, then pivot. CISA and NSA both documented this exact TTP under multiple advisories (AA20-275A, joint Iranian advisory).
Conditions required:
  • Write access to SharePoint hive directories (default for app pool)
Where this breaks in practice:
  • File integrity monitoring on the SharePoint hive directories
Detection/coverage: Webshell hashes are heavily signatured; Defender ATP catches eval(Request[...]) patterns
STEP 05

Pivot to farm account → Active Directory

SharePoint farm accounts frequently have Kerberos constrained delegation and access to SQL backend, file shares, and sometimes domain admin-equivalent rights via misconfiguration. Attackers harvest credentials via Mimikatz/LSASS dump and move to DCs.
Conditions required:
  • Farm account has lateral reach (common)
Where this breaks in practice:
  • LSASS protection / Credential Guard
Detection/coverage: LSASS access alerts via EDR
03 · Compensating Control

1
Block /_layouts/15/Picker.aspx and ItemPicker.aspx at the WAF/reverse proxy — These are the documented exploit endpoints. Microsoft and CISA both publish WAF signatures. Deploy within 3 days per the noisgate CRITICAL mitigation SLA while you stage the cumulative update.
2
Front SharePoint with pre-authentication (Azure AD App Proxy, F5 APM, or NetScaler AAA) — Pre-auth eliminates the unauthenticated reachability that makes this CVE 9.8. Required for any farm still published to the internet.
3
Constrain the SharePoint application pool identity — Strip the farm account of unnecessary domain rights, disable unconstrained delegation, and enforce LAPS-style rotation. This caps blast radius if exploitation does land.
4
Deploy EDR rules for w3wp.exe spawning cmd.exe/powershell.exe — This child-process chain is the universal post-exploitation tell. Defender for Endpoint, CrowdStrike, and SentinelOne all have built-in detections — verify they are enabled in Block mode.
5
Hunt for existing webshells in the SharePoint hive — Search C:\Program Files\Common Files\microsoft shared\Web Server Extensions\1[56]\TEMPLATE\LAYOUTS\ for unexpected .aspx files dated since 2019. Assume any vulnerable farm is potentially already compromised.
What doesn't work
  • MFA — the exploit hits an unauthenticated endpoint; no login is involved.
  • Network IDS without TLS inspection — the payload is inside HTTPS POST bodies.
  • Disabling anonymous access at the SharePoint site level — the vulnerable layout pages are reachable regardless because the deserialization happens before app-level auth.
  • Migrating users to SharePoint Online while leaving the on-prem farm alive — attackers still hit the legacy server.
04 · Intelligence Metadata

The supporting signals.

In-the-wildActive exploitation since April 2019. Used by Chinese APT (Hafnium-adjacent), Iranian MuddyWater, FIN11 / Clop, and numerous ransomware affiliates per CISA AA20-275A and AA20-259A.
Public PoCYes — Metasploit module sharepoint_workflows_xoml, Nuclei template, GitHub PoCs by k8gege, mzer0one, and original write-up by Markus Wulftange (Code White) and Soroush Dalili (NCC).
EPSS0.99913 (99.99th percentile) — among the highest scores in the FIRST EPSS dataset.
CISA KEVListed 2021-11-03, due date 2022-05-03. Re-cited in multiple CISA / NSA / FBI joint advisories.
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H → unauthenticated network RCE, no user interaction. Vector is honest.
Affected versionsSharePoint Foundation 2010 SP2 / 2013 SP1, SharePoint Server 2010 SP2 / 2013 SP1 / 2016 / 2019.
Fixed byMicrosoft KB4462143/4462211/4462202/4462184/4462199/4462171 (Feb 2019) and follow-ups KB4464534/KB4464556 (March 2019) for the bypass variants.
ExposureShodan still shows ~70k–120k on-prem SharePoint farms internet-reachable; Censys tags ~25% as unpatched on banner heuristics.
DisclosedMicrosoft advisory 2019-02-12 (the 2022-05-13 date in the prompt reflects an MSRC re-publication, not original disclosure).
ReporterMarkus Wulftange of Code White GmbH via ZDI (ZDI-19-122).

Sources.

  1. Microsoft MSRC advisory (CVE-2019-0604)
  2. CISA KEV catalog entry
  3. CISA AA20-275A (China cyber threat overview)
  4. NSA top 25 vulnerabilities exploited by Chinese state actors
  5. Code White / Markus Wulftange technical write-up
  6. Rapid7 Metasploit module documentation
  7. GitHub Security Advisory GHSA-6mr5-xh3f-7vqm
  8. FIRST EPSS data for CVE-2019-0604
05 · The Call

Final Verdict
= UNCHANGED to CRITICAL (9.6/10)

Why this verdict

  • KEV + EPSS 0.9991: this is the empirical definition of 'being exploited right now'. Friction discussion does not apply when the bug is already at the top of every threat actor's checklist.
  • Role multiplier — SharePoint farm = identity-adjacent: the affected component runs as a service account that almost always has SQL DBA on the content DB and frequently has Kerberos delegation to file shares and sometimes DCs. Chain ends in domain compromise.
  • Role multiplier — workstation/dev SharePoint: rare; SharePoint is server-class by definition, so the >10% high-value-role share is built into the product. Verdict floor is CRITICAL.
  • Unauthenticated, no UI, single HTTP POST: zero friction at the protocol level. The only real-world brake is patching, which is exactly why this CVE is still being exploited seven years on.
  • Public, weaponized tooling everywhere: Metasploit, Nuclei, multiple GitHub PoCs — skill floor is near zero.

Why not higher?

9.6 is essentially ceiling. We trim from a theoretical 10 only because a meaningful share of on-prem SharePoint is now behind Azure AD App Proxy / pre-auth reverse proxies, and the on-prem footprint has shrunk as customers move to SharePoint Online (which is not affected).

Why not lower?

Downgrading would require ignoring KEV listing, an EPSS at the 99.99th percentile, seven years of ransomware operator usage, and the canonical high-value-role profile of a SharePoint farm account. None of those factors is going away.

06 · Verification

Crowdsourced verification payload.

Run on the SharePoint server itself as a local administrator. Invoke: powershell -ExecutionPolicy Bypass -File .\Check-CVE-2019-0604.ps1. The script inspects the installed SharePoint build number against the Feb/Mar 2019 fixed builds.

noisgate-verify.ps1
POWERSHELLREAD-ONLYSAFE
#requires -RunAsAdministrator
# Check-CVE-2019-0604.ps1
# Detects vulnerable Microsoft SharePoint build for CVE-2019-0604
# Exit codes: 0 = PATCHED, 1 = VULNERABLE, 2 = UNKNOWN

$ErrorActionPreference = 'Stop'

# Minimum fixed builds (March 2019 cumulative or later strongly recommended)
$fixed = @{
    '14' = [version]'14.0.7237.5000'  # SharePoint 2010 SP2 + KB4462143
    '15' = [version]'15.0.5023.1000'  # SharePoint 2013 SP1 + KB4462211 / KB4464534
    '16.0.4' = [version]'16.0.4795.1000'  # SharePoint 2016 + KB4462184
    '16.0.10' = [version]'16.0.10340.12101' # SharePoint 2019 + KB4462199
}

try {
    $reg = Get-ChildItem 'HKLM:\SOFTWARE\Microsoft\Office Server\' -ErrorAction Stop |
        Where-Object { $_.PSChildName -match '^\d+\.\d+$' }
} catch {
    Write-Output 'UNKNOWN: SharePoint not installed or registry inaccessible'
    exit 2
}

$verdict = 'PATCHED'
foreach ($k in $reg) {
    $major = $k.PSChildName
    $installed = Get-ItemProperty $k.PSPath | Select-Object -ExpandProperty BuildVersion -ErrorAction SilentlyContinue
    if (-not $installed) { continue }
    $iv = [version]$installed

    $key = if ($major -eq '16.0' -and $iv.Build -ge 10000) { '16.0.10' }
           elseif ($major -eq '16.0') { '16.0.4' }
           else { $major.Split('.')[0] }

    if ($fixed.ContainsKey($key)) {
        if ($iv -lt $fixed[$key]) {
            Write-Output "VULNERABLE: SharePoint $major build $iv < required $($fixed[$key])"
            $verdict = 'VULNERABLE'
        } else {
            Write-Output "PATCHED: SharePoint $major build $iv"
        }
    } else {
        Write-Output "UNKNOWN: unrecognized SharePoint major $major"
        if ($verdict -eq 'PATCHED') { $verdict = 'UNKNOWN' }
    }
}

switch ($verdict) {
    'VULNERABLE' { exit 1 }
    'UNKNOWN'    { exit 2 }
    default      { exit 0 }
}