
Python toolkit to audit Apache HTTP Server against CVE-2026-23918 (HTTP/2 double-free RCE) and 4 related CVEs. Passive scanner with ALPN verification + read-only local auditor. No exploits.
Defensive audit tools for CVE-2026-23918 (Apache HTTPD HTTP/2 double-free RCE) and four related CVEs disclosed in the May 4, 2026 Apache Software Foundation security advisory.
| CVE | Severity | Component | Impact | Affected |
|---|---|---|---|---|
| CVE-2026-23918 | High (CVSS 8.8) | HTTP/2 | Double Free / RCE | 2.4.66 only |
| CVE-2026-24072 | Moderate | mod_rewrite (ap_expr) | Privilege Escalation | ≤ 2.4.66 |
| CVE-2026-28780 | Low | mod_proxy_ajp | Heap Buffer Overflow | ≤ 2.4.66 |
| CVE-2026-29168 | Low | mod_md (OCSP) | Resource Exhaustion | 2.4.30 – 2.4.66 |
| CVE-2026-29169 | Low | mod_dav_lock | NULL Ptr Deref / DoS | ≤ 2.4.66 |
All issues are patched in Apache HTTP Server 2.4.67.
These tools are intended for use only against systems you own or have explicit written authorization to test. Unauthorized scanning may be illegal in your jurisdiction.
The toolkit is defensive by design:
Server: HTTP header and uses standard TLS ALPN — the same mechanism every modern browser uses to negotiate HTTP/2..
├── apache_passive_audit.py # External asset audit (banner-grab + ALPN)
├── apache_local_audit.py # On-host / SSH local audit
├── LICENSE # MIT
├── .gitignore
└── README.md
python3 and every later release.git clone https://github.com/sibersan/cve-2026-23918.git
cd cve-2026-23918
chmod +x apache_passive_audit.py apache_local_audit.py
apache_passive_audit.pyReads the HTTP Server: header to detect the Apache version and matches it against the CVE table. Additionally, for HTTPS targets, performs a standard TLS ALPN negotiation to determine whether HTTP/2 is exposed — this is the key precondition for CVE-2026-23918 to be exploitable. No exploit payloads are sent.
The script offers h2 and http/1.1 in the TLS handshake's ALPN extension (RFC 7301). The server's choice is the standard, unambiguous answer to "is HTTP/2 enabled?" — used by every modern browser and curl. It does not trigger the vulnerability or any unusual behavior.
The risk verdict reflects this:
# Single target
python3 apache_passive_audit.py -t https://web.example.com
# Multiple targets
python3 apache_passive_audit.py -t https://a.example.com -t https://b.example.com
# Targets file, parallel, CSV + JSON output
python3 apache_passive_audit.py -f targets.txt -w 20 -o report.csv --json report.json
# CI / log-friendly (no colors)
python3 apache_passive_audit.py -f targets.txt --no-color
targets.txt format (one target per line, # for comments):
https://www.example.com
intranet.example.local:8443
# old staging box
http://10.0.5.12
| Code | Meaning |
|---|---|
| 0 | All targets safe |
| 1 | At least one target UNKNOWN or ERROR |
| 2 | At least one target VULNERABLE or |
ServerTokens Prod or Minimal hide the version — the script honestly returns UNKNOWN. Use the local audit to confirm.apache_local_audit.pyRuns on the target host (or via SSH) and inspects the Apache binary, version, loaded modules, and HTTP/2 configuration. It also evaluates exploitability preconditions: e.g. if the version is 2.4.66 but HTTP/2 is disabled, the risk for CVE-2026-23918 is downgraded accordingly.
sudo python3 apache_local_audit.py
# JSON report (for centralized inventory)
sudo python3 apache_local_audit.py --json /var/log/apache_audit_$(hostname).json
# Custom binary path
sudo python3 apache_local_audit.py --binary /opt/apache/bin/httpd
httpd -v / apache2 -v — versionhttpd -V — build info, HTTPD_ROOT, SERVER_CONFIG_FILEapache2ctl -M or httpd -M — loaded modulesdpkg-query / rpm -q — package versionInclude/IncludeOptional (including Debian's sites-enabled/, mods-enabled/) → Protocols directive (h2 / h2c / http/1.1)| Flag | Description |
|---|---|
--binary | Apache binary path (override auto-detect) |
--json | JSON report output |
--no-color | Disable colored output |
| Code | Meaning |
|---|---|
| 0 | SAFE |
| 1 | PATCH_NEEDED or UNKNOWN |
| 2 | VULNERABLE or AT_RISK |
sudo/root is recommended for full configuration reads. Without it, some files in sites-enabled/, mods-enabled/, or /etc/httpd/conf.d/ may be unreadable.
To run the local audit on multiple hosts and collect reports centrally, an Ansible ad-hoc example:
ansible all -i inventory.ini -b -m script \
-a "apache_local_audit.py --json /tmp/apache_audit.json --no-color"
ansible all -i inventory.ini -b -m fetch \
-a "src=/tmp/apache_audit.json dest=./reports/ flat=no"
Collected JSON files can be merged with jq or a small Python script.
For CVE-2026-23918 (until patched):
h2 and h2c from the Protocols directive in your configuration, or sudo a2dismod http2 on Debian/Ubuntu, then reload the service.mod_dav_lock if not in use (CVE-2026-29169)..htaccess write access (CVE-2026-24072).Official advisory: https://httpd.apache.org/security/vulnerabilities_24.html
Pull requests are welcome. When adding a new CVE, please:
CVE_TABLE with the affected version range and match lambda.needs field for precondition checks (loaded module, enabled protocol, etc.).from __future__ import annotations, PEP 585 generics (list[int]), subprocess.run(capture_output=True), and @dataclass.MIT © 2026 SiberSAN
This software is provided "as is", without warranty of any kind. Validate in a test environment before production use. The user assumes all legal responsibility for any use against unauthorized systems.
| Flag | Description |
|---|
-t, --target | Single target (may be repeated) |
-f, --file | Targets list file |
-o, --csv | CSV report output |
--json | JSON report output |
--timeout | Request timeout in seconds (default 10) |
-w, --workers | Parallel worker threads (default 10) |
--no-color | Disable colored output |
AT_RISK| Level | Meaning |
|---|
VULNERABLE | Version matches an advisory CVE range AND its precondition is met (e.g. HTTP/2 enabled) |
AT_RISK | Unpatched version but the High-severity precondition is NOT met; other CVEs still apply |
SAFE | Version ≥ 2.4.67 |
UNKNOWN | Banner hidden (ServerTokens Prod) or masked by reverse proxy/WAF — verify with the local audit script |
NOT_APACHE | Not Apache (nginx, IIS, etc.) |
ERROR | Connection error |
| Level | Meaning |
|---|
VULNERABLE | Unpatched version + High-severity CVE preconditions met (e.g. HTTP/2 enabled) |
AT_RISK | Unpatched version + at least one CVE precondition met |
PATCH_NEEDED | Unpatched version but no relevant module/protocol enabled — patch anyway |
SAFE | Version ≥ 2.4.67 |
UNKNOWN | Version could not be detected |