De Node2Shell a HTTP2Shell (CVE-2026-111497): Cómo la Vulnerabilidad RCE en Brotli Impacta a Python, Java y Todo el Ecosistema Web
Por qué CVE-2026-111497 va mucho más allá de Node.js: cómo el desbordamiento de búfer CVSS 9.2 en libbrotli de Google (c/dec/decode.c) impacta a Python (urllib3, requests, aiohttp, httpx), Java (brotli4j, Netty, Spring Cloud Gateway), Rust y proxies en C++.
c/dec/decode.c, versiones 1.0.3–1.2.0), cualquier lenguaje o biblioteca de red que enlace con libbrotli nativo —incluyendo Python (brotli, brotlicffi, urllib3, aiohttp, httpx), Java (brotli4j, Netty, Reactor Netty, Vert.x), Node.js, Bun, Rust (brotli-sys), PHP y proxies en C++— está expuesto al descomprimir flujos Brotli no confiables.En nuestro análisis técnico anterior sobre Node2Shell (CVE-2026-111497), examinamos cómo una vulnerabilidad de escritura fuera de límites (Out-of-Bounds Write, CWE-787) en la biblioteca de compresión Brotli permitía la Ejecución Remota de Código (RCE) sin autenticación en servidores Node.js con Express 5, body-parser o fetch().
Sin embargo, en los días posteriores a la divulgación del 21 de octubre, los equipos de seguridad e ingeniería llegaron a una conclusión fundamental: tratar a CVE-2026-111497 únicamente como una "vulnerabilidad de Node.js" ignora el 80% de la superficie real de ataque.
El fallo en c/dec/decode.c no pertenece a V8 ni a JavaScript. Se trata de la implementación oficial en C del estándar RFC 7932 (Brotli) mantenida por Google e integrada —mediante extensiones C de Python, paquetes JNI de Java, crates FFI de Rust, envoltorios cgo de Go y bibliotecas compartidas del sistema operativo (libbrotlidec.so)— en prácticamente todos los ecosistemas de programación modernos. Al extenderse las alertas hacia Python, Java, C++, Bun y proxies perimetrales, la vulnerabilidad adoptó su nombre definitivo: HTTP2Shell.
En esta continuación analizamos cómo un desbordamiento de búfer en C atraviesa las barreras de lenguajes con memoria gestionada como Python y Java, qué dependencias activan Brotli en silencio y cómo auditar, mitigar y parchear toda tu infraestructura políglota.
1. Por Qué Lenguajes con "Memoria Segura" como Python y Java Son Vulnerables
Una duda frecuente en equipos que operan servicios en Python (Django, FastAPI, Celery) o Java (Spring Boot, Netty, Quarkus) es: "Ejecutamos nuestro código sobre una máquina virtual con verificación de límites de arreglos. ¿Cómo puede afectarnos un desbordamiento de memoria en C?"
La respuesta está en los enlaces nativos de alto rendimiento (C-extensions y JNI). Descomprimir flujos HTTP de alto tráfico en Python puro o bytecode de Java resulta costoso en CPU. Para lograr velocidad de línea, las bibliotecas HTTP más utilizadas en ambos lenguajes empaquetan y ejecutan la biblioteca en C de Google (libbrotlidec) directamente dentro del proceso del sistema operativo:
Flujo HTTP Malicioso (Content-Encoding: br)
│
┌──────────────────────────────┼──────────────────────────────┐
▼ ▼ ▼
┌───────────────────┐ ┌───────────────────┐ ┌───────────────────┐
│ PILA PYTHON │ │ PILA JAVA / JVM │ │ NODE / BUN / C++ │
├───────────────────┤ ├───────────────────┤ ├───────────────────┤
│ urllib3 / requests│ │ Netty / WebFlux │ │ Express 5 / Undici│
│ aiohttp / httpx │ │ Vert.x / Gateway │ │ Bun / Envoy / C++ │
│ │ │ │ │ │ │ │ │
│ ▼ │ │ ▼ │ │ ▼ │
│ brotli (CPython) │ │ brotli4j (JNI) │ │ node:zlib (C++) │
│ o brotlicffi │ │ libbrotlidec.so │ │ brotli nativo │
└─────────┬─────────┘ └─────────┬─────────┘ └─────────┬─────────┘
│ │ │
└────────────────────────────┼──────────────────────────────┘
▼
Decodificador C de Google: c/dec/decode.c
(Versiones 1.0.3 hasta 1.2.0)
│
💥 Escritura Fuera de Límites en el Heap (CWE-787) del ProcesoEn el instante en que la ejecución cruza desde Python (vía CPython C API / CFFI) o desde Java (vía JNI) hacia c/dec/decode.c, las protecciones de la máquina virtual dejan de aplicar. El decodificador en C escribe directamente sobre el heap nativo del proceso, junto a las estructuras PyObject de Python o la memoria nativa de la JVM.
2. El Impacto en Python: brotli, brotlicffi, urllib3 y aiohttp
En el ecosistema Python, HTTP2Shell es especialmente peligroso porque el soporte para Brotli se activa de forma automática y silenciosa en cuanto el paquete C está instalado en el entorno virtual.
- Cuando
urllib3(el motor debajo derequests),httpxoaiohttpse importan al iniciar tu aplicación, ejecutan internamente una comprobación opcional en busca de los paquetesbrotliobrotlicffi. - Incluso si tu equipo nunca instaló
brotlidirectamente, decenas de dependencias transitivas (SDKs de nube, herramientas de scraping, clientes de IA o conectores de APIs) instalan la rueda binariaBrotli(que contiene_brotli.cpython-*.so). - En cuanto ese binario existe en
site-packages,requests,urllib3,httpxyaiohttpañaden automáticamentebral encabezadoAccept-Encodingde todas tus peticiones salientes y envían cualquier respuesta conContent-Encoding: brdirecto al decodificador en C vulnerable.
requests.get(), urllib3, httpx o aiohttp —así como servidores FastAPI/Starlette/Django que utilicen brotli-asgi— puede ser comprometido por un flujo Brotli malicioso si tiene instalado brotli < 1.2.1.3. El Impacto en Java y la JVM: brotli4j, Netty y Spring Cloud Gateway
En Java existen dos formas muy distintas de descomprimir Brotli, y saber cuál está en tu árbol de dependencias de Maven o Gradle define tu nivel de riesgo:
| Biblioteca / Artefacto Java | Tipo de Implementación | Exposición a CVE-2026-111497 (CWE-787) |
|---|---|---|
com.aayushatharva.brotli4j:brotli4j(Usado por Netty netty-codec-http, Reactor Netty, Spring WebFlux / Cloud Gateway, Vert.x) |
Envoltorio Nativo C vía JNI (Empaqueta libbrotlidec.so / .dll / .dylib dentro de los JARs) |
VULNERABLE A CORRUPCIÓN DE HEAP NATIVO Y RCE si incluye Google Brotli 1.0.3–1.2.0. Evade la seguridad de memoria de la JVM vía JNI. |
Enlaces JNI / JNA / Panama hacia libbrotlidec.so.1 del sistema operativo |
Biblioteca Compartida del SO | VULNERABLE hasta actualizar el paquete libbrotli del sistema a 1.0.10 / 1.1.1 / 1.2.1+. |
org.brotli:dec(Usado en okhttp3:okhttp-brotli y rutas puras en Java) |
Bytecode 100% Puro en Java | Sin RCE Nativo: La verificación de límites de la JVM lanza una excepción Java segura (BrotliRuntimeException) sin corromper memoria nativa. |
Cuando una aplicación basada en Netty, Spring Cloud Gateway, Spring WebFlux o Vert.x registra HttpContentDecompressor y detecta brotli4j en el classpath, extrae el binario nativo libbrotlidec.so del JAR hacia /tmp y lo carga en el proceso de la JVM mediante System.load(). A partir de ese momento, cualquier petición o respuesta HTTP con Content-Encoding: br se procesa en código C nativo dentro de la máquina virtual.
4. Otros Lenguajes e Infraestructura Afectada
- Rust (
brotli-sys): Aunque el cratebrotliescrito en Rust puro es seguro en memoria, los crates que enlazan la biblioteca C mediantebrotli-sysejecutan el código C vulnerable dentro de bloquesunsafe. - Go (
cbrotlivíacgo): Los binarios de Go compilados concgocontragoogle/brotli/go/cbrotli(a diferencia del paquete puro en Goandybalholm/brotli) llaman directamente ac/dec/decode.c. - PHP (
ext-brotli) y Ruby (gemabrotli): Extensiones nativas en C que enlazan conlibbrotlidec. - Proxies en C/C++ y Herramientas del Sistema (
Envoy,Nginx ngx_brotli,Apache mod_brotli,curl): Cualquier proxy inverso o servicio que descomprima flujos Brotli entrantes usando versiones sin parchear delibbrotli.
5. Guía de Auditoría, Mitigación y Parcheo Políglota
Paso 1: Auditar Todas las Capas de tu Infraestructura
# 1. Verificar biblioteca compartida del sistema operativo (Debian/Ubuntu, RHEL, Alpine)
dpkg -l | grep -i brotli || rpm -qa | grep -i brotli || apk info -vv | grep -i brotli
# 2. Verificar entornos virtuales y contenedores de Python
python3 -c "import brotli; print('Python brotli:', brotli.__version__)" 2>/dev/null
pip list | grep -iE "brotli|brotlicffi|urllib3|aiohttp|httpx"
# 3. Verificar árboles de dependencias de Java (Maven / Gradle) y JARs desplegados
mvn dependency:tree | grep -iE "brotli4j|netty-codec-http"
find / -name "*brotli4j*.jar" 2>/dev/null
# 4. Verificar versión integrada en Node.js
node -p "({ node: process.version, brotli: process.versions.brotli })"Paso 2: Actualizar a las Versiones Parcheadas
- Google
libbrotli(C/C++ y paquetes del SO): Actualizar a1.2.1+(o las ramas mantenidas1.1.1/1.0.10que incorporan el commit0ed4268). - Python: Actualizar los paquetes en tus entornos (
pip install --upgrade "Brotli>=1.2.1" brotlicffi). Si un microservicio en Python no necesita descomprimir Brotli, desinstala la extensión C (pip uninstall brotli brotlicffi) para querequestsyurllib3utilicen exclusivamentegzip. - Java (
brotli4j/ Netty): Actualizarcom.aayushatharva.brotli4j:brotli4ja la versión compilada con Brotli1.2.1+, o excluir temporalmentebrotli4jen tupom.xml/build.gradle. - Node.js: Actualizar a
v26.12.1+,v24.22.1+ov22.23.4+.
Paso 3: Mitigaciones en Código para Python y Java
1. En Python (restringir Accept-Encoding en clientes HTTP salientes):
import requests
session = requests.Session()
session.headers.update({"Accept-Encoding": "gzip, deflate"})
resp = session.get("https://webhook-externo.ejemplo.com/payload")2. En Java (excluir temporalmente el JAR nativo brotli4j en Maven):
<exclusions>
<exclusion>
<groupId>com.aayushatharva.brotli4j</groupId>
<artifactId>brotli4j</artifactId>
</exclusion>
</exclusions>Paso 4: Parcheo Virtual en el Borde (Nginx y WAF ModSecurity / Coraza / Centinela)
Una sola regla en tu proxy inverso o WAF protege simultáneamente a todos tus servicios en Python, Java y Node.js frente a peticiones entrantes maliciosas:
# Proxy Inverso Nginx: Rechazar peticiones de clientes comprimidas con Brotli
if ($http_content_encoding ~* "\bbr\b") {
return 415;
}# Regla ModSecurity / Coraza / Centinela
SecRule REQUEST_HEADERS:Content-Encoding "(?i)\bbr\b" \
"id:1011497,phase:1,deny,status:415,log,t:none,msg:'HTTP2Shell / Node2Shell (CVE-2026-111497) Peticion Brotli Entrante Bloqueada'"6. Caza de Amenazas en Entornos Java y Python
En Servicios Python (Gunicorn / Uvicorn / Celery): Busca procesos trabajadores terminados abruptamente con señal 11 (SIGSEGV) o señal 6 (SIGABRT):
journalctl -u gunicorn -u uvicorn -u celery --since "7 days ago" | grep -E "signal 11|SIGSEGV|SIGABRT|core dumped"En Servicios Java / JVM: Busca volcados de caída nativa de HotSpot (hs_err_pid*.log) cuya traza nativa mencione libbrotlidec.so o BrotliDecoderDecompressStream:
grep -rnE "libbrotlidec|BrotliDecoder" /var/log/ /tmp/ /app/ 2>/dev/nullConclusión
La evolución de Node2Shell hacia HTTP2Shell (CVE-2026-111497) deja una lección clave para la ingeniería de seguridad moderna: la seguridad de memoria de una aplicación es tan fuerte como la biblioteca en C más profunda de su árbol de dependencias. Audita tus entornos virtuales de Python, árboles de dependencias Maven/Gradle en Java, binarios de Node.js e imágenes de contenedores, actualiza libbrotli a 1.2.1+ y bloquea los flujos Content-Encoding: br entrantes no solicitados en tu perímetro.