nasa / nasa/cFS

[SECURITY] Missing lower-bound validation in CI_LAB_DecodeInputMessage allows zero-length packets

Open Beginner friendly
#985 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
C
Stars
1.5k
Forks
391
Avg merge
1d 11h
Merged PRs (30d)
19

Description

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

  1. 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)
  2. CI_LAB_ReadUpLink() receives the packet via OS_SocketRecvFrom()
  3. CI_LAB_DecodeInputMessage() checks MsgSize > SourceSize7 > 768false → passes validation
  4. The 7-byte buffer is cast to CFE_SB_Buffer_t * and sent to CFE_SB_TransmitBuffer()
  5. 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

  • This is a distinct vulnerability from #952 (TO_LAB heap over-read) and #953 (CFE_SB_TransmitMsg memcpy), though all share the same root cause.
  • The CI_LAB ingress path is reachable without authentication on any deployment that loads CI_LAB (default NOS3 configuration).
  • The fix is a single-line change adding MsgSize < sizeof(CFE_MSG_Message_t) || to the existing if condition.
  • Fixing this at the ingress point provides defense-in-depth, even after the SB layer is patched.

Reporter Info
Erfan, Independent Space Software Security Researcher

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in apps/ci_lab/fsw/src/ci_lab_passthru_decode.c at CI_LAB_DecodeInputMessage(), then trace its caller CI_LAB_ReadUpLink(). Reproduce the documented zero-length CCSDS packet and verify that undersized messages are rejected with CFE_STATUS_WRONG_MSG_LENGTH and are not forwarded to the Software Bus.

Written by the indexing model from the issue text.

Assessment

Tech stack
c
Domain
networking, security
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
70/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.