This is a loaded trapdoor inside the database lobby, not a hole in the front wall
CVE-2026-33120 is a Microsoft SQL Server remote code execution bug caused by an untrusted pointer dereference. The published description says an *authorized* attacker can execute code over the network, which matters more than the RCE label: the attacker needs valid SQL access plus network reachability to the Database Engine. NVD lists affected Windows/x64 build ranges across SQL Server 2016, 2017, 2019, 2022, and 2025, including 13.0.6300.2 to before 13.0.6485.1, 14.0.1000.169 to before 14.0.2105.1, 15.0.2000.5 to before 15.0.2165.1, 16.0.1000.6 to before 16.0.1175.1, and 17.0.1000.7 to before 17.0.1110.1, plus corresponding CU/GDR branches.
Microsoft's HIGH 8.8 score is technically defensible in a lab because successful exploitation yields code execution on a database host. In real enterprise estates, though, the chain starts *after* an attacker already has SQL credentials or an app/service account and can reach the SQL port, which is a major friction point and usually means post-initial-access. With no CISA KEV listing, no public exploitation evidence in the reviewed primary sources, and very low EPSS, this lands as MEDIUM for most fleets; if you knowingly expose SQL Server externally or let broad low-trust users authenticate directly to it, treat those specific instances as locally higher risk.
4 steps from start to impact.
Obtain working SQL credentials
Impacket mssqlclient.py or native sqlcmd to validate access.- Valid SQL or Windows-auth credentials
- Target instance accepts remote logins
- Attacker can route to the SQL Server host
- This is not pre-auth; it assumes credential theft or an existing foothold
- Many enterprise databases are only reachable from app tiers or admin jump segments
- MFA at the user tier may indirectly reduce some Windows-auth abuse paths
Reach the vulnerable TDS service
1433, though named instances and custom ports are common. This is where segmentation matters: the bug is network-reachable only if the SQL listener is reachable from the attacker's position.- SQL listener exposed to the attacker's network zone
- Firewall rules permit the connection
- Target runs an affected build
- Many production SQL servers are internal-only and not internet-facing
- Named instances, custom ports, and SQL Browser restrictions complicate blind reachability
- Host firewalls and ACLs often limit direct workstation-to-database traffic
Trigger the memory corruption path
sqlservr.exe are rarely one-packet copy-paste exploits.- Exact vulnerable build family
- Reachable vulnerable code path after login
- Exploit reliability for the target patch branch and memory layout
- No public PoC was surfaced in reviewed primary sources
- Crash-to-RCE engineering is materially harder than crash-only triggering
- Modern EDR, WER dumps, and service restarts can expose failed attempts
Land code execution on a crown-jewel host
- Exploit completes reliably
- SQL Server service account has useful OS or network privileges
- Post-exploitation controls do not stop payload execution
- Some deployments run constrained service accounts instead of over-privileged domain identities
- Application allowlisting or EDR may block noisy payloads after code execution
- Blast radius is often limited to the specific SQL host or cluster, not the entire enterprise
The supporting signals.
| In-the-wild status | No reviewed primary source shows active exploitation. CISA KEV does not list CVE-2026-33120 as of 2026-05-30, and the CVE/NVD records do not cite exploit references. |
|---|---|
| Proof-of-concept availability | No public PoC was surfaced in the reviewed primary sources. That does not prove exploit absence, but it does raise attacker effort because this is an authenticated memory-corruption bug, not a commodity web injection. |
| EPSS | User-supplied intel: 0.00089, which is very low and directionally consistent with an auth-required enterprise-server bug rather than an internet-burner. |
| KEV status | Not KEV-listed. That removes the strongest practical upgrade signal in patch prioritization. |
| CVSS vector readout | AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H means network-reachable and low-complexity after the attacker already has valid privileges. The PR:L is the whole story here: it implies stolen creds, app-tier compromise, or an insider position. |
| Affected version ranges | NVD lists affected branches for SQL Server 2016, 2017, 2019, 2022, and 2025, covering both GDR and CU/GDR tracks. Examples include 13.0.6300.2 to before 13.0.6485.1, 14.0.3006.16 to before 14.0.3525.1, 15.0.4003.23 to before 15.0.4465.1, 16.0.4003.1 to before 16.0.4250.1, and 17.0.4006.2 to before 17.0.4030.1. |
| Fixed versions | Published fixed builds include 13.0.6485.1 / 13.0.7080.1, 14.0.2105.1 / 14.0.3525.1, 15.0.2165.1 / 15.0.4465.1, 16.0.1175.1 / 16.0.4250.1, and 17.0.1110.1 / 17.0.4030.1, depending on branch. |
| Exposure reality | Microsoft documents TCP 1433 as the default SQL Server Database Engine port. That means internet exposure is easy to find when admins do the wrong thing, but in well-run enterprises direct external exposure is supposed to be uncommon and app-tier-mediated access is more typical. |
| Scanning and detection coverage | Expect better asset/version detection than exploit detection. This is a strong candidate for authenticated VM checks, registry/build inventory, and CMDB-driven patch targeting; it's a weak candidate for reliable unauthenticated network-only CVE confirmation. |
| Disclosure and attribution | Disclosed on 2026-04-14 by Microsoft Corporation as the CNA. Public researcher attribution is not credited in the reviewed CVE/NVD/MSRC-linked sources. |
noisgate verdict.
The decisive factor is the authenticated remote requirement on a product that is usually reachable only from controlled network zones or app tiers. This is still real RCE on a crown-jewel platform, but for most enterprises it is a post-compromise accelerator rather than a front-door initial-access bug.
Why this verdict
- Start from the vendor's 8.8 because authenticated network RCE on SQL Server can have ugly impact when it lands on a production database host.
- Subtract for attacker position:
PR:Lmeans the chain begins with a valid SQL login or Windows-auth path, which usually implies stolen app creds, a compromised service account, insider access, or an existing foothold. - Subtract again for reachable population: most enterprise SQL servers are not intentionally exposed to the internet and are often only reachable from app tiers, admin jump hosts, or tightly scoped subnets.
- No exploitation amplifier: there is no CISA KEV listing, no reviewed primary-source evidence of in-the-wild abuse, and the supplied EPSS is extremely low.
- Keep it above LOW because once the attacker is in position, the blast radius can be serious: code execution lands on a sensitive data-tier asset where service accounts, backups, linked servers, and trusted east-west paths often exist.
Why not higher?
This is not pre-auth and not broadly wormable from the internet in the way patch-now-everything flaws are. The absence of KEV status, lack of reviewed public exploit evidence, and the fact that many deployments place SQL behind network and application boundaries all compound downward pressure on severity.
Why not lower?
A successful exploit is still OS-level code execution on a database server, not a harmless crash. Low-privileged authenticated access is not rare in large environments because application pools, service accounts, reporting users, and reused credentials create real paths to that starting point.
What to do — in priority order.
- Restrict SQL reachability — Limit inbound TDS access to known app servers, admin jump hosts, and replication partners only. For a MEDIUM verdict there is no mitigation SLA — go straight to the 365-day remediation window, but this is the best compensating control to apply during that window because it removes the network precondition outright.
- Reduce low-trust SQL logins — Review application, reporting, integration, and contractor accounts that can authenticate directly to SQL Server; disable stale logins, rotate shared secrets, and prefer tightly scoped service identities. There is no mitigation SLA for MEDIUM, so fold this into the remediation workstream and complete it before patch closeout within the 365-day remediation window.
- Hunt for unusual SQL client activity — Alert on new source hosts talking to SQL, service-account logins from unexpected systems, and post-auth TDS activity outside normal application patterns. There is no mitigation SLA for MEDIUM, but these detections should be in place during the remediation window because failed exploit attempts are more likely to show up as anomalous auth and crash telemetry than tidy IoCs.
- Constrain the SQL service account — If the SQL Server service still runs with broad local or domain privileges, reduce that now; it directly cuts blast radius if code execution is achieved. For this MEDIUM case there is no mitigation SLA, so handle it as part of the remediation plan before the 365-day patch deadline closes.
- A WAF does not help because this is native SQL/TDS traffic, not HTTP application traffic.
- MFA on web portals is not a direct control for TDS sessions once an attacker already has a usable SQL login or a service account secret.
- Signature-only antivirus is a poor primary defense here because the hard part is the in-memory trigger; failed attempts may just look like crashes, and successful ones can use living-off-the-land follow-on activity.
Crowdsourced verification payload.
Run this on each SQL Server host from an elevated PowerShell session, or push it with your EDR/RMM. Example: powershell -ExecutionPolicy Bypass -File .\check-CVE-2026-33120.ps1; it needs local read access to HKLM and works best as local admin, but it does not require SQL credentials.
# check-CVE-2026-33120.ps1
# Purpose: Determine whether locally installed Microsoft SQL Server instances are vulnerable to CVE-2026-33120
# Output: VULNERABLE / PATCHED / UNKNOWN
# Exit codes: 0=all discovered instances patched, 1=one or more vulnerable, 2=unknown / unable to assess
$ErrorActionPreference = 'Stop'
function Compare-Version {
param(
[Parameter(Mandatory=$true)][string]$A,
[Parameter(Mandatory=$true)][string]$B
)
$aParts = $A.Split('.') | ForEach-Object { [int]$_ }
$bParts = $B.Split('.') | ForEach-Object { [int]$_ }
$max = [Math]::Max($aParts.Count, $bParts.Count)
for ($i = 0; $i -lt $max; $i++) {
$av = if ($i -lt $aParts.Count) { $aParts[$i] } else { 0 }
$bv = if ($i -lt $bParts.Count) { $bParts[$i] } else { 0 }
if ($av -lt $bv) { return -1 }
if ($av -gt $bv) { return 1 }
}
return 0
}
function Test-InRange {
param(
[Parameter(Mandatory=$true)][string]$Version,
[Parameter(Mandatory=$true)][string]$MinInclusive,
[Parameter(Mandatory=$true)][string]$MaxExclusive
)
return ((Compare-Version -A $Version -B $MinInclusive) -ge 0 -and (Compare-Version -A $Version -B $MaxExclusive) -lt 0)
}
# Vulnerable version ranges from NVD / Microsoft CNA data
$ranges = @(
@{ Branch='SQL Server 2016 GDR'; Min='13.0.6300.2'; Max='13.0.6485.1' },
@{ Branch='SQL Server 2016 CU/GDR'; Min='13.0.7000.253'; Max='13.0.7080.1' },
@{ Branch='SQL Server 2017 GDR'; Min='14.0.1000.169'; Max='14.0.2105.1' },
@{ Branch='SQL Server 2017 CU/GDR'; Min='14.0.3006.16'; Max='14.0.3525.1' },
@{ Branch='SQL Server 2019 GDR'; Min='15.0.2000.5'; Max='15.0.2165.1' },
@{ Branch='SQL Server 2019 CU/GDR'; Min='15.0.4003.23'; Max='15.0.4465.1' },
@{ Branch='SQL Server 2022 GDR'; Min='16.0.1000.6'; Max='16.0.1175.1' },
@{ Branch='SQL Server 2022 CU/GDR'; Min='16.0.4003.1'; Max='16.0.4250.1' },
@{ Branch='SQL Server 2025 GDR'; Min='17.0.1000.7'; Max='17.0.1110.1' },
@{ Branch='SQL Server 2025 CU/GDR'; Min='17.0.4006.2'; Max='17.0.4030.1' }
)
$instanceRoots = @(
'HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL',
'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Microsoft SQL Server\Instance Names\SQL'
)
$instances = @()
foreach ($root in $instanceRoots) {
if (Test-Path $root) {
$props = Get-ItemProperty -Path $root
foreach ($p in $props.PSObject.Properties) {
if ($p.Name -notmatch '^PS') {
$instances += [PSCustomObject]@{
InstanceName = $p.Name
InstanceId = [string]$p.Value
SourcePath = $root
}
}
}
}
}
$instances = $instances | Sort-Object InstanceName, InstanceId -Unique
if (-not $instances -or $instances.Count -eq 0) {
Write-Output 'UNKNOWN - No SQL Server instances discovered in registry.'
exit 2
}
$foundVuln = $false
$foundUnknown = $false
foreach ($inst in $instances) {
$setupPaths = @(
"HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\$($inst.InstanceId)\Setup",
"HKLM:\SOFTWARE\WOW6432Node\Microsoft\Microsoft SQL Server\$($inst.InstanceId)\Setup"
)
$version = $null
$edition = $null
foreach ($sp in $setupPaths) {
if (Test-Path $sp) {
try {
$item = Get-ItemProperty -Path $sp
if ($item.Version) { $version = [string]$item.Version }
if ($item.Edition) { $edition = [string]$item.Edition }
if ($version) { break }
} catch {
# continue
}
}
}
if (-not $version) {
Write-Output ("UNKNOWN - Instance '{0}' ({1}) version could not be determined." -f $inst.InstanceName, $inst.InstanceId)
$foundUnknown = $true
continue
}
$matchedRange = $null
foreach ($r in $ranges) {
if (Test-InRange -Version $version -MinInclusive $r.Min -MaxExclusive $r.Max) {
$matchedRange = $r
break
}
}
if ($matchedRange) {
$foundVuln = $true
if ($edition) {
Write-Output ("VULNERABLE - Instance '{0}' version {1} ({2}); matches {3} vulnerable range {4} to < {5}." -f $inst.InstanceName, $version, $edition, $matchedRange.Branch, $matchedRange.Min, $matchedRange.Max)
} else {
Write-Output ("VULNERABLE - Instance '{0}' version {1}; matches {2} vulnerable range {3} to < {4}." -f $inst.InstanceName, $version, $matchedRange.Branch, $matchedRange.Min, $matchedRange.Max)
}
} else {
if ($edition) {
Write-Output ("PATCHED - Instance '{0}' version {1} ({2}); not in published vulnerable ranges for CVE-2026-33120." -f $inst.InstanceName, $version, $edition)
} else {
Write-Output ("PATCHED - Instance '{0}' version {1}; not in published vulnerable ranges for CVE-2026-33120." -f $inst.InstanceName, $version)
}
}
}
if ($foundVuln) {
exit 1
} elseif ($foundUnknown) {
exit 2
} else {
exit 0
}
If you remember one thing.
Sources
- NVD CVE-2026-33120
- CVE.org record for CVE-2026-33120
- CISA Known Exploited Vulnerabilities Catalog
- Microsoft Learn: Configure the Windows Firewall to Allow SQL Server Access
- Microsoft Learn: SQL Server 2022 build versions
- Microsoft Learn: SQL Server 2025 on Linux release history
- Microsoft Learn: SQL Server 2017 build versions
- Microsoft Learn: SQL Server 2019 build versions
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.