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

I wanted to write detection rules to identify what products are vulnerable to a CVE. In this post I walk you through my research.

An introduction CPEs

Having a standardised way of to describe products becomes very useful when managing those you’re using (for example in a software bill of materials). That is where Common Platform Enumerations (CPEs) come in;

CPE is a structured naming scheme for information technology systems, software, and packages. Based upon the generic syntax for Uniform Resource Identifiers (URI), CPE includes a formal name format, a method for checking names against a system, and a description format for binding text and tests to a name.

Source: https://nvd.nist.gov/products/cpe

CPEs were originally managed by MITRE but ownership has since been transferred to the US National Institute of Standard of Technology (NIST).

CPEs are important in this context because this is how the NVD report product combinations in CVEs.

For this exercise, the CPE match string is the important part, as these are what are reported in CVEs. CPE match strings are a computer readable format to describe the details of products. Here is how they are written;

cpe:2.3:<part>:<vendor>:<product>:
<version>:<update>:<edition>:<language>:<sw_edition>:<target_sw:>:<target_hw>:<other>

Where;

  • cpe: always cpe
  • 2.3: the CPE spec version (latest version is 2.3)
  • <part>: The part attribute SHALL have one of these three string values:
    • a for applications,
    • o for operating systems,
    • h for hardware devices
  • <vendor>: described or identifies the person or organisation that manufactured or created the product
  • <product>: describes or identifies the most common and recognisable title or name of the product
  • <version>: vendor-specific alphanumeric strings characterising the particular release version of the product
  • <update>: vendor-specific alphanumeric strings characterising the particular update, service pack, or point release of the product.
  • <edition> assigned the logical value ANY (*) except where required for backward compatibility with version 2.2 of the CPE specification
  • <language>: valid language tags as defined by [RFC5646]
  • <sw_edition>: characterises how the product is tailored to a particular market or class of end users.
  • <target_sw>: characterises the software computing environment within which the product operates.
  • <target_hw>: characterises the instruction set architecture (e.g., x86) on which the product being described or identified operates
  • <other>: capture any other general descriptive or identifying information which is vendor- or product-specific and which does not logically fit in any other attribute value

Here is an example of a CPE match string (for Apple Quicktime v7.71.80.42);

cpe:2.3:a:apple:quicktime:7.71.80.42:*:*:*:*:*:*:*

Where;

  • part: a (application)
  • vendor: apple
  • product: quicktime
  • version: 7.71.80.42
  • update: *
  • edition: *
  • language: *
  • sw_edition: *
  • target_sw: *
  • target_hw: *
  • other: *

Where an unquoted * is a wildcard, and means any value. For example any language value that exists (e.g. en, fr, etc.) would match the above string. It can also be passed at the beginning or the end of a string (e.g. quick* would match quicktime).

It is also possible to use unquoted question marks too (e.g. bar?, bar??), where the ? translates to a single-character wild card. So bar? would match bart but not barts, and bar?? would match barts but not bart.

You will also see a single - character in some properties. This means no specified value exists. For example, if it is in the version property, it means no version is ever defined for the product by the vendor.

Finally, you will also see escape characters (\) in the match string. These should exist where there is any printed non-alphanumeric character. Here, cpe:2.3:a:apple:swiftnio_http\/2:1.19.1:*:*:*:*:swift:*:*, a backslash \ escape the forward slash / present in the version string.

A word of warning, if consuming data via the NVD API you might see double backslashes to account for JSON escapes (e.g. cpe:2.3:a:apple:swiftnio_http\\/2:1.19.1:*:*:*:*:swift:*:*).

CPE match strings are referenced in CVEs to define what products, and/or combination of products are vulnerable to the CVE.

An introduction CVEs

The mission of the CVE® Program is to identify, define, and catalog publicly disclosed cybersecurity vulnerabilities. There is one CVE Record for each vulnerability in the catalog. The vulnerabilities are discovered then assigned and published by organizations from around the world that have partnered with the CVE Program. Partners publish CVE Records to communicate consistent descriptions of vulnerabilities. Information technology and cybersecurity professionals use CVE Records to ensure they are discussing the same issue, and to coordinate their efforts to prioritize and address the vulnerabilities.

Source: https://www.cve.org/About/Overview

In January 1999, the MITRE Corporation published “Towards a Common Enumeration of Vulnerabilities”.

The aim; to identify, define, and catalog publicly disclosed cybersecurity vulnerabilities.

Very soon after this meeting, the original 321 Common Vulnerabilities and Exposures (CVE) Entries, including entries from previous years, was created and the CVE List was officially launched to the public in September 1999.

Each CVE has a unique ID. In its first iteration, 9,999 CVEs were allowed per year because CVE IDs were assigned using the format CVE-YYYY-NNNN (CVE-2001-1473). Currently, tens-of-thousands of CVEs are reported a year. To account for this explosion of CVEs, the CVE ID syntax was extended by adding one more digit to the N potion from four to five digits to CVE-YYYY-NNNNN in 2015 (some now have up to 7 digits, e.g. CVE-2019-1010218).

