A SharePoint workflow compiler that trusts user-supplied XML like a valet who starts any car you hand them keys to
CVE-2020-0646 is a code-injection flaw in the .NET Framework's System.Workflow.Activities namespace. When SharePoint on-premise processes XOML (Extensible Object Markup Language) workflow definitions, the CallExternalMethodActivity's InterfaceType attribute is compiled into C# without sanitizing embedded characters. An authenticated SharePoint user can inject arbitrary C# into the generated code, achieving remote code execution as the SharePoint application pool identity — typically a high-privilege domain service account. Affected .NET Framework versions include 3.5, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, and 4.8 on Windows Server. The vulnerability was patched in the January 2020 .NET Framework cumulative update.
Microsoft scored this 9.8 CRITICAL with a CVSS vector of AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H — but the PR:N is demonstrably wrong. The MDSec disclosure and the Metasploit module both confirm that authenticated SharePoint access is required (the SOAP call to webpartpages.asmx needs a valid session). A corrected vector with PR:L would land around 8.8. That said, the vulnerability is KEV-listed with confirmed in-the-wild exploitation, has a rock-solid Metasploit module rated 'excellent', and EPSS sits at the 99th percentile. The vendor severity label of CRITICAL is directionally correct despite the inflated vector — any SharePoint user counts as 'authenticated', which in most enterprises means thousands of potential attackers including compromised accounts.
5 steps from start to impact.
Obtain SharePoint authentication
- Valid SharePoint user credentials or session token
- SharePoint on-premise (not SharePoint Online, which was patched Nov 2019)
- SharePoint Online deployments are not vulnerable
- MFA on SharePoint reduces credential-stuffing success
Craft malicious XOML payload
CallExternalMethodActivity element whose InterfaceType attribute contains injected C# code. The injection escapes the generated function scope using syntax like System.String);}Object/**/cmd=System.Diagnostics.Process.Start("cmd.exe".... The Metasploit module exploit/windows/http/sharepoint_workflows_xoml automates this entirely — no manual crafting needed.- Knowledge of the injection technique (public since Jan 2020)
- Metasploit Framework or equivalent tooling
- None — Metasploit module is rated 'excellent' reliability
Send SOAP request to workflow endpoint
/_vti_bin/webpartpages.asmx endpoint, invoking ValidateWorkflowMarkupAndCreateSupportObjects with the malicious XOML in the workflowMarkupText parameter. The SharePoint server compiles the XOML into C# and executes it, triggering the injected code.- Network access to SharePoint HTTP/HTTPS port (80/443)
- Unpatched .NET Framework on the SharePoint server
- January 2020 .NET patch blocks the injection
- WAF with deep SOAP inspection could block the payload
cmd.exe or powershell.exe spawned by w3wp.exe.Code execution as SharePoint app pool identity
- Successful XOML compilation with injected code
- EDR on the SharePoint server should flag process creation from w3wp.exe
- Application whitelisting would block arbitrary binaries
w3wp.exe; Windows event logs for new process creation (Event ID 4688); network-level detection of C2 traffic from the SharePoint server.Lateral movement and data access
- SharePoint service account has typical domain privileges
- No network segmentation isolating the SharePoint tier
- Network segmentation limiting SharePoint server egress
- Credential tiering preventing domain admin tokens on the SharePoint server
The supporting signals.
| In-the-wild exploitation | Confirmed. CISA KEV-listed 2021-11-03. Active exploitation observed in campaigns targeting SharePoint on-premise deployments. |
|---|---|
| KEV status | Listed 2021-11-03, BOD 22-01 remediation due date 2022-05-03 (long past). Any unpatched system is overdue by 4+ years. |
| Proof of concept | Metasploit module exploit/windows/http/sharepoint_workflows_xoml (excellent reliability). Developed by Spencer McIntyre and Soroush Dalili. Also on Exploit-DB #48275. |
| EPSS | 0.99222 (99th percentile) — among the highest-probability exploited vulnerabilities tracked. |
| CVSS vector | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H (9.8) — PR:N is incorrect; exploit requires authenticated SharePoint access. Corrected vector with PR:L ≈ 8.8. |
| Affected versions | .NET Framework 3.5, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8 on all supported Windows Server editions running SharePoint on-premise. |
| Fixed versions | January 14, 2020 .NET Framework security updates. Multiple KBs: KB4532938, KB4532950, KB4532951, KB4532952, KB4532958, KB4532959, KB4532960, KB4532961, KB4534978, and others per OS version. |
| Disclosure timeline | Discovered by Soroush Dalili (MDSec). SharePoint Online patched Nov 2019, on-premise patch released Jan 14, 2020. |
| Scanning / exposure | SharePoint on-premise instances exposed to the internet are scannable via Shodan (http.title:"SharePoint"). Most enterprises run SharePoint internally, limiting external attack surface but not insider/post-compromise risk. |
| Attack complexity | Trivially exploitable with Metasploit. No special configuration, race conditions, or memory corruption — pure logic bug with deterministic exploitation. |
noisgate verdict.
The single most decisive factor is the KEV listing with confirmed active exploitation combined with a weaponized Metasploit module rated 'excellent' reliability — the exploit is deterministic, not probabilistic. While the authentication requirement means the CVSS 9.8 PR:N vector overstates unauthenticated risk, the bar is any SharePoint user credential (thousands per enterprise), and the blast radius is full code execution on a domain-joined server running as a privileged service account.
Why this verdict
- Incorrect CVSS vector, but direction is right: Microsoft's PR:N is wrong — authentication is required. A corrected vector yields ~8.8 rather than 9.8. However, the authentication bar (any SharePoint user) is low enough that this does not warrant a severity downgrade from CRITICAL.
- KEV + EPSS 99th percentile: Confirmed exploitation in the wild with CISA KEV listing since November 2021. EPSS of 0.99 places this in the top 1% of all CVEs for exploitation probability. These are hard overrides against any downgrade.
- Metasploit 'excellent' module: The exploit is fully weaponized, deterministic, and requires zero manual effort. Point-and-shoot RCE once you have a SharePoint session cookie.
- Role multiplier: SharePoint on-premise is a high-value target in enterprise environments. (a) *Low-value role:* dev/test SharePoint — exploitation yields local server access only, blast radius = host. (b) *Typical role:* production SharePoint — contains sensitive documents, PII, intellectual property; service account is domain-joined with elevated privileges; blast radius = tenant + lateral movement. (c) *High-value role:* SharePoint integrated with AD, running as a domain service account with delegation rights — compromise enables Kerberos ticket harvesting, potential domain escalation; blast radius = domain. SharePoint on-premise represents ≥10% high-value-role deployments by definition (it's a core collaboration platform with privileged service accounts), so the verdict floor is CRITICAL.
- Vulnerability age: Patched in January 2020 — over 6 years ago. Any system still unpatched represents a severe configuration management failure and likely has other unpatched vulnerabilities compounding risk.
Why not higher?
This is already CRITICAL, the highest severity bucket. The reassessed score of 9.0 (vs. vendor's 9.8) reflects the authentication requirement that Microsoft's CVSS vector incorrectly omits — PR should be L, not N. A perfect 10.0 would require true unauthenticated, wormable exploitation.
Why not lower?
KEV listing and active exploitation are hard floors that prevent any downgrade below CRITICAL for a vulnerability with this blast radius. The authentication requirement (any SharePoint user) does not materially reduce the threat population — in a typical enterprise, thousands of accounts qualify, and any single compromised credential suffices. The Metasploit module eliminates all exploitation complexity. SharePoint servers are domain-joined, high-privilege assets where code execution cascades into lateral movement.
What to do — in priority order.
- Patch .NET Framework immediately — Apply the January 2020 .NET Framework security update to all SharePoint on-premise servers. This is a 6-year-old patch — per the noisgate mitigation SLA for CRITICAL, compensating controls should be deployed within 3 days, but the actual fix (the patch itself) should be applied within hours given the KEV listing and exploitation history.
- Deploy WAF rules blocking XOML injection — Configure your WAF (if fronting SharePoint) to inspect SOAP request bodies to
webpartpages.asmxfor theValidateWorkflowMarkupAndCreateSupportObjectsmethod with suspiciousInterfaceTypeattribute values containing C# syntax (semicolons, braces,System.Diagnostics). Deploy within 3 days per noisgate mitigation SLA. - Monitor w3wp.exe child processes via EDR — Create an EDR detection rule alerting on any child process spawned by
w3wp.exeon SharePoint servers — especiallycmd.exe,powershell.exe, or any unsigned binary. This catches post-exploitation regardless of the injection vector. Deploy within 3 days. - Restrict SharePoint workflow permissions — Audit and reduce the set of users who can create or modify SharePoint workflows. Remove workflow creation rights from standard users if business processes allow. This shrinks the authenticated attacker population.
- Network-segment SharePoint servers — Ensure SharePoint servers cannot initiate outbound connections to arbitrary hosts (limits C2) and restrict lateral movement by placing them in a dedicated VLAN with controlled egress. Deploy within 3 days.
- Disabling SharePoint workflows at the farm level may seem like a fix, but it breaks legitimate business processes and doesn't address the underlying .NET Framework vulnerability — other XOML processing paths may exist.
- IP-based access restrictions alone don't help if the attacker is an insider or uses a compromised VPN session — the exploit works from any network position that can reach SharePoint.
- Antivirus signature scanning is unreliable because the payload is inline XML/C# text in a SOAP body, not a binary — most AV engines won't inspect HTTP request bodies at the application layer.
Crowdsourced verification payload.
Run this on each SharePoint server with administrator privileges. Execute: powershell -ExecutionPolicy Bypass -File .\Check-CVE-2020-0646.ps1. The script checks the installed .NET Framework versions and verifies whether the January 2020 security updates are applied.
# Check-CVE-2020-0646.ps1
# Checks whether the January 2020 .NET Framework patches for CVE-2020-0646 are installed.
# Run on: SharePoint on-premise servers
# Requires: Administrator privileges
# Output: VULNERABLE / PATCHED / UNKNOWN
$ErrorActionPreference = 'Stop'
try {
# Known KBs for the January 2020 .NET Framework security update
$patchKBs = @(
'KB4532938','KB4532950','KB4532951','KB4532952',
'KB4532958','KB4532959','KB4532960','KB4532961',
'KB4532962','KB4534978','KB4534976','KB4534977',
'KB4535101','KB4535102','KB4535103','KB4535104',
'KB4535105'
)
# Check for installed hotfixes matching the patch KBs
$installedKBs = Get-HotFix -ErrorAction SilentlyContinue | Select-Object -ExpandProperty HotFixID
# Also check via registry for .NET Framework updates
$netRegPath = 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full'
$netRelease = 0
if (Test-Path $netRegPath) {
$netRelease = (Get-ItemProperty $netRegPath -Name Release -ErrorAction SilentlyContinue).Release
}
# Check if SharePoint is installed
$spInstalled = $false
$spSnapin = Get-PSSnapin -Registered -Name 'Microsoft.SharePoint.PowerShell' -ErrorAction SilentlyContinue
if ($spSnapin) { $spInstalled = $true }
if (-not $spInstalled) {
$spHive = 'HKLM:\SOFTWARE\Microsoft\Shared Tools\Web Server Extensions'
if (Test-Path $spHive) {
$versions = Get-ChildItem $spHive -ErrorAction SilentlyContinue
foreach ($v in $versions) {
$loc = (Get-ItemProperty $v.PSPath -Name 'Location' -ErrorAction SilentlyContinue).Location
if ($loc -and (Test-Path (Join-Path $loc 'ISAPI\Microsoft.SharePoint.dll'))) {
$spInstalled = $true
break
}
}
}
}
if (-not $spInstalled) {
Write-Host 'UNKNOWN - SharePoint not detected on this host. CVE-2020-0646 is exploitable via SharePoint workflows.'
exit 2
}
$foundPatch = $false
foreach ($kb in $patchKBs) {
if ($installedKBs -contains $kb) {
$foundPatch = $true
Write-Host "PATCHED - Found $kb (January 2020 .NET Framework security update) on this SharePoint server."
break
}
}
if (-not $foundPatch) {
# Fallback: check if any .NET cumulative update post-Jan 2020 is installed
$postJan2020 = Get-HotFix -ErrorAction SilentlyContinue | Where-Object {
$_.InstalledOn -gt [datetime]'2020-01-14' -and $_.Description -match 'Security Update'
} | Where-Object { $_.HotFixID -match 'KB4' }
if ($postJan2020) {
Write-Host "PATCHED - Post-January 2020 security updates detected. Verify .NET Framework patches specifically."
exit 0
} else {
Write-Host 'VULNERABLE - No January 2020 .NET Framework security update (or later) found. CVE-2020-0646 is exploitable.'
exit 1
}
} else {
exit 0
}
} catch {
Write-Host "UNKNOWN - Error during check: $_"
exit 2
}If you remember one thing.
w3wp.exe) within 3 days. Per the noisgate remediation SLA, apply the January 2020 .NET Framework security update within 90 days — but given this is KEV-listed with confirmed exploitation, override that to patch immediately, within hours. Any system still unpatched for CVE-2020-0646 in August 2026 represents a fundamental configuration management failure; escalate to your CISO and investigate why patch compliance missed this for over six years.Sources
- MDSec - Code Injection in Workflows Leading to SharePoint RCE
- Microsoft Security Update Guide - CVE-2020-0646
- Metasploit Module - SharePoint Workflows XOML Injection
- Exploit-DB #48275 - SharePoint Workflows XOML Injection
- CISA Known Exploited Vulnerabilities Catalog
- Metasploit PR #13122 - CVE-2020-0646 Module
- Senserva - CVE-2020-0646 Advisory
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.