-
Notifications
You must be signed in to change notification settings - Fork 300
Description
OpENer version
OpENer v2.3-558-g1e99582
Commit
1e99582227c86cbdc7c86caeb7ba04c56134d174
OS and/or distribution
Ubuntu 24.04.5
Environment
Build type:
- non-ASan debug build for GDB reproduction
- ASan-instrumented build for sanitizer verification
Description
An out-of-bounds read vulnerability was found in OpENer in the CPF parsing logic, specifically in:
CreateCommonPacketFormatStructure()source/src/enet_encap/cpf.c
The issue is caused by trusting an attacker-controlled CPF item_count value without consistently validating subsequent reads against the provided data_length.
During debugging, the CPF parser was entered with a 16-byte CPF slice, but the first two bytes:
01 e8
were parsed as:
item_count = 0xe801
As a result, the parser continued processing structured fields after data had already reached cpf_start + data_length, leading to an out-of-bounds read.
Relevant code region:
size_t length_count = 0;
CipUint item_count = GetUintFromMessage(&data);
// OPENER_ASSERT(4U >= item_count); /* Sanitizing data - probably needs to be changed for productive code */
common_packet_format_data->item_count = item_count;
...
for(size_t j = 0; j < (address_item_count > 2 ? 2 : address_item_count); j++) /* TODO there needs to be a limit check here???*/
{
common_packet_format_data->address_info_item[j].type_id =
GetIntFromMessage(&data);
Actual behavior if applicable
- ASan build reports a heap-buffer-overflow
- In a non-ASan debug build, GDB shows that parsing continues even when:
data == cpf_start + data_length - The first invalid read is observed around:
source/src/enet_encap/cpf.c:280
Expected behavior or suggestion
The parser should reject malformed CPF data and stop parsing before any read that would advance beyond the provided data_length.
Steps to reproduce
1.Complie with afl-gcc/afl-g++:
cd bin/posix
###afl
CC=afl-gcc \
CXX=afl-g++ \
cmake \
-DOpENer_PLATFORM=POSIX \
-DUSE_FUZZ_AFL=ON \
-DBUILD_SHARED_LIBS=OFF \
../../source
make -j"$(nproc)" OpENer_afl
###asan
AFL_USE_ASAN=1 \
CC=afl-gcc \
CXX=afl-g++ \
cmake \
-DOpENer_PLATFORM=POSIX \
-DUSE_FUZZ_AFL=ON \
-DBUILD_SHARED_LIBS=OFF \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DCMAKE_C_FLAGS="-O1 -g -fno-omit-frame-pointer" \
-DCMAKE_CXX_FLAGS="-O1 -g -fno-omit-frame-pointer" \
../../source
make -j"$(nproc)" OpENer_afl_asan
2.Then using inputs:
./OpENer_afl < poc.bin
./OpENer_afl_asan < poc.bin
POC File
GDB output
Breakpoint 6, NotifyCommonPacketFormat (...) at /root/OpENer/source/src/enet_encap/cpf.c:42
(gdb) p/x $cpf_start
$13 = 0x50e92e
(gdb) p $cpf_len
$14 = 16
(gdb) p/x $cpf_end
$15 = 0x50e93e
(gdb) p (long)($cpf_end - $cpf_start)
$16 = 16
(gdb) x/16bx $cpf_start
0x50e92e: 0x01 0xe8 0x00 0x00 0x00 0x00 0xb2 0x00
0x50e936: 0x06 0x00 0x04 0x02 0x20 0x01 0x24 0x01
(gdb) next
245 common_packet_format_data->item_count = item_count;
(gdb) p item_count
$17 = 59393
(gdb) p/x item_count
$18 = 0xe801
(gdb) rwatch *$cpf_end
Hardware read watchpoint 7: *$cpf_end
(gdb) continue
Hardware read watchpoint 7: *$cpf_end
CreateCommonPacketFormatStructure (data=0x50e93e "", data_length=16, ...)
at /root/OpENer/source/src/enet_encap/cpf.c:280
(gdb) bt
#0 CreateCommonPacketFormatStructure (...) at /root/OpENer/source/src/enet_encap/cpf.c:280
#1 NotifyCommonPacketFormat (...) at /root/OpENer/source/src/enet_encap/cpf.c:46
#2 HandleReceivedSendRequestResponseDataCommand (...) at /root/OpENer/source/src/enet_encap/encap.c:558
#3 HandleReceivedExplictTcpData (...) at /root/OpENer/source/src/enet_encap/encap.c:186
(gdb) info locals
length_count = 16
item_count = 59393
ASAN output
=================================================================
==14630==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x5060000000bc at pc 0x61b74ecb235c bp 0x7ffe079445f0 sp 0x7ffe079445e8
READ of size 1 at 0x5060000000bc thread T0
#0 0x61b74ecb235b in CreateCommonPacketFormatStructure /root/OpENer/source/src/enet_encap/cpf.c:298:75
#1 0x61b74ecb0629 in NotifyCommonPacketFormat /root/OpENer/source/src/enet_encap/cpf.c:46:12
#2 0x61b74ecb62c7 in HandleReceivedSendRequestResponseDataCommand /root/OpENer/source/src/enet_encap/encap.c:558:22
#3 0x61b74ecb62c7 in HandleReceivedExplictTcpData /root/OpENer/source/src/enet_encap/encap.c:186:26
#4 0x61b74ec75bc2 in CallTcp /root/OpENer/source/src/ports/POSIX/OpENer_afl.c:163:8
#5 0x61b74ec75bc2 in ExecuteFallbackSinglePacket /root/OpENer/source/src/ports/POSIX/OpENer_afl.c:497:9
#6 0x61b74ec75bc2 in main /root/OpENer/source/src/ports/POSIX/OpENer_afl.c:515:5
#7 0x7cbf3522a1c9 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#8 0x7cbf3522a28a in __libc_start_main csu/../csu/libc-start.c:360:3
#9 0x61b74eb92a94 in _start (/home/ivcm/OpENer/poc/OpENer_afl_asan+0x70a94) (BuildId: d74ed6c3acba79ce)
0x5060000000bc is located 0 bytes after 60-byte region [0x506000000080,0x5060000000bc)
allocated by thread T0 here:
#0 0x61b74ec2d8e3 in malloc (/home/ivcm/OpENer/poc/OpENer_afl_asan+0x10b8e3) (BuildId: d74ed6c3acba79ce)
#1 0x61b74ec75a8a in CallTcp /root/OpENer/source/src/ports/POSIX/OpENer_afl.c:154:28
#2 0x61b74ec75a8a in ExecuteFallbackSinglePacket /root/OpENer/source/src/ports/POSIX/OpENer_afl.c:497:9
#3 0x61b74ec75a8a in main /root/OpENer/source/src/ports/POSIX/OpENer_afl.c:515:5
#4 0x7cbf3522a1c9 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#5 0x7cbf3522a28a in __libc_start_main csu/../csu/libc-start.c:360:3
#6 0x61b74eb92a94 in _start (/home/ivcm/OpENer/poc/OpENer_afl_asan+0x70a94) (BuildId: d74ed6c3acba79ce)
SUMMARY: AddressSanitizer: heap-buffer-overflow /root/OpENer/source/src/enet_encap/cpf.c:298:75 in CreateCommonPacketFormatStructure
Shadow bytes around the buggy address:
0x505ffffffe00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x505ffffffe80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x505fffffff00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x505fffffff80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x506000000000: fa fa fa fa 00 00 00 00 00 00 04 fa fa fa fa fa
=>0x506000000080: 00 00 00 00 00 00 00[04]fa fa fa fa fa fa fa fa
0x506000000100: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x506000000180: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x506000000200: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x506000000280: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x506000000300: 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
==14630==ABORTING