If you are reading this blog post via a 3rd party source it is very likely that many parts of it will not render correctly (usually, the interactive graphs). Please view the post on dogesec.com for the full interactive viewing experience.

tl;dr

Despite countless frameworks, best practices, blog posts… so many developers still hardcode credentials into their code.

Key Findings

  • 37,439 CVEs were published between October 2023 through September 2024
  • 35,346 CWEs were assigned to those CVEs (520 unique CWEs in total)
  • CWE-79 Improper Neutralization of Input During Web Page Generation (‘Cross-site Scripting’) was the most reported weakness (in 6,006 of the CVEs, 17% of all CWEs)
  • Basic weaknesses like, CWE-532: Insertion of Sensitive Information into Log File (247 CVEs, 0.7%), CWE-798: Use of Hard-coded Credentials (213 CVEs, 0.6%), and CWE-306: Missing Authentication for Critical Function (208 CVEs, 0.6%) were also high up the list.

Overview

Many of those on the vendor side of cyber-security will often joke that insecure software keeps the majority of the industry in business.

There is some truth in that statement. We couldn’t expect perfect software and there needs to be checks in place by the industry (including responsible disclosure).

In a previous post I looked at some interesting data points about CVEs over the course of the last 25 years. This time around I wanted to take a look at some of the common weakness categories for published vulnerabilities over the last year (October 2023 through September 2024).

Follow along

If you’d like to follow along with the searches used in this post, follow the instructions described in that previous post to import the data.

Once you’ve done that, there’s one final stix2arango command you need to run;

python3 utilities/arango_cti_processor/insert_archive_cwe.py \
  --versions 4_15 \
  --database cti_knowledge_base_store

Analysis

An overview of the data

RETURN LENGTH(
  FOR doc IN nvd_cve_vertex_collection
    FILTER doc.type == "vulnerability"
    FILTER DATE_TIMESTAMP(doc.created) >= DATE_TIMESTAMP("2023-10-01T00:00:00Z")
    FILTER DATE_TIMESTAMP(doc.created) <= DATE_TIMESTAMP("2024-09-30T00:00:00Z")
    RETURN doc
)
[
  37439
]

In total, 37,439 CVEs were published over this period.

RETURN (
  FOR doc IN nvd_cve_vertex_collection
    FILTER doc.type == "vulnerability"
    FILTER DATE_TIMESTAMP(doc.created) >= DATE_TIMESTAMP("2023-10-01T00:00:00Z")
    FILTER DATE_TIMESTAMP(doc.created) <= DATE_TIMESTAMP("2024-09-30T00:00:00Z")
    COLLECT monthYear = CONCAT(DATE_YEAR(doc.created), "-", 
                               (DATE_MONTH(doc.created) < 10 ? "0" : ""), 
                               DATE_MONTH(doc.created)) WITH COUNT INTO count
    SORT monthYear
    RETURN {
      monthYear: monthYear,
      count: count
    }
)

Vulnerabilities by month Oct 2023 - Sept 2024

Most common weaknesses

When considering the following numbers keep in mind that not all CVEs have CWEs assigned. Sometimes it is because NVD are yet to analyse the CVE (and that’s a common problem given the NVDs backlog). Also some CVEs are assigned NVD-CWE-noinfo which means the NVD had insufficient information when analysing the CVE to assign a CWE.

For those that do have CWEs assigned;

// Step 1: Build a lookup table for CWE IDs and names from `mitre_cwe_vertex_collection`
LET cwe_lookup = (
  FOR cwe_doc IN mitre_cwe_vertex_collection
    FILTER TO_BOOL(cwe_doc.external_references)
    FOR cwe_ref IN cwe_doc.external_references
      FILTER cwe_ref.source_name == "cwe"
      RETURN { cwe_id: cwe_ref.external_id, name: cwe_doc.name }
)

