Project

General

Profile

Security #8624

Updated by Jason Ish about 18 hours ago

Original report 

 <pre> 
 Hello Suricata Security Team 
 I am writing to report a NULL pointer dereference vulnerability in Suricata 8.0.5 that causes the IDS/IPS process to crash (SIGSEGV) during startup or rule reload when loading JSON/NDJSON dataset enrichment files. 

   ───────────────────────────────────────────────────────────────────────────── 
   SUMMARY 
   ───────────────────────────────────────────────────────────────────────────── 
 Component : src/datasets-context-json.c 
 Affected    : Suricata 8.0.5 (latest release at time of writing) 
 CWE         : CWE-476 (NULL Pointer Dereference) 
 Severity    : Medium 
 Impact      : Crash of the Suricata process; denial of detection/prevention 
 Attack surface: Local JSON/NDJSON enrichment feed files or rule/intel feed 
 update pipelines (no network traffic required) 
  ───────────────────────────────────────────────────────────────────────────── 
  ROOT CAUSE 
 ───────────────────────────────────────────────────────────────────────────── 
  
 When loading a dataset with format json or ndjson, the four functions below call json_string_value() to retrieve the string for the value_key field of each JSON object. Jansson's json_string_value()    returns NULL when the node is not of JSON string type (e.g. integer, boolean, null, array, or object). The returned pointer is passed directly to strlen(), inet_pton(), or DatasetParseIpv6String() 
   without a NULL check, causing a NULL pointer dereference and process crash. 
   Affected functions and lines (src/datasets-context-json.c): 
   Line 470 – DatajsonAddMd5Element 
     const char *hash_string = json_string_value(key); 
     if (strlen(hash_string) != SC_MD5_HEX_LEN) { ... }     // NULL dereference 

   Line 514 – DatajsonAddSha256Element 
     const char *hash_string = json_string_value(key); 
     if (strlen(hash_string) != SC_SHA256_HEX_LEN) { ... } // NULL dereference 

   Line 559 – DatajsonAddIpv4Element 
     const char *ip_string = json_string_value(key); 
     if (inet_pton(AF_INET, ip_string, &in) != 1) { ... }    // NULL dereference 

   Line 599 – DatajsonAddIPv6Element 
     const char *ip_string = json_string_value(key); 
     int ret = DatasetParseIpv6String(set, ip_string, &in6); // NULL dereference 

   For the IPv4/IPv6 path, the crash occurs inside DatasetParseIpv6String() (src/datasets.c:159) where strchr(line, ':') is called with a NULL pointer: 

   int DatasetParseIpv6String(Dataset *set, const char *line, struct in6_addr *in6) 
   { 
       const char *got_colon = strchr(line, ':');    // crashes when line == NULL 

   ───────────────────────────────────────────────────────────────────────────── 
   PROOF OF CONCEPT 
   ───────────────────────────────────────────────────────────────────────────── 

   The crash is triggered by loading a syntactically valid NDJSON file where the field referenced by value_key holds a non-string JSON value. No special privileges or network access are required — only 
   the ability to influence the local enrichment file (e.g. via a threat-intel feed update pipeline). 
   Four crash cases were confirmed on Suricata 8.0.5 (with debug symbols): 
   Case 1: md5 dataset, value_key is a JSON integer 
   NDJSON file: 
   {"md5_value": 12345, "extra": "context"} 
   Suricata rule: 
   alert dns any any -> any any ( 
     msg:"poc md5"; dns.query; 
     dataset:isset,test_md5,type md5, 
       load bad_md5.ndjson, format ndjson, 
       value_key md5_value, context_key extra; 
     sid:1001; rev:1;) 
   Crash stack (sig 11): 
   DatajsonAddMd5Element+0x58 
   DatajsonLoadTypeFromJsonline → DatajsonGet → DetectDatasetSetup 
   SigParse → SigLoadSignatures → SuricataInit → main 
  
   Case 2: sha256 dataset, value_key is a JSON boolean 
   NDJSON file: 
   {"sha256_value": true, "extra": "context"} 
   Suricata rule: 
   alert dns any any -> any any ( 
     msg:"poc sha256"; dns.query; 
     dataset:isset,test_sha256,type sha256, 
       load bad_sha256.ndjson, format ndjson, 
       value_key sha256_value, context_key extra; 
     sid:1002; rev:1;) 
   Crash stack (sig 11): 
   DatajsonAddSha256Element+0x58 
   DatajsonLoadTypeFromJsonline → DatajsonGet → DetectDatasetSetup ... 
  
   Case 3: ip dataset, value_key is JSON null 
   NDJSON file: 
   {"ip_value": null, "extra": "context"} 
   Suricata rule: 
   alert tcp any any -> any any ( 
     msg:"poc ip null"; flow:to_server; ip.dst; 
     dataset:isset,test_ip,type ip, 
       load bad_ipv4.ndjson, format ndjson, 
       value_key ip_value, context_key extra; 
     sid:1003; rev:1;) 
   Crash stack (sig 11): 
   DatasetParseIpv6String+0x32     ← strchr(NULL, ':') 
   DatajsonAddIPv6Element+0x5e    
   DatajsonLoadTypeFromJsonline → DatajsonGet → DetectDatasetSetup ... 
  
   Case 4: ip dataset, value_key is a JSON array 
   NDJSON file: 
   {"ip_value": [1, 2, 3], "extra": "context"} 
   Same rule structure as Case 3. Same crash path: strchr(NULL, ':') inside DatasetParseIpv6String. 
  
   All four cases were reproduced using suricata -T (config test mode), confirming the crash occurs at dataset load time before any traffic is processed. 

   ───────────────────────────────────────────────────────────────────────────── 
   SUGGESTED FIX 
   ───────────────────────────────────────────────────────────────────────────── 

   Add a NULL guard immediately after every json_string_value() call in the four affected functions: 

   const char *s = json_string_value(key); 
   if (s == NULL) { 
       FatalErrorOnInit("dataset %s: value_key '%s' is not a JSON string", 
                        set->name, json_key); 
       return 0; 
   } 
   /* proceed with strlen / inet_pton / DatasetParseIpv6String */ 

 We also recommend adding regression tests for all four dataset types (md5, sha256, ipv4, ipv6/ip) with non-string value_key values (integer, boolean, null, array, object) in both json and ndjson formats. 


 Please let me know if you need additional information, a patch, or test cases. I am happy to coordinate on a responsible disclosure timeline. 
 </pre> 

 Bug does not exist in 7 as datasets-context-json.c was introduced in 8 

 [Credits] 
 Changcheng Wu, Clouditera (https://github.com/Clouditera)

Back