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

Double Free and possible RCE vulnerability in Apache HTTP Server with the HTTP/2 protocol

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

This is a faulty airbag in one exact model year, not a defect across the whole fleet

CVE-2026-23918 is a CWE-415 double-free in Apache HTTP Server's mod_http2 early-reset path. The vendor advisory, NVD, and oss-security all line up on one key fact: the affected upstream release is Apache HTTP Server 2.4.66, fixed in 2.4.67. In practice, a host is meaningfully exposed only when mod_http2 is loaded and HTTP/2 is actually enabled for reachable listeners.

The vendor's HIGH 8.8 baseline is directionally fair for an actually exposed host because the attacker position is strong: network reachability, no user interaction, and denial-of-service is credible with possible RCE under favorable heap conditions. But the real-world population is much smaller than a typical Apache bug because this is a single-version regression, many enterprise distros shipped fixes via backports or were never on 2.4.66 at all, and there is no KEV listing or solid in-the-wild exploitation evidence. That pushes this down from panic-grade to targeted-high.

"Dangerous if you actually run 2.4.66 with HTTP/2, but the exposed population is much narrower than the 8.8 suggests"
02 · The Attack Path

4 steps from start to impact.

STEP 01

Find an HTTP/2-capable Apache target

The attacker first needs a reachable Apache service that negotiates h2 or accepts h2c. Commodity tooling like curl --http2, nghttp, or nmap NSE can confirm HTTP/2 support quickly. This is internet-reachable in many environments, but only the subset actually serving HTTP/2 matters.
Conditions required:
  • Attacker can reach the web service over the network
  • HTTP/2 is enabled on the listener or virtual host
  • mod_http2 is loaded
Where this breaks in practice:
  • A lot of Apache estates still terminate HTTP/2 on a CDN, ALB, or reverse proxy instead of Apache itself
  • Many internal Apache nodes are plain HTTP/1.1 only
  • WAF/CDN fronting can hide or absorb direct protocol probing
Detection/coverage: External attack-surface scanners and config auditing can usually identify h2 exposure, but they do not prove the backend is the vulnerable 2.4.66 build.
STEP 02

Land on the narrow vulnerable build

The vulnerable slice is unusually tight: upstream 2.4.66. An attacker may infer this through banners, package metadata leaks, or simply spray broadly at Apache HTTP/2 targets and look for the crash signature. The narrow version window is the biggest real-world brake on exploit utility.
Conditions required:
  • Target is running upstream 2.4.66 or an equivalent vulnerable packaging of the same code path
  • The deployment has not already received a distro backport or non-vulnerable mod_http2 package
Where this breaks in practice:
  • Debian bullseye was explicitly marked not affected
  • Ubuntu said this issue only affected 26.04 LTS in its supported releases
  • Red Hat tracking states RHEL mod_http2 builds were confirmed not vulnerable
Detection/coverage: VM scanners can catch raw 2.4.66 banners, but package-backport logic creates false positives unless the scanner understands distro advisories.
STEP 03

Trigger the early-reset double free

Using a purpose-built client such as nghttp2-based tooling or the public h2ghost.py detector, the attacker sends crafted HTTP/2 frame sequences that drive the early stream reset path. The advertised low-complexity part is believable for process crash; public defensive tooling claims a minimal frame pattern can reproduce DoS conditions.
Conditions required:
  • HTTP/2 request path is reachable end-to-end
  • The server processes the crafted reset sequence in the vulnerable mod_http2 path
Where this breaks in practice:
  • Middleboxes that downgrade or normalize HTTP/2 can break the frame sequence
  • Not every deployment exposes the same request path or timing behavior
  • Some scanners and generic fuzzers will miss this because they do not exercise protocol-state edge cases
Detection/coverage: Network IDS is weak here unless it understands HTTP/2 frame semantics. Server-side monitoring is better: child crashes, restart spikes, and segfault/core-dump telemetry are the useful signals.
STEP 04

Turn memory corruption into impact

The reliable impact is service instability or child-process crash. Escalating from crash to code execution depends on allocator behavior, heap layout, module mix, and runtime environment; several writeups treat RCE as plausible rather than broadly weaponized. That gap matters a lot when scoring urgency.
Conditions required:
  • Attacker can repeatedly exercise the bug
  • Target runtime offers favorable heap conditions for corruption reuse
