Skip to content

Multiple memory safety vulnerabilities in CoAP option parsing and serialization #48

@ByamB4

Description

@ByamB4

Summary

Multiple memory safety and logic vulnerabilities exist in microcoap's CoAP option parsing and serialization code. The most severe is a buffer overflow in coap_build() that enables remote code execution on microcontroller targets.

Vulnerability 1: coap_build() Buffer Overflow (CWE-787, Critical)

File: coap.c, function coap_build(), lines 295-331

The bounds check in the option serialization loop is insufficient:

if (((size_t)(p-buf)) > *buflen)     // (1) uses > instead of >=
     return COAP_ERR_BUFFER_TOO_SMALL;
// After this check passes, the following writes have NO bounds checks:
*p++ = (0xFF & (delta << 4 | len));  // 1 byte
if (delta == 13)
    *p++ = (optDelta - 13);          // up to 1 byte
else if (delta == 14) {
    *p++ = ((optDelta-269) >> 8);    // up to 2 bytes
    *p++ = (0xFF & (optDelta-269));
}
// ... same pattern for len ...
memcpy(p, pkt->opts[i].buf.p, pkt->opts[i].buf.len);  // N bytes, no check

Problems:

  1. The check uses > instead of >= (off-by-one: when p-buf == *buflen, p is already past the buffer)
  2. The check is performed before writing but doesn't account for the bytes about to be written (1 header + up to 4 extended bytes + option value)

On the primary deployment targets (Arduino/ESP8266/ESP32 with 64-256 byte buffers), a crafted CoAP request with many large options causes coap_build() to write past the output buffer when constructing a response.

Impact: Heap/stack buffer overflow → remote code execution on microcontrollers (no ASLR, no stack canaries, no DEP on most MCUs).

Vulnerability 2: Option Length uint16_t Overflow (CWE-190, High)

File: coap.c, function coap_parseOption(), line 130

uint16_t len, delta;
// ...
len = ((p[1] << 8) | p[2]) + 269;  // result up to 65804, wraps in uint16_t

When the extended length bytes yield a value where (p[1] << 8) | p[2] > 65266, the result overflows uint16_t. The length wraps to a small value, the bounds check on line 137 passes, and only the wrapped number of bytes are consumed. The remaining bytes of the actual option value are misinterpreted as subsequent option headers — cascading parse corruption from a single crafted packet.

Same issue affects delta on lines 109/148.

Vulnerability 3: Option Number Truncation (CWE-681, High)

File: coap.c line 141, coap.h line 40

Already reported as issue #47 (2019, unfixed). coap_option_t.num is uint8_t but CoAP option numbers go up to 65804. Assignment option->num = delta + *running_delta silently truncates. An attacker can make option 267 appear as option 11 (URI-Path), bypassing endpoint routing and any wire-level option filtering.

Additional Issues

  • Finding 7 (Medium): Options beyond MAXOPT (16) silently dropped — security-relevant options ignored
  • Finding 8 (Medium): Token length size_tuint8_t truncation in coap_make_response()

Suggested Fixes

  1. coap_build(): Before writing each option, compute total bytes needed and verify (p - buf) + total_needed <= *buflen
  2. coap_parseOption(): Change delta and len to uint32_t
  3. coap_option_t.num: Change from uint8_t to uint16_t

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions