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_atlas.py \
  --versions 4_7_0 \
  --database blog_demo \
  --ignore_embedded_relationships

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;

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

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.