Where this breaks in practice:
  • Possible RCE is not the same as proven reliable RCE at scale
  • Process isolation, crash-only outcomes, and watchdog restarts reduce attacker payoff
  • Modern hardening and non-default allocators can collapse the exploit chain back to DoS
Detection/coverage: EDR and crash telemetry are more likely to catch post-corruption instability than the initial frame trigger. Public exploit coverage appears limited to PoC/detector-grade tooling, not mature mass-exploitation kits.
03 · Intelligence Metadata

The supporting signals.

In-the-wild statusNo authoritative public evidence of active exploitation found in the sources reviewed; not in CISA KEV.
Proof-of-concept availabilityPublic GitHub tooling exists: alt3kx/CVE-2026-23918 publishes h2ghost.py, positioned as a double-free detector with crash-check logic. Treat that as PoC-adjacent defender tooling, not proof of reliable RCE.
EPSS0.00952 supplied in your intel block, which is low and consistent with a narrow-version bug lacking visible exploitation momentum.
KEV statusNot listed in the CISA Known Exploited Vulnerabilities Catalog.
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H = network reachable, low complexity, no user interaction, but the published PR:L requirement looks more pessimistic for defenders than the attack path suggests; the main real-world limiter is exposure population, not privileges.
Affected versionsUpstream Apache and NVD say Apache HTTP Server 2.4.66. This is unusually narrow and is the strongest downward pressure on severity.
Fixed versionsUpstream fix is 2.4.67. Debian tracker shows fixed packages such as 2.4.67-1~deb12u2 for bookworm and notes bullseye was not affected; Ubuntu USN-8239-1 shipped fixes including 2.4.66-2ubuntu2.1 for 26.04 LTS and backported fixes for older supported releases.
Exposure realityInference from vendor docs and distro advisories: Apache as a product is common, but the truly exposed slice is Apache 2.4.66 + mod_http2 + HTTP/2 enabled + directly reachable path. That is far smaller than 'all Apache servers.'
Disclosure timelinePublished 2026-05-04 in NVD/GitHub Advisory Database; Apache released 2.4.67 the same day.
Reporting researchersApache credits Bartlomiej Dmitruk (striga.ai) and Stanislaw Strzalkowski (isec.pl).
04 · The Call

noisgate verdict.

Final Verdict
= UNCHANGED to HIGH (7.6/10)

The single most decisive factor is the very narrow affected population: upstream 2.4.66 only, plus mod_http2 must be loaded and HTTP/2 must actually be exposed. I kept this in HIGH because for the hosts that do meet those conditions the attacker position is still strong—network-reachable, low-friction crash potential, and non-zero RCE upside.

HIGH Affected upstream version range is narrowly limited to 2.4.66
MEDIUM Reliable DoS impact on exposed vulnerable hosts
LOW Broadly reliable RCE in heterogeneous enterprise deployments

Why this verdict

  • Downgraded for exposure math: this is not a broad Apache class break; it is a single-version regression centered on upstream 2.4.66.
  • Downgraded for deployment prerequisites: the host also needs mod_http2 loaded and HTTP/2 enabled on a reachable service path. That excludes a meaningful chunk of Apache fleets behind proxies, CDNs, or HTTP/1.1-only configs.
  • Downgraded for distro reality: Debian bullseye is marked not affected, Ubuntu says only 26.04 LTS was affected in its supported set, and Red Hat tracking says RHEL mod_http2 builds were confirmed not vulnerable.
  • Held at HIGH because attacker position is still strong on exposed nodes: the vulnerable path is remote, no user interaction is needed, and public tooling exists to exercise the bug path.
  • Held at HIGH because possible RCE rides on top of a memory-safety flaw: even if most real outcomes are crash-first, internet-facing memory corruption in a web server should not be treated as routine backlog work.

Why not higher?

There is no KEV entry, no solid public evidence of active exploitation in the reviewed sources, and no demonstrated ecosystem-wide reliable RCE chain. Most importantly, the affected population is constrained by a single upstream version plus a protocol/module requirement, which sharply limits the number of enterprise hosts that are actually reachable to this bug.