// Step 2: Use the lookup table to map CWE names to IDs in `nvd_cve_vertex_collection`
FOR doc IN nvd_cve_vertex_collection
  FILTER doc.type == "vulnerability"
  FILTER DATE_TIMESTAMP(doc.created) >= DATE_TIMESTAMP("2023-10-01T00:00:00Z")
  FILTER DATE_TIMESTAMP(doc.created) <= DATE_TIMESTAMP("2024-09-30T00:00:00Z")
  FILTER TO_BOOL(doc.external_references)

  // Extract and match CWE IDs using the lookup table
  FOR ref IN doc.external_references
    FILTER ref.source_name == "cwe"
    LET current_cwe_id = ref.external_id
    
    // Get the CWE name from the lookup table
    LET cwe_name = FIRST(FOR cwe IN cwe_lookup FILTER cwe.cwe_id == current_cwe_id RETURN cwe.name)
    
    COLLECT cwe_id = current_cwe_id, name = cwe_name WITH COUNT INTO count
    FILTER cwe_id != "NVD-CWE-noinfo"  // Exclude "NVD-CWE-noinfo"
    SORT count DESC
    RETURN {
      cwe_id: cwe_id,
      name: name,
      count: count
    }

A total of 35,346 CWEs were assigned to those CVEs.

Weaknesses found in vulnerabilities Oct 2023 - Sept 2024

Here are the top 40;

cwe_id name count
CWE-79 Improper Neutralization of Input During Web Page Generation (‘Cross-site Scripting’) 6006
CWE-89 Improper Neutralization of Special Elements used in an SQL Command (‘SQL Injection’) 2644
CWE-352 Cross-Site Request Forgery (CSRF) 1615
CWE-787 Out-of-bounds Write 1491
CWE-862 Missing Authorization 1091
CWE-22 Improper Limitation of a Pathname to a Restricted Directory (‘Path Traversal’) 1028
CWE-416 Use After Free 1013
CWE-125 Out-of-bounds Read 902
CWE-121 Stack-based Buffer Overflow 857
CWE-78 Improper Neutralization of Special Elements used in an OS Command (‘OS Command Injection’) 845
CWE-200 Exposure of Sensitive Information to an Unauthorized Actor 775
CWE-20 Improper Input Validation 768
CWE-434 Unrestricted Upload of File with Dangerous Type 719
CWE-284 Improper Access Control 660
CWE-120 Buffer Copy without Checking Size of Input (‘Classic Buffer Overflow’) 615
CWE-476 NULL Pointer Dereference 584
CWE-94 Improper Control of Generation of Code (‘Code Injection’) 569
CWE-269 Improper Privilege Management 499
CWE-77 Improper Neutralization of Special Elements used in a Command (‘Command Injection’) 494
CWE-400 Uncontrolled Resource Consumption 441
CWE-122 Heap-based Buffer Overflow 426
CWE-918 Server-Side Request Forgery (SSRF) 408
CWE-287 Improper Authentication 405
CWE-502 Deserialization of Untrusted Data 384
CWE-190 Integer Overflow or Wraparound 312
CWE-863 Incorrect Authorization 297
CWE-119 Improper Restriction of Operations within the Bounds of a Memory Buffer 283
CWE-639 Authorization Bypass Through User-Controlled Key 250
CWE-532 Insertion of Sensitive Information into Log File 247
CWE-798 Use of Hard-coded Credentials 213
CWE-306 Missing Authentication for Critical Function 208
CWE-601 URL Redirection to Untrusted Site (‘Open Redirect’) 205
CWE-427 Uncontrolled Search Path Element 198
CWE-770 Allocation of Resources Without Limits or Throttling 184
CWE-276 Incorrect Default Permissions 174
CWE-401 Missing Release of Memory after Effective Lifetime 165
CWE-74 Improper Neutralization of Special Elements in Output Used by a Downstream Component (‘Injection’) 153
CWE-362 Concurrent Execution using Shared Resource with Improper Synchronization (‘Race Condition’) 148
CWE-732 Incorrect Permission Assignment for Critical Resource 135
CWE-59 Improper Link Resolution Before File Access (‘Link Following’) 133

There are some basic software development errors listed here.

The top two entries, XSS (Cross-Site Scripting) (CWE-79) and SQL injection (CWE-89), are fundamental to web application security and are always covered as part of basic development best practices. Both are common attack vectors and are often included in secure development guidelines like OWASP’s top security risks.

