
Exploit de prova de conceito para CVE-2026-10672, uma leitura fora dos limites no cliente de pull de atualização de firmware LwM2M do Zephyr RTOS. Inclui reprodução em C independente e servidor CoAP/LwM2M malicioso para testes.
Prova de conceito para CVE-2026-10672, uma leitura fora dos limites no cliente de pull de atualização de firmware LwM2M do Zephyr RTOS (subsys/net/lib/lwm2m/lwm2m_pull_context.c).
lwm2m_pull_context_start_transfer() em lwm2m_pull_context.cmemcpy(context.uri, uri, LWM2M_PACKAGE_URI_LEN) copia exatamente 128 bytes para char uri[128] sem terminador NUL quando o URI do Pacote fornecido pelo servidor (/5/0/1) é ≥ 128 bytes. Subsequentemente, strlen(context.uri), http_parser_parse_url(), e a opção CoAP PROXY_URI anexam e depois leem além do buffer na memória struct adjacente (is_firmware_uri, os ponteiros de função result_cb / write_cb, e o contexto de conexão DTLS). Os bytes lidos a mais são exfiltrados na requisição CoAP de saída.context.uri[128] (CONFIG_LWM2M_SWMGMT_PACKAGE_URI_LEN, default 128; LWM2M_PACKAGE_URI_LEN é #defined para isso)99a164df5cea5af76e32b57c6d51854f018969a2 — adiciona strlen(uri) >= sizeof(context.uri) → -ENOMEM e muda para strcpy().| Arquivo | Propósito |
|---|---|
poc.c |
gcc -O0 -g -o poc poc.c
./poc
Esperado: um URI de Pacote de 200 bytes produz uma opção CoAP PROXY_URI de 141 bytes — o URI de 128 bytes mais 13 bytes vazados de context.is_firmware_uri, padding da struct, e os ponteiros de função result_cb/write_cb. O caminho de código corrigido rejeita o URI com -ENOMEM e não copia nada.
gcc -O0 -g -fsanitize=address -o poc-asan poc.c
./poc-asan
A sonda aloca exatamente 128 bytes, preenche-os com bytes não NUL (espelhando um context.uri completo sem terminador) e chama strlen():
ERROR: AddressSanitizer: heap-buffer-overflow
READ of size 129 at 0x...
0x... is located 0 bytes after 128-byte region [...,0x...)
# 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
O script emite um CoAP PUT /5/0/1 (Escrita LwM2M do recurso URI do Pacote) seguido por um CoAP POST /5/0/2 (Execução LwM2M Update, que inicia o pull do firmware e aciona o bug). Em LwM2M de produção, a sessão roda sobre DTLS (UDP/5684); o atacante em escopo é um servidor de gerenciamento malicioso/comprometido, ou um adversário no caminho quando a autenticação do servidor DTLS não é aplicada.
Apenas para pesquisa de segurança autorizada e fins educacionais. Não use essas ferramentas contra dispositivos que você não possui ou não tem permissão explícita para testar.
Reprodução C independente dos caminhos de código vulnerável/corrigido. Re-declara fielmente struct firmware_pull_context (o buffer uri[128] mais os campos adjacentes que são lidos a mais) e o consumidor vazado do CoAP PROXY_URI. |
lwm2m_evil_server.py | Servidor CoAP/LwM2M mínimo que entrega o URI do Pacote superdimensionado para /5/0/1 de um cliente vulnerável via UDP (modo NoSec) — a metade de entrega em rede do ataque. Sem dependências externas. |