The NVD is tasked with analysing each CVE once it has been published to the CVE List using the reference information provided with the CVE and any publicly available information at the time of analysis to associate tags, CVSS scores, CWEs, and CPE match statements. The full process is described here.

You can browse the NVD CVE database here to see examples of the data the NVD team include with each CVE. In this post I am interested in what NVD title Known Affected Software Configorations.

An example of a Known Affected Software Configoration for CVE-2019-1010218, above.

CVE API

The NVD website is populated by the same data you can retrieve from the CVE and CPE APIs.

Here is an example request to the CVE API:

GET https://services.nvd.nist.gov/rest/json/cves/2.0?cveId=CVE-2019-1010218

Which prints all the information about the CVE;

{
    "resultsPerPage": 1,
    "startIndex": 0,
    "totalResults": 1,
    "format": "NVD_CVE",
    "version": "2.0",
    "timestamp": "2023-01-08T14:10:27.753",
    "vulnerabilities": [
        {
            "cve": {
                "id": "CVE-2019-1010218",
                "sourceIdentifier": "[email protected]",
                "published": "2019-07-22T18:15:10.917",
                "lastModified": "2020-09-30T13:40:18.163",
                "vulnStatus": "Analyzed",
                "descriptions": [
                    {
                        "lang": "en",
                        "value": "Cherokee Webserver Latest Cherokee Web server Upto Version 1.2.103 (Current stable) is affected by: Buffer Overflow - CWE-120. The impact is: Crash. The component is: Main cherokee command. The attack vector is: Overwrite argv[0] to an insane length with execl. The fixed version is: There's no fix yet."
                    },
                    {
                        "lang": "es",
                        "value": "El servidor web de Cherokee más reciente de Cherokee Webserver Hasta Versión 1.2.103 (estable actual) está afectado por: Desbordamiento de Búfer - CWE-120. El impacto es: Bloqueo. El componente es: Comando cherokee principal. El vector de ataque es: Sobrescribir argv[0] en una longitud no sana con execl. La versión corregida es: no hay ninguna solución aún."
                    }
                ],
                "metrics": {
                    "cvssMetricV31": [
                        {
                            "source": "[email protected]",
                            "type": "Primary",
                            "cvssData": {
                                "version": "3.1",
                                "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
                                "attackVector": "NETWORK",
                                "attackComplexity": "LOW",
                                "privilegesRequired": "NONE",
                                "userInteraction": "NONE",
                                "scope": "UNCHANGED",
                                "confidentialityImpact": "NONE",
                                "integrityImpact": "NONE",
                                "availabilityImpact": "HIGH",
                                "baseScore": 7.5,
                                "baseSeverity": "HIGH"
                            },
                            "exploitabilityScore": 3.9,
                            "impactScore": 3.6
                        }
                    ],
                    "cvssMetricV2": [
                        {
                            "source": "[email protected]",
                            "type": "Primary",
                            "cvssData": {
                                "version": "2.0",
                                "vectorString": "AV:N/AC:L/Au:N/C:N/I:N/A:P",
                                "accessVector": "NETWORK",
                                "accessComplexity": "LOW",
                                "authentication": "NONE",
                                "confidentialityImpact": "NONE",
                                "integrityImpact": "NONE",
                                "availabilityImpact": "PARTIAL",
                                "baseScore": 5.0
                            },
                            "baseSeverity": "MEDIUM",
                            "exploitabilityScore": 10.0,
                            "impactScore": 2.9,
                            "acInsufInfo": false,
                            "obtainAllPrivilege": false,
                            "obtainUserPrivilege": false,
                            "obtainOtherPrivilege": false,
                            "userInteractionRequired": false
                        }
                    ]
                },
                "weaknesses": [
                    {
                        "source": "[email protected]",
                        "type": "Primary",
                        "description": [
                            {
                                "lang": "en",
                                "value": "CWE-787"
                            }
                        ]
                    },
                    {
                        "source": "[email protected]",
                        "type": "Secondary",
                        "description": [
                            {
                                "lang": "en",
                                "value": "CWE-120"
                            }
                        ]
                    }
                ],
                "configurations": [
                    {
                        "nodes": [
                            {
                                "operator": "OR",
                                "negate": false,
                                "cpeMatch": [
                                    {
                                        "vulnerable": true,
                                        "criteria": "cpe:2.3:a:cherokee-project:cherokee_web_server:*:*:*:*:*:*:*:*",
                                        "versionEndIncluding": "1.2.103",
                                        "matchCriteriaId": "DCE1E311-F9E5-4752-9F51-D5DA78B7BBFA"
                                    }
                                ]
                            }
                        ]
                    }
                ],
                "references": [
                    {
                        "url": "https://i.imgur.com/PWCCyir.png",
                        "source": "[email protected]",
                        "tags": [
                            "Exploit",
                            "Third Party Advisory"
                        ]
                    }
                ]
            }
        }
    ]
}

The full CVE API response schema for reference.

The configurations section holds the information I need to create the Known Affected Software Configoration… but not all!

