Skip to content

[SECURITY] Heap over-read via untrusted CCSDS length in TO_LAB sendto #952

@0rbitingZer0

Description

@0rbitingZer0

Checklist (Please check before submitting)

  • I reviewed the Contributing Guide.
  • I performed a cursory search to see if the bug report is relevant, not redundant, nor in conflict with other tickets.

Describe the bug
TO_LAB's TO_LAB_EncodeOutputMessage() reads the message size from the CCSDS packet header via CFE_MSG_GetSize() and passes it directly as the send length to OS_SocketSendTo() without validating it against the actual Software Bus buffer allocation. A message with an inflated CCSDS Length field causes adjacent heap memory to be read and transmitted over UDP.

An attacker with the ability to inject a crafted message onto the Software Bus (for example, via CI_LAB UDP command ingress in a lab configuration) can set a small payload but an inflated CCSDS length, causing TO_LAB to transmit heap memory beyond the actual buffer boundary over the telemetry UDP stream.

To Reproduce

  1. Build cFS Draco with AddressSanitizer enabled
  2. Start cFS with CI_LAB and TO_LAB
  3. Send a UDP packet to CI_LAB with a valid CCSDS header but the Length field claiming 512 bytes for a 16-byte actual payload
  4. TO_LAB reads 512 bytes from the 16-byte buffer and transmits the adjacent 496 bytes of heap memory over UDP
  5. ASan confirms heap-buffer-overflow READ at the exact point where sendto() reads past the buffer

Proof-of-concept source and ASan output are available upon request.

Expected behavior
The encode function should validate that the CCSDS-derived message size does not exceed the actual buffer allocation before passing it to sendto(). At minimum, the size should be clamped to CFE_MISSION_SB_MAX_SB_MSG_SIZE.

Code snips
apps/to_lab/fsw/src/to_lab_passthru_encode.c (lines 46-49):

CFE_MSG_Size_t SourceBufferSize;
ResultStatus = CFE_MSG_GetSize(&SourceBuffer->Msg, &SourceBufferSize);
*DestBufferOut = SourceBuffer;
*DestSizeOut   = SourceBufferSize;  // TRUSTS CCSDS HEADER, NO BOUNDS CHECK

CFE_MSG_GetSize() computes size purely from CCSDS header:

*Size = (MsgPtr->CCSDS.Pri.Length[0] << 8) + MsgPtr->CCSDS.Pri.Length[1] + 7;

Caller in apps/to_lab/fsw/src/to_lab_app.c (lines 313-322):

OsStatus = OS_SocketSendTo(TO_LAB_Global.TLMsockid, NetBufPtr, NetBufSize, &d_addr);

Note: This is a downstream symptom of a systemic root cause where CFE_SB_TransmitMsg itself trusts the CCSDS header size for its memcpy. Fixing the root cause at the SB API level would remediate this and similar findings across the framework.

System observed on:

  • Hardware: x86_64
  • OS: Linux (Ubuntu 22.04, with ASan)
  • Versions: cFS Draco release, commit 83c735e; TO_LAB passthru encode path

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions