
Hallazgos de seguridad de EDK2 BrotliCustomDecompressLib — divulgación coordinada
Un desbordamiento de búfer de heap en el propio glue de descompresión Brotli de EDK2
(MdeModulePkg/Library/BrotliCustomDecompressLib), presente desde 2017, sin corregir
en HEAD a fecha de 2026-10-25. Confirmado con ASAN mediante una prueba de concepto y una
demostración de corrupción controlada de extremo a extremo.
El wrapper de Brotli de EDK2 lee el tamaño de salida descomprimido de una
cabecera de sección GUIDed controlada por el atacante, lo trunca de UINT64 → UINT32 sin
ninguna comprobación, y lo pasa al núcleo DXE, que asigna un búfer de ese tamaño.
BrotliDecompressInternal descomprime entonces en ese búfer sin límite — se
ejecuta hasta que termina el flujo Brotli, escribiendo más allá de la asignación.
Resultado: desbordamiento de heap (primitiva de escritura) en la fase DXE, antes de que finalice la verificación de Secure Boot. Un atacante que controle la imagen de firmware (flash, cápsula, o ESP) puede sobrescribir objetos de pool adyacentes — punteros a función, flags de seguridad, estructuras de protocolo — con bytes elegidos.
Este es el hermano Brotli pasado por alto de CVE-2021-28211 (LZMA recibió una
guarda >MAX_UINT32 en 2021; Brotli nunca la recibió). Un barrido de variantes confirma que Brotli
es el único descompresor de EDK2 que carece tanto de la guarda de truncamiento como de un
límite de salida.
| Archivo | Qué hace |
|---|---|
BrotliDecompress.c:238 | Convierte el tamaño decodificado UINT64 a UINT32 — sin guarda MAX_UINT32 |
BrotliDecompress.c:118–157 | Descomprime en el búfer de destino sin comprobación de límites |
GuidedSectionExtraction.c | Llama a GetInfo y luego a Decompress — confía en el tamaño declarado |
CoreSectionExtraction.c:1597 | Asigna el búfer de destino con el tamaño declarado |
Todo en tianocore/edk2, MdeModulePkg/Library/BrotliCustomDecompressLib.
| Artefacto | Descripción |
|---|---|
harness/edk2_brotli_overflow_poc.c | Prueba de concepto ASAN: flujo de 4096 bytes en un búfer de 64 bytes |
harness/asan_output.txt | Salida de ASAN: heap-buffer-overflow en BrotliDecompressInternal → memcpy |
harness/edk2_brotli_overflow_demo.c | Demostración de extremo a extremo: corrupción controlada de objetos de pool adyacentes |
harness/demo_output.txt | Salida de la demostración: punteros a función secuestrados, Secure Boot deshabilitado |
harness/lvfs_brotli_scan.py | Escáner de firmware LVFS (medición del radio de impacto) |
harness/lvfs_scan_output.txt | Resultados del escaneo: 0/200 imágenes de firmware usan Brotli |
evidence/ | Copias de los archivos fuente vulnerables de EDK2 en HEAD |
FINDINGS.md | Informe completo: referencias de línea, búsqueda de trabajos previos, barrido de variantes, auditoría de LZMA |
Estrecho. Dos estudios independientes no encontraron ninguna plataforma que use secciones GUIDed de Brotli en la práctica:
BrotliCustomDecompressLib. Todas las coincidencias son el propio MdeModulePkg.dsc.El código vulnerable se distribuye en el árbol de EDK2 pero es código muerto hoy en día — añadido en 2017, nunca adoptado por IBVs ni OEMs. El fallo es real y explotable en principio; si la adopción de Brotli aumenta, se vuelve inmediatamente alcanzable.
Dos cambios, que coinciden con lo que LZMA y Tiano ya tienen:
MAX_UINT32 a BrotliUefiDecompressGetInfo
(BrotliDecompress.c:238): rechazar tamaños decodificados > MAX_UINT32, como
hace LzmaDecompress.c:149 desde CVE-2021-28211.BrotliDecompressInternal: rastrear los bytes escritos y
detenerse en DestinationSize, como hace el descompresor Tiano con mOrigSize.Compilar la PoC en Linux con libbrotli y GCC:
# ASAN proof (aborts at the overflow)
gcc -fsanitize=address -g -O1 -o poc harness/edk2_brotli_overflow_poc.c \
-lbrotlienc -lbrotlidec
./poc
# Controlled-corruption demo (completes the overflow, shows the damage)
gcc -g -O1 -o demo harness/edk2_brotli_overflow_demo.c \
-lbrotlienc -lbrotlidec
./demo
Divulgación pública completa, 2026-10-26. No se otorgó un periodo de divulgación coordinada a TianoCore. El reducido radio de impacto (ningún firmware en producción afectado) y el hecho de que el error hermano de LZMA es público desde 2021 motivaron esta decisión.