Above you can see a configurations.nodes.cpeMatch object.

The nested property criteria contains a CPE match string to capture all CPEs that should be considered for this node (remember the use of wildcards * could refer to numerous versions, languages, etc.).

In addition to the CPE match string (criteria) there are 4 four properties that can be, but not required, used describe the version ranges of the product;

  • versionStartIncluding
  • versionStartExcluding
  • versionEndIncluding
  • versionEndExcluding

Above it is "versionEndIncluding": "1.2.103", meaning all versions up until 1.2.103 match to this string.

Although even with this information, I still don’t have named variations of the product that are affected.

To get all affected variations covered by the CPE match string, you will need to use the CPE Match API.

This is where the matchCriteriaId property comes in (here DCE1E311-F9E5-4752-9F51-D5DA78B7BBFA),

CPE Match Criteria API

GET https://services.nvd.nist.gov/rest/json/cpematch/2.0?matchCriteriaId=DCE1E311-F9E5-4752-9F51-D5DA78B7BBFA

Returns one match;

{
    "resultsPerPage": 1,
    "startIndex": 0,
    "totalResults": 1,
    "format": "NVD_CPEMatchString",
    "version": "2.0",
    "timestamp": "2024-08-05T08:15:05.813",
    "matchStrings": [
        {
            "matchString": {
                "matchCriteriaId": "DCE1E311-F9E5-4752-9F51-D5DA78B7BBFA",
                "criteria": "cpe:2.3:a:cherokee-project:cherokee_web_server:*:*:*:*:*:*:*:*",
                "versionEndIncluding": "1.2.103",
                "lastModified": "2019-10-08T16:44:34.360",
                "cpeLastModified": "2019-10-08T16:44:34.377",
                "created": "2019-10-08T16:44:34.360",
                "status": "Active",
                "matches": [
                    {
                        "cpeName": "cpe:2.3:a:cherokee-project:cherokee_web_server:1.0.12:*:*:*:*:*:*:*",
                        "cpeNameId": "946ED27F-93AB-4447-9F04-30FEE3EAA8E7"
                    },
                    {
                        "cpeName": "cpe:2.3:a:cherokee-project:cherokee_web_server:1.0.13:*:*:*:*:*:*:*",
                        "cpeNameId": "E706BE3F-8E91-48E4-8677-C94244016A67"
                    },
                    {
                        "cpeName": "cpe:2.3:a:cherokee-project:cherokee_web_server:1.0.14:*:*:*:*:*:*:*",
                        "cpeNameId": "FB6C0C33-D9B8-45C2-BE5E-E836AA912A29"
                    },
                    {
                        "cpeName": "cpe:2.3:a:cherokee-project:cherokee_web_server:1.0.15:*:*:*:*:*:*:*",
                        "cpeNameId": "8EFC2886-764E-427B-8A8E-ADE7B848A516"
                    },
                    {
                        "cpeName": "cpe:2.3:a:cherokee-project:cherokee_web_server:1.0.16:*:*:*:*:*:*:*",
                        "cpeNameId": "6E542416-8B7A-402E-AFF7-97FEC339BC39"
                    },
                    {
                        "cpeName": "cpe:2.3:a:cherokee-project:cherokee_web_server:1.0.17:*:*:*:*:*:*:*",
                        "cpeNameId": "5C22473B-9EBD-49B6-86D6-E15538291DE6"
                    },
                    {
                        "cpeName": "cpe:2.3:a:cherokee-project:cherokee_web_server:1.0.18:*:*:*:*:*:*:*",
                        "cpeNameId": "2AF60F33-AABE-4C14-BE86-668AADDEC011"
                    },
                    {
                        "cpeName": "cpe:2.3:a:cherokee-project:cherokee_web_server:1.0.21:*:*:*:*:*:*:*",
                        "cpeNameId": "A36E8601-4E38-47E0-B91D-65B42A0A7AE8"
                    },
                    {
                        "cpeName": "cpe:2.3:a:cherokee-project:cherokee_web_server:1.2.0:*:*:*:*:*:*:*",
                        "cpeNameId": "64DCAC28-ADF7-442A-8746-2C237C877D27"
                    },
                    {
                        "cpeName": "cpe:2.3:a:cherokee-project:cherokee_web_server:1.2.2:*:*:*:*:*:*:*",
                        "cpeNameId": "59CF5F3E-5158-4116-8733-F65859CB43C3"
                    },
                    {
                        "cpeName": "cpe:2.3:a:cherokee-project:cherokee_web_server:1.2.98:*:*:*:*:*:*:*",
                        "cpeNameId": "2274D1F6-911C-45D1-8ED5-89B63DA542AD"
                    },
                    {
                        "cpeName": "cpe:2.3:a:cherokee-project:cherokee_web_server:1.2.99:*:*:*:*:*:*:*",
                        "cpeNameId": "460FA01F-61D5-4B8E-9F0E-B98159A4F980"
                    },
                    {
                        "cpeName": "cpe:2.3:a:cherokee-project:cherokee_web_server:1.2.101:*:*:*:*:*:*:*",
                        "cpeNameId": "9163CD3B-EEED-4658-8CFD-944827E2B05E"
                    },
                    {
                        "cpeName": "cpe:2.3:a:cherokee-project:cherokee_web_server:1.2.102:*:*:*:*:*:*:*",
                        "cpeNameId": "45747884-B233-4095-AA7E-012698B4C6A5"
                    },
                    {
                        "cpeName": "cpe:2.3:a:cherokee-project:cherokee_web_server:1.2.103:*:*:*:*:*:*:*",
                        "cpeNameId": "6F607266-EFB1-4737-A579-AFF23B18E5B1"
                    }
                ]
            }
        }
    ]
}

