java-topology/whitepaper/outreach/suricata.md
russell@unturf.com 6784cdf1cf feat: add 39 outreach docs (batches 6-8)
Batch 6 (9): dolibarr, jitsi-videobridge, zed, tryton, suricata,
  strawberry, zulip, zesarux, zephyr
Batch 7 (15): xonotic (4), xash3d (3), xenia, xtuple, zabbix (2),
  zathura, zebra, yabause, zephyr-0001
Batch 8 (15): woodpecker (2), wine (4), widelands (3), wesnoth (3),
  wekan (3)

Mix of CWE-407 and CWE-312.
2026-04-14 17:06:28 -04:00

5.6 KiB

Suricata IDS/IPS — CWE-407 + CWE-312 Disclosure Brief

2026-04-13 · Patches available — awaiting upstream merge

Finding

Three defects in Suricata across the HTTP JSON logger and threshold configuration parser. One CWE-312 credential logging defect and two CWE-407 algorithmic complexity defects. All patched. Patches ready for upstream review. The credential defect fires on every HTTP transaction logged; the complexity defects fire at startup and on every HTTP header output.

The Defects

suricata-0001a (PATCHED — HIGH, CWE-312): src/output-json-http.c:310

// When dump-all-headers is enabled, credential-bearing headers
// (Authorization, Proxy-Authorization, Cookie, Set-Cookie) are
// logged verbatim to eve.json
SCJbSetString(js, "value", value);  // no credential filtering

When Suricata's dump-all-headers option activates (common in forensic and SOC deployments), HTTP headers log verbatim to eve.json. This includes Authorization (Bearer tokens, Basic auth), Proxy-Authorization, Cookie (session tokens), and Set-Cookie headers. Every HTTP transaction through Suricata writes credentials to disk in cleartext.

suricata-0001b (PATCHED — MEDIUM, CWE-407): src/util-threshold-config.c:984

// SigFindSignatureBySidGid() does O(S) linear scan per threshold line
// Total: O(T * S) at startup

SCThresholdConfParseFile() processes T threshold configuration lines, each calling SigFindSignatureBySidGid() which performs a linear scan of the full signature list (S signatures). With S=30,000 sigs and T=1,000 threshold lines, startup cost reaches 30,000,000 comparisons.

suricata-0002 (PATCHED — MEDIUM, CWE-407): src/output-json-http.c:322

// Inner loop iterates all HTTP_FIELD_SIZE=53 fields per header
for (HttpField f = HTTP_FIELD_ACCEPT; f < HTTP_FIELD_SIZE; f++) {
    if ((http_ctx->fields & (1ULL << f)) != 0) {
        if (bstr_cmp_c_nocase(htp_header_name(h), http_fields[f].htp_field)) {

When custom HTTP fields activate (not dump-all-headers), each header in each transaction scans all 53 possible HTTP field types. With H headers per transaction and T transactions per second, this costs O(H53T) per second. Most deployments enable only 1-5 custom fields.

Complexity Proof

suricata-0001b: At S=30,000 signatures, T=1,000 threshold lines:

  • Defective: 1,000 * 30,000 = 30,000,000 comparisons at startup
  • Fixed: 30,000 hash insertions + 1,000 hash lookups = 31,000 operations
  • ~1,000x startup speedup.

suricata-0002: At H=20 headers, E=3 enabled fields:

  • Defective: 20 * 53 = 1,060 comparisons per transaction
  • Fixed: 20 * 3 = 60 comparisons per transaction
  • ~18x per-transaction speedup.

Impact

Suricata protects critical infrastructure worldwide as the dominant open-source IDS/IPS/NSM engine. Deployed by ISPs, government agencies, SOCs, and enterprise security teams.

suricata-0001a directly exposes credentials in eve.json logs. SOC teams routinely enable dump-all-headers for incident investigation. Every Authorization header (Bearer tokens, API keys, Basic auth credentials) and every session Cookie passes through Suricata and lands in plaintext in log files, SIEM backends, and Elasticsearch indices. An attacker with read access to Suricata logs gains session tokens for every monitored HTTP service.

The complexity defects (suricata-0001b, suricata-0002) affect startup time and per-transaction logging overhead respectively.

The Fix

suricata-0001a: Add a credential denylist and redact matching header values:

// Before
SCJbSetString(js, "value", value);

// After
static const char * const credential_headers[] = {
    "authorization", "proxy-authorization", "cookie", "set-cookie", NULL,
};
bool is_credential = false;
for (int ci = 0; credential_headers[ci] != NULL; ci++) {
    if (strcasecmp(name, credential_headers[ci]) == 0) {
        is_credential = true;
        break;
    }
}
if (is_credential) {
    SCJbSetString(js, "value", "[REDACTED]");
} else {
    SCJbSetString(js, "value", value);
}

suricata-0001b: Build a hash table of (sid, gid) at parse start for O(1) lookup:

// Build once: O(S) hash table from de_ctx->sig_list
// Lookup per threshold line: O(1) instead of O(S)

suricata-0002: Precompute enabled field names at config time, scan only those at runtime:

// Before: scan all 53 fields per header
for (HttpField f = HTTP_FIELD_ACCEPT; f < HTTP_FIELD_SIZE; f++) { ... }

// After: scan only E enabled fields per header
for (uint32_t ei = 0; ei < http_ctx->enabled_htp_fields_cnt; ei++) { ... }

Patch

Fixes available:

  • defects/suricata-0001/patch/suricata-0001.patch (CWE-312 credential redaction)
  • defects/suricata-0001/patch/suricata-0001-threshold-sig-lookup-hashmap.patch (CWE-407 threshold parser)
  • defects/suricata-0002/patch/suricata-0002.patch (CWE-407 HTTP field scan)

Three-location patch across output-json-http.c and util-threshold-config.c. CWE-312: credential headers redacted in eve.json. CWE-407 threshold: ~1,000x startup speedup. CWE-407 HTTP fields: ~18x per-transaction speedup.

What We Ask

Patches ready for review.

  1. Confirm receipt and assign a Redmine issue reference (redmine.openinfosecfoundation.org).
  2. Assess severity — suricata-0001a exposes credentials in eve.json on every HTTP transaction when dump-all-headers activates.
  3. Coordinate a disclosure date — we target 90 days from first contact.
  4. We will credit the OISF/Suricata team in the public disclosure. Preferred acknowledgment format welcome.

Contact: see cover email. This brief is confidential until coordinated disclosure.