Describe the bug
CI_LAB_DecodeInputMessage() in ci_lab_passthru_decode.c validates the CCSDS MsgSize from the packet header against the received SourceSize using only an upper-bound check (MsgSize > SourceSize). There is no lower-bound validation.
An attacker can send a deliberately malformed CCSDS Space Packet with Length=0 (total MsgSize = 7 bytes, which is less than sizeof(CFE_MSG_Message_t) = 16 bytes for telemetry or 8 bytes for commands). Because 0 > 768 is false, the malformed packet passes validation with CFE_SUCCESS and is forwarded directly to the Software Bus via CFE_SB_TransmitBuffer().
This is the same root cause as:
- cFE #2697: Integer underflow in
CFE_SB_GetUserDataLength
- cFE #2698: Heap exfiltration via undersized CCSDS Length in TO_LAB
- cFE #2699: Unbounded loop in
CFE_MSG_ComputeCheckSum
All of these stem from the cFE Message layer trusting the attacker-controlled CCSDS Length field without lower-bound validation.
To Reproduce
- Send a single UDP datagram to the CI_LAB ingest port (default UDP/5012) containing only a CCSDS Primary Header:
StreamId = any valid command MsgId
Sequence = arbitrary
Length = 0x0000 (decoded total = 7 bytes)
CI_LAB_ReadUpLink() receives the packet via OS_SocketRecvFrom()
CI_LAB_DecodeInputMessage() checks MsgSize > SourceSize → 7 > 768 → false → passes validation
- The 7-byte buffer is cast to
CFE_SB_Buffer_t * and sent to CFE_SB_TransmitBuffer()
- Any subscriber that reads the message size via
CFE_MSG_GetSize() and uses it for memcpy, loop iteration, or buffer allocation will perform an out-of-bounds read or integer underflow
Expected behavior
CI_LAB_DecodeInputMessage() should validate that MsgSize >= sizeof(CFE_MSG_Header_t) (the minimum valid CCSDS Space Packet size) before accepting the packet. The check should be:
CFE_MSG_GetSize(&MsgBufPtr->Msg, &MsgSize);
if (MsgSize < sizeof(CFE_MSG_Message_t) || MsgSize > SourceSize)
{
Status = CFE_STATUS_WRONG_MSG_LENGTH;
}
else
{
Status = CFE_SUCCESS;
}
This is consistent with the fix applied in CFE_SB_MessageTxn_SetContentSize() (cFE PR #2702) which added the lower-bound check.
Code snips
File: apps/ci_lab/fsw/src/ci_lab_passthru_decode.c, lines 68-82:
CFE_MSG_GetSize(&MsgBufPtr->Msg, &MsgSize);
if (MsgSize > SourceSize) // ← Only upper bound
// ← No lower bound check!
{
Status = CFE_STATUS_WRONG_MSG_LENGTH;
CFE_EVS_SendEvent(CI_LAB_INGEST_LEN_ERR_EID, CFE_EVS_EventType_ERROR,
"CI: cmd dropped - length mismatch, ...");
}
else
{
Status = CFE_SUCCESS; // ← Attacker reaches here with MsgSize=7
}
System observed on
- Hardware: x86-64 (POSIX cFS / NOS3 simulator)
- OS: Linux 6.8.0 (Ubuntu 24.04)
- Versions: cFE v7.0.0-rc4+dev370 (bundle cFS Draco v7.0.0, commit
432c9302)
Additional context
Reporter Info
Erfan, Independent Space Software Security Researcher
Describe the bug
CI_LAB_DecodeInputMessage()inci_lab_passthru_decode.cvalidates the CCSDSMsgSizefrom the packet header against the receivedSourceSizeusing only an upper-bound check (MsgSize > SourceSize). There is no lower-bound validation.An attacker can send a deliberately malformed CCSDS Space Packet with
Length=0(totalMsgSize= 7 bytes, which is less thansizeof(CFE_MSG_Message_t)= 16 bytes for telemetry or 8 bytes for commands). Because0 > 768isfalse, the malformed packet passes validation withCFE_SUCCESSand is forwarded directly to the Software Bus viaCFE_SB_TransmitBuffer().This is the same root cause as:
CFE_SB_GetUserDataLengthCFE_MSG_ComputeCheckSumAll of these stem from the cFE Message layer trusting the attacker-controlled CCSDS Length field without lower-bound validation.
To Reproduce
StreamId= any valid command MsgIdSequence= arbitraryLength=0x0000(decoded total = 7 bytes)CI_LAB_ReadUpLink()receives the packet viaOS_SocketRecvFrom()CI_LAB_DecodeInputMessage()checksMsgSize > SourceSize→7 > 768→ false → passes validationCFE_SB_Buffer_t *and sent toCFE_SB_TransmitBuffer()CFE_MSG_GetSize()and uses it formemcpy, loop iteration, or buffer allocation will perform an out-of-bounds read or integer underflowExpected behavior
CI_LAB_DecodeInputMessage()should validate thatMsgSize >= sizeof(CFE_MSG_Header_t)(the minimum valid CCSDS Space Packet size) before accepting the packet. The check should be:This is consistent with the fix applied in
CFE_SB_MessageTxn_SetContentSize()(cFE PR #2702) which added the lower-bound check.Code snips
File:
apps/ci_lab/fsw/src/ci_lab_passthru_decode.c, lines 68-82:System observed on
432c9302)Additional context
MsgSize < sizeof(CFE_MSG_Message_t) ||to the existingifcondition.Reporter Info
Erfan, Independent Space Software Security Researcher