The full CPE Match response schema for reference.

The CPE criteria (in the CVE API response) showed the CPE match string; cpe:2.3:a:cherokee-project:cherokee_web_server:*:*:*:*:*:*:*:*. Using the Match Criteria API by passing the matchCriteriaId = DCE1E311-F9E5-4752-9F51-D5DA78B7BBFA shows us the complete list of valid CPE Match Strings. Put another way, all iterations of the products that match the CPE match string in the CVE response.

In this case, 15 versions of cherokee_web_server are vulnerable to CVE-2019-1010218.

However, this is one of the most simplistic examples of a CPE node configuration inside a CVE.

CVE Node Configurations

In many cases products will only be vulnerable if it is being run in a certain way, or with other products. For example, Google Chrome 103.0.5060.114 might be vulnerable running on Apple MacOS but not on Windows OS.

Similarly it might be vulnerable on Apple MacOS 12.0.0 but not Apple MacOS 12.0.1 because a patch was issued to fix the vulnerability.

NVD describe three different types of configurations;

  1. Basic: A single node containing one or more sets of match criteria. This configuration type communicates that each CPE match string that matches the match criteria is considered vulnerable.
  2. Running On/With: A combination of nodes containing both vulnerable and non-vulnerable match criteria. This configuration type communicates that CPE match strings that match the match criteria from both nodes must be present before a vulnerability applies.
  3. Advanced: A complex combination of nodes with many enumerations based on the CPE 2.3 specification. Advanced configurations are displayed with the actual nodes and node values on the vulnerability detail page instead of in a simplified form such as the Basic and Running On/With configuration types.

I appreciate this is likely confusing to begin with so let me illustrate with some real examples.

1. Basic node configurations

As the name would suggest, these are fairly simple.

CVE-2022-29098 offers a good example: https://nvd.nist.gov/vuln/detail/CVE-2022-29098

First start by reviewing the Known Affected Software Configurations section of the page. It is a useful reference in understanding how the response of the API should be read.

CVE-2022-29098 NVD site

You can see one configoration with 6 CPE match strings shown (this is what is returned by the CVE API). If you open each one up (“Show matching CPEs”) you can see the specific CPEs that match (this is the data returned by the CPE Match Criteria API).

Querying via the APIs to demonstrate…

GET https://services.nvd.nist.gov/rest/json/cves/2.0/?cveId=CVE-2022-29098

Here is what the CVE API returns (note the full response has been cut for brevity shown using ...);

{
    "resultsPerPage": 1,
    "startIndex": 0,
    "totalResults": 1,
    "format": "NVD_CVE",
    "version": "2.0",
    "timestamp": "2023-01-09T19:40:03.140",
    "vulnerabilities": [
        {
            "cve": {
                "id": "CVE-2022-29098",
                "sourceIdentifier": "[email protected]",
                "published": "2022-06-01T15:15:09.010",
                "lastModified": "2022-06-08T19:14:09.453",
                "vulnStatus": "Analyzed",
                ...
                "configurations": [
                    {
                        "nodes": [
                            {
                                "operator": "OR",
                                "negate": false,
                                "cpeMatch": [
                                    {
                                        "vulnerable": true,
                                        "criteria": "cpe:2.3:a:dell:powerscale_onefs:9.0.0:*:*:*:*:*:*:*",
                                        "matchCriteriaId": "30687628-5C7F-4BB5-B990-93703294FDF0"
                                    },
                                    {
                                        "vulnerable": true,
                                        "criteria": "cpe:2.3:a:dell:powerscale_onefs:9.1.0:*:*:*:*:*:*:*",
                                        "matchCriteriaId": "68291D44-DBE1-4923-A848-04E64288DC23"
                                    },
                                    {
                                        "vulnerable": true,
                                        "criteria": "cpe:2.3:a:dell:powerscale_onefs:9.1.1:*:*:*:*:*:*:*",
                                        "matchCriteriaId": "DCC55FA4-AD91-4DA6-B60E-A4E34DDAE95A"
                                    },
                                    {
                                        "vulnerable": true,
                                        "criteria": "cpe:2.3:a:dell:powerscale_onefs:9.2.0:*:*:*:*:*:*:*",
                                        "matchCriteriaId": "B948CD53-3D17-4230-9B77-FCE8E0E548B9"
                                    },
                                    {
                                        "vulnerable": true,
                                        "criteria": "cpe:2.3:a:dell:powerscale_onefs:9.2.1:*:*:*:*:*:*:*",
                                        "matchCriteriaId": "5AB99A1A-8DD3-4DDE-B70C-0E91D1D3B682"
                                    },
                                    {
                                        "vulnerable": true,
                                        "criteria": "cpe:2.3:a:dell:powerscale_onefs:9.3.0:*:*:*:*:*:*:*",
                                        "matchCriteriaId": "61F14753-D64C-4E8B-AA94-07E014848B4D"
                                    }
                                ]
                            }
                        ]
                    }
                ],
                ...
            }
        }
    ]
}

