← Back to Feed CACHED · 2026-05-17 09:42:19 · cache_key CVE-2025-29912
tenable:72704 · Disclosed 2014-02-26

Microsoft

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

This is a rusting fire escape, not an open front door

Plugin 72704 is a local inventory finding, not a specific remotely exploitable flaw. It fires when Windows reports an out-of-support .NET Framework version such as 4.0, 4.5, 4.5.1, 4.5.2, 4.6, or 4.6.1; older 2.0/3.0 can also matter when they are present outside the supported .NET 3.5 SP1 servicing model. Microsoft retired .NET Framework 4.5.2, 4.6, and 4.6.1 on April 26, 2022; 4.5, 4.5.1, and 4.0 ended on January 12, 2016.

Tenable's CRITICAL / 10.0 label does not describe a real exploit path here; the plugin itself says it uses a default unsupported software score. In practice, the risk is that unsupported runtimes stop receiving security fixes, so future or already-known app-layer bugs can persist longer. That is meaningful exposure, but it is not equivalent to an unauthenticated internet-facing RCE with a known PoC.

"This is tech debt with teeth, not a one-packet critical: downgrade hard from Tenable’s default 10.0"
02 · The Attack Path

4 steps from start to impact.

STEP 01

Find an application still running on unsupported .NET

The attacker first needs a reachable workload that actually depends on the old runtime, typically an IIS app, legacy line-of-business service, or thick-client helper service. Tooling here is ordinary recon like nmap, httpx, or internal asset inventory; plugin 72704 itself is only telling defenders that such a runtime may exist on the host.
Conditions required:
  • A Windows host has an unsupported .NET Framework runtime installed
  • There is a real application or service still using that runtime
  • The application is reachable from the attacker's position
Where this breaks in practice:
  • Many flagged hosts are workstations or internal servers with no direct external exposure
  • .NET 4.x is an in-place runtime, so a current 4.8/4.8.1 install usually supersedes older 4.x branches
  • Internet scanning cannot generally fingerprint a host just from the presence of an old .NET Framework runtime
Detection/coverage: High coverage for defender-side asset discovery via authenticated scan or agent; poor internet-side observability.
STEP 02

Map the runtime and app to a separate exploit

Because 72704 is not a CVE, the attacker must pair it with a different bug: an app-specific flaw, deserialization issue, file-upload bug, auth bypass, or a framework-adjacent vulnerability that remains unpatched on the old branch. Common weaponization would use Nuclei, public exploit repos, or custom Metasploit-style tradecraft against the *application*, not against the Tenable finding.
Conditions required:
  • A separate exploitable bug exists in the app stack
  • The unsupported runtime prevents or delays receiving the relevant fix
  • The attacker can identify the app/framework combination
Where this breaks in practice:
  • No single public PoC maps to 'plugin 72704'
  • The attacker must know or infer the specific application and vulnerable code path
  • Modern WAFs, reverse proxies, auth gateways, and EDR often break commodity exploit chains before code execution
Detection/coverage: Vulnerability scanners may catch known app CVEs, but not the abstract 'unsupported runtime equals future exploitability' condition.
STEP 03

Execute in the application context

If a separate bug is available, exploitation lands in the app's security context such as the IIS app pool identity or service account. Tooling becomes app-specific exploit code, malicious serialized payloads, or upload/command injection chains rather than anything intrinsic to .NET Framework Unsupported.
Conditions required:
  • A vulnerable code path is reachable
  • Exploit mitigations such as authentication, input validation, or segmentation do not block the attempt
Where this breaks in practice:
  • Many legacy .NET apps are internal-only and already behind VPN, SSO, or network segmentation
  • Even successful exploitation often starts with low-privileged service identities
Detection/coverage: EDR, IIS logs, ASP.NET error logs, WAF telemetry, and Windows eventing often show the real exploit attempt here.
STEP 04

Pivot from one legacy app to broader impact

