जमा करें #888018: NASA cFS 7.0.1 Integer Underflowजानकारी

शीर्षकNASA cFS 7.0.1 Integer Underflow
विवरण# CFE-SB-USERDATALEN-UNDERFLOW ## Summary `CFE_SB_GetUserDataLength()` returns `TotalMsgSize - HdrSize` without checking that the CCSDS-declared total message size is at least as large as the cFE Software Bus header size. A CCSDS command with a secondary header present and a declared size of 7 bytes can produce an 8-byte command-header size, causing unsigned underflow to a huge `size_t` user-data length. This is a safe source-chain/model package only. It does not transmit packets, inject Software Bus traffic, or provide exploitation logic. ## Target - Product: NASA cFS/cFE - Version checked: cFS `v7.0.1`, cFE `v7.0.1` - Component: cFE Software Bus (`CFE_SB`) - Primary file: `src/cFS/cfe/modules/sb/fsw/src/cfe_sb_util.c` - Public-history anchor: cFS/cFE `CFE_SB` has public CVE history through `CVE-2026-5475`. ## Source Chain - `src/cFS/cfe/modules/msg/fsw/src/cfe_msg_ccsdspri.c:379` computes total packet size from the CCSDS length field plus `CFE_MSG_SIZE_OFFSET`. - `src/cFS/cfe/modules/sb/fsw/src/cfe_sb_msg_id_util.c:92` returns `sizeof(CFE_MSG_CommandHeader_t)` for command packets with secondary headers. - `src/cFS/cfe/modules/sb/fsw/src/cfe_sb_util.c:77` reads `TotalMsgSize` from the packet header. - `src/cFS/cfe/modules/sb/fsw/src/cfe_sb_util.c:78` derives `HdrSize`. - `src/cFS/cfe/modules/sb/fsw/src/cfe_sb_util.c:80` returns `TotalMsgSize - HdrSize` without a lower-bound check. - `src/cFS/cfe/modules/msg/fsw/src/cfe_msg_sechdr_checksum.c:44` computes checksum over the CCSDS-declared length, so a short declared command can be checksum-valid under the same length rule. - `src/cFS/cfe/modules/msg/fsw/src/cfe_msg_integrity.c:73` default verification accepts messages unless mission-specific verification is added. ## Safe PoC Result The PoC constructs a structured CCSDS command model: - Primary Header: command type, secondary-header-present bit, APID `1`, standalone sequence, length field `0`. - Secondary Header: function-code byte chosen so the cFS XOR checksum over the declared 7 bytes is valid; checksum byte exists in the local buffer but is not included by the declared length. - Declared total size: `7`. - Modeled command header size: `8`. - 64-bit result: `7 - 8 -> 18446744073709551615`. - 32-bit result: `7 - 8 -> 4294967295`. Evidence JSON: `analysis/reports/rce_lpe/cfe_sb_userdatalen_underflow_20260615.json`. ## Impact If an application or downstream handler calls `CFE_SB_GetUserDataLength()` on such a malformed short command and uses the returned value for copy/parse bounds, it can turn a small malformed message into a huge trusted length. This is most directly a memory-safety primitive or denial-of-service risk in consumers of the public API. ## Caveats - This package does not show unauthenticated RCE, LPE, or a complete exploit chain. - Default cFE command dispatch may reject many specific command handlers through exact expected-length checks. - The finding is strongest as a public API safety issue in a CVE-history component, not as a proven standalone mission compromise. ## Suggested Fix - In `CFE_SB_GetUserDataLength()`, return `0` or an error-compatible sentinel if `CFE_MSG_GetSize()` fails, `HdrSize == 0`, or `TotalMsgSize < HdrSize`. - In `CFE_SB_SetUserDataLength()`, check `DataLength > CFE_MISSION_SB_MAX_SB_MSG_SIZE - HdrSize` before addition. - Consider enforcing a minimum message size in default verification for command/telemetry packets with secondary headers. ### poc.py ``` #!/usr/bin/env python3 """ Safe model for CAND-CFE-SB-USERDATALEN-UNDERFLOW. This script does not transmit packets, inject Software Bus traffic, or exploit a target. It verifies the original cFS/cFE source anchors and models the arithmetic in CFE_SB_GetUserDataLength() for a CCSDS command whose declared packet size is smaller than the cFE command header size. """ from __future__ import annotations import argparse import json from datetime import datetime, timezone from pathlib import Path CANDIDATE = "CAND-CFE-SB-USERDATALEN-UNDERFLOW" CFE_MSG_SIZE_OFFSET = 7 CFE_MSG_COMMAND_HEADER_SIZE = 8 CFE_MISSION_SB_MAX_SB_MSG_SIZE = 32768 def find_line(source: str, needle: str) -> int: for index, line in enumerate(source.splitlines(), start=1): if needle in line: return index return -1 def find_line_after(source: str, anchor: str, needle: str) -> int: lines = source.splitlines() start_index = 0 for index, line in enumerate(lines): if anchor in line: start_index = index break for index, line in enumerate(lines[start_index:], start=start_index + 1): if needle in line: return index return -1 def cfs_checksum(packet: bytes, declared_size: int) -> int: checksum = 0xFF for value in packet[:declared_size]: checksum ^= value return checksum & 0xFF def build_checksum_valid_short_command() -> dict[str, object]: packet = bytearray(CFE_MSG_COMMAND_HEADER_SIZE) # CCSDS primary header, big endian: # version=0, type=command, secondary-header-present=1, APID=1 packet[0] = 0x18 packet[1] = 0x01 # Sequence flags=standalone, sequence count=0 packet[2] = 0xC0 packet[3] = 0x00 # CCSDS length field = 0 => CFE_MSG_GetSize() reports 7 bytes. packet[4] = 0x00 packet[5] = 0x00 declared_size = CFE_MSG_SIZE_OFFSET # Command secondary header starts at byte 6. Because checksum computation is # driven by the declared size, a 7-byte command includes the function-code # byte but not the checksum byte. Choose the function code so the cFS XOR # checksum over the declared bytes is already valid. fcn_code = 0xFF for value in packet[:6]: fcn_code ^= value packet[6] = fcn_code & 0xFF packet[7] = 0x00 return { "packet_hex": packet.hex(), "declared_size": declared_size, "actual_buffer_size": len(packet), "function_code_for_valid_declared_checksum": packet[6], "checksum_over_declared_size": cfs_checksum(packet, declared_size), "checksum_valid_under_cfe_rule": cfs_checksum(packet, declared_size) == 0, } def model_get_user_data_length(total_msg_size: int, header_size: int, bits: int) -> int: mask = (1 << bits) - 1 return (total_msg_size - header_size) & mask def model_set_user_data_length(data_length: int, header_size: int, bits: int) -> dict[str, object]: mask = (1 << bits) - 1 total = (header_size + data_length) & mask return { "data_length": data_length, "wrapped_total_msg_size": total, "passes_max_msg_size_check": total <= CFE_MISSION_SB_MAX_SB_MSG_SIZE, "would_call_CFE_MSG_SetSize": CFE_MSG_SIZE_OFFSET <= total <= (0xFFFF + CFE_MSG_SIZE_OFFSET), } def main() -> int: parser = argparse.ArgumentParser() parser.add_argument("--workspace-root", default=".", help="Workspace root containing src/cFS") parser.add_argument( "--output", default="analysis/reports/rce_lpe/cfe_sb_userdatalen_underflow_20260615.json", ) parser.add_argument( "--log", default="submission_packages/CAND-CFE-SB-USERDATALEN-UNDERFLOW/crash_evidence.log", ) parser.add_argument("--expect-crash", action="store_true", help="Return success only if the marker condition is present") args = parser.parse_args() root = Path(args.workspace_root) sb_util_path = root / "src" / "cFS" / "cfe" / "modules" / "sb" / "fsw" / "src" / "cfe_sb_util.c" sb_hdr_path = root / "src" / "cFS" / "cfe" / "modules" / "sb" / "fsw" / "src" / "cfe_sb_msg_id_util.c" msg_size_path = root / "src" / "cFS" / "cfe" / "modules" / "msg" / "fsw" / "src" / "cfe_msg_ccsdspri.c" checksum_path = root / "src" / "cFS" / "cfe" / "modules" / "msg" / "fsw" / "src" / "cfe_msg_sechdr_checksum.c" integrity_path = root / "src" / "cFS" / "cfe" / "modules" / "msg" / "fsw" / "src" / "cfe_msg_integrity.c" sb_util = sb_util_path.read_text(encoding="utf-8", errors="replace") sb_hdr = sb_hdr_path.read_text(encoding="utf-8", errors="replace") msg_size = msg_size_path.read_text(encoding="utf-8", errors="replace") checksum_source = checksum_path.read_text(encoding="utf-8", errors="replace") integrity_source = integrity_path.read_text(encoding="utf-8", errors="replace") anchors = { "get_user_data_length_function": find_line(sb_util, "size_t CFE_SB_GetUserDataLength"), "get_size_call": find_line_after( sb_util, "size_t CFE_SB_GetUserDataLength", "CFE_MSG_GetSize(MsgPtr, &TotalMsgSize);", ), "header_size_call": find_line_after( sb_util, "size_t CFE_SB_GetUserDataLength", "HdrSize = CFE_SB_MsgHdrSize(MsgPtr);", ), "unchecked_subtract": find_line_after( sb_util, "size_t CFE_SB_GetUserDataLength", "return TotalMsgSize - HdrSize;", ), "set_user_data_lengt ```
स्रोत⚠️ https://github.com/nasa/cFS
उपयोगकर्ता
 juntheworld (UID 99760)
सबमिशन13/07/2026 04:11 PM (2 महीनों पहले)
संयम29/08/2026 04:40 PM (2 months later)
स्थितिस्वीकृत
VulDB प्रविष्टि397030 [NASA cFS तक 7.0.1 cFE Software Bus cfe_sb_util.c CFE_SB_GetUserDataLength TotalMsgSize/HdrSize बफ़र ओवरफ़्लो]
अंक19

Do you need the next level of professionalism?

Upgrade your account now!