
Prueba de concepto de exploit para la vulnerabilidad de doble liberación en Apache mod_http2 (CVE-2026-23918) con fases de reconocimiento, explotación y evaluación de riesgo de ejecución remota de código (RCE).
Afectado: Apache HTTP Server 2.4.66 con mod_http2 + Event MPM
Corregido en: Apache 2.4.67 (mod_h2 v2.0.37)
CVSS 3.1: 8.8 ALTA — Posible ejecución remota de código no autenticado
CWE: CWE-415 (Double Free)
mod_http2 en Apache 2.4.66 tiene un error de doble liberación (double-free) dentro de h2_mplx.c:m_stream_cleanup(). El problema ocurre cuando un cliente envía un frame HEADERS inmediatamente seguido de un RST_STREAM en el mismo flujo. Si el tiempo es el adecuado, el flujo termina siendo insertado dos veces en el array de purga m->spurge. Cuando se destruye el mplx, el pool APR se libera dos veces, lo que corrompe el heap y causa un SIGABRT o SIGSEGV.
Apache parcheó esto en mod_h2 v2.0.37 introduciendo add_for_purge(), una simple verificación de deduplicación que evita que el mismo flujo se añada dos veces.
// Vulnerable (< v2.0.37)
APR_ARRAY_PUSH(m->spurge, h2_stream *) = stream; // can happen twice
// Fixed (v2.0.37+)
static int add_for_purge(h2_mplx *m, h2_stream *stream) {
for (int i = 0; i < m->spurge->nelts; ++i)
if (APR_ARRAY_IDX(m->spurge, i, h2_stream*) == stream)
return FALSE;
APR_ARRAY_PUSH(m->spurge, h2_stream *) = stream;
return TRUE;
}
Por defecto, el script ejecuta un pipeline de 3 fases en el objetivo:
| Fase | Qué hace |
|---|---|
| 1 — Reconocimiento | Detecta la versión de Apache, soporte HTTP/2 mediante ALPN, tipo de MPM |
| 2 — Explotación | Envía ráfagas de HEADERS+RST_STREAM en hilos, intenta modo inline y luego modo staged |
| 3 — Evaluación de RCE | Mide la consistencia del bloqueo y puntúa el nivel de riesgo |
La puntuación de RCE se calcula a partir de tres señales detectables de forma remota. Primero, si se está ejecutando Apache 2.4.66. Segundo, si se usa MPM Event o Worker (mod_http2 se niega a iniciar con Prefork, por lo que si HTTP/2 funciona, es un MPM con hilos). Tercero, qué tan determinista es el bloqueo — un bloqueo en la primera ronda significa que la corrupción del heap es controlada y reproducible, que es lo que se necesita para RCE.
pip install hpack requests
# Full PoC on a single target (default behavior)
python poc.py -t 192.168.1.100
# Increase pressure with more rounds, bigger bursts and more threads
python poc.py -t 192.168.1.100 -n 20 -b 500 -w 5
# Passive check only, nothing is sent to the target
python poc.py -t example.com --check-only
# Scan a whole list of targets
python poc.py -l sites.txt -o results.json
# Passive check on a list
python poc.py -l sites.txt --check-only
# Generate a Markdown report after the run
python poc.py -t target.com --report report.md
# one target per line, comments are ignored
192.168.1.100
example.com
example.com:8443
https://example.com
http://example.com:8080
La solución adecuada es actualizar Apache a 2.4.67 o posterior. Si no puedes actualizar de inmediato, deshabilitar HTTP/2 elimina por completo la superficie de ataque:
# Before
Protocols h2 http/1.1
# After (disables HTTP/2)
Protocols http/1.1
Esta herramienta está destinada únicamente a pruebas de seguridad autorizadas e investigación. Asegúrate de tener permiso explícito por escrito antes de ejecutarla contra cualquier objetivo. El autor no se hace responsable del mal uso.
| Flag | Por defecto | Descripción |
|---|
-t | — | Objetivo único (nombre de host o IP) |
-l | — | Archivo con objetivos, uno por línea |
-p | 443 | Puerto |
-n | 10 | Número de rondas de explotación |
-b | 200 | Pares HEADERS+RST por ronda |
-w | 3 | Conexiones paralelas por ronda |
-d | 0.1 | Retardo entre rondas en segundos |
-m | inline | Modo de ataque: inline o staged |
--no-tls | — | Usar h2c en lugar de TLS |
--check-only | — | Solo reconocimiento pasivo, sin explotación |
-o | — | Guardar resultados en un archivo JSON |
--report | — | Generar un informe Markdown |
-v | — | Salida detallada |
| Nivel | Qué significa |
|---|
| CRITICAL | 2.4.66 confirmado, HTTP/2 activo, MPM Event detectado, el bloqueo es determinista — parchear ahora |
| HIGH | 2.4.66 confirmado, HTTP/2 activo, MPM con hilos en uso |
| MEDIUM | 2.4.66 detectado pero HTTP/2 o bloqueo aún no confirmados |
| LOW | La versión no coincide o no se detectó HTTP/2 |
| NONE | Ya parcheado a 2.4.67+ o no afectado |