CVE-2026-23918 is not a vague Apache headline. It is a specific Apache HTTP Server 2.4.66 issue in HTTP/2 handling, described by Apache as “http2: double free and possible RCE on early reset.” Apache fixed it in Apache HTTP Server 2.4.67, released on May 4, 2026. The official Apache advisory lists 2.4.66 as the affected version, credits Bartlomiej Dmitruk of striga.ai and Stanislaw Strzalkowski of isec.pl as finders, and shows that the issue was reported to the Apache security team on December 10, 2025 and fixed in source on December 11, 2025. (Apache HTTP Server)
The practical question behind “CVE-2026-23918 PoC” is not simply whether someone can send a packet sequence that makes a server crash. The useful question is how a security team can prove exposure without turning a production web tier into the test target. A safe workflow needs to answer five things: whether Apache 2.4.66 is present, whether mod_http2 is loaded, whether HTTP/2 is reachable from the relevant network path, whether the deployment uses an exposed worker model that makes the issue meaningful, and whether the fix has actually reached the running process rather than only the package cache.
The confirmed remediation is straightforward: upgrade to Apache HTTP Server 2.4.67 or to the patched package supplied by the operating system or control-panel vendor. NVD repeats the Apache description, classifies the weakness as CWE-415 Double Free, lists CISA-ADP’s CVSS 3.1 score as 8.8 High, and shows the vector as CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H. NVD also notes that its own assessment had not yet been provided at the time shown on the page, which matters when comparing vendor and third-party scoring. (NVD)
The rest of the work is precision. A careless PoC can become a denial-of-service test. A careless scanner result can become a false emergency. A careful validation path gives responders enough proof to patch, prioritize, and close the loop without handing operators an unsafe exploit recipe.
The bug in one page
| Feld | What is known |
|---|---|
| CVE | CVE-2026-23918 |
| Produkt | Apache HTTP Server |
| Affected version | Apache HTTP Server 2.4.66 |
| Fixed version | Apache HTTP Server 2.4.67 |
| Komponente | HTTP/2 handling through mod_http2 |
| Official Apache impact wording | Double free and possible RCE on early reset |
| Weakness class | CWE-415 Double Free |
| Official Apache severity label | Important |
| CVSS shown by NVD from CISA-ADP | 8.8 High |
| Primary operational risk | Worker crash and denial of service are the clearest public impact path |
| RCE status | Possible and publicly discussed, but more environment-dependent than a crash |
| First action | Patch to 2.4.67 or a distro-vendor fixed package |
| Safe validation | Version, module, protocol, MPM, package, process, and log verification |
| Unsafe validation | Running public crash or RCE PoCs against production or third-party systems |
Apache’s official wording is deliberately short. It confirms the vulnerable version, the affected protocol area, the fixed version, and the timeline. NVD adds the CWE classification and CISA-ADP score. The Hacker News published additional researcher-provided technical detail: the issue was described as a double-free in Apache httpd 2.4.66 mod_http2, specifically in the stream cleanup path of h2_mplx.c, triggered when a client sends an HTTP/2 HEADERS frame followed immediately by RST_STREAM with a non-zero error code before the multiplexer has registered the stream. That article also states that DoS is the easiest outcome and that the reported RCE path depends on allocator and memory-layout conditions. (Apache HTTP Server)
That distinction is the line between useful engineering and hype. A double-free in a web server is serious because it is a memory-management bug in a network-exposed parser and stream lifecycle path. It does not mean every Apache deployment is instantly one packet away from a stable shell. It does mean Apache 2.4.66 with HTTP/2 enabled deserves fast inventory and patching, especially when exposed to the internet.
Why CVE-2026-23918 is an HTTP/2 bug, not just an Apache version string