Why not lower?

Once you do have an exposed 2.4.66 + HTTP/2 host, the attacker does not need prior foothold, phishing, or local access. That keeps this above MEDIUM: it is still an internet-facing memory-corruption issue with at least credible denial-of-service and plausible code-execution upside.

05 · Compensating Control

What to do — in priority order.

  1. Disable HTTP/2 where you can — Remove h2/h2c from Protocols or unload mod_http2 on affected Apache 2.4.66 systems that cannot be patched immediately. This directly removes the vulnerable code path and, for a HIGH verdict, should be deployed within 30 days.
  2. Put a proxy in front of stragglers — If the application must stay up, terminate HTTP/2 on a CDN, load balancer, or reverse proxy and speak HTTP/1.1 to the backend Apache node. That reduces direct attacker reachability to the vulnerable parser and should be implemented within 30 days for any remaining exposed 2.4.66 instances.
  3. Alert on child crashes and restarts — Create detections for httpd/apache2 segfaults, core dumps, abnormal worker exits, and restart bursts. This will not stop exploitation, but it is the best short-term signal for attempted trigger activity while mitigations are being rolled out within the 30-day window.
  4. Hunt for exact version plus module state — Inventory hosts for upstream 2.4.66, then intersect with http2_module loaded and Protocols exposing h2 or h2c. Do this first so you patch the real blast radius instead of burning cycles on unaffected Apache servers; complete the hunt inside the 30-day HIGH mitigation window.
What doesn't work
  • A generic WAF rule is not a dependable fix because the bug lives in HTTP/2 frame/state handling, not a simple URL or header pattern the WAF can reliably match.
  • Version-only scanning without distro awareness does not help enough; Apache package backports and independent mod_http2 packaging can create false positives and false comfort.
  • Assuming 'we run Apache behind TLS, so we're safe' does nothing here. If the backend Apache still negotiates or receives HTTP/2, TLS is just the transport wrapper around the vulnerable protocol path.
06 · Verification

Crowdsourced verification payload.

Run this on the target Linux host that runs Apache, not from an auditor workstation. Invoke it as bash cve-2026-23918-check.sh with a user that can run apachectl/httpd -M and read Apache config files; root is helpful but not strictly required.

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# CVE-2026-23918 Apache HTTP/2 exposure check
# Exit codes:
#   0 = PATCHED / not vulnerable
#   1 = VULNERABLE
#   2 = UNKNOWN / could not determine

set -u

say() { printf '%s\n' "$*"; }
fail_unknown() { say "UNKNOWN - $*"; exit 2; }
patched() { say "PATCHED - $*"; exit 0; }
vuln() { say "VULNERABLE - $*"; exit 1; }

APACHECTL=""
for c in apache2ctl apachectl httpd; do
  if command -v "$c" >/dev/null 2>&1; then
    APACHECTL="$c"
    break
  fi
done

[ -n "$APACHECTL" ] || fail_unknown "Apache control binary not found"

VER_OUT="$($APACHECTL -v 2>/dev/null || true)"
[ -n "$VER_OUT" ] || fail_unknown "Could not read Apache version with '$APACHECTL -v'"

SERVER_VER="$(printf '%s\n' "$VER_OUT" | sed -n 's#.*Apache/\([0-9][0-9.]*\).*#\1#p' | head -n1)"
[ -n "$SERVER_VER" ] || fail_unknown "Could not parse Apache version from: $VER_OUT"

MODULES="$($APACHECTL -M 2>/dev/null || true)"
if [ -z "$MODULES" ]; then
  MODULES="$($APACHECTL -l 2>/dev/null || true)"
fi

HTTP2_LOADED="no"
printf '%s\n' "$MODULES" | grep -Eiq '(^|\s)http2_module(\s|$)|mod_http2' && HTTP2_LOADED="yes"

CONF_ROOTS="/etc/apache2 /etc/httpd /usr/local/apache2/conf"
HTTP2_ENABLED="unknown"
FOUND_PROTOCOLS=""
for root in $CONF_ROOTS; do
  if [ -d "$root" ]; then
    MATCHES="$(grep -RniE '^[[:space:]]*Protocols[[:space:]].*(h2|h2c)' "$root" 2>/dev/null || true)"
    if [ -n "$MATCHES" ]; then
      HTTP2_ENABLED="yes"
      FOUND_PROTOCOLS="$MATCHES"
      break
    fi
  fi
done

if [ "$HTTP2_ENABLED" = "unknown" ]; then
  if [ "$HTTP2_LOADED" = "no" ]; then
    HTTP2_ENABLED="no"
  fi
fi

PKG_INFO=""
if command -v dpkg-query >/dev/null 2>&1; then
  PKG_INFO="$(dpkg-query -W -f='${Package} ${Version}\n' apache2 2>/dev/null || true)"
elif command -v rpm >/dev/null 2>&1; then
  PKG_INFO="$(rpm -q httpd mod_http2 2>/dev/null || true)"
fi

# Known safe/not-affected distro cases from vendor/distro advisories
if printf '%s\n' "$PKG_INFO" | grep -Eq 'apache2 2\.4\.52-1ubuntu4\.20|apache2 2\.4\.58-1ubuntu8\.12|apache2 2\.4\.64-1ubuntu3\.4|apache2 2\.4\.66-2ubuntu2\.1'; then
  patched "Ubuntu fixed package detected: $(printf '%s' "$PKG_INFO" | tr '\n' '; ')"
fi
if printf '%s\n' "$PKG_INFO" | grep -Eq 'apache2 2\.4\.67-1~deb11u1|apache2 2\.4\.67-1~deb12u2|apache2 2\.4\.67-1~deb13u2|apache2 2\.4\.67-1\b'; then
  patched "Debian fixed package detected: $(printf '%s' "$PKG_INFO" | tr '\n' '; ')"
fi
if printf '%s\n' "$PKG_INFO" | grep -Eq '^httpd-|^mod_http2-' ; then
  # RHEL/Fedora packaging is complicated here; Red Hat says RHEL builds were not vulnerable,
  # but we avoid over-claiming for all RPM-based environments without exact product context.
  :
fi

if [ "$SERVER_VER" != "2.4.66" ]; then
  patched "Apache version is $SERVER_VER, and upstream advisory limits CVE-2026-23918 to 2.4.66"
fi

# At this point Apache version is 2.4.66.
if [ "$HTTP2_LOADED" = "no" ]; then
  patched "Apache 2.4.66 is present, but mod_http2 does not appear to be loaded"
fi

if [ "$HTTP2_ENABLED" = "yes" ]; then
  vuln "Apache 2.4.66 with mod_http2 loaded and HTTP/2 enabled detected. Matching Protocols lines: $(printf '%s' "$FOUND_PROTOCOLS" | head -n 3 | tr '\n' ' ' )"
fi

if [ "$HTTP2_ENABLED" = "no" ]; then
  patched "Apache 2.4.66 with mod_http2 loaded, but no HTTP/2 Protocols directives were found"
fi

fail_unknown "Apache 2.4.66 detected and mod_http2 appears loaded, but HTTP/2 enablement could not be determined from standard config paths"
07 · Bottom Line

If you remember one thing.

TL;DR
Monday morning, do not launch a fleet-wide Apache panic. Instead, scope for the exact bad slice: upstream 2.4.66, mod_http2 loaded, and HTTP/2 exposed. For any internet-facing matches, apply a compensating control such as disabling HTTP/2 or offloading it at the edge within the noisgate mitigation SLA of ≤30 days, and complete the actual upgrade to the vendor-fixed build or distro-fixed package within the noisgate remediation SLA of ≤180 days. If your inventory shows you never ran 2.4.66, close it out with documented rationale and move on.

Sources

  1. Apache HTTP Server 2.4 vulnerabilities
  2. NVD CVE-2026-23918
  3. oss-security disclosure
  4. Debian Security Tracker CVE-2026-23918
  5. Ubuntu USN-8239-1
  6. Apache mod_http2 documentation
  7. GitHub Advisory GHSA-p8fm-9c82-pw4g
  8. CISA Known Exploited Vulnerabilities Catalog
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.