Post-exploitation impact depends on what the app can touch: databases, file shares, service credentials, or AD-integrated resources. Typical operator tools would be Mimikatz, Rubeus, Seatbelt, or built-in PowerShell after initial code execution, but that is now a post-compromise chain, not severity intrinsic to the unsupported runtime finding.
Conditions required:
  • The compromised service account has meaningful privileges or secrets
  • Lateral movement paths exist from that host
Where this breaks in practice:
  • Least-privilege service accounts, gMSAs, credential isolation, and EDR materially shrink blast radius
  • A single outdated runtime on one host does not automatically imply domain-wide compromise
Detection/coverage: Strong coverage from EDR, Windows security logs, identity detections, and network analytics once activity moves beyond the app.
03 · Intelligence Metadata

The supporting signals.

In-the-wild statusNo direct active exploitation signal for plugin 72704 because it is not a CVE. Any exploitation would be via a separate application or framework-adjacent flaw.
Proof-of-concept availabilityNo single PoC exists for 'Microsoft .NET Framework Unsupported' as reported by Tenable. Attackers would need a second bug and a matching exploit chain.
EPSSN/A — EPSS is CVE-based, and this finding is lifecycle/inventory exposure rather than a cataloged CVE.
KEV statusNot KEV-listed; CISA KEV tracks specific CVEs, not generic unsupported software findings.
Vendor score reality checkTenable marks this CRITICAL 10.0 with the note 'Default unsupported software score'. That is a policy shortcut, not evidence of unauthenticated remote exploitability.
Affected versionsUnsupported branches include .NET Framework 4.0, 4.5, 4.5.1 (ended 2016-01-12) and 4.5.2, 4.6, 4.6.1 (retired 2022-04-26). .NET 2.0/3.0 are long out of support unless effectively covered via supported .NET 3.5 SP1 servicing rules.
Supported / fixed versionsFor 4.x, move to 4.6.2+ at minimum; Microsoft recommends 4.8 or 4.8.1. .NET 3.5 SP1 remains supported on supported OSes, and Microsoft states 4.x upgrades are in-place.
Exposure and scanning realityThis is a Type: Local plugin for Windows hosts. It is best treated as authenticated asset hygiene, not as an internet-exposed attack surface measurement.
Disclosure / detection timelineTenable published plugin 72704 on 2014-02-26 and updated detection on 2024-03-29, including .NET 2.0 handling when not installed with .NET 3.5.
Researcher / authorityLifecycle authority is Microsoft; detection authority is Tenable. There is no named vulnerability reporter because this is not a discrete disclosed CVE.
04 · The Call

noisgate verdict.

Final Verdict
DOWNGRADED to MEDIUM (4.8/10)

The decisive factor is that this finding requires a second, separate exploit path before an attacker gets anything useful; the Tenable item itself is not directly exploitable. Real-world exposure is further narrowed because it is a local inventory signal and many affected .NET workloads are internal or wrapped by modern controls.

HIGH Vendor severity is overstated for real-world exploitability
HIGH Lifecycle dates for affected .NET Framework branches
MEDIUM Host-level business impact without knowing which apps depend on the runtime

Why this verdict

  • Not a CVE, not an exploit: this is an unsupported-software detection, so attackers still need a separate vulnerable app or framework-adjacent flaw to weaponize it
  • Exposure is usually narrower than the score implies: the plugin is Local, requires authenticated/agent visibility to detect, and many affected workloads are internal rather than internet-facing
  • Downward pressure from modern controls: WAF, reverse proxies, MFA, segmentation, and EDR often stop or contain the *actual* exploit chain that would have to accompany this finding

Why not higher?

There is no single exploit, no KEV listing for this finding, and no evidence that 'unsupported .NET present' alone produces immediate compromise. A CRITICAL rating would only make sense after you tie this to a specific exposed application and a live exploitable bug.

Why not lower?

Unsupported runtimes do create real security debt because security fixes stop, and legacy .NET apps often carry sensitive business logic or service credentials. In large estates, these systems age into silent exception zones where future patch response gets slower and harder.

05 · Compensating Control