There is only one nodes. The operator for the entire node is OR.

Therefore each cpeMatch object in is considered with the OR statement.

Basic configurations only consider individual products (and not combinations, e.g. running on) so all CPEs are vulnerable = true (meaning the product itself is always vulnerable).

In this case, the 6 configurations variations that lead to matches (the third, forth, and fifth nodes shown below are cut from the JSON snippet above);

  1. Dell PowerScale OneFS version 9.0.0 ("matchCriteriaId": "30687628-5C7F-4BB5-B990-93703294FDF0") OR,
  2. Dell PowerScale OneFS version 9.1.0 ("matchCriteriaId": "68291D44-DBE1-4923-A848-04E64288DC23") OR,
  3. Dell PowerScale OneFS version 9.1.1 ("matchCriteriaId": "DCC55FA4-AD91-4DA6-B60E-A4E34DDAE95A") OR,
  4. Dell PowerScale OneFS (version 9.2.0) ("matchCriteriaId": "B948CD53-3D17-4230-9B77-FCE8E0E548B9") OR,
  5. Dell PowerScale OneFS (version 9.2.1) ("matchCriteriaId": "5AB99A1A-8DD3-4DDE-B70C-0E91D1D3B682") OR,
  6. Dell PowerScale OneFS (version 9.3.0) ("matchCriteriaId": "61F14753-D64C-4E8B-AA94-07E014848B4D")

In this example, each matchCriteriaId returns the same CPE match string as shown in the CVE (meaning only one product version exists for this match string), e.g. querying the Match Criteria API;

GET https://services.nvd.nist.gov/rest/json/cpematch/2.0/?matchCriteriaId=30687628-5C7F-4BB5-B990-93703294FDF0
                "matches": [
                    {
                        "cpeName": "cpe:2.3:a:dell:powerscale_onefs:9.0.0:*:*:*:*:*:*:*",
                        "cpeNameId": "2B8F2852-98F4-44E1-BBF2-6597C2481DB1"
                    }
                ]

However, keep in mind as I move on to other examples that this is not always the case (more CPEs might be returned by a matchCriteriaId).

2. Running On/With node configurations

This type of configuration is defined using a combination of products that have a relationship (Running On/With) that makes at least one of these products vulnerable.

In this example, nodes can now contain both vulnerable and non-vulnerable products.

To explain this I will use CVE-2022-27948 as a an example: https://nvd.nist.gov/vuln/detail/CVE-2022-27948

CVE-2022-27948 NVD site

If you open up each CPE match string (“Show matching CPEs”) you’ll see a list of CPEs listed.

Querying via the CVE API;

GET https://services.nvd.nist.gov/rest/json/cves/2.0/?cveId=CVE-2022-27948

Here is what the CVE API returns (note 3 nodes have been cut for brevity shown using ...);

{
    "resultsPerPage": 1,
    "startIndex": 0,
    "totalResults": 1,
    "format": "NVD_CVE",
    "version": "2.0",
    "timestamp": "2023-01-10T07:37:08.677",
    "vulnerabilities": [
        {
            "cve": {
                "id": "CVE-2022-27948",
                "sourceIdentifier": "[email protected]",
                "published": "2022-03-27T13:15:13.573",
                "lastModified": "2022-04-06T03:39:12.913",
                "vulnStatus": "Analyzed",
                ...
                "configurations": [
                    {
                        "operator": "AND",
                        "nodes": [
                            {
                                "operator": "OR",
                                "negate": false,
                                "cpeMatch": [
                                    {
                                        "vulnerable": true,
                                        "criteria": "cpe:2.3:o:tesla:model_3_firmware:*:*:*:*:*:*:*:*",
                                        "versionEndIncluding": "2022-03-26",
                                        "matchCriteriaId": "86619D7A-ACB6-489C-9C29-37C6018E5B4B"
                                    },
                                    {
                                        "vulnerable": true,
                                        "criteria": "cpe:2.3:o:tesla:model_s_firmware:*:*:*:*:*:*:*:*",
                                        "versionEndIncluding": "2022-03-26",
                                        "matchCriteriaId": "FD68704D-C711-491F-B278-B02C6866738C"
                                    },
                                    {
                                        "vulnerable": true,
                                        "criteria": "cpe:2.3:o:tesla:model_x_firmware:*:*:*:*:*:*:*:*",
                                        "versionEndIncluding": "2022-03-26",
                                        "matchCriteriaId": "C3517683-8493-4D0D-9792-5C9034B1F0B3"
                                    }
                                ]
                            },
                            {
                                "operator": "OR",
                                "negate": false,
                                "cpeMatch": [
                                    {
                                        "vulnerable": false,
                                        "criteria": "cpe:2.3:h:tesla:model_3:-:*:*:*:*:*:*:*",
                                        "matchCriteriaId": "825A79FD-C872-4564-9782-83BEEADDF5D9"
                                    },
                                    {
                                        "vulnerable": false,
                                        "criteria": "cpe:2.3:h:tesla:model_s:-:*:*:*:*:*:*:*",
                                        "matchCriteriaId": "8D28E699-B843-4641-9BA6-406D88231E7C"
                                    },
                                    {
                                        "vulnerable": false,
                                        "criteria": "cpe:2.3:h:tesla:model_x:-:*:*:*:*:*:*:*",
                                        "matchCriteriaId": "C550FF8A-58ED-4265-B33F-10AFDEA95519"
                                    }
                                ]
                            }
                        ]
                    }
                ],
                ...
            }
        }
    ]
}