Outside of the top 20 more basic software development exist too;

  1. CWE-532: Insertion of Sensitive Information into Log File (247 CVEs)
  2. CWE-798: Use of Hard-coded Credentials (213 CVEs)
  3. CWE-306: Missing Authentication for Critical Function (208 CVEs)

I can use a CWE ID to retreive the products that have shipped with these weaknesses. Here I use CWE-798 (Use of Hard-coded Credentials).

// Step 1: Collect all vulnerability IDs with CWE-798 within the specified date range
LET vulnerability_ids_with_cwe_798 = (
  FOR vuln_doc IN nvd_cve_vertex_collection
    FILTER vuln_doc.type == "vulnerability"
    FILTER TO_BOOL(vuln_doc.external_references)
    FILTER DATE_TIMESTAMP(vuln_doc.created) >= DATE_TIMESTAMP("2023-10-01T00:00:00Z")
    FILTER DATE_TIMESTAMP(vuln_doc.created) <= DATE_TIMESTAMP("2024-09-30T00:00:00Z")
    
    // Check for vulnerabilities with CWE-798
    FOR ref IN vuln_doc.external_references
      FILTER ref.source_name == "cwe"
      FILTER ref.external_id == "CWE-798"
      RETURN vuln_doc.id  // Collect vulnerability ID directly
)

// Step 2: Collect unique vendor/product pairs from each indicator
LET all_unique_vulnerable_criteria = (
  FOR vuln_id IN vulnerability_ids_with_cwe_798
    // Replace "vulnerability--" with "indicator--" to get the corresponding indicator ID
    LET indicator_id = CONCAT("indicator--", SPLIT(vuln_id, "--")[1])
    
    // Retrieve the indicator document
    FOR indicator_doc IN nvd_cve_vertex_collection
      FILTER indicator_doc.id == indicator_id
      
      // Deduplicate vendor/product pairs within each indicator
      LET unique_criteria = UNIQUE(
        FOR vuln IN indicator_doc.x_cpes.vulnerable
          LET parts = SPLIT(vuln.criteria, ":")
          RETURN {
            vendor: parts[3],
            product: parts[4]
          }
      )
      
      // Return deduplicated vendor/product pairs for this indicator
      FOR criteria IN unique_criteria
        RETURN criteria
)

// Step 3: Count occurrences of each unique vendor/product pair across all indicators
FOR criteria IN all_unique_vulnerable_criteria
  COLLECT vendor = criteria.vendor, product = criteria.product WITH COUNT INTO count
  SORT count DESC
  RETURN {
    vendor: vendor,
    product: product,
    count: count
  }
vendor product count of CVEs with CWE-798
hitron_systems dvr_hvr-4781_firmware 6
boschrexroth ctrlx_hmi_web_panel_wr2115_firmware 4
ibm security_verify_governance 4
boschrexroth ctrlx_hmi_web_panel_wr2110_firmware 4
bosch nexo-os 4
boschrexroth ctrlx_hmi_web_panel_wr2107_firmware 4
hongdian h8951-4g-esp_firmware 3
sierrawireless aleos 3
autel maxicharger_ac_elite_business_c50_firmware 2
fedirtsapana simple_http_server_plus 2
enbw senec_storage_box_firmware 2
zohocorp manageengine_ddi_central 2
dell e-lab_navigator 2
skoda-auto superb_3_firmware 2
kiloview p1_firmware 2
cisco emergency_responder 2
machinesense feverwarn_firmware 2
estomed simple_care 2
ibm merge_efilm_workstation 2
csharp cws_collaborative_development_platform 2

The count shows distinct CVEs that reference CWE-798 and have the product shown as vulnerable.

The main takeaway from the above table is that this happens to big and small vendors alike (see CISCO and IBM), and also more-often in firmware (which is often harder to mitigate the issue of leaked credentials in).


Vulmatch

Straightforward vulnerability management. Know when software you use is vulnerable, how it is being exploited, and how to detect an attack.

Vulmatch. Straightforward vulnerability management.

Discuss this post

Head on over to the DOGESEC community to discuss this post.

DOGESEC community

Posted by:

David Greenwood

David Greenwood, Do Only Good Everyday



Never miss an update


Sign up to receive new articles in your inbox as they published.

Your subscription could not be saved. Please try again.
Your subscription has been successful.