Summary
The BACnet MS/TP receive path decodes COBS frames into an output pointer inside the same fixed input buffer, but passes the full input-buffer size as the decode capacity. A long valid COBS payload can therefore write past the end of the actual remaining buffer.
Details
- Affected file:
src/bacnet/datalink/mstp.c
- Affected function:
MSTP_Receive_Frame_FSM
- Root cause:
cobs_frame_decode() receives &InputBuffer[Index + 1] as output, but receives InputBufferSize instead of InputBufferSize - (Index + 1) as output capacity.
- Existing validation only checks
(Index + 1) < InputBufferSize; it does not check that the decoded payload fits after that shifted output pointer.
- The PoC is a direct project-code harness around
src/bacnet/datalink/cobs.c that mirrors the vulnerable mstp.c call shape.
- Reachability caveat: this package proves the MS/TP COBS decode memory-corruption primitive with a local source-backed harness. It does not send BACnet traffic to a real device and does not prove RCE.
PoC
Local reproduction:
cd ~/bacnet-stack
cd .bug-hunter/github-advisory-pocs/BUG-09-mstp-cobs-overflow
./build.sh
./run.sh
cat output.log
cat asan.log
size_t encoded_len = cobs_frame_encode(
arena,
INPUT_SIZE,
payload,
sizeof(payload));
size_t decode_offset = encoded_len;
size_t actual_remaining_capacity = INPUT_SIZE - decode_offset;
/*
* Vulnerable shape:
* output pointer = arena + decode_offset
* capacity passed = full INPUT_SIZE
*
* Correct capacity should be:
* INPUT_SIZE - decode_offset
*/
size_t decoded_len = cobs_frame_decode(
&arena[decode_offset],
INPUT_SIZE,
arena,
encoded_len);
Expected result:
output.log shows actual_remaining_capacity=498, incorrect_capacity_passed=1507, and expected_overflow_bytes=502.
input_buffer_size=1507
encoded_len=1009
decode_offset=1009
actual_remaining_capacity=498
incorrect_capacity_passed=1507
decoded_payload_size=1000
expected_overflow_bytes=502
asan.log shows AddressSanitizer: heap-buffer-overflow in cobs_decode().
ERROR: AddressSanitizer: heap-buffer-overflow
WRITE of size 1
SUMMARY: AddressSanitizer: heap-buffer-overflow ... cobs_decode
Impact
- Vulnerability class: out-of-bounds write.
- Attacker prerequisites: ability to deliver a crafted BACnet MS/TP COBS frame to a stack instance that uses this receive path.
- Affected deployment context: BACnet MS/TP datalink deployments with COBS frame types enabled.
- Proven impact from PoC: local sanitizer-confirmed heap out-of-bounds write.
- Reachability caveat: this package proves the parser/datalink decode primitive locally. It does not prove code execution.
Suggested Fix
Pass the true remaining output capacity to cobs_frame_decode(), or decode into a separate buffer whose full capacity matches the value passed to the decoder.
Remediation
Remediated by resolving buffer overflow in COBS frame decoding as suggested and added unit test for tight buffer handling in PR #1425.
Summary
The BACnet MS/TP receive path decodes COBS frames into an output pointer inside the same fixed input buffer, but passes the full input-buffer size as the decode capacity. A long valid COBS payload can therefore write past the end of the actual remaining buffer.
Details
src/bacnet/datalink/mstp.cMSTP_Receive_Frame_FSMcobs_frame_decode()receives&InputBuffer[Index + 1]as output, but receivesInputBufferSizeinstead ofInputBufferSize - (Index + 1)as output capacity.(Index + 1) < InputBufferSize; it does not check that the decoded payload fits after that shifted output pointer.src/bacnet/datalink/cobs.cthat mirrors the vulnerablemstp.ccall shape.PoC
Local reproduction:
Expected result:
output.logshowsactual_remaining_capacity=498,incorrect_capacity_passed=1507, andexpected_overflow_bytes=502.asan.logshowsAddressSanitizer: heap-buffer-overflowincobs_decode().Impact
Suggested Fix
Pass the true remaining output capacity to
cobs_frame_decode(), or decode into a separate buffer whose full capacity matches the value passed to the decoder.Remediation
Remediated by resolving buffer overflow in COBS frame decoding as suggested and added unit test for tight buffer handling in PR #1425.