Note in this response, the top nodes object has an operator property (in the previous response, an operator was only seen at the cpeMatch level). In this case its an AND

This allows for more complex Running On/With combinations where each cpeMatch within a node can be considered using this addition operator.

The top level operator in this example is AND. In total there are two cpeMatches in this nodes

Each cpeMatch itself has an OR operator, and each of these cpeMatches has three CPE match string’s within it. The first contains only Tesla operating system (o) CPEs. The second contains only Tesla hardware (h) CPEs.

Logically, it is saying any entry from the first cpeMatch AND any entry from the second cpeMatch nested in the nodes will create a match.

It’s also important to point out here that each matchCriteriaId returns more versions of the product (this is why the “Show matching CPEs” dropdown shows more versions).

Here’s an example of the response from the CPE Match Criteria API for match criteria id 86619D7A-ACB6-489C-9C29-37C6018E5B4B;

GET https://services.nvd.nist.gov/rest/json/cpematch/2.0?matchCriteriaId=86619D7A-ACB6-489C-9C29-37C6018E5B4B
                "matches": [
                    {
                        "cpeName": "cpe:2.3:o:tesla:model_3_firmware:-:*:*:*:*:*:*:*",
                        "cpeNameId": "979F9EB6-C9F6-49EE-9FED-2ED17E400E86"
                    },
                    {
                        "cpeName": "cpe:2.3:o:tesla:model_3_firmware:11.0:*:*:*:*:*:*:*",
                        "cpeNameId": "62DCA7AD-A796-486F-8FB6-DEACC078D402"
                    },
                    {
                        "cpeName": "cpe:2.3:o:tesla:model_3_firmware:2022-03-26:*:*:*:*:*:*:*",
                        "cpeNameId": "F010C8B7-83E9-45FB-A5D4-26EDF34EC312"
                    }
                ]

Here you can see this CPE match string shown in the CVE API response captures 3 products.

Looking at all six matchCriteriaIds;

  • 86619D7A-ACB6-489C-9C29-37C6018E5B4B: returns 3 CPEs (shown above) (are vulnerable)
  • FD68704D-C711-491F-B278-B02C6866738C: returns 2 CPEs (are vulnerable)
  • C3517683-8493-4D0D-9792-5C9034B1F0B3: returns 3 CPEs (are vulnerable)
  • 825A79FD-C872-4564-9782-83BEEADDF5D9: returns 1 CPEs
  • 8D28E699-B843-4641-9BA6-406D88231E7C: returns 1 CPEs
  • C550FF8A-58ED-4265-B33F-10AFDEA95519: returns 1 CPEs

In this example you also need to consider the value of the vulnerable property. You’ll see in the first node, but for all entries this is true. In the second, they’re all false.

This is essentially describing the combinations of products, and which of them are actually affected by a vulnerability when running in this way.

