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++.

De Node2Shell a HTTP2Shell CVE-2026-111497 RCE en Brotli para Python Java y Node.js
🌐
Escalada Crítica de Amenaza: De Node2Shell a HTTP2Shell (CVE-2026-111497) Lo que comenzó como Node2Shell se ha expandido rápidamente hacia HTTP2Shell. Debido a que CVE-2026-111497 (CVSS: 9.2 Crítica) reside en la implementación de referencia en C del decodificador Brotli de Google (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 Proceso

En 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.

  1. Cuando urllib3 (el motor debajo de requests), httpx o aiohttp se importan al iniciar tu aplicación, ejecutan internamente una comprobación opcional en busca de los paquetes brotli o brotlicffi.
  2. Incluso si tu equipo nunca instaló brotli directamente, decenas de dependencias transitivas (SDKs de nube, herramientas de scraping, clientes de IA o conectores de APIs) instalan la rueda binaria Brotli (que contiene _brotli.cpython-*.so).
  3. En cuanto ese binario existe en site-packages, requests, urllib3, httpx y aiohttp añaden automáticamente br al encabezado Accept-Encoding de todas tus peticiones salientes y envían cualquier respuesta con Content-Encoding: br directo al decodificador en C vulnerable.
🐍
Dónde Están Más Expuestos los Servicios en Python Cualquier backend en Python, worker de Celery, agente de IA, validador de webhooks o recolector de datos que consulte URLs externas mediante 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 crate brotli escrito en Rust puro es seguro en memoria, los crates que enlazan la biblioteca C mediante brotli-sys ejecutan el código C vulnerable dentro de bloques unsafe.
  • Go (cbrotli vía cgo): Los binarios de Go compilados con cgo contra google/brotli/go/cbrotli (a diferencia del paquete puro en Go andybalholm/brotli) llaman directamente a c/dec/decode.c.
  • PHP (ext-brotli) y Ruby (gema brotli): Extensiones nativas en C que enlazan con libbrotlidec.
  • 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 de libbrotli.

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 a 1.2.1+ (o las ramas mantenidas 1.1.1 / 1.0.10 que incorporan el commit 0ed4268).
  • 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 que requests y urllib3 utilicen exclusivamente gzip.
  • Java (brotli4j / Netty): Actualizar com.aayushatharva.brotli4j:brotli4j a la versión compilada con Brotli 1.2.1+, o excluir temporalmente brotli4j en tu pom.xml / build.gradle.
  • Node.js: Actualizar a v26.12.1+, v24.22.1+ o v22.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/null

Conclusió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.

Read more