What to do — in priority order.

  1. Map runtime to business apps — Identify which flagged hosts actually run IIS sites, Windows services, or vendor apps that depend on the old runtime. For a MEDIUM verdict there is no mitigation SLA — go straight to application mapping and complete remediation within 365 days, prioritizing anything internet-facing or handling privileged workflows first.
  2. Reduce reachability — Put legacy .NET-backed apps behind VPN, reverse proxy, allowlists, or internal-only segmentation where possible so unsupported code is not broadly reachable. There is no mitigation SLA for this bucket, but apply these containment changes during normal change windows while you work the 365-day remediation target.
  3. Hunt for legacy app concentration — Correlate plugin 72704 with host role data, IIS inventory, installed software, and CMDB ownership to separate harmless workstation residue from real server-side exposure. Use that triage to focus engineering time on the handful of business apps that would matter in a breach path, then finish vendor-supported runtime upgrades within 365 days.
  4. Increase telemetry on exposed legacy apps — Turn up IIS, ASP.NET, WAF, and EDR monitoring on internet-facing or tier-0-adjacent hosts that still depend on old runtimes. There is no mitigation SLA here, but logging improvements are low-friction and buy visibility while remediation proceeds inside the 365-day window.
What doesn't work
  • MFA does not fix the runtime problem; it only helps if the eventual exploit path needs a login
  • Perimeter AV is irrelevant to most server-side web exploit chains against legacy .NET apps
  • Closing the Tenable finding in the scanner does nothing to change the runtime lifecycle or the future patch gap
06 · Verification

Crowdsourced verification payload.

Run this on the target Windows host from an elevated PowerShell session: powershell -ExecutionPolicy Bypass -File .\check-dotnet-unsupported.ps1. It needs local registry read access; administrator is recommended to avoid redirection/visibility issues on hardened servers.

noisgate-verify.ps1
POWERSHELLREAD-ONLYSAFE
# check-dotnet-unsupported.ps1

# Exit codes:

#   0 = PATCHED

#   1 = VULNERABLE

#   2 = UNKNOWN


$ErrorActionPreference = 'Stop'

function Get-RegValue {
    param(
        [Microsoft.Win32.RegistryView]$View,
        [string]$SubKey,
        [string]$ValueName
    )
    try {
        $base = [Microsoft.Win32.RegistryKey]::OpenBaseKey([Microsoft.Win32.RegistryHive]::LocalMachine, $View)
        $key = $base.OpenSubKey($SubKey)
        if ($null -eq $key) { return $null }
        return $key.GetValue($ValueName, $null)
    } catch {
        return $null
    }
}

function Test-KeyPresent {
    param(
        [Microsoft.Win32.RegistryView]$View,
        [string]$SubKey
    )
    try {
        $base = [Microsoft.Win32.RegistryKey]::OpenBaseKey([Microsoft.Win32.RegistryHive]::LocalMachine, $View)
        $key = $base.OpenSubKey($SubKey)
        return ($null -ne $key)
    } catch {
        return $false
    }
}

$views = @([Microsoft.Win32.RegistryView]::Registry64, [Microsoft.Win32.RegistryView]::Registry32)
$reasons = New-Object System.Collections.Generic.List[string]
$checkedSomething = $false

# Detect .NET 3.5 SP1 (supported runtime for 1.0-3.5 apps on supported OSes)

$net35Installed = $false
foreach ($view in $views) {
    $v35Install = Get-RegValue -View $view -SubKey 'SOFTWARE\Microsoft\NET Framework Setup\NDP\v3.5' -ValueName 'Install'
    if ($v35Install -eq 1) {
        $net35Installed = $true
        $checkedSomething = $true
        break
    }
}

# Detect .NET 4.x using Release key

$release = $null
foreach ($view in $views) {
    $tmp = Get-RegValue -View $view -SubKey 'SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full' -ValueName 'Release'
    if ($null -ne $tmp) {
        $release = [int]$tmp
        $checkedSomething = $true
        break
    }
}

