A haunted-house creak from 2012 that scanners keep flagging but attackers stopped trying to weaponize a decade ago
MS12-020 bundles two RDP flaws, headlined by CVE-2012-0002, a use-after-free in the way RDPWD.SYS handles the maxChannelIDs field of a T.125 ConnectMCSPDU packet during the pre-authentication phase of RDP session setup. On paper it's a pre-auth remote code execution against Windows XP SP2/SP3, Server 2003 SP2, Vista SP2, Server 2008/2008 R2, and Windows 7 GA/SP1 — every RDP listener on the planet in early 2012. If Network Level Authentication (NLA) is enabled the attacker must first authenticate, collapsing the bug to post-auth; if NLA is off, it's wire-reachable.
Microsoft rated this Critical and Tenable inherited it as HIGH. That was defensible in March 2012, when Windows XP and 2003 dominated fleets and NLA was rare. In 2026 the calculus is different: every affected OS is end-of-life, NLA has been the default since Windows 8/2012, and despite 14 years of researcher attention the only public weapon is the Metasploit *DoS* module (ms12_020_maxchannelids) plus Chinese-forum BSOD PoCs — no reliable public RCE ever materialized. The vendor label overstates the practical risk on any modern fleet; it's still real on the XP/2003 ghosts sitting in OT closets.
4 steps from start to impact.
Reach TCP/3389 on an affected host
port:3389 os:"Windows XP"; internal exposure is common on flat OT/legacy segments.- TCP/3389 reachable
- target running unpatched pre-Win8 Windows
- RDP service enabled
- Every affected OS is EOL — modern fleets don't have them
- Perimeter firewalls almost never expose 3389 externally in 2026
- Internal segmentation and jump-host patterns limit east-west 3389
Confirm NLA is disabled
- NLA off on target
- or valid domain credentials for post-auth reach
- NLA has been widely deployed since ~2013
- CIS/DISA STIGs mandate NLA
- Even legacy 2008 R2 hosts commonly have NLA forced by GPO
rdp-enum-encryption NSE script, Nessus plugin 58453 (Terminal Services NLA check).Send crafted T.125 ConnectMCSPDU with malformed maxChannelIDs
rdpclient.py, or Metasploit auxiliary/dos/windows/rdp/ms12_020_maxchannelids — to send a specially crafted ConnectMCSPDU packet that triggers a use-after-free in RDPWD.SYS. This reliably produces a BSOD 0x9F / BUGCODE_USB_DRIVER-style crash. Achieving code execution requires controlling the freed-object reuse under kernel non-paged pool pressure.- Working PoC/tool
- packet path to 3389
- target under attacker-influenced memory pressure for RCE
- Public tooling is DoS-only
- Kernel pool grooming on XP/2003/7 is fragile across hotfix levels
- No commodity weaponization exists after 14 years of researcher attention
SID 2014384/2014385 fire on the malformed packet pattern; kernel crash telemetry from EDR.Achieve kernel RCE (theoretical) or settle for DoS
- Reliable exploit primitive
- No public reliable RCE
- Modern EDR (where deployed on legacy hosts) catches post-exploitation quickly
Computer Configuration → Admin Templates → Windows Components → Remote Desktop Services → Remote Desktop Session Host → Security → Require user authentication for remote connections by using Network Level Authentication = Enabled. This collapses the pre-auth attack surface. Deploy in the standard MEDIUM 365-day remediation window; no mitigation SLA required.- RDP account lockout policies — the vulnerable code executes before credential validation when NLA is off, so lockouts are never triggered.
- Strong RDP passwords — irrelevant to a pre-auth code path.
- TLS-wrapped RDP (SSL cert on 3389) — the bug is in the MCS channel setup that runs inside the encrypted session; wrapping does not remove the vulnerable code.
The supporting signals.
| In the wild | No confirmed RCE campaigns. Widespread opportunistic DoS scanning throughout 2012–2015. Never added to CISA KEV. |
|---|---|
| Public PoC | Metasploit auxiliary/dos/windows/rdp/ms12_020_maxchannelids (DoS), Luigi Auriemma's original packet capture, numerous Python rdpclient.py derivatives on GitHub — all DoS-only |
| EPSS | ~0.94 (very high percentile) — reflects age and scanner noise, not observed RCE |
| KEV status | Not listed. CISA has never added CVE-2012-0002 to the Known Exploited Vulnerabilities catalog |
| CVSS v2 | AV:N/AC:M/Au:N/C:C/I:C/A:C = 9.3 — the pre-NLA-default era rating |
| Affected | Windows XP SP2/SP3, Server 2003 SP2, Vista SP2, Server 2008 SP2, Server 2008 R2 (SP0/SP1), Windows 7 GA/SP1 — all EOL |
| Fixed in | KB2621440 (Windows), KB2667402 (Terminal Server), released 2012-03-13 |
| Exposure | Shodan shows <50k public 3389 listeners identifying as XP/2003/Vista globally in 2026, most in residential/APAC ranges; enterprise external exposure is negligible |
| Disclosed | 2012-03-13 (Patch Tuesday) |
| Reporter | Luigi Auriemma via ZDI (ZDI-12-044) |
Sources.
Why this verdict
- No weaponized RCE in 14 years: despite Metasploit, ZDI attention, and Luigi Auriemma's original research, every public artifact is a DoS. Kernel UAF exploitation on XP/2003/7 non-paged pool never became commodity.
- NLA neutralizes the pre-auth path: Network Level Authentication has been default since Windows 8/2012 and is universally enforced by CIS/DISA baselines. On any NLA-enforced host the bug collapses to post-auth.
- Installed base collapse: Windows XP, Server 2003, Vista, Server 2008, and Windows 7 are all past end-of-support. A 2026 enterprise finding this plugin fire is almost certainly looking at an isolated legacy appliance, not a production Windows fleet.
- Not KEV-listed: CISA has never added CVE-2012-0002, reflecting the absence of confirmed exploitation-in-the-wild evidence over 14 years.
- Role multiplier — legacy DC / OT HMI: if the flagged host is a Windows 2008 R2 domain controller still in production or an XP-embedded SCADA HMI, a DoS bugcheck causes real operational impact and the host itself is a fleet-wide risk regardless of this CVE. Fix the deployment role, not just this bug.
Why not higher?
HIGH would require either active KEV listing, a working public RCE, or meaningful modern-OS exposure — none exist. The bug is real but 14 years of researcher pressure produced only denial-of-service, and CVSS v2's 9.3 was calibrated against a pre-NLA-default world that no longer exists.
Why not lower?
LOW/IGNORE would ignore that this scanner finding is a reliable canary for an unpatched, end-of-life Windows host on your network — which is itself a serious hygiene failure and a target for dozens of *other* unpatched CVEs (MS17-010, BlueKeep, PrintNightmare). The host needs remediation; the CVE just points at it.
Crowdsourced verification payload.
Run on the target Windows host as Administrator to check for the KB2621440 hotfix and NLA state. Invoke: powershell -ExecutionPolicy Bypass -File Check-MS12-020.ps1. Outputs VULNERABLE, PATCHED, or UNKNOWN and exits with codes 1/0/2 respectively.
#requires -RunAsAdministrator
# Check-MS12-020.ps1 — noisgate verification for CVE-2012-0002 / MS12-020
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN
$ErrorActionPreference = 'Stop'
# 1. OS applicability
$os = (Get-CimInstance Win32_OperatingSystem).Version
$major = [int]$os.Split('.')[0]
$minor = [int]$os.Split('.')[1]
# Vulnerable: 5.1 (XP), 5.2 (2003), 6.0 (Vista/2008), 6.1 (7/2008R2)
$vulnerableFamily = ($major -eq 5) -or ($major -eq 6 -and $minor -le 1)
if (-not $vulnerableFamily) {
Write-Output 'PATCHED (OS family not affected by MS12-020)'
exit 0
}
# 2. Hotfix check — KB2621440 (Windows) or KB2667402 (Terminal Server)
try {
$hotfixes = Get-HotFix -ErrorAction Stop | Select-Object -ExpandProperty HotFixID
} catch {
Write-Output 'UNKNOWN (could not enumerate hotfixes)'
exit 2
}
$patched = ($hotfixes -contains 'KB2621440') -or ($hotfixes -contains 'KB2667402')
# 3. NLA state (mitigating factor, not a fix)
$nla = 'unknown'
try {
$ts = Get-CimInstance -Namespace root\cimv2\TerminalServices -Class Win32_TSGeneralSetting -Filter "TerminalName='RDP-Tcp'" -ErrorAction Stop
$nla = if ($ts.UserAuthenticationRequired -eq 1) { 'enabled' } else { 'disabled' }
} catch { $nla = 'unknown' }
if ($patched) {
Write-Output "PATCHED (KB2621440/2667402 present; NLA=$nla)"
exit 0
} else {
Write-Output "VULNERABLE (KB2621440/2667402 missing; NLA=$nla; OS=$os)"
exit 1
}