HTTP/2 changes the shape of a web request. HTTP/1.1 mostly asks operators to think in terms of request lines, headers, bodies, keep-alive connections, and sometimes pipelining. HTTP/2 adds a binary framing layer, streams, multiplexing, SETTINGS, flow control, HEADERS frames, DATA frames, and stream reset semantics. RFC 9113 defines HTTP/2 as an optimized transport for HTTP semantics over a TCP connection. It also defines a frame as the smallest unit of communication in an HTTP/2 connection and describes streams as bidirectional flows of frames within that connection. (rfc-editor.org)
That design gives browsers and APIs performance advantages. Many requests can share one connection. A client can cancel one stream without closing the entire TCP session. A server can manage many concurrent streams, apply flow control, and send responses without the same head-of-line behavior seen at the HTTP message level in older designs. The same design also gives implementation bugs more state to mishandle.
Apache enables HTTP/2 through mod_http2. The Apache HTTP/2 guide says a build with mod_http2 needs the module loaded and a Protocols directive such as Protocols h2 http/1.1 to make HTTP/2 active for secure connections. The same documentation shows that Protocols h2 h2c http/1.1 enables both TLS HTTP/2 and cleartext h2c, and that placement can apply globally or to a specific virtual host. (Apache HTTP Server)
That means “we run Apache” is not enough. A team needs to answer the actual exposure chain:
| Frage | Warum das wichtig ist |
|---|---|
| Is the server running Apache HTTP Server 2.4.66 or a downstream package containing the vulnerable code path | The official affected version is 2.4.66 |
Ist mod_http2 loaded | The bug is in HTTP/2 handling |
| Is HTTP/2 enabled for the relevant virtual host | A loaded module may not be reachable |
| Is the server reachable directly or through a proxy that passes HTTP/2 to Apache | Edge termination can change exposure |
| Which MPM is active | Public researcher commentary distinguishes multithreaded MPM exposure from prefork behavior |
| Has the running process been restarted after patching | Package upgrades do not always replace already-running workers |
| Are containers or golden images still pinned to 2.4.66 | Runtime patching can miss immutable images |
Apache’s MPM model matters because it changes how the server accepts and handles work. Apache documentation describes Multi-Processing Modules as the components responsible for binding network ports, accepting requests, and dispatching children to handle them. It also says Apache can choose different MPMs such as threaded worker oder event, while prefork is used for stability or older compatibility needs. (Apache HTTP Server)
Apache’s HTTP/2 guide adds an important operational note: HTTP/2 is supported in all MPMs that ship with httpd, but prefork has severe restrictions, and the guide says event is generally the best choice if supported. (Apache HTTP Server) Public reporting on CVE-2026-23918 specifically says researcher commentary identified default deployments with mod_http2 and a multithreaded MPM as the easy DoS path, while prefork was said not to be affected by the flaw. (Die Hacker-Nachrichten)
The safe conclusion is not “prefork equals ignore.” The safe conclusion is that exposure depends on version, module, protocol reachability, MPM, and downstream patch status. Patch anyway if you are on the affected branch. Use the MPM detail for triage, not as an excuse to leave vulnerable packages installed.
The early reset path
A client cancels an HTTP/2 stream with RST_STREAM. That is not inherently malicious. It is a normal feature. A browser might cancel requests for images that are no longer visible. An API client might cancel a request after a timeout. A reverse proxy might reset a stream when an upstream response path is no longer useful.
RFC 9113 defines the HTTP/2 frame header and the stream identifier field. Frame type determines semantics, and stream identifiers attach frames to a particular stream except for connection-level frames. (rfc-editor.org) IANA’s HTTP/2 registry maps frame type 0x01 to HEADERS and 0x03 to RST_STREAM, both defined by RFC 9113. (iana.org)
For CVE-2026-23918, the reported trigger is not merely “an attacker uses RST_STREAM.” The reported trigger is a tight ordering problem in the Apache HTTP/2 stream cleanup path. The public technical description says the client sends HEADERS and then immediately sends RST_STREAM with a non-zero error code on the same stream before the multiplexer has registered that stream. Two callbacks then run in a sequence that can push the same stream pointer into a cleanup array twice. Later cleanup destroys the stream twice, resulting in a double free. (Die Hacker-Nachrichten)
That explanation is valuable for defenders because it tells you where to look for telemetry: not a strange URL, not a malicious file extension, not a CGI path, and not a web shell signature. The attack is a protocol-state and memory-lifecycle issue. If TLS terminates at Apache, a network sensor outside the TLS boundary probably cannot see the HTTP/2 frames. If TLS terminates at a load balancer and Apache receives cleartext HTTP/2 or HTTP/1.1 behind it, the relevant logs and packet visibility move to a different part of the stack.
It also explains why simple WAF matching is weak. A WAF rule that looks for /etc/passwd, ${jndi:, SQL keywords, or <script> is irrelevant. The dangerous input is not an application parameter. It is a sequence of HTTP/2 frames that interacts with server stream cleanup logic.
Double free, crash, and possible RCE
A double free occurs when software releases the same memory region twice. In a memory-safe language this class is usually prevented by ownership rules or runtime checks. Apache httpd is written in C and uses native memory management, Apache Portable Runtime abstractions, pools, callbacks, and module-specific lifecycle logic. Those designs can be reliable, but a wrong state transition can still free an object after it has already been scheduled for destruction.
The immediate consequence of a double free is often a crash. Modern allocators include checks that detect corrupted allocator state and abort the process. That is still serious in a web server because each crash drops active requests and can be sustained into service disruption. Public reporting says the DoS path for CVE-2026-23918 is easier than the RCE path and can crash a worker in default deployments with mod_http2 and a multithreaded MPM. (Die Hacker-Nachrichten)
Remote code execution is a different level of proof. RCE through double-free usually depends on shaping memory reuse so that a freed location is replaced with attacker-influenced data or a fake object, then causing the program to treat that data as trusted structure or control data. Public reporting says the researchers built a working x86_64 proof of concept in lab conditions, but it also notes caveats such as needing an information leak for system() and scoreboard offsets, plus probabilistic heap behavior. (Die Hacker-Nachrichten)
That should shape risk communication. It is fair to say CVE-2026-23918 is a high-priority memory-corruption issue with possible RCE. It is not precise to tell every operator that public internet RCE is guaranteed in their environment. The most defensible language is: the crash path is the most immediately actionable risk, and the RCE potential justifies urgent patching rather than waiting for stable exploit maturity.
The PoC question
Security teams search for PoCs because they need proof. Developers and infrastructure owners often do not prioritize a finding until someone can show that it matters. Bug bounty hunters search for PoCs because a CVE with a working validation method can convert an asset inventory result into a reportable issue. Red teams search for PoCs because they need controlled evidence inside an authorized scope.
CVE-2026-23918 is a case where “PoC” needs discipline. A public proof that sends the crash-triggering HTTP/2 frame sequence can deny service to a real web server. A public RCE PoC would be even more sensitive because the underlying issue is in an internet-facing web server. A responsible technical workflow can still be useful without handing readers a copy-paste crash tool.
A safe PoC for production should prove exposure, not exploit the memory corruption. That means the proof should identify a vulnerable Apache version, confirm mod_http2, confirm HTTP/2 reachability, confirm the loaded MPM where possible, and collect evidence that a patch removed the exposure. A destructive PoC belongs only in an isolated lab that the tester owns or has explicit permission to crash.
| PoC type | Production-safe | What it proves | Example evidence |
|---|---|---|---|
| Version and package validation | Ja | Apache or downstream package may contain the affected code | apachectl -v, package manager output |
| Module and protocol validation | Ja | mod_http2 and HTTP/2 are reachable | apachectl -M, ALPN result, curl --http2 |
| MPM validation | Ja | Runtime model affects risk triage | apachectl -M, config dump |
| Log-based crash hunting | Ja | Possible exploitation or unstable vulnerable process | journalctl, container logs, Apache error logs |
| Controlled crash reproduction | No for production | Triggerability in a lab | Isolated test server, not shared infrastructure |
| RCE research PoC | No for production | Code execution under specific allocator and memory conditions | Private lab, full authorization, crash-tolerant environment |
| Internet-wide scanning with trigger frames | Nein | Little legitimate value and high harm | Vermeiden Sie |
This line also protects the tester. Running a crash PoC against a third-party Apache server without permission is not “validation.” It is an unauthorized denial-of-service attempt. Even inside a company, a production crash can violate change-control rules and service-level commitments.
Safe exposure validation

Start locally on systems you administer. The goal is to identify Apache 2.4.66 plus HTTP/2 exposure. Run commands as a user with permission to inspect the service.
# Debian, Ubuntu, and derivatives
apache2 -v 2>/dev/null || apachectl -v 2>/dev/null
# RHEL, AlmaLinux, Rocky Linux, Fedora, and derivatives
httpd -v 2>/dev/null || apachectl -v 2>/dev/null
# Show loaded modules and find HTTP/2 plus the active MPM
apachectl -M 2>/dev/null | egrep 'http2|mpm'
# Dump virtual host mapping
apachectl -S 2>/dev/null
# Validate configuration syntax before and after any change
apachectl -t
On a vulnerable-looking host, look for http2_module and an MPM such as mpm_event_module oder mpm_worker_module. Absence of http2_module lowers practical exposure to this CVE, but it does not replace patching if the package is still affected. A module might be loaded later by configuration management, a container image might be reused elsewhere, and a scanner result might reflect a different network path.
Now inspect the HTTP/2 configuration.
# Common Apache config locations
grep -RIn --include='*.conf' \
-E '^\s*Protocols|^\s*LoadModule\s+http2_module|^\s*H2Direct|^\s*H2MaxSessionStreams' \
/etc/apache2 /etc/httpd /usr/local/apache2/conf 2>/dev/null
A common secure-site configuration looks like this:
LoadModule http2_module modules/mod_http2.so
<VirtualHost *:443>
ServerName www.example.com
Protocols h2 http/1.1
SSLEngine on
SSLCertificateFile /path/to/fullchain.pem
SSLCertificateKeyFile /path/to/key.pem
</VirtualHost>
For short-term containment, if you cannot patch immediately, you can remove HTTP/2 from the affected virtual host and restart Apache. That is a temporary reduction of exposure, not the fix.
<VirtualHost *:443>
ServerName www.example.com
Protocols http/1.1
</VirtualHost>
After changing protocol support, restart or reload in the way your environment supports. A restart is clearer during emergency response because it ensures the vulnerable process exits, but it can affect active connections.
# Debian and Ubuntu
sudo systemctl restart apache2
# RHEL-like systems
sudo systemctl restart httpd
# Source or container installs
sudo apachectl graceful
Where possible, prefer patching first and using HTTP/2 disablement only as a bridge. Apache’s official recommendation is to upgrade to 2.4.67. (Apache HTTP Server)
Remote protocol validation without triggering the bug
You can confirm whether a public endpoint negotiates HTTP/2 without sending a harmful frame sequence. This does not prove the server is vulnerable by itself, but it helps prioritize assets.
TARGET=www.example.com
# Check ALPN negotiation. Look for "ALPN protocol: h2".
echo | openssl s_client -connect "${TARGET}:443" -servername "${TARGET}" -alpn h2 2>/dev/null \
| egrep -i 'ALPN protocol|subject=|issuer='
# Confirm curl supports HTTP/2 and see the negotiated protocol.
curl -I --http2 "https://${TARGET}/" -sS -o /dev/null -w 'http_version=%{http_version}\nremote_ip=%{remote_ip}\nssl_verify=%{ssl_verify_result}\n'
Expected outputs:
| Output | Bedeutung |
|---|---|
ALPN protocol: h2 | The TLS endpoint negotiated HTTP/2 |
http_version=2 | curl completed the request over HTTP/2 |
http_version=1.1 | The endpoint did not negotiate HTTP/2 for this request |
| No ALPN line | The server, proxy, or test path may not support h2 |
| Certificate mismatch | Test the correct SNI name before drawing conclusions |
This step can mislead if a CDN or load balancer terminates TLS. If Cloudflare, AWS ALB, NGINX, Envoy, HAProxy, or another edge component terminates HTTP/2 and forwards HTTP/1.1 to Apache, the public endpoint may support HTTP/2 while Apache behind it does not see HTTP/2 frames. Conversely, an internal service mesh might send HTTP/2 to Apache even if the public edge does not expose it.
The right inventory model separates layers:
| Ebene | What to check |
|---|---|
| Public edge | ALPN h2, CDN or load balancer configuration |
| Reverse proxy | Whether upstream to Apache uses HTTP/2, h2c, or HTTP/1.1 |
| Apache process | Version, loaded modules, MPM, virtual host Protocols |
| Package source | Vendor patch status and backport notes |
| Runtime | Whether old workers are still running |
| Image | Whether container base images still include 2.4.66 |
A safe Python validator for ALPN and banner evidence
The following script does not trigger the vulnerability. It only checks TLS ALPN negotiation and performs a normal HTTPS HEAD request using Python’s standard library. Python’s standard library does not speak HTTP/2 here, so the HEAD request is not an HTTP/2 proof. The useful signal is the negotiated ALPN value from the TLS handshake.
#!/usr/bin/env python3
"""
Non-destructive CVE-2026-23918 exposure helper.
What it does:
- Connects to a TLS endpoint with SNI.
- Offers h2 and http/1.1 through ALPN.
- Reports which protocol the server selected.
- Sends a normal HTTPS HEAD request only when the selected protocol is http/1.1.
What it does not do:
- It does not send crafted HTTP/2 frames.
- It does not send RST_STREAM.
- It does not test for a crash.
- It does not prove exploitation.
"""
import argparse
import socket
import ssl
from datetime import datetime, timezone
def check_alpn(host: str, port: int, timeout: float) -> dict:
context = ssl.create_default_context()
context.set_alpn_protocols(["h2", "http/1.1"])
with socket.create_connection((host, port), timeout=timeout) as raw_sock:
with context.wrap_socket(raw_sock, server_hostname=host) as tls_sock:
cert = tls_sock.getpeercert()
selected = tls_sock.selected_alpn_protocol()
cipher = tls_sock.cipher()
return {
"host": host,
"port": port,
"selected_alpn": selected,
"cipher": cipher[0] if cipher else None,
"tls_version": tls_sock.version(),
"cert_subject": cert.get("subject"),
"checked_at": datetime.now(timezone.utc).isoformat(),
}
def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument("host", help="Hostname to test, for example www.example.com")
parser.add_argument("--port", type=int, default=443)
parser.add_argument("--timeout", type=float, default=5.0)
args = parser.parse_args()
result = check_alpn(args.host, args.port, args.timeout)
print(f"target={result['host']}:{result['port']}")
print(f"selected_alpn={result['selected_alpn']}")
print(f"tls_version={result['tls_version']}")
print(f"cipher={result['cipher']}")
print(f"checked_at={result['checked_at']}")
if result["selected_alpn"] == "h2":
print("risk_note=HTTP/2 is reachable at this TLS endpoint. Check Apache version, mod_http2, MPM, and upstream path.")
elif result["selected_alpn"] == "http/1.1":
print("risk_note=This TLS endpoint selected HTTP/1.1 for this test. Apache may still need local package verification.")
else:
print("risk_note=No ALPN protocol was selected. Validate with curl, openssl, and local Apache configuration.")
if __name__ == "__main__":
main()
Run it like this:
python3 safe_h2_alpn_check.py www.example.com
Interpretation should be conservative. selected_alpn=h2 means HTTP/2 is available on that TLS endpoint, not that Apache behind it is vulnerable. selected_alpn=http/1.1 means that test did not negotiate HTTP/2, not that every internal or alternate virtual host is safe. The script is useful as one piece of evidence in a wider asset review.
Local package validation across Linux distributions
Version strings can be tricky because Linux distributions often backport fixes without changing the upstream version in the way a source build would. For CVE-2026-23918, the upstream Apache version boundary is clean: Apache says 2.4.66 is affected and 2.4.67 fixes it. Downstream packages may show distro-specific release strings.
Ubuntu’s CVE page lists CVE-2026-23918 with high priority, describes it as “http2: double free and possible RCE on early reset,” and shows Ubuntu 26.04 LTS resolute fixed in 2.4.66-2ubuntu2.1 while earlier listed releases are marked not affected. Ubuntu’s note says that although the core issue exists in earlier releases, without the mod_http2 v2.0.33 allocator change that went into httpd 2.4.66, it does not result in a double-free. (Ubuntu)
That is a good example of why “2.4.66” is not always the whole answer. A distro package can be called 2.4.66 and still include a fix, or an older branch can contain code that looks related but is not affected in the same way. Trust the vendor advisory for your package source.
Use package-native checks:
# Debian and Ubuntu
dpkg-query -W apache2 apache2-bin 2>/dev/null
apt-cache policy apache2 apache2-bin 2>/dev/null
# RHEL, AlmaLinux, Rocky Linux, Fedora
rpm -qa | egrep '^httpd|^mod_http2|^ea-apache24'
dnf info httpd mod_http2 2>/dev/null | sed -n '1,80p'
# SUSE and openSUSE
rpm -qa | egrep '^apache2|^apache2-mod_http2'
zypper info apache2 2>/dev/null | sed -n '1,100p'
# Source builds
/usr/local/apache2/bin/httpd -v 2>/dev/null
/usr/local/apache2/bin/apachectl -M 2>/dev/null | egrep 'http2|mpm'
For cPanel EasyApache 4 environments, cPanel’s support article for CVE-2026-23918 tells administrators to update EasyApache packages and shows examples for AlmaLinux, CloudLinux, Imunify360, and Ubuntu. It also states the issue affects Apache HTTP Server 2.4.66 and recommends upgrading to 2.4.67. (support.cpanel.net)
# cPanel EasyApache on AlmaLinux, from cPanel guidance
sudo dnf clean all
sudo dnf makecache
sudo dnf -y update 'ea-apache*'
# cPanel EasyApache on Ubuntu, from cPanel guidance
sudo apt update
sudo apt install --only-upgrade "ea-apache24*"
The exact repository channel matters. Do not copy a distro command blindly across environments. Use it as a model for the package family you actually run.
Container and image checks
Containers make this CVE easier to miss. A host might be patched while an application still runs an old httpd:2.4.66 image. A Kubernetes deployment might restart into the same vulnerable image because the tag is pinned. A CI build might cache the vulnerable base layer.
Start with local container inventory:
# Running containers with Apache-like images or commands
docker ps --format '{{.ID}} {{.Image}} {{.Command}} {{.Names}}' \
| egrep -i 'httpd|apache|apache2'
# Inspect images for version hints
docker images --format '{{.Repository}}:{{.Tag}} {{.ID}} {{.CreatedSince}}' \
| egrep -i 'httpd|apache'
# Check inside a running container you own
docker exec -it <container_id> httpd -v
docker exec -it <container_id> httpd -M | egrep 'http2|mpm'
For Kubernetes:
# Find pods and images that may contain Apache httpd
kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.namespace}{" "}{.metadata.name}{" "}{range .spec.containers[*]}{.image}{" "}{end}{"\n"}{end}' \
| egrep -i 'httpd|apache'
# Check a specific pod
kubectl exec -n <namespace> <pod> -- httpd -v
kubectl exec -n <namespace> <pod> -- httpd -M | egrep 'http2|mpm'
Then check image source, not only running containers. Update Dockerfiles and Helm values. Rebuild from a fixed base image. Redeploy. Confirm the new pod or container is actually running the fixed package. Remove vulnerable images from registries where feasible or mark them blocked in admission control.
A safe Kubernetes admission policy can enforce “no known-vulnerable Apache images” by digest or tag, but tag-based controls are weaker than digest-based controls. The best long-term pattern is SBOM plus image scanning plus deployment-time policy.
Patch strategy
The clean fix is to move to Apache HTTP Server 2.4.67 or a vendor-patched package. Apache’s 2.4 vulnerability page says users are recommended to upgrade to 2.4.67 for CVE-2026-23918. (Apache HTTP Server) The same 2.4.67 section lists several other fixed issues, including CVE-2026-24072 in mod_rewrite, CVE-2026-28780 in mod_proxy_ajp, CVE-2026-29168 in mod_md, CVE-2026-29169 in mod_dav_lock, CVE-2026-33006 in mod_auth_digest, CVE-2026-33007 in mod_authn_socache, and multiple AJP or response-splitting issues. (Apache HTTP Server)
That makes 2.4.67 more than a single-CVE update. If your change board asks why this patch cannot wait, the answer is not only possible RCE in HTTP/2. It is also that the release aggregates fixes across authentication, rewrite behavior, proxy parsing, DAV locking, response splitting, and AJP parsing.
A production patch plan should include:
| Schritt | Evidence to collect |
|---|---|
| Identify all Apache assets | CMDB export, package query, container inventory |
| Confirm exposed HTTP/2 | ALPN result, Apache config, proxy config |
| Rank externally reachable 2.4.66 first | DNS, load balancer, ingress, firewall context |
| Patch package or rebuild image | Package manager logs, image digest |
| Restart or roll deployment | Process start time, pod age, systemd status |
| Verify fixed version | apachectl -v, package release string, vendor advisory |
| Verify HTTP/2 policy | curl --http2, openssl s_client, config dump |
| Hunt for pre-patch crashes | Error logs, journald, container logs, SIEM |
| Document remediation | Ticket, evidence, owner, timestamp |
For Debian or Ubuntu systems:
sudo apt update
sudo apt install --only-upgrade apache2 apache2-bin apache2-data apache2-utils
sudo systemctl restart apache2
apache2 -v
apachectl -M | egrep 'http2|mpm'
For RHEL-like systems:
sudo dnf clean all
sudo dnf update httpd mod_http2
sudo systemctl restart httpd
httpd -v
apachectl -M | egrep 'http2|mpm'
For source builds, download and verify Apache’s official source release, rebuild with the same module policy, deploy into a staging environment, then roll through production. Source-build environments need special care because package-manager checks will not tell the whole story.
Temporary HTTP/2 disablement
Disabling HTTP/2 can reduce attack surface when emergency patching is blocked by a maintenance window, dependency constraint, or vendor packaging delay. It is not equivalent to applying the fix. It also may change performance characteristics for clients.
A temporary global reduction might look like this:
# Temporary containment only
Protocols http/1.1
A virtual-host reduction might look like this:
<VirtualHost *:443>
ServerName app.example.com
Protocols http/1.1
</VirtualHost>
After the change:
apachectl -t
sudo systemctl restart apache2 || sudo systemctl restart httpd
echo | openssl s_client -connect app.example.com:443 -servername app.example.com -alpn h2 2>/dev/null \
| egrep -i 'ALPN protocol'
If HTTP/2 has been removed successfully for that endpoint, openssl s_client should not show ALPN protocol: h2 for that SNI path. Test important virtual hosts individually because Apache’s Protocols directive can be scoped differently per server or virtual host. Apache’s HTTP/2 guide explicitly shows that Protocols placement can affect all connections or only a specific virtual host. (Apache HTTP Server)
Before disabling HTTP/2, coordinate with application owners. Some gRPC, service-to-service, or performance-sensitive paths may assume HTTP/2. If Apache is behind a proxy, you also need to know whether the proxy will downgrade upstream traffic or fail requests.
Detection and hunting
CVE-2026-23918 is not a web request payload vulnerability. You are unlikely to catch it by searching access logs for a suspicious path. The more useful signals are process crashes, allocator aborts, worker exits, restart loops, abnormal HTTP/2 reset telemetry at a proxy, and sudden request drops.
Start with host logs:
# Debian and Ubuntu Apache logs
sudo egrep -i 'segfault|double free|free\(\)|corruption|child pid|exit signal|http2|h2_|AH' \
/var/log/apache2/error.log /var/log/apache2/error.log.* 2>/dev/null
# RHEL-like Apache logs
sudo egrep -i 'segfault|double free|free\(\)|corruption|child pid|exit signal|http2|h2_|AH' \
/var/log/httpd/error_log /var/log/httpd/error_log-* 2>/dev/null
# systemd journal
sudo journalctl -u apache2 --since '2026-05-04' 2>/dev/null \
| egrep -i 'segfault|double free|corruption|exit signal|http2|h2_'
sudo journalctl -u httpd --since '2026-05-04' 2>/dev/null \
| egrep -i 'segfault|double free|corruption|exit signal|http2|h2_'
For containers:
# Docker
docker logs <container_id> 2>&1 \
| egrep -i 'segfault|double free|free\(\)|corruption|exit signal|http2|h2_'
# Kubernetes
kubectl logs -n <namespace> <pod> --previous 2>&1 \
| egrep -i 'segfault|double free|free\(\)|corruption|exit signal|http2|h2_'
kubectl get pods -A | egrep -i 'CrashLoopBackOff|Error|Restart'
A Sigma-style detection for Linux web server crash indicators can be used as a starting point. Tune field names to your SIEM.
title: Apache HTTP Server Possible HTTP2 Memory Corruption Crash
id: 4d81fd8b-9f86-4a7d-b7c0-cve-2026-23918-hunt
status: experimental
description: Detects Apache httpd or apache2 crash patterns that may be consistent with memory corruption or worker crash activity during CVE-2026-23918 exposure review.
logsource:
product: linux
service: syslog
detection:
process_terms:
- 'apache2'
- 'httpd'
crash_terms:
- 'segfault'
- 'double free'
- 'free():'
- 'corrupted'
- 'malloc'
- 'child pid'
- 'exit signal'
condition: process_terms and crash_terms
fields:
- host
- service
- message
- timestamp
falsepositives:
- Unrelated Apache module crashes
- Local administrator testing in a lab
- Non-Apache processes writing similar allocator errors
level: high
For Splunk:
(index=linux OR index=web OR index=containers)
("apache2" OR "httpd")
("segfault" OR "double free" OR "free():" OR "corrupted" OR "child pid" OR "exit signal" OR "malloc")
earliest="05/04/2026:00:00:00"
| stats count min(_time) as firstSeen max(_time) as lastSeen values(source) as sources by host
| convert ctime(firstSeen) ctime(lastSeen)
| sort -count
For Microsoft Sentinel using a syslog-style table:
Syslog
| where TimeGenerated >= datetime(2026-05-04)
| where SyslogMessage has_any ("apache2", "httpd")
| where SyslogMessage has_any ("segfault", "double free", "free():", "corrupted", "child pid", "exit signal", "malloc")
| summarize Count=count(), FirstSeen=min(TimeGenerated), LastSeen=max(TimeGenerated), Messages=make_set(SyslogMessage, 5) by Computer
| order by Count desc
For Kubernetes logs in a centralized platform:
ContainerLog
| where TimeGenerated >= datetime(2026-05-04)
| where LogEntry has_any ("apache2", "httpd", "mod_http2", "h2_")
| where LogEntry has_any ("segfault", "double free", "free():", "corrupted", "exit signal", "malloc")
| summarize Count=count(), FirstSeen=min(TimeGenerated), LastSeen=max(TimeGenerated), Samples=make_set(LogEntry, 5) by Computer, ContainerID, Image
| order by Count desc
No single detection proves exploitation. Treat these queries as triage. If they match on a host that was running Apache 2.4.66 with HTTP/2 enabled before patching, preserve logs, identify request timing, check edge telemetry, and verify whether crashes stopped after remediation.
Network visibility limits
HTTP/2 over TLS hides frames from passive network sensors that do not terminate TLS. That means an IDS sitting outside the TLS boundary will see a TLS connection, not the HEADERS and RST_STREAM sequence. If TLS terminates at a reverse proxy, that proxy may expose useful telemetry: protocol version, stream reset counts, connection close reasons, upstream error spikes, and per-client reset behavior.
Useful edge signals include:
| Signal | Warum das wichtig ist |
|---|---|
| Spike in HTTP/2 stream resets from a small set of clients | Could indicate probing or abuse |
| Many short-lived HTTP/2 sessions with few completed responses | Could indicate protocol-state testing |
| Apache upstream 502 or connection reset bursts | Could indicate worker crashes behind a proxy |
| Apache process restart loops | Stronger host-side signal |
| Drop in successful requests during reset spikes | Potential service impact |
| Post-patch disappearance of crash pattern | Supports remediation effectiveness |
Cloudflare’s public Rapid Reset analysis is about CVE-2023-44487, not CVE-2026-23918, but it is still useful for understanding how HTTP/2 reset behavior can stress infrastructure. Cloudflare described HTTP/2 request cancellation with RST_STREAM, how canceled streams quickly return capacity to clients, and why stream concurrency alone does not necessarily stop rapid reset abuse. (The Cloudflare Blog)
Do not overfit that lesson. CVE-2023-44487 is a protocol-level resource exhaustion pattern. CVE-2026-23918 is an Apache implementation memory safety issue. Both involve HTTP/2 reset behavior, but the defensive evidence differs. Rapid Reset often appears as volumetric L7 abuse. CVE-2026-23918 hunting should focus more on vulnerable Apache version exposure and process instability.
Why scanners can be wrong
A scanner can under-report or over-report CVE-2026-23918.
It can under-report when Apache hides behind a proxy that strips banners, when version output is customized, when the scanner only tests HTTP/1.1, when the vulnerable Apache instance is reachable only from an internal network, or when the scanner cannot inspect containers and golden images.
It can over-report when it sees an upstream version string but the distribution has backported the fix, when the public HTTP/2 endpoint is actually a CDN that forwards HTTP/1.1 to Apache, when mod_http2 is installed but not loaded, or when Apache 2.4.66 is present on disk but no running process uses it.
The safest scanner output is not “vulnerable” or “not vulnerable.” It is a bundle of evidence:
{
"asset": "web-frontend-17",
"apache_version": "Apache/2.4.66",
"package_version": "2.4.66-2ubuntu2.1",
"vendor_status": "fixed according to Ubuntu for resolute",
"http2_module_loaded": true,
"active_mpm": "event",
"public_alpn_h2": true,
"edge_terminates_tls": false,
"running_process_start_time": "2026-05-06T18:42:00Z",
"post_patch_restart_confirmed": true,
"risk_decision": "fixed package present, monitor logs, no crash indicators after restart"
}
A good report also states what was not tested. It should say, for example, “No destructive HTTP/2 reset PoC was executed” or “HTTP/2 reachability was validated only from the public internet, not from internal service mesh paths.”
CVSS and severity nuance
NVD currently shows CISA-ADP’s CVSS 3.1 score as 8.8 High with PR:L, while public researcher commentary quoted by The Hacker News describes the DoS path as not requiring authentication. SUSE’s page shows both a CNA score of 8.8 and a SUSE score of 8.1 with different vector assumptions, including AC:H und PR:N in SUSE’s vector. (NVD)
That discrepancy is not unusual during fresh vulnerability handling. CVSS can reflect different interpretations of preconditions, authentication, exploit outcome, or environment. For responders, the decision should not wait for perfect scoring harmony. The affected version is narrow, the fixed version is known, the component is often internet-facing, and the bug class is memory corruption with possible RCE. Those facts are enough to patch quickly.
A practical severity model can use the following:
| Zustand | Priorität |
|---|---|
Apache 2.4.66, mod_http2 loaded, public HTTP/2 reachable, event or worker MPM | Emergency patch |
| Apache 2.4.66, HTTP/2 internal only, sensitive internal service | High priority patch |
| Apache 2.4.66 installed but HTTP/2 not loaded | Patch soon and prevent module enablement |
| Distro package marked fixed by vendor, process restarted | Verify and monitor |
| Older distro package marked not affected by vendor | Track advisory, do not override vendor analysis without evidence |
| Source build at 2.4.66 | Upgrade to 2.4.67 |
| Container image pinned to 2.4.66 | Rebuild and redeploy |
This model is not a substitute for your own change-control process. It is a way to stop low-quality debates such as “CVSS says High, not Critical, so it can wait.” Internet-facing memory corruption in a web server should not wait for exploit kits to become convenient.
Related CVEs that help frame the risk
CVE-2026-23918 is easier to understand when compared to other HTTP/2 and Apache HTTP Server issues.
| CVE | Product area | Why it is relevant | Key difference |
|---|---|---|---|
| CVE-2023-44487 | HTTP/2 Rapid Reset | Shows how RST_STREAM behavior can be abused at scale | Protocol-level DoS, not Apache-specific double free |
| CVE-2025-49630 | Apache mod_proxy_http2 | Another Apache HTTP/2-related DoS class | Affects certain proxy configurations with HTTP/2 backend and ProxyPreserveHost on |
| CVE-2026-24072 | Apache mod_rewrite and ap_expr | Same Apache 2.4.67 release family | Local .htaccess author privilege issue, not HTTP/2 |
| CVE-2026-28780 | Apache mod_proxy_ajp | Same 2.4.67 release family | AJP backend interaction, not client-side HTTP/2 reset |
NVD describes CVE-2023-44487 as an HTTP/2 denial-of-service condition where request cancellation can reset many streams quickly and notes exploitation in the wild during August through October 2023. (NVD) That matters because it trained defenders to look at HTTP/2 resets as a real attack surface, not just benign browser behavior.
NVD describes CVE-2025-49630 as a denial-of-service issue in Apache HTTP Server versions 2.4.26 through 2.4.63, triggered in certain proxy configurations where a reverse proxy is configured for an HTTP/2 backend with ProxyPreserveHost on. (NVD) That helps separate Apache HTTP/2 proxy bugs from the CVE-2026-23918 client-facing early reset double-free.
Apache’s 2.4.67 advisory list also shows why operators should read the whole release note. CVE-2026-24072 affects mod_rewrite und ap_expr, CVE-2026-28780 affects mod_proxy_ajp, CVE-2026-29168 affects mod_md, and several other issues affect authentication, AJP parsing, DAV locking, and response handling. (Apache HTTP Server)
The comparison prevents two mistakes. The first mistake is treating every HTTP/2 reset issue as the same bug. The second is patching only the one CVE that made the headline while leaving the same Apache fleet exposed to the rest of the release’s fixes.
Safe lab reproduction principles
A controlled lab can be useful for exploit developers, defenders, and product security teams. It should be isolated, disposable, and owned by the tester. It should not share a production network path, customer data, live traffic, or a persistent credential store.
A safe lab has:
| Anforderung | Reason |
|---|---|
| Dedicated VM or container host | Prevents collateral service impact |
| No public exposure | Prevents others from abusing the vulnerable instance |
| Explicitly vulnerable Apache 2.4.66 | Keeps the test honest |
| HTTP/2 enabled only for the lab | Prevents accidental exposure |
| Crash-tolerant process supervision | The expected DoS path may kill workers |
| Full packet capture inside the lab | Supports learning without public harm |
| ASAN or debug build where possible | Makes memory errors easier to observe |
| No secrets | Memory corruption testing can leak or corrupt data |
| Clear teardown step | Prevents vulnerable images from lingering |
A lab can use normal Apache configuration checks and packet capture to understand how HTTP/2 streams behave. It does not need to publish a weaponized frame generator to be valuable. If a team has a legitimate need to test the crash trigger, that code should stay inside the authorized lab workflow and not be pointed at shared environments.
A lab evidence bundle might include:
asset: lab-apache-2466
scope: isolated local VM
apache_version_before: 2.4.66
mod_http2: loaded
mpm: event
protocols: h2 http/1.1
test_type: controlled crash reproduction
production_targets: none
result_before_patch: worker crash observed
apache_version_after: 2.4.67
result_after_patch: crash condition no longer reproduced
artifacts: config dump, packet capture, error log, process log, patch log
That evidence is more useful than a screenshot of a terminal. It shows precondition, test boundary, result, remediation, and retest.
Remediation validation with automation
Large environments rarely have one Apache server. They have old VM images, cPanel hosts, Kubernetes ingress services, internal reverse proxies, developer test boxes, forgotten staging systems, and product appliances. Manual verification can miss the asset that matters.
A practical workflow for authorized teams is to automate only the safe parts first: discover Apache services, fingerprint reachable HTTP/2, collect local package and module evidence where credentials exist, rank externally exposed 2.4.66 systems, patch through the owning platform, and retest. Penligent’s public materials describe agentic workflows with controlled actions, evidence, one-click reports, CVE validation, and integration of security tools into an AI-driven workflow. Those capabilities are naturally relevant to this kind of authorized validation when the operator keeps scope locked and avoids destructive PoC execution on production systems. (Sträflich)
The key is governance. A useful AI-assisted workflow should preserve every command, target, output, and decision. For CVE-2026-23918, a safe task should say “confirm exposure and collect proof without sending malicious HTTP/2 reset sequences.” If destructive testing is required, it should be a separate lab-only task with explicit approval. Penligent’s own homepage includes an authorized-use disclaimer, which is the right default for any tool that can execute security tests. (Sträflich)
A production runbook
Use this as a practical sequence for a security team responding to CVE-2026-23918.
Step 1, identify Apache assets
# Example fleet commands to adapt for your EDR, MDM, or config management system
apachectl -v 2>/dev/null || httpd -v 2>/dev/null || apache2 -v 2>/dev/null
apachectl -M 2>/dev/null | egrep 'http2|mpm'
Collect hostname, owner, environment, internet exposure, package source, and restart method.
Step 2, identify externally reachable HTTP/2
while read -r host; do
echo "== $host =="
echo | openssl s_client -connect "${host}:443" -servername "$host" -alpn h2 2>/dev/null \
| egrep -i 'ALPN protocol|Verify return code'
done < hosts.txt
Do not treat this as exploitation. It is reachability evidence.
Step 3, classify exposure
| Klasse | Definition | Aktion |
|---|---|---|
| A | 2.4.66, HTTP/2 reachable, mod_http2 loaded, event or worker MPM | Patch sofort |
| B | 2.4.66, HTTP/2 internal only | Patch quickly, monitor logs |
| C | 2.4.66 installed, HTTP/2 not loaded | Patch and prevent future enablement |
| D | Vendor-fixed package installed and process restarted | Close after validation |
| E | Non-Apache or Apache not in affected range according to vendor | Document evidence |
Step 4, patch
Use vendor packages where possible. Avoid cherry-picking random commits from blogs unless your engineering team maintains source builds and understands the patch series. Ubuntu’s CVE page explicitly says its patch details are informational and recommends not cherry-picking updates. (Ubuntu)
Step 5, restart and verify process replacement
# Show service state
systemctl status apache2 2>/dev/null || systemctl status httpd 2>/dev/null
# Show process start times
ps -eo pid,lstart,cmd | egrep 'apache2|httpd' | grep -v grep
# Confirm version again
apache2 -v 2>/dev/null || httpd -v 2>/dev/null || apachectl -v 2>/dev/null
A package upgrade without process replacement is incomplete. If old workers remain alive, they may still contain vulnerable code.
Step 6, hunt pre-patch indicators
Run log searches from May 4, 2026 onward, or from the first time public details entered your monitoring window.
sudo journalctl --since '2026-05-04' \
| egrep -i 'apache2|httpd|segfault|double free|corruption|exit signal|h2_|http2'
Preserve logs for incident review if you see repeated crashes on exposed servers.
Step 7, retest safely
Repeat version, module, ALPN, and process checks. Confirm that no Apache 2.4.66 containers remain. Confirm configuration management will not roll back the fix.
Step 8, close with evidence
A good closure note includes:
CVE: CVE-2026-23918
Asset: web-prod-17
Owner: platform-web
Before: Apache 2.4.66, mod_http2 loaded, event MPM, public h2 enabled
Action: upgraded vendor package and restarted service
After: fixed package confirmed, process restart confirmed, h2 policy reviewed
Crash indicators: none found in error logs or journald from 2026-05-04 to closure
Validation: no destructive PoC executed against production
Status: remediated
Common mistakes
Treating a public PoC as a required production test
You do not need to crash production to prove risk. If a server is Apache 2.4.66, has mod_http2 loaded, exposes HTTP/2, and runs a relevant MPM, that is enough to justify patching.
Trusting the public banner
Many Apache deployments hide or alter Server headers. Others sit behind proxies. Use local package data and process checks where possible.
Ignoring containers
Host patching does not update pinned container images. Rebuild and redeploy.
Assuming the CDN removes all risk
A CDN that terminates HTTP/2 and forwards HTTP/1.1 to Apache may reduce exposure to this specific frame-level path. But internal HTTP/2 paths, alternate hostnames, direct-origin access, or misconfigured bypass routes can still matter.
Closing the ticket after package install
Restart validation is part of remediation. Old workers can remain until restart or graceful replacement.
Disabling HTTP/2 forever without tracking the exception
Temporary mitigations become permanent drift when nobody owns them. If you disable HTTP/2, create a follow-up task to patch and decide whether to re-enable it.
Treating all Apache versions as equally affected
Apache’s advisory identifies 2.4.66 for this CVE. Ubuntu’s analysis also notes why earlier Ubuntu releases were marked not affected even though related code existed. (Apache HTTP Server) Avoid broad claims that every Apache version before 2.4.67 is affected by CVE-2026-23918.
What a good bug bounty report should say
For authorized bounty work, a strong report should avoid destructive testing unless the program explicitly allows it. It should show exposure with non-destructive evidence.
A concise report structure:
Title:
Apache HTTP Server 2.4.66 with HTTP/2 enabled is exposed to CVE-2026-23918
Summary:
The target negotiates HTTP/2 and appears to be served by Apache HTTP Server 2.4.66 with mod_http2 enabled. Apache fixed CVE-2026-23918 in 2.4.67. The vulnerability is a double-free in HTTP/2 early reset handling with possible RCE and a clearer worker-crash risk.
Scope:
Only non-destructive validation was performed. No crafted RST_STREAM crash trigger was sent.
Evidence:
- ALPN negotiation selected h2.
- HTTP response or owner-provided package evidence indicates Apache 2.4.66.
- mod_http2 is enabled according to configuration evidence.
- Apache advisory recommends upgrade to 2.4.67.
Impact:
A vulnerable exposed deployment may be susceptible to worker crash and possible memory-corruption impact. Public reporting describes DoS as the more direct path and RCE as environment-dependent.
Remediation:
Upgrade to Apache HTTP Server 2.4.67 or the vendor-patched package. Restart Apache and verify no old workers remain. If patching is delayed, temporarily disable HTTP/2 for affected virtual hosts.
Do not include a crash script unless the program explicitly asks for it and provides a safe test window. Even then, coordinate before running it.
What defenders should tell leadership
A leadership update should be accurate, short, and free of exploit theater.
CVE-2026-23918 is an Apache HTTP Server 2.4.66 HTTP/2 double-free issue fixed in 2.4.67. The clearest risk is worker crashes and denial of service, with possible remote code execution under more specific memory conditions. We are prioritizing internet-facing Apache 2.4.66 systems with HTTP/2 enabled, patching or applying vendor-fixed packages, restarting services, and hunting for crash indicators since public disclosure. We are not running destructive PoCs against production.
That message gives executives the risk, scope, action, and safety boundary.
The bottom line
CVE-2026-23918 deserves fast action because it sits in an exposed web server, involves HTTP/2 stream lifecycle handling, and belongs to a memory-corruption class that can move beyond simple crashes in the right environment. The official fix is Apache HTTP Server 2.4.67, and downstream vendors are publishing their own package statuses and update paths. (Apache HTTP Server)
The right PoC mindset is controlled proof, not public disruption. Prove version. Prove module state. Prove HTTP/2 reachability. Prove MPM context. Prove the package is fixed. Prove the process restarted. Prove crash indicators are absent or investigated. Save destructive frame-level testing for a lab you own.
A safe CVE-2026-23918 validation program should leave production more stable than it found it. Anything else is not validation; it is risk creation.
References and further reading
Apache HTTP Server 2.4 vulnerabilities, official Apache advisory for CVE-2026-23918 and 2.4.67 fixes. (Apache HTTP Server)
NVD record for CVE-2026-23918, including description, CWE-415, CISA-ADP CVSS 3.1 score, and affected CPE information. (NVD)
Openwall oss-security posting for CVE-2026-23918, including affected version, credits, and disclosure timeline. (Openwall)
RFC 9113, HTTP/2 specification, including frame and stream concepts. (rfc-editor.org)
Apache HTTP/2 guide, including mod_http2, Protocols, MPM notes, and debugging tools. (Apache HTTP Server)
Apache mod_http2 documentation, including H2Direct, H2MaxSessionStreams, and stream-related directives. (Apache HTTP Server)
The Hacker News technical reporting on CVE-2026-23918, including researcher-provided details on the stream cleanup path, DoS behavior, and RCE caveats. (Die Hacker-Nachrichten)
Ubuntu CVE-2026-23918 page, including Ubuntu package status and notes about why earlier Ubuntu releases were marked not affected. (Ubuntu)
SUSE CVE-2026-23918 page, including SUSE severity and vector differences. (suse.com)
cPanel CVE-2026-23918 support article, including EasyApache update commands. (support.cpanel.net)
Cloudflare technical breakdown of HTTP/2 Rapid Reset, useful background for HTTP/2 reset behavior and defensive telemetry. (The Cloudflare Blog)
NVD record for CVE-2025-49630, an Apache mod_proxy_http2 denial-of-service issue useful for comparison. (NVD)
Penligent homepage, including controlled agentic workflows, CVE exploit generation language, evidence-first results, and authorized-use disclaimer. (Sträflich)
Penligent overview of automated penetration testing workflows, including CVE validation, tool execution, reporting, and multi-agent task flow. (Sträflich)