It’s easier to explain this by writing it all out, as there are a lot of combinations in this CVE.

  • Tesla Model 3 Firmware (86619D7A-ACB6-489C-9C29-37C6018E5B4B – 3 CPEs) AND Tesla Model 3 Hardware (825A79FD-C872-4564-9782-83BEEADDF5D9 – 1 CPE) (only firmware CPEs vulnerable) OR,
  • Tesla Model 3 Firmware (86619D7A-ACB6-489C-9C29-37C6018E5B4B – 3 CPEs) AND Tesla Model S Hardware (8D28E699-B843-4641-9BA6-406D88231E7C – 1 CPE) (only firmware CPEs vulnerable) OR,
  • Tesla Model 3 Firmware (86619D7A-ACB6-489C-9C29-37C6018E5B4B – 3 CPEs) AND Tesla Model X Hardware (C550FF8A-58ED-4265-B33F-10AFDEA95519 – 1 CPE) (only firmware CPEs vulnerable) OR,
  • Tesla Model S Firmware (FD68704D-C711-491F-B278-B02C6866738C – 2 CPEs) AND Tesla Model 3 Hardware (825A79FD-C872-4564-9782-83BEEADDF5D9 – 1 CPE) (only firmware CPEs vulnerable) OR,
  • Tesla Model S Firmware (FD68704D-C711-491F-B278-B02C6866738C – 2 CPEs) AND Tesla Model S Hardware (8D28E699-B843-4641-9BA6-406D88231E7C – 1 CPE) (only firmware CPEs vulnerable) OR,
  • Tesla Model S Firmware (FD68704D-C711-491F-B278-B02C6866738C – 2 CPEs) AND Tesla Model X Hardware (C550FF8A-58ED-4265-B33F-10AFDEA95519 – 1 CPE) (only firmware CPEs vulnerable) OR,
  • Tesla Model X Firmware (C3517683-8493-4D0D-9792-5C9034B1F0B3 – 3 CPEs) AND Tesla Model 3 Hardware (825A79FD-C872-4564-9782-83BEEADDF5D9 – 1 CPE) (only firmware CPEs vulnerable) OR,
  • Tesla Model X Firmware (C3517683-8493-4D0D-9792-5C9034B1F0B3 – 3 CPEs) AND Tesla Model S Hardware (8D28E699-B843-4641-9BA6-406D88231E7C – 1 CPE) (only firmware CPEs vulnerable) OR,
  • Tesla Model X Firmware (C3517683-8493-4D0D-9792-5C9034B1F0B3 – 3 CPEs) AND Tesla Model X Hardware (C550FF8A-58ED-4265-B33F-10AFDEA95519 – 1 CPE) (only firmware CPEs vulnerable)

In total there are 24 possible product combinations that are vulnerable in this CVE.

3. Advanced node configurations

The operators and structure in the previous configuration types are no different in advanced configurations. It is the number of nodes (aka Configurations) returned in the response that allows them to become more advanced.

To illustrate this, I will use CVE-2019-18939: https://nvd.nist.gov/vuln/detail/CVE-2019-18939

CVE-2019-18939 NVD site

Here you can see unlike the previous two examples, there are now multiple configurations.

To demonstrate, querying the CVE API;

GET https://services.nvd.nist.gov/rest/json/cves/2.0/?cveId=CVE-2019-18939

Here is what the API returns (cut for brevity shown using ...);’

{
    "resultsPerPage": 1,
    "startIndex": 0,
    "totalResults": 1,
    "format": "NVD_CVE",
    "version": "2.0",
    "timestamp": "2023-01-10T08:23:24.183",
    "vulnerabilities": [
        {
            "cve": {
                "id": "CVE-2019-18939",
                "sourceIdentifier": "[email protected]",
                "published": "2019-11-14T19:15:13.410",
                "lastModified": "2021-07-21T11:39:23.747",
                "vulnStatus": "Analyzed",
                ...
                "configurations": [
                    {
                        "nodes": [
                            {
                                "operator": "AND",
                                "negate": false,
                                "cpeMatch": [
                                    {
                                        "vulnerable": true,
                                        "criteria": "cpe:2.3:a:hm-print_project:hm-print:1.2a:*:*:*:*:*:*:*",
                                        "matchCriteriaId": "286DA904-5631-4AAF-86DE-97C23982D2C5"
                                    },
                                    {
                                        "vulnerable": false,
                                        "criteria": "cpe:2.3:h:eq-3:homematic_ccu2:-:*:*:*:*:*:*:*",
                                        "matchCriteriaId": "9C2CF19C-7EDE-4E3C-A736-E6736FF03FDC"
                                    },
                                    {
                                        "vulnerable": true,
                                        "criteria": "cpe:2.3:o:eq-3:homematic_ccu2_firmware:2.47.20:*:*:*:*:*:*:*",
                                        "matchCriteriaId": "38BE17DA-7C5E-427E-B824-151EB27CFF26"
                                    }
                                ]
                            }
                        ]
                    },
                    {
                        "nodes": [
                            {
                                "operator": "AND",
                                "negate": false,
                                "cpeMatch": [
                                    {
                                        "vulnerable": true,
                                        "criteria": "cpe:2.3:a:hm-print_project:hm-print:1.2:*:*:*:*:*:*:*",
                                        "matchCriteriaId": "F5D8290F-3541-4452-99CB-0766CDC59073"
                                    },
                                    {
                                        "vulnerable": false,
                                        "criteria": "cpe:2.3:h:eq-3:homematic_ccu3:-:*:*:*:*:*:*:*",
                                        "matchCriteriaId": "33113AD0-F378-49B2-BCFC-C57B52FD3A04"
                                    },
                                    {
                                        "vulnerable": true,
                                        "criteria": "cpe:2.3:o:eq-3:homematic_ccu3_firmware:3.47.18:*:*:*:*:*:*:*",
                                        "matchCriteriaId": "285F4E29-E299-4F83-9F7E-BB19933AD654"
                                    }
                                ]
                            }
                        ]
                    },
                    {
                        "nodes": [
                            {
                                "operator": "AND",
                                "negate": false,
                                "cpeMatch": [
                                    {
                                        "vulnerable": true,
                                        "criteria": "cpe:2.3:a:hm-print_project:hm-print:1.2a:*:*:*:*:*:*:*",
                                        "matchCriteriaId": "286DA904-5631-4AAF-86DE-97C23982D2C5"
                                    },
                                    {
                                        "vulnerable": false,
                                        "criteria": "cpe:2.3:h:eq-3:homematic_ccu3:-:*:*:*:*:*:*:*",
                                        "matchCriteriaId": "33113AD0-F378-49B2-BCFC-C57B52FD3A04"
                                    },
                                    {
                                        "vulnerable": true,
                                        "criteria": "cpe:2.3:o:eq-3:homematic_ccu3_firmware:3.47.18:*:*:*:*:*:*:*",
                                        "matchCriteriaId": "285F4E29-E299-4F83-9F7E-BB19933AD654"
                                    }
                                ]
                            }
                        ]
                    },
                    {
                        "nodes": [
                            {
                                "operator": "AND",
                                "negate": false,
                                "cpeMatch": [
                                    {
                                        "vulnerable": true,
                                        "criteria": "cpe:2.3:a:hm-print_project:hm-print:1.2:*:*:*:*:*:*:*",
                                        "matchCriteriaId": "F5D8290F-3541-4452-99CB-0766CDC59073"
                                    },
                                    {
                                        "vulnerable": false,
                                        "criteria": "cpe:2.3:h:eq-3:homematic_ccu2:-:*:*:*:*:*:*:*",
                                        "matchCriteriaId": "9C2CF19C-7EDE-4E3C-A736-E6736FF03FDC"
                                    },
                                    {
                                        "vulnerable": true,
                                        "criteria": "cpe:2.3:o:eq-3:homematic_ccu2_firmware:2.47.20:*:*:*:*:*:*:*",
                                        "matchCriteriaId": "38BE17DA-7C5E-427E-B824-151EB27CFF26"
                                    }
                                ]
                            }
                        ]
                    }
                ],
                ...
            }
        }
    ]
}

