Cuando dos frames botan tu servidor: CVE-2026-23918 en Apache mod_http2

Una vulnerabilidad de double-free en HTTP/2 que hace que derribar un servidor Apache sea ridículamente fácil

El 5 de mayo de 2026 salió un advisory que me hizo levantar de la silla [1]. No es para menos: alguien descubrió que con exactamente dos frames HTTP/2, sin autenticación, sin headers especiales, sin nada, podías tirar abajo un worker de Apache. Y no me refiero a un timeout gracioso. Me refiero a un segfault limpio, de esos que dejan un core dump en el log y te hacen mirar el monitor con cara de «¿qué acaba de pasar?».

La vulnerabilidad se llama CVE-2026-23918, afecta a Apache HTTP Server 2.4.66, y tiene un CVSS de 8.8 [3]. Pero el número ese no cuenta toda la historia. Lo que la hace particularmente desagradable es lo trivial que resulta explotarla para denegación de servicio, y lo factible que es llegar a ejecución remota de código bajo ciertas condiciones.

Vamos a lo grueso. El bug está en mod_http2, específicamente en el archivo h2_mplx.c, en el path de cleanup de streams [1][2]. Cuando un cliente manda un frame HEADERS por HTTP/2 e inmediatamente después manda un RST_STREAM con un código de error distinto de cero, todo en el mismo stream y antes de que el multiplexer haya registrado ese stream, se produce una carrera entre dos callbacks de nghttp2.

El on_frame_recv_cb se dispara por el RST y el on_stream_close_cb por el cierre. Ambos terminan llamando a h2_mplx_c1_client_rst, que a su vez invoca m_stream_cleanup. El resultado: el mismo puntero h2_stream se empuja dos veces al array spurge. Cuando c1_purge_streams itera y llama h2_stream_destroy seguido de apr_pool_destroy sobre cada entrada, la segunda llamada opera sobre memoria ya liberada. Un double-free clásico.

Recuerdo haber depurado un bug de double-free hace años en un proyecto con C y la sensación de impotencia al ver que el heap se corrompía de formas que no tenían sentido hasta que caí en la cuenta de que había dos free() al mismo puntero. Es ese tipo de error que te hace revisar el código una y otra vez sin verlo, porque tu cerebro asume que nadie limpiaría el mismo recurso dos veces. Pero ahí está.

La denegación de servicio es ridículamente sencilla. Una conexión TCP, dos frames, chau worker. Apache lo reinicia, sí, pero todas las peticiones que estaban procesando ese worker se pierden, y el patrón se puede sostener indefinidamente mientras el atacante siga enviando. Bartlomiej Dmitruk, co-fundador de Striga.ai y uno de los descubridores, lo dijo claro en declaraciones a The Hacker News [1]: el DoS funciona en cualquier despliegue con mod_http2 y un MPM multihilo. No requiere privilegios, no requiere autenticación, no requiere nada.

Lo que sí requiere condiciones específicas es la ejecución remota de código [2]. Necesitas que Apache Portable Runtime use el asignador mmap, que es el default en sistemas basados en Debian y en la imagen Docker oficial de httpd. Con eso, un atacante puede colocar una estructura h2_stream falsa en la dirección virtual liberada mediante reutilización de mmap, apuntar su función de pool cleanup a system(), y usar la memoria del scoreboard de Apache como contenedor estable para las estructuras falsas y el comando a ejecutar.

Lo del scoreboard es lo que a mí me pone nervioso. Esa memoria vive en una dirección fija durante toda la vida del servidor, incluso con ASLR habilitado [1]. Eso convierte lo que sería una explotación puramente probabilística en algo bastante más práctico. Dmitruk confirmó que construyeron un proof-of-concept funcional en x86_64 que logra ejecución en minutos bajo condiciones de laboratorio [1]. Sí, necesita un info leak para las offsets de system() y del scoreboard, y el heap spray es probabilístico, pero «probabilístico» no significa «imposible». Significa «cuestión de tiempo».

Dmitruk y Stanislaw Strzalkowski de ISEC.pl reportaron la vulnerabilidad el 10 de diciembre de 2025 [2]. El patch se commiteó al día siguiente, el 11 de diciembre. Pero la versión parcheada, Apache 2.4.67, no se liberó hasta el 4 de mayo de 2026 [2][6]. Cinco meses entre el fix interno y la liberación pública. Entiendo que un proyecto como Apache tiene procesos de release que no se apresuran, pero cinco meses con un double-free que puede derivar en RCE en la imagen Docker oficial… es un margen amplio.

Solo afecta a la versión 2.4.66 [3]. Si estás en 2.4.65 o anterior, no estás vulnerable. Si ya actualizaste a 2.4.67, tampoco. El MPM prefork no se ve afectado [1], pero prefork es básicamente el modo legacy de Apache y prácticamente nadie lo usa en despliegues modernos con HTTP/2.

La solución directa es actualizar a 2.4.67. Si no puedes actualizar de inmediato, desactiva mod_http2 comentando la línea LoadModule en tu configuración. Pierdes HTTP/2, pero eliminas la superficie de ataque. No hay workaround intermedio.

Lo que me llama la atención de este CVE es cómo un error tan simple, un double-free producido por una secuencia perfectamente legal de frames HTTP/2, puede tener consecuencias tan graves. No se necesita un exploit sofisticado para el DoS. Y el camino al RCE, aunque condicional, tiene piezas que se alinean de una forma preocupante: el mmap allocator como default en Debian, el scoreboard en dirección fija, la imagen Docker vulnerable lista para descargar. A veces la seguridad no se rompe por algo brillante. Se rompe porque alguien limpió dos veces el mismo plato.

Referencias

[1] The Hacker News. “Critical Apache HTTP/2 Flaw (CVE-2026-23918) Enables DoS and Potential RCE”, 5 de mayo de 2026. https://thehackernews.com/2026/05/critical-apache-http2-flaw-cve-2026.html

[2] Hadrian. “CVE-2026-23918: Apache HTTP Server Double-Free RCE in HTTP/2 Implementation”, 5 de mayo de 2026. https://hadrian.io/blog/cve-2026-23918-apache-http-server-double-free-rce-in-http-2-implementation

[3] NIST National Vulnerability Database. “CVE-2026-23918 Detail”. https://nvd.nist.gov/vuln/detail/CVE-2026-23918

[4] York University UIT. “Apache HTTP Server Vulnerability (CVE-2026-23918)”, 9 de mayo de 2026. https://www.yorku.ca/uit/2026/05/apache-http-server-vulnerability-cve-2026-23918

[5] Red Hat Customer Portal. “CVE-2026-23918”, 5 de mayo de 2026. https://access.redhat.com/security/cve/cve-2026-23918

[6] Apache Software Foundation. “Apache HTTP Server 2.4 vulnerabilities”. https://httpd.apache.org/security/vulnerabilities_24.html

[7] UC Berkeley Security. “Critical Apache 2.4.66 HTTP/2 Flaw Allows RCE & DoS (CVE-2026-23918)”, 6 de mayo de 2026. https://security.berkeley.edu/news/critical-apache-2466-http2-flaw-allows-rce-dos-cve-2026-23918

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.