if ($null -ne $release) {
    # 4.6.2 minimum supported baseline for 4.x branches

    if ($release -lt 394802) {
        $reasons.Add("Unsupported .NET 4.x detected (Release=$release, below 4.6.2 minimum)")
    }
} else {
    # No 4.5+ release key. Check for older 4.0 installs.

    foreach ($view in $views) {
        $v4ClientInstall = Get-RegValue -View $view -SubKey 'SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Client' -ValueName 'Install'
        $v4FullInstall   = Get-RegValue -View $view -SubKey 'SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full'   -ValueName 'Install'
        if ($v4ClientInstall -eq 1 -or $v4FullInstall -eq 1) {
            $checkedSomething = $true
            $reasons.Add('Unsupported .NET 4.0/4.5-era installation detected without supported 4.5+ Release key')
            break
        }
    }
}

# Detect standalone 2.0 / 3.0. If 3.5 SP1 is installed, those app runtimes are serviced under 3.5 support.

foreach ($view in $views) {
    $v20 = Get-RegValue -View $view -SubKey 'SOFTWARE\Microsoft\NET Framework Setup\NDP\v2.0.50727' -ValueName 'Install'
    if ($v20 -eq 1) {
        $checkedSomething = $true
        if (-not $net35Installed) {
            $reasons.Add('Standalone .NET 2.0 detected without .NET 3.5 SP1 support context')
        }
        break
    }
}

foreach ($view in $views) {
    $v30 = Get-RegValue -View $view -SubKey 'SOFTWARE\Microsoft\NET Framework Setup\NDP\v3.0\Setup' -ValueName 'InstallSuccess'
    if ($v30 -eq 1) {
        $checkedSomething = $true
        if (-not $net35Installed) {
            $reasons.Add('Standalone .NET 3.0 detected without .NET 3.5 SP1 support context')
        }
        break
    }
}

# Detect very old 1.1

foreach ($view in $views) {
    $v11 = Get-RegValue -View $view -SubKey 'SOFTWARE\Microsoft\NET Framework Setup\NDP\v1.1.4322' -ValueName 'Install'
    if ($v11 -eq 1) {
        $checkedSomething = $true
        $reasons.Add('Unsupported .NET 1.1 detected')
        break
    }
}

# Report

if ($reasons.Count -gt 0) {
    Write-Output 'VULNERABLE'
    $reasons | ForEach-Object { Write-Output $_ }
    exit 1
}

if ($checkedSomething) {
    Write-Output 'PATCHED'
    if ($null -ne $release) {
        Write-Output ("Supported .NET 4.x Release key detected: {0}" -f $release)
    } elseif ($net35Installed) {
        Write-Output 'Supported .NET 3.5 SP1 runtime detected and no unsupported standalone legacy branches found'
    } else {
        Write-Output 'No unsupported .NET Framework branches detected by registry inspection'
    }
    exit 0
}

Write-Output 'UNKNOWN'
Write-Output 'Could not determine installed .NET Framework state from expected registry keys'
exit 2
07 · Bottom Line

If you remember one thing.

TL;DR
Monday morning: treat this as legacy-runtime hygiene, not an emergency outage-driven critical. Use the first pass to separate internet-facing or privileged server workloads from harmless workstation residue, then tie each flagged host to an owning application. For a MEDIUM verdict there is no noisgate mitigation SLA — go straight to the 365-day remediation window; use the noisgate remediation SLA to complete supported-runtime upgrades within 365 days. If you find a flagged host backing an exposed IIS app or a tier-0 business service, escalate that individual application based on *its* exposure and bugs rather than the scanner's default 10.0.

Sources

  1. Tenable plugin 72704
  2. Tenable plugin 72704 changelog
  3. Microsoft .NET Framework lifecycle
  4. .NET Framework support policy
  5. .NET Framework lifecycle FAQ
  6. .NET Framework 4.5.2/4.6/4.6.1 end-of-support FAQ
  7. Install .NET Framework on Windows
  8. Determine which .NET Framework versions are installed
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.