
Kit de herramientas en Python para auditar Apache HTTP Server contra CVE-2026-23918 (RCE por double-free en HTTP/2) y 4 CVE relacionados. Escáner pasivo con verificación ALPN + auditor local de solo lectura. Sin exploits.
Herramientas de auditoría defensiva para CVE-2026-23918 (RCE por doble liberación en HTTP/2 de Apache HTTPD) y cuatro CVEs relacionados divulgados en el aviso de seguridad de la Apache Software Foundation del 4 de mayo de 2026.
| CVE | Gravedad | Componente | Impacto | Afectados |
|---|---|---|---|---|
| CVE-2026-23918 | Alta (CVSS 8.8) | HTTP/2 | Doble liberación / RCE | solo 2.4.66 |
| CVE-2026-24072 | Moderada | mod_rewrite (ap_expr) | Escalada de privilegios | ≤ 2.4.66 |
| CVE-2026-28780 | Baja | mod_proxy_ajp | Desbordamiento de búfer en heap | ≤ 2.4.66 |
| CVE-2026-29168 | Baja | mod_md (OCSP) | Agotamiento de recursos | 2.4.30 – 2.4.66 |
| CVE-2026-29169 | Baja | mod_dav_lock | Desreferencia de puntero NULL / DoS | ≤ 2.4.66 |
Todos los problemas están corregidos en Apache HTTP Server 2.4.67.
Estas herramientas están pensadas para usarse solo contra sistemas de tu propiedad o para los que tengas autorización escrita explícita para realizar pruebas. El escaneo no autorizado puede ser ilegal en tu jurisdicción.
El kit está diseñado para ser defensivo:
Server: y utiliza ALPN TLS estándar, el mismo mecanismo que todos los navegadores modernos usan para negociar 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 predeterminado de Ubuntu 18.04 y todas las versiones posteriores.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.pyLee la cabecera HTTP Server: para detectar la versión de Apache y la compara con la tabla de CVEs. Además, para objetivos HTTPS, realiza una negociación ALPN TLS estándar para determinar si HTTP/2 está expuesto; esta es la precondición clave para que CVE-2026-23918 sea explotable. No se envían payloads de explotación.
El script ofrece h2 y http/1.1 en la extensión ALPN del handshake TLS (RFC 7301). La elección del servidor es la respuesta estándar e inequívoca a «¿está habilitado HTTP/2?», utilizada por todos los navegadores modernos y por curl. No activa la vulnerabilidad ni ningún comportamiento inusual.
El veredicto de riesgo refleja esto:
# 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
Formato de targets.txt (un objetivo por línea, # para comentarios):
https://www.example.com
intranet.example.local:8443
# old staging box
http://10.0.5.12
| Flag | Descripción |
|---|---|
-t, --target | Objetivo único (puede repetirse) |
-f, --file | Archivo de lista de objetivos |
-o, --csv | Salida de informe CSV |
--json | Salida de informe JSON |
--timeout | Tiempo de espera de la solicitud en segundos (por defecto 10) |
-w, --workers | Hilos de trabajo paralelos (por defecto 10) |
--no-color | Deshabilitar salida de color |
| Código | Significado |
|---|---|
| 0 | Todos los objetivos seguros |
| 1 | Al menos un objetivo UNKNOWN o ERROR |
| 2 | Al menos un objetivo VULNERABLE o AT_RISK |
| Nivel | Significado |
|---|---|
VULNERABLE | La versión coincide con un rango de CVE del aviso Y su precondición se cumple (p. ej., HTTP/2 habilitado) |
AT_RISK | Versión sin parchear pero la precondición de gravedad alta NO se cumple; otros CVEs siguen aplicando |
SAFE | Versión ≥ 2.4.67 |
UNKNOWN | Banner oculto (ServerTokens Prod) o enmascarado por proxy inverso/WAF — verifíquelo con el script de auditoría local |
NOT_APACHE | No es Apache (nginx, IIS, etc.) |
ERROR | Error de conexión |
ServerTokens Prod o Minimal ocultan la versión; el script devuelve honestamente UNKNOWN. Use la auditoría local para confirmar.apache_local_audit.pySe ejecuta en el host objetivo (o vía SSH) e inspecciona el binario de Apache, la versión, los módulos cargados y la configuración de HTTP/2. También evalúa las precondiciones de explotabilidad: p. ej., si la versión es 2.4.66 pero HTTP/2 está deshabilitado, el riesgo para CVE-2026-23918 se reduce en consecuencia.
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 — versiónhttpd -V — información de compilación, HTTPD_ROOT, SERVER_CONFIG_FILEapache2ctl -M o httpd -M — módulos cargadosdpkg-query / rpm -q — versión del paqueteInclude/IncludeOptional (incluyendo sites-enabled/, mods-enabled/ de Debian) → directiva Protocols (h2 / h2c / http/1.1)| Flag | Descripción |
|---|---|
--binary | Ruta del binario de Apache (anula la detección automática) |
--json | Salida de informe JSON |
--no-color | Deshabilitar salida de color |
| Código | Significado |
|---|---|
| 0 | SAFE |
| 1 | PATCH_NEEDED o UNKNOWN |
| 2 | VULNERABLE o AT_RISK |
| Nivel | Significado |
|---|---|
VULNERABLE | Versión sin parchear + precondiciones del CVE de gravedad alta cumplidas (p. ej., HTTP/2 habilitado) |
AT_RISK | Versión sin parchear + al menos una precondición de CVE cumplida |
PATCH_NEEDED | Versión sin parchear pero ningún módulo/protocolo relevante habilitado — parchee de todos modos |
SAFE | Versión ≥ 2.4.67 |
UNKNOWN | No se pudo detectar la versión |
Se recomienda sudo/root para poder leer toda la configuración. Sin ellos, algunos archivos en sites-enabled/, mods-enabled/, o /etc/httpd/conf.d/ pueden resultar ilegibles.
Para ejecutar la auditoría local en varios hosts y recopilar informes de forma centralizada, un ejemplo con Ansible ad-hoc:
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"