← Back to Feed CACHED · 2026-05-17 09:42:19 · cache_key CVE-2025-29912
CVE-2026-33120 · CWE-822 · Disclosed 2026-04-14

Untrusted pointer dereference in SQL Server

ASSESSED — NOISGATE V0.5
Vendor
Reassessed
Verdict:
01 · The Real Story

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.

"This is dangerous on the wrong SQL box, but it is not a fleet-wide fire drill without pre-auth reach or exploitation evidence."
02 · The Attack Path

4 steps from start to impact.

STEP 01

Obtain working SQL credentials

The attacker first needs a valid SQL login or AD-backed identity that SQL Server will accept. In practice that usually comes from stolen application connection strings, dumped service-account secrets, password reuse, or a prior foothold using tools like Impacket mssqlclient.py or native sqlcmd to validate access.
Conditions required:
  • Valid SQL or Windows-auth credentials
  • Target instance accepts remote logins
  • Attacker can route to the SQL Server host
Where this breaks in practice:
  • 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
Detection/coverage: Good detection opportunity: failed/successful SQL logins, unusual source IPs, new client fingerprints, and service-account use outside known app servers are all observable.
STEP 02

Reach the vulnerable TDS service

The attacker must connect to the Database Engine over TDS, typically on TCP 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.
Conditions required:
  • SQL listener exposed to the attacker's network zone
  • Firewall rules permit the connection
  • Target runs an affected build
Where this breaks in practice:
  • 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
Detection/coverage: Network scanners can identify MSSQL exposure, but CVE confirmation is usually version-based rather than packet-signature-based.
STEP 03

Trigger the memory corruption path

After authentication, the attacker needs to drive the specific code path that dereferences an untrusted pointer and turn it into stable code execution. That likely requires a bespoke TDS/RPC harness, fuzzing output, or a private exploit rather than ordinary SQL statements, because memory corruption bugs in sqlservr.exe are rarely one-packet copy-paste exploits.
Conditions required:
  • Exact vulnerable build family
  • Reachable vulnerable code path after login
  • Exploit reliability for the target patch branch and memory layout
Where this breaks in practice:
  • 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
Detection/coverage: Weak scanner coverage for exploitability; stronger host telemetry comes from SQL Server crashes, Windows Error Reporting, unexpected service restarts, and EDR memory-corruption alerts.
STEP 04

Land code execution on a crown-jewel host

If the exploit is successful, code runs in the SQL Server service context on a database host that often holds sensitive data and trusted network paths. That can turn a low-privileged database login into OS-level execution, credential theft, lateral movement, or destructive impact against the data tier.
Conditions required:
  • Exploit completes reliably
  • SQL Server service account has useful OS or network privileges
  • Post-exploitation controls do not stop payload execution
Where this breaks in practice:
  • 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
Detection/coverage: High-value host; EDR, Sysmon, service-account monitoring, child-process creation from SQL Server, and unusual outbound network activity should all be tuned here.
03 · Intelligence Metadata

The supporting signals.

In-the-wild statusNo 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 availabilityNo 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.
EPSSUser-supplied intel: 0.00089, which is very low and directionally consistent with an auth-required enterprise-server bug rather than an internet-burner.
KEV statusNot KEV-listed. That removes the strongest practical upgrade signal in patch prioritization.
CVSS vector readoutAV: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 rangesNVD 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 versionsPublished 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 realityMicrosoft 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 coverageExpect 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 attributionDisclosed on 2026-04-14 by Microsoft Corporation as the CNA. Public researcher attribution is not credited in the reviewed CVE/NVD/MSRC-linked sources.
04 · The Call

noisgate verdict.

Final Verdict
DOWNGRADED to MEDIUM (6.4/10)

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.

HIGH The attack requires valid authenticated access to SQL Server
HIGH Affected and fixed build ranges
MEDIUM Current lack of public PoC / exploitation evidence
MEDIUM Typical enterprise exposure is internal or app-tier-limited rather than direct internet-facing

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:L means 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.

05 · Compensating Control

What to do — in priority order.

  1. 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.
  2. 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.
  3. 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.
  4. 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.
What doesn't work
  • 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.
06 · Verification

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.

noisgate-verify.ps1
POWERSHELLREAD-ONLYSAFE
# 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
}
07 · Bottom Line

If you remember one thing.

TL;DR
Monday morning: inventory every SQL Server instance, identify which ones are directly reachable from user subnets, partner networks, or the internet, and fast-track those outliers first because they are where this bug stops looking academic. For the general fleet, noisgate mitigation SLA: no mitigation SLA — go straight to the 365-day remediation window; noisgate remediation SLA: move vulnerable SQL Server builds to the April 14, 2026 fixed branches within 365 days, while pulling any internet-exposed or broadly reachable instances forward into the next normal patch cycle rather than treating this as backlog-only hygiene.

Sources

  1. NVD CVE-2026-33120
  2. CVE.org record for CVE-2026-33120
  3. CISA Known Exploited Vulnerabilities Catalog
  4. Microsoft Learn: Configure the Windows Firewall to Allow SQL Server Access
  5. Microsoft Learn: SQL Server 2022 build versions
  6. Microsoft Learn: SQL Server 2025 on Linux release history
  7. Microsoft Learn: SQL Server 2017 build versions
  8. Microsoft Learn: SQL Server 2019 build versions
Peer Review

What defenders are saying.

Submit a review attribution: handle + country only
0 flags selected · stored anonymously
Validation Results

Crowdsourced verification outputs.

Results submitted by users who ran the verification payload against their environment.