
Detection rules for CVE-2026-23918 Apache http2 RCE - Credit: stringa.ai, isec.pl
Published: 2026-05-04
CVSSv3: 8.8 (High)
Type: Remote Code Execution / Denial of Service (Double-Free Memory Corruption)
Component: Apache HTTP Server mod_http2 (h2_mplx.c stream cleanup path)
Affected: Apache HTTP Server 2.4.66 with HTTP/2 enabled and multi-threaded MPM
References:
CVE-2026-23918 is a double-free memory corruption vulnerability in the HTTP/2 protocol implementation of Apache HTTP Server 2.4.66, affecting only the mod_http2 module's stream cleanup path in h2_mplx.c. It allows an unauthenticated remote attacker to crash Apache worker processes (Denial of Service) with a single TCP connection and two HTTP/2 frames. Under conditions present on Debian-derived systems and official Apache Docker images, the double-free can be shaped into full Remote Code Execution.
DoS exploitation has been confirmed in the wild. Large-scale internet scans targeting HTTP/2 endpoints have been observed. The RCE exploit has been proven viable in controlled environments, though there is no evidence of widespread public exploitation for RCE at this time.
MPM prefork is not affected — the vulnerability requires a multi-threaded MPM configuration (worker, event, or similar). CVE-2026-23918 affects only Apache HTTP Server version 2.4.66.
Attacker opens HTTP/2 connection to Apache 2.4.66 (mod_http2 loaded, multi-threaded MPM)
└─ Sends HTTP/2 HEADERS frame on stream N (opens the stream)
└─ Immediately sends RST_STREAM on stream N (non-zero error code)
└─ Sent BEFORE the multiplexer has registered the stream
Two nghttp2 callbacks fire in sequence:
├─ on_frame_recv_cb (RST received) → calls h2_mplx_c1_client_rst → m_stream_cleanup
└─ on_stream_close_cb (stream closed) → calls h2_mplx_c1_client_rst → m_stream_cleanup
Result: same h2_stream pointer pushed onto spurge[] cleanup array TWICE
c1_purge_streams() iterates spurge[] and calls h2_stream_destroy() on each entry:
├─ First call: valid — frees the stream
└─ Second call: DOUBLE-FREE — operates on already-freed memory → heap corruption
DoS path (trivial, in the wild):
└─ Heap corruption → SIGABRT in worker process → worker dies → service disruption
RCE path (requires mmap allocator — default on Debian/Ubuntu and official Docker):
└─ Attacker places fake h2_stream struct at freed virtual address via mmap reuse
└─ Points pool cleanup function pointer to system()
└─ Uses Apache scoreboard shared memory (fixed address, ASLR-resistant) as payload container
└─ c1_purge_streams() executes system() with attacker-controlled argument → RCE
Key asymmetry: The DoS path requires no heap manipulation skill and is actively being exploited. The RCE path is technically demanding but has been demonstrated in lab conditions and will almost certainly be weaponized in the near future given the scoreboard's ASLR-resistant fixed address.
This section explains why the detection tooling here differs substantially from a typical local privilege escalation package.
Copy Fail (CVE-2026-31431) was a host-side, post-access vulnerability. The attacker needed existing presence on the system. Detection lived primarily at the syscall layer (auditd, Wazuh) with YARA scanning for the PoC script on disk.
CVE-2026-23918 is a network-side, pre-access vulnerability. The exploit arrives as HTTP/2 protocol frames over the wire before any application code runs. This shifts the detection stack significantly:
| Layer | Copy Fail (LPE) | CVE-2026-23918 (RCE) |
|---|---|---|
| Primary detection | Auditd syscall rules | Suricata network rules |
| WAF (ModSecurity) | Limited — can't see exploit | Relevant — anomaly + post-exploit |
| Auditd | Core detection | Outcome detection (crashes, post-exploit) |
| YARA | Scans for PoC script | Scans for web shells (post-exploit artifacts) |
| Network IDS | Not applicable | First-class detection layer |
| TLS inspection | N/A | Required for full Suricata coverage |
The rule-of-thumb: for network-level RCE, work outward-in (network → WAF → host). For local privilege escalation, work from the host outward.
Read this before deploying any rules.
1. TLS terminates HTTP/2 visibility. Most production Apache deployments serve HTTPS. Suricata cannot inspect the contents of encrypted HTTP/2 frames without TLS decryption being configured. If your Suricata deployment does not have access to TLS session keys or a decryption mirror, the network-level rules below will only catch:
For HTTPS deployments, enable Suricata's TLS decryption via the tls-decrypt setting and session key logging, or rely on the WAF (ModSecurity/Coraza) and host-based (auditd/Wazuh) layers instead.
2. ModSecurity cannot block the exploit trigger. The double-free occurs inside the HTTP/2 frame parser, before a complete HTTP request is assembled and passed to ModSecurity. The WAF sees the request only after frame parsing completes — at which point the damage may already be done. ModSecurity in this package is used for anomaly detection, rate limiting, and post-exploitation detection, not as a blocker for the trigger.
3. MPM prefork is unaffected.
If your Apache deployment uses mpm_prefork_module (single-threaded), this vulnerability does not apply. The bug only manifests in multi-threaded MPMs (mpm_event_module or mpm_worker_module). Check with apachectl -V | grep MPM before deploying rules that would produce false positives on prefork servers.
4. RCE requires the mmap allocator. The RCE path (not the DoS path) requires APR's mmap allocator, which is the default on Debian-derived distributions and official Apache Docker images. RHEL/CentOS-based deployments using jemalloc or system malloc have reduced RCE risk, but are still fully vulnerable to DoS.
5. No stable post-exploitation IoCs yet. No vendor-published IoCs for post-exploitation activity exist as of this writing. The YARA rules and auditd rules targeting post-exploitation behavior are based on general web shell and privilege escalation patterns — they will catch common outcomes but not a sophisticated, bespoke payload.
Apply in order of preference. Each is more disruptive than the last, but each is more complete.