The use of multiple nodes allow for more combinations of CPEs to be included (though they’re not necessarily more “advanced”).

The response above has four separate nodes. Each is considered in isolation.

Each element inside a cpeMatch node is considered with an AND statement, as defined in the its operator field values.

Looking at the CPEs inside each matchCriteriaId (using the CPE Match API) returns a single CPE match string:

  • Node 1
    • 286DA904-5631-4AAF-86DE-97C23982D2C5: 1 CPE (are vulnerable)
    • 9C2CF19C-7EDE-4E3C-A736-E6736FF03FDC: 1 CPE
    • 38BE17DA-7C5E-427E-B824-151EB27CFF26: 1 CPE (are vulnerable)
  • Node 2
    • F5D8290F-3541-4452-99CB-0766CDC59073: 1 CPE (are vulnerable)
    • 33113AD0-F378-49B2-BCFC-C57B52FD3A04: 1 CPE
    • 285F4E29-E299-4F83-9F7E-BB19933AD654: 1 CPE (are vulnerable)
  • Node 3
    • 286DA904-5631-4AAF-86DE-97C23982D2C5: 1 CPE (are vulnerable)
    • 33113AD0-F378-49B2-BCFC-C57B52FD3A04: 1 CPE
    • 285F4E29-E299-4F83-9F7E-BB19933AD654: 1 CPE (are vulnerable)
  • Node 4
    • F5D8290F-3541-4452-99CB-0766CDC59073: 1 CPE (are vulnerable)
    • 9C2CF19C-7EDE-4E3C-A736-E6736FF03FDC: 1 CPE
    • 38BE17DA-7C5E-427E-B824-151EB27CFF26: 1 CPE (are vulnerable)

With this information, I know there are exactly 4 CPE combinations that lead to a match (one for each nodes);

  1. eQ-3 Homematic CCU2 (hardware) (version unspecified -) AND EQ-3 HomeMatic CCU2 version 2.47.20 (firmware) AND HM Print Project HM Print version 1.2a (application) (firmware and application are vulnerable), OR,
  2. eQ-3 Homematic CCU3 (hardware) (version unspecified -) AND EQ-3 HomeMatic CCU3 version 3.47.18 (firmware) AND HM Print Project HM Print version 1.2 (application) (firmware and application are vulnerable), OR,
  3. eQ-3 Homematic CCU3 (hardware) (version unspecified -) AND EQ-3 HomeMatic CCU3 version 3.47.18 (firmware) AND HM Print Project HM Print version 1.2a (application) (firmware and application are vulnerable), OR,
  4. eQ-3 Homematic CCU2 (hardware) (version unspecified -) AND EQ-3 HomeMatic CCU2 version 2.47.20 (firmware) AND HM Print Project HM Print version 1.2 (application) (firmware and application are vulnerable)

In summary

Using this logic, you can create detection patterns to identify vulnerable CPEs to a CVE.

In the next post I’ll show you how to create such a detection rules in STIX Pattern format.

Posted by:

David Greenwood

David Greenwood, Do Only Good Everyday




Discuss this post


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

DOGESEC community

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.