staropram / cantcoap

CoAP implementation that focuses on simplicity by offering a minimal set of functions and straightforward interface.
BSD 2-Clause "Simplified" License
86 stars 38 forks source link

Stack Buffer Overflow in CoapPDU::getOptionDelta Function at cantcoap.cpp #38

Open Terminator111 opened 1 month ago

Terminator111 commented 1 month ago

I triggered a stack-buffer-overflow bug reported by AddressSanitizer when fuzzing cantcoap. The bug was identified in the CoapPDU::getOptionDelta function at cantcoap.cpp, which occurs when processing CoAP options. This buffer overflow happens when accessing the option array without performing proper boundary checks.

Affected Code:

uint16_t CoapPDU::getOptionDelta(uint8_t *option) {
    uint16_t delta = (option[0] & 0xF0) >> 4;
    if(delta < 13) {
        return delta;
    } else if(delta == 13) {
        // single byte option delta
        return (option[1] + 13);
    } else if(delta == 14) {
        uint8_t *from = &option[1];
        uint16_t value = endian_load16(uint16_t, from);
        return value + 269;
    } else {
        // should only ever occur in payload marker
        return delta;
    }
}

Asan Report:


==548195==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffdfcc2d974 at pc 0x0000004cad79 bp 0x7ffdfcc2d6e0 sp 0x7ffdfcc2d6d8
READ of size 1 at 0x7ffdfcc2d974 thread T0
    #0 0x4cad78 in CoapPDU::getOptionDelta(unsigned char*) /root/protocolFuzz/coap/cantcoap/cantcoap.cpp:1406:20
    #1 0x4cad78 in CoapPDU::validate() /root/protocolFuzz/coap/cantcoap/cantcoap.cpp:339:17
    #2 0x4c883c in main /root/protocolFuzz/coap/cantcoap/examples/plain/server.cpp:233:15
    #3 0x7fd84332f082 in __libc_start_main /build/glibc-LcI20x/glibc-2.31/csu/../csu/libc-start.c:308:16
    #4 0x41c3fd in _start (/root/protocolFuzz/coap/cantcoap/examples/plain/server+0x41c3fd)

Address 0x7ffdfcc2d974 is located in stack of thread T0 at offset 564 in frame
    #0 0x4c700f in main /root/protocolFuzz/coap/cantcoap/examples/plain/server.cpp:141

  This frame has 7 object(s):
    [32, 40) 'bindAddr' (line 153)
    [64, 564) 'buffer' (line 190) <== Memory access at offset 564 overflows this variable
    [640, 672) 'uriBuffer' (line 191)
    [704, 708) 'recvURILen' (line 192)
    [720, 848) 'recvAddr' (line 195)
    [880, 884) 'recvAddrLen' (line 196)
    [896, 942) 'straddr' (line 199)
SUMMARY: AddressSanitizer: stack-buffer-overflow /root/protocolFuzz/coap/cantcoap/cantcoap.cpp:1406:20 in CoapPDU::getOptionDelta(unsigned char*)
Shadow bytes around the buggy address:
  0x10003f97dad0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10003f97dae0: 00 00 00 00 00 00 00 00 f1 f1 f1 f1 00 f2 f2 f2
  0x10003f97daf0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10003f97db00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10003f97db10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x10003f97db20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00[04]f2
  0x10003f97db30: f2 f2 f2 f2 f2 f2 f2 f2 00 00 00 00 f2 f2 f2 f2
  0x10003f97db40: 04 f2 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10003f97db50: 00 00 f2 f2 f2 f2 04 f2 00 00 00 00 00 06 f3 f3
  0x10003f97db60: f3 f3 f3 f3 00 00 00 00 00 00 00 00 00 00 00 00
  0x10003f97db70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  Shadow gap:              cc
==548195==ABORTING```
staropram commented 5 days ago

Thanks for this, I'll take a look when I get time.