-
Notifications
You must be signed in to change notification settings - Fork 728
Closed
Labels
Description
Summary
pocs.tar.gz
asan_reports.tar.gz
AddressSanitizer detected two critical memory safety issues in BgpLayer.cpp of the PcapPlusPlus project: Heap-use-after-free and Heap-buffer-overflow in BgpLayer::getHeaderLen(). These can both lead to crashes and potential security vulnerabilities.
Root Cause Analysis
Suspected Problematic Code
size_t BgpLayer::getHeaderLen() const
{
if (m_DataLen < sizeof(bgp_common_header))
return m_DataLen;
uint16_t messageLen = be16toh(getBasicHeader()->length);
if (m_DataLen < messageLen)
return m_DataLen;
return (size_t)messageLen;
}Possible Explanation
- For use-after-free: The lifecycle of the packet/layer objects and their backing memory is not tightly controlled. After freeing the buffer, the code still tries to access fields via dangling pointers.
- For buffer-overflow: Insufficient bounds checking when parsing variable-length and potentially malformed BGP messages, especially if the internal
lengthfield is corrupted.
Suggested Fix
-
Use-after-free:
- Ensure that all layer/packet objects referencing a
RawPacketare invalidated or detached before the underlying memory is freed or cleared. - Consider using smart pointers or explicit memory management to enforce ownership/lifetime guarantees.
- Ensure that all layer/packet objects referencing a
-
Buffer-overflow:
- Always validate that accesses to
m_Dataand any structure members are withinm_DataLen. - When reading the length field from the header, ensure the header is fully within the buffer, and that the field's value does not cause out-of-bounds accesses for further parsing.
- Always validate that accesses to
Platform
- OS:
Ubuntu 22.04.5 LTS - Clang version:
Ubuntu clang version 16.0.6 (++20231112100510+7cbf1a259152-1~exp1~20231112100554.106) - Version commit
0588d88eca769a02e660161f8965ef6152ada90e
Steps to Reproduce
export SRC=/src OUT=/out
mkdir $SRC $OUT
apt-get update && apt-get install -y cmake autoconf flex bison zip
export CC=clang CXX=clang++ CFLAGS='-fsanitize=address -g -O1' CXXFLAGS='-fsanitize=address -g -O1' LDFLAGS="-fuse-ld=lld" LIB_FUZZING_ENGINE='-fsanitize=fuzzer'
git clone --depth=1 https://github.com/seladb/PcapPlusPlus PcapPlusPlus
git clone --depth=1 https://github.com/the-tcpdump-group/tcpdump.git tcpdump
git clone --depth=1 https://github.com/the-tcpdump-group/libpcap.git libpcap
cd $SRC/PcapPlusPlus
$SRC/PcapPlusPlus/Tests/Fuzzers/ossfuzz.sh
$OUT/FuzzTargetNg pocASAN report
Use-after-free:
=================================================================
==530017==ERROR: AddressSanitizer: heap-use-after-free on address 0x613000000585 at pc 0x598652937a70 bp 0x7ffeb98a5560 sp 0x7ffeb98a5558
READ of size 2 at 0x613000000585 thread T0
#0 0x598652937a6f in pcpp::BgpLayer::getHeaderLen() const /src/PcapPlusPlus/Packet++/src/BgpLayer.cpp:21:25
#1 0x5986529f306c in pcpp::Packet::extendLayer(pcpp::Layer*, int, unsigned long) /src/PcapPlusPlus/Packet++/src/Packet.cpp:621:33
#2 0x5986529d4823 in pcpp::Layer::extendLayer(int, unsigned long) /src/PcapPlusPlus/Packet++/src/Layer.cpp:85:20
#3 0x59865293b3c4 in pcpp::BgpOpenMessageLayer::setOptionalParameters(std::vector<pcpp::BgpOpenMessageLayer::optional_parameter, std::allocator<pcpp::BgpOpenMessageLayer::optional_parameter>> const&) /src/PcapPlusPlus/Packet++/src/BgpLayer.cpp:267:15
#4 0x5986528eb1ad in readParsedPacket(pcpp::Packet, pcpp::Layer*) /src/PcapPlusPlus/Tests/Fuzzers/ReadParsedPacket.h:440:22
#5 0x5986528e5b50 in LLVMFuzzerTestOneInput /src/PcapPlusPlus/Tests/Fuzzers/FuzzTarget.cpp:66:5
#6 0x5986527f4e90 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) crtstuff.c
#7 0x5986527ded6f in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) crtstuff.c
#8 0x5986527e4826 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) crtstuff.c
#9 0x59865280dcf2 in main (/out/FuzzTargetNg+0x1a7cf2) (BuildId: 97bfbeafd983e755)
#10 0x76efe31c8d8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#11 0x76efe31c8e3f in __libc_start_main csu/../csu/libc-start.c:392:3
#12 0x5986527d9c74 in _start (/out/FuzzTargetNg+0x173c74) (BuildId: 97bfbeafd983e755)
0x613000000585 is located 5 bytes inside of 337-byte region [0x613000000580,0x6130000006d1)
freed by thread T0 here:
#0 0x5986528e2d5d in operator delete[](void*) (/out/FuzzTargetNg+0x27cd5d) (BuildId: 97bfbeafd983e755)
#1 0x598652a23a08 in pcpp::RawPacket::clear() /src/PcapPlusPlus/Packet++/src/RawPacket.cpp:100:4
#2 0x598652a23a08 in pcpp::RawPacket::~RawPacket() /src/PcapPlusPlus/Packet++/src/RawPacket.cpp:24:3
#3 0x5986527f4e90 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) crtstuff.c
#4 0x5986527ded6f in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) crtstuff.c
#5 0x5986527e4826 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) crtstuff.c
#6 0x59865280dcf2 in main (/out/FuzzTargetNg+0x1a7cf2) (BuildId: 97bfbeafd983e755)
#7 0x76efe31c8d8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
previously allocated by thread T0 here:
#0 0x5986528e250d in operator new[](unsigned long) (/out/FuzzTargetNg+0x27c50d) (BuildId: 97bfbeafd983e755)
#1 0x598652a23bc7 in pcpp::RawPacket::copyDataFrom(pcpp::RawPacket const&, bool) /src/PcapPlusPlus/Packet++/src/RawPacket.cpp:60:16
#2 0x598652a23bc7 in pcpp::RawPacket::RawPacket(pcpp::RawPacket const&) /src/PcapPlusPlus/Packet++/src/RawPacket.cpp:30:3
SUMMARY: AddressSanitizer: heap-use-after-free /src/PcapPlusPlus/Packet++/src/BgpLayer.cpp:21:25 in pcpp::BgpLayer::getHeaderLen() const
Shadow bytes around the buggy address:
0x613000000300: 00 00 00 00 00 00 00 00 00 00 00 00 00 fa fa fa
0x613000000380: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00
0x613000000400: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x613000000480: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x613000000500: 00 00 01 fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x613000000580:[fd]fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x613000000600: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x613000000680: fd fd fd fd fd fd fd fd fd fd fd fa fa fa fa fa
0x613000000700: fa fa fa fa fa fa fa fa fd fd fd fd fd fd fd fd
0x613000000780: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x613000000800: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
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
==530017==ABORTING
Buffer-overflow:
=================================================================
==530034==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6170000004d0 at pc 0x64a8cc0b5a70 bp 0x7fff24c584a0 sp 0x7fff24c58498
READ of size 2 at 0x6170000004d0 thread T0
#0 0x64a8cc0b5a6f in pcpp::BgpLayer::getHeaderLen() const /src/PcapPlusPlus/Packet++/src/BgpLayer.cpp:21:25
#1 0x64a8cc17256c in pcpp::Packet::shortenLayer(pcpp::Layer*, int, unsigned long) /src/PcapPlusPlus/Packet++/src/Packet.cpp:673:33
#2 0x64a8cc1535e8 in pcpp::Layer::shortenLayer(int, unsigned long) /src/PcapPlusPlus/Packet++/src/Layer.cpp:114:20
#3 0x64a8cc0bd645 in pcpp::BgpUpdateMessageLayer::setWithdrawnRoutes(std::vector<pcpp::BgpUpdateMessageLayer::prefix_and_ip, std::allocator<pcpp::BgpUpdateMessageLayer::prefix_and_ip>> const&) /src/PcapPlusPlus/Packet++/src/BgpLayer.cpp:581:15
#4 0x64a8cc069b62 in readParsedPacket(pcpp::Packet, pcpp::Layer*) /src/PcapPlusPlus/Tests/Fuzzers/ReadParsedPacket.h:451:24
#5 0x64a8cc063b50 in LLVMFuzzerTestOneInput /src/PcapPlusPlus/Tests/Fuzzers/FuzzTarget.cpp:66:5
#6 0x64a8cbf72e90 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) crtstuff.c
#7 0x64a8cbf5cd6f in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) crtstuff.c
#8 0x64a8cbf62826 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) crtstuff.c
#9 0x64a8cbf8bcf2 in main (/out/FuzzTargetNg+0x1a7cf2) (BuildId: 97bfbeafd983e755)
#10 0x7429e2b78d8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#11 0x7429e2b78e3f in __libc_start_main csu/../csu/libc-start.c:392:3
#12 0x64a8cbf57c74 in _start (/out/FuzzTargetNg+0x173c74) (BuildId: 97bfbeafd983e755)
0x6170000004d0 is located 430 bytes after 674-byte region [0x617000000080,0x617000000322)
allocated by thread T0 here:
#0 0x64a8cc06050d in operator new[](unsigned long) (/out/FuzzTargetNg+0x27c50d) (BuildId: 97bfbeafd983e755)
#1 0x64a8cc1a2e70 in pcpp::RawPacket::reallocateData(unsigned long) /src/PcapPlusPlus/Packet++/src/RawPacket.cpp:144:24
#2 0x64a8cc169a22 in pcpp::Packet::reallocateRawData(unsigned long) /src/PcapPlusPlus/Packet++/src/Packet.cpp:202:21
#3 0x64a8cc170ed3 in pcpp::Packet::extendLayer(pcpp::Layer*, int, unsigned long) /src/PcapPlusPlus/Packet++/src/Packet.cpp
#4 0x64a8cc152823 in pcpp::Layer::extendLayer(int, unsigned long) /src/PcapPlusPlus/Packet++/src/Layer.cpp:85:20
#5 0x64a8cc0bd1f7 in pcpp::BgpUpdateMessageLayer::setWithdrawnRoutes(std::vector<pcpp::BgpUpdateMessageLayer::prefix_and_ip, std::allocator<pcpp::BgpUpdateMessageLayer::prefix_and_ip>> const&) /src/PcapPlusPlus/Packet++/src/BgpLayer.cpp:571:15
#6 0x64a8cc069b62 in readParsedPacket(pcpp::Packet, pcpp::Layer*) /src/PcapPlusPlus/Tests/Fuzzers/ReadParsedPacket.h:451:24
#7 0x64a8cc063b50 in LLVMFuzzerTestOneInput /src/PcapPlusPlus/Tests/Fuzzers/FuzzTarget.cpp:66:5
#8 0x64a8cbf72e90 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) crtstuff.c
#9 0x64a8cbf5cd6f in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) crtstuff.c
#10 0x64a8cbf62826 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) crtstuff.c
#11 0x64a8cbf8bcf2 in main (/out/FuzzTargetNg+0x1a7cf2) (BuildId: 97bfbeafd983e755)
#12 0x7429e2b78d8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
SUMMARY: AddressSanitizer: heap-buffer-overflow /src/PcapPlusPlus/Packet++/src/BgpLayer.cpp:21:25 in pcpp::BgpLayer::getHeaderLen() const
Shadow bytes around the buggy address:
0x617000000200: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x617000000280: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x617000000300: 00 00 00 00 02 fa fa fa fa fa fa fa fa fa fa fa
0x617000000380: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x617000000400: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x617000000480: fa fa fa fa fa fa fa fa fa fa[fa]fa fa fa fa fa
0x617000000500: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x617000000580: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x617000000600: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x617000000680: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x617000000700: 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
==530034==ABORTING
PcapPlusPlus versions tested on
PcapPlusPlus master branch
Other PcapPlusPlus version (if applicable)
hash: 0588d88eca769a02e660161f8965ef6152ada90e
Operating systems tested on
Linux
Other operation systems (if applicable)
No response
Compiler version
clang version 16.0.6
Packet capture backend (if applicable)
No response