## https://sploitus.com/exploit?id=6F71ACF5-6AA8-5E0B-A9B4-09D9091D7204
# CVE-2026-10672 โ Zephyr LwM2M Firmware Update OOB Read PoC
Proof of concept for **CVE-2026-10672**, an out-of-bounds read in Zephyr RTOS's
LwM2M firmware-update pull client (`subsys/net/lib/lwm2m/lwm2m_pull_context.c`).
## Vulnerability
- **CVE**: CVE-2026-10672
- **CVSS**: 8.2 High (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:L)
- **CWE**: CWE-125 (Out-of-bounds Read)
- **Component**: `lwm2m_pull_context_start_transfer()` in `lwm2m_pull_context.c`
- **Root cause**: `memcpy(context.uri, uri, LWM2M_PACKAGE_URI_LEN)` copies exactly
128 bytes into `char uri[128]` with no NUL terminator when the server-supplied
Package URI (`/5/0/1`) is โฅ 128 bytes. Subsequent `strlen(context.uri)`,
`http_parser_parse_url()`, and the CoAP `PROXY_URI` option append then read past
the buffer into adjacent struct memory (`is_firmware_uri`, the `result_cb` /
`write_cb` function pointers, and the DTLS connection context). The over-read
bytes are exfiltrated in the outbound CoAP request.
- **Buffer**: `context.uri[128]` (`CONFIG_LWM2M_SWMGMT_PACKAGE_URI_LEN`, default 128;
`LWM2M_PACKAGE_URI_LEN` is `#define`d to it)
- **Affected**: Zephyr v3.0.0 through v4.4.0 (the pull-context refactor that
introduced the copy first shipped in v3.0.0)
- **Fixed**: Zephyr v4.4.1 and v4.3.1
- **Fix commit**: [`99a164df5cea5af76e32b57c6d51854f018969a2`](https://github.com/zephyrproject-rtos/zephyr/commit/99a164df5cea5af76e32b57c6d51854f018969a2)
โ adds `strlen(uri) >= sizeof(context.uri)` โ `-ENOMEM` and switches to `strcpy()`.
## Contents
| File | Purpose |
|---|---|
| `poc.c` | Standalone C reproduction of the vulnerable/fixed code paths. Faithfully re-declares `struct firmware_pull_context` (the `uri[128]` buffer plus the adjacent fields that get over-read) and the leaky CoAP `PROXY_URI` consumer. |
| `lwm2m_evil_server.py` | Minimal CoAP/LwM2M server that delivers the over-sized Package URI to `/5/0/1` of a vulnerable client over UDP (NoSec mode) โ the network-delivery half of the attack. No external dependencies. |
## Build & run the C reproduction
```bash
gcc -O0 -g -o poc poc.c
./poc
```
Expected: a 200-byte Package URI produces a CoAP `PROXY_URI` option of **141 bytes**
โ the 128-byte URI plus **13 bytes leaked** from `context.is_firmware_uri`,
struct padding, and the `result_cb`/`write_cb` function pointers. The fixed code
path rejects the URI with `-ENOMEM` and copies nothing.
### ASan confirmation
```bash
gcc -O0 -g -fsanitize=address -o poc-asan poc.c
./poc-asan
```
The probe allocates exactly 128 bytes, fills them with non-NUL bytes (mirroring a
full `context.uri` with no terminator) and calls `strlen()`:
```
ERROR: AddressSanitizer: heap-buffer-overflow
READ of size 129 at 0x...
0x... is located 0 bytes after 128-byte region [...,0x...)
```
## Run the malicious LwM2M server
```bash
# Build and inspect the CoAP packets without sending:
python3 lwm2m_evil_server.py --dry-run --uri-len 200
# Send to a vulnerable client (NoSec CoAP, UDP/5683):
python3 lwm2m_evil_server.py --target 10.0.0.42 --port 5683 --uri-len 200 --listen 2
```
The script issues a CoAP **PUT `/5/0/1`** (LwM2M Write of the Package URI
resource) followed by a CoAP **POST `/5/0/2`** (LwM2M Execute *Update*, which
starts the firmware pull and triggers the bug). In production LwM2M the session
runs over DTLS (UDP/5684); the attacker in scope is a malicious/compromised
management server, or an on-path adversary when DTLS server authentication is
not enforced.
## Full article
https://www.hunt-benito.com/blog/zephyr-lwm2m-firmware-update-oob-read-cve-2026-10672-truncated-package-uri/
## Disclaimer
For authorized security research and educational purposes only. Do not use these
tools against devices you do not own or have explicit permission to test.