Posted by:

David Greenwood

David Greenwood, Chief of Signal

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. Please view the post on signalscorps.com for the full interactive viewing experience.

In this post I will show you how to analyse CPE combinations reported in CVEs to identify vulnerable products.

Note: Vulmatch is an ever evolving product therefore the concepts described in this post might not always be relevant for the latest version.

My last post talked about how the Vulmatch UI also allows users to select configurations of software, e.g. Apple Quicktime v7.71.80.42 running on Apple MacOS v12.0.1.

This is because CVEs contain Known Affected Software Configurations (inside the configurations section of the CVE API responses) that define combinations of CPEs required to make a product vulnerable.

For example, Apple Quicktime v7.71.80.42 running on Apple MacOS v12.0.1 might be vulnerable, but Apple Quicktime v7.71.80.42 running on Apple MacOS v11.0.1 might not be vulnerable.

Known Affected Software Configurations patterns (built from nodes) define these combinations.

If you browsed the NVD CVE website you would have seen the section in each CVE titled Known Affected Software Configurations. It looks like this;

Known Affected Software Configurations example

These configurations can be found in the responses using the NVD CVE API (introduced in the previous post).

For example;

GET https://services.nvd.nist.gov/rest/json/cve/1.0/CVE-2020-9952?apiKey=

The response contains "cve"."configurations"."nodes" consisting of cpe_match, children and operator fields.

Let me explain the cpe_match nested values first using the response from the last request;

"nodes": [
    {
        "operator": "OR",
        "children": [],
        "cpe_match": [
                {
                    "vulnerable": true,
                    "cpe23Uri": "cpe:2.3:o:apple:ipad_os:*:*:*:*:*:*:*:*",
                    "versionEndExcluding": "14.0",
                    "cpe_name": []
                },

The cpe_match always contains a cpe23Uri. Even very old CVEs return the URI in 2.3 format (the latest version of the CPE dictionary) – MITRE and NVD keep CVEs up-to-date when the CPE dictionary version evolves.

There are 4 four properties that can be, but not required, used describe the version ranges of the product;

  • versionStartIncluding
  • versionStartExcluding
  • versionEndIncluding
  • versionEndExcluding

These values, should they be used, will be present in the cpe_match object.

It is possible to use a combination of StartX and EndX pairs in the same cpe_match. For example,

GET https://services.nvd.nist.gov/rest/json/cve/1.0/CVE-2020-3878?apiKey=
"cpe_match": [
    {
        "vulnerable": true,
        "cpe23Uri": "cpe:2.3:a:apple:icloud:*:*:*:*:*:windows:*:*",
        "versionStartIncluding": "11.0",
        "versionEndExcluding": "11.4",
        "cpe_name": []
    },

This response snippet alone (ignoring anything else in the response) is saying; the version of Apple iCloud (running on target software Windows) is vulnerable from versions starting 11.0 up to the version before 11.4.

To help solve this ambiguity as to exact versions, passing the argument addOns=dictionaryCpes in your request provides more information about the CPE versions (also available via the CPE API covered later in this post). As shown in the previous post, this parameter is used when backfilling and updating CVE records in Vulmatch.

Take the first example above, it states "versionEndExcluding": "14.0". Though it does not state all the versions that actually exist for the Apple Ipad OS that are vulnerable (I just know all of them before 14)

GET https://services.nvd.nist.gov/rest/json/cve/1.0/CVE-2020-3878?apiKey=&addOns=dictionaryCpes
{
  "vulnerable": true,
  "cpe23Uri": "cpe:2.3:a:apple:icloud:*:*:*:*:*:windows:*:*",
  "versionStartIncluding": "11.0",
  "versionEndExcluding": "11.2",
  "cpe_name": [
    {
      "cpe23Uri": "cpe:2.3:a:apple:icloud:11.0:*:*:*:*:windows:*:*",
      "lastModifiedDate": "2020-08-17T13:59Z"
    },
    {
      "cpe23Uri": "cpe:2.3:a:apple:icloud:11.1:*:*:*:*:windows:*:*",
      "lastModifiedDate": "2021-03-18T18:09Z"
    }
  ]
},

Now I can see the exact versions affected are 11.0 and 11.1.

Finally, you will also notice a vulnerable field under cpe_match. Sometimes this field can be falsemeaning the product in question is not vulnerable to this CVE.

It is very important to note, if this field is true it does not necessarily mean if you are using that product that it can be exploited either.

This is because a configuration container not only defines the products affected, but also relationships between products that can cause a vulnerability.

For example (not a real one), Google Chrome 103.0.5060.114 might be vulnerable running on Apple MacOS 12.0.0 but not Apple MacOS 11.0.0.

Each node has either an OR or an AND operator value (and in rare cases a NEGATEflag) to convey the logical relationship of the CPE or child nodes within. For example, if the vulnerability exists only when both CPE products are present, the operator is AND. If the vulnerability exists if either CPE is present, then the operator is OR. Though the use of nodes and operators can create more complex relationships.

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 URI 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 URIs 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.

Let me illustrate with some real examples.

1. Basic 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

CVE-2022-29098 Known Affected Software Configurations

GET https://services.nvd.nist.gov/rest/json/cve/1.0/CVE-2022-29098?apiKey=&addOns=dictionaryCpes

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

"configurations": {
  "CVE_data_version": "4.0",
    "nodes": [
      {
      "operator": "OR",
      "children": [],
      "cpe_match": [
        {
        "vulnerable": true,
        "cpe23Uri": "cpe:2.3:a:dell:powerscale_onefs:9.0.0:*:*:*:*:*:*:*",
        "cpe_name": [
          {
            "cpe23Uri": "cpe:2.3:a:dell:powerscale_onefs:9.0.0:*:*:*:*:*:*:*",
            "lastModifiedDate": "2022-06-27T18:02Z"
          }
          ]
        },
        {
          "vulnerable": true,
          "cpe23Uri": "cpe:2.3:a:dell:powerscale_onefs:9.1.0:*:*:*:*:*:*:*",
          "cpe_name": [
            {
              "cpe23Uri": "cpe:2.3:a:dell:powerscale_onefs:9.1.0:*:*:*:*:*:*:*",
              "lastModifiedDate": "2022-06-27T18:02Z"
            }
            ]
          },
          ...
          {
            "vulnerable": true,
            "cpe23Uri": "cpe:2.3:a:dell:powerscale_onefs:9.1.1:*:*:*:*:*:*:*",
            "cpe_name": [
              {
                "cpe23Uri": "cpe:2.3:a:dell:powerscale_onefs:9.1.1:*:*:*:*:*:*:*",
                "lastModifiedDate": "2022-06-27T18:02Z"
              }
              ]
            }
          ]
        }
      ]
    },

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

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

Basic configurations only consider individual products (and not combinations) so all CPEs are "vulnerable": true.

In this case, the 6 configurations variations that lead to matches (note, the third, forth, and fifth nodes are omitted in the snippet above);

  1. Dell PowerScale OneFS (version 9.0.0) (application) [application vulnerable to CVE] OR,
  2. Dell PowerScale OneFS (version 9.1.0) (application) [application vulnerable to CVE] OR,
  3. Dell PowerScale OneFS (version 9.1.1) (application) [application vulnerable to CVE] OR,
  4. Dell PowerScale OneFS (version 9.2.0) (application) [application vulnerable to CVE] OR,
  5. Dell PowerScale OneFS (version 9.2.1) (application) [application vulnerable to CVE] OR,
  6. Dell PowerScale OneFS (version 9.3.0) (application) [application vulnerable to CVE]

Note, matching considers the lowest nested cpe23Uri field values (where the version number is explicitly defined, if present). In this example the lowest nested cpe23Uri is always the value for; nodes.cpe_match.cpe_name.cpe23Uri. Keep this in mind when reviewing the next example.

2. Running On/With

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 a node 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 Known Affected Software Configurations

GET https://services.nvd.nist.gov/rest/json/cve/1.0/CVE-2022-27948?apiKey=&addOns=dictionaryCpes
"nodes": [
    {
        "operator": "AND",
        "children": [
            {
                "operator": "OR",
                "children": [],
                "cpe_match": [
                    {
                        "vulnerable": true,
                        "cpe23Uri": "cpe:2.3:o:tesla:model_s_firmware:*:*:*:*:*:*:*:*",
                        "versionEndIncluding": "2022-03-26",
                        "cpe_name": []
                    },
                    {
                        "vulnerable": true,
                        "cpe23Uri": "cpe:2.3:o:tesla:model_x_firmware:*:*:*:*:*:*:*:*",
                        "versionEndIncluding": "2022-03-26",
                        "cpe_name": [
                                {
                                    "cpe23Uri": "cpe:2.3:o:tesla:model_x_firmware:-:*:*:*:*:*:*:*",
                                    "lastModifiedDate": "2021-06-30T18:26Z"
                                },
                                {
                                    "cpe23Uri": "cpe:2.3:o:tesla:model_x_firmware:2020-11-23:*:*:*:*:*:*:*",
                                    "lastModifiedDate": "2021-06-30T18:26Z"
                                }
                        ]
                    },
                    {
                        "vulnerable": true,
                        "cpe23Uri": "cpe:2.3:o:tesla:model_3_firmware:*:*:*:*:*:*:*:*",
                        "versionEndIncluding": "2022-03-26",
                        "cpe_name": [
                            {
                                "cpe23Uri": "cpe:2.3:o:tesla:model_3_firmware:-:*:*:*:*:*:*:*",
                                "lastModifiedDate": "2020-08-26T22:42Z"
                            }
                        ]
                    }
                ]
            },
            {
                "operator": "OR",
                "children": [],
                "cpe_match": [
                    {
                        "vulnerable": false,
                        "cpe23Uri": "cpe:2.3:h:tesla:model_3:-:*:*:*:*:*:*:*",
                        "cpe_name": [
                          {
                              "cpe23Uri": "cpe:2.3:h:tesla:model_3:-:*:*:*:*:*:*:*",
                              "lastModifiedDate": "2020-08-26T22:42Z"
                          }
                        ]
                    },
                    {
                        "vulnerable": false,
                        "cpe23Uri": "cpe:2.3:h:tesla:model_x:-:*:*:*:*:*:*:*",
                        "cpe_name": [
                          {
                              "cpe23Uri": "cpe:2.3:h:tesla:model_x:-:*:*:*:*:*:*:*",
                              "lastModifiedDate": "2021-08-17T17:09Z"
                          }
                        ]
                    },
                    {
                        "vulnerable": false,
                        "cpe23Uri": "cpe:2.3:h:tesla:model_s:-:*:*:*:*:*:*:*",
                        "cpe_name": []
                    }
                ]
            }
        ],
        "cpe_match": []

Again we have a single node but this time notice how this time the top level cpe_match field is empty. The actual CPE match logic is moved to the children field (because a comparison expression between the children cpe_matches is required). You can see multiple cpe_match objects nested in the children object.

The top level operator here is AND. This is defining how the two cpe_match objects inside the children element of this node should be considered. In this case one or more entries in the first cpe_match payload AND one or more entries in the second cpe_match payload must exist.

The first cpe_match contains only operating system (o) CPEs. The second cpe_match contains only hardware (h) CPEs. Logically, it is saying any entry from the first node AND any entry from the second node will create a match.

Another important note before reviewing the logic in this example, note how in the first cpe_match value, the first children.cpe_name object is empty;

{
  "vulnerable": true,
  "cpe23Uri": "cpe:2.3:o:tesla:model_s_firmware:*:*:*:*:*:*:*:*",
  "versionEndIncluding": "2022-03-26",
  "cpe_name": []
},

I will explain more about why this happens in part 4, however for now it is important that you remember that matching considers the lowest nested cpe23Uri field values. In the snippet above that is; nodes.cpe_match.cpe23Uri. Be careful, in this example different cpe23Uris are considered at different levels.

The versionEndIncluding property, or any versionX property for that matter, is ignored by Vulmatch.

Written out, here are here are the 12 configurations variations that lead to matches defined in this CVE;

  1. Tesla Model 3 (hardware) (version unspecified -) AND Tesla Model S (firmware) (any specified or unspecified version *) [firmware vulnerable to CVE], OR,
  2. Tesla Model 3 (hardware) (version unspecified -) AND Tesla Model X (firmware) (version unspecified -) [firmware vulnerable to CVE], OR,
  3. Tesla Model 3 (hardware) (version unspecified -) AND Tesla Model X (firmware) (version 2020-11-23) [firmware vulnerable to CVE], OR,
  4. Tesla Model 3 (hardware) (version unspecified -) AND Tesla Model 3 (firmware) (version unspecified -) [firmware vulnerable to CVE], OR,
  5. Tesla Model X (hardware) (version unspecified -) AND Tesla Model S (firmware) (any specified or unspecified version *) [firmware vulnerable to CVE], OR,
  6. Tesla Model X (hardware) (version unspecified -) AND Tesla Model X (firmware) (version unspecified -) [firmware vulnerable to CVE], OR,
  7. Tesla Model X (hardware) (version unspecified -) AND running Tesla Model X (firmware) (version 2020-11-23) [firmware vulnerable to CVE], OR,
  8. Tesla Model X (hardware) (version unspecified -) AND running Tesla Model 3 (firmware) (version unspecified -) [firmware vulnerable to CVE], OR,
  9. Tesla Model S (hardware) (version unspecified -) AND running Tesla Model S (firmware) (any specified or unspecified version *) [firmware vulnerable to CVE], OR,
  10. Tesla Model S (hardware) (version unspecified -) AND running Tesla Model X (firmware) (version unspecified -) [firmware vulnerable to CVE], OR,
  11. Tesla Model S (hardware) (version unspecified -) AND running Tesla Model X (firmware) (version 2020-11-23) [firmware vulnerable to CVE], OR,
  12. Tesla Model S (hardware) (version unspecified -) AND running Tesla Model 3 (firmware) (version unspecified -) [firmware vulnerable to CVE]

Note, if a field contains only a hyphen - it essentially means undefined (e.g. an undefined version). Whereas a * denotes any value exists for version (any version number, including undefined). Undefined (-) is often used to capture the top level of a product.

For example, cpe:2.3:h:apple:macbook_pro:-:*:*:*:*:*:*:* only returns one result, an undefined Apple MacBook Pro CPE. Whereas cpe:2.3:h:apple:macbook_pro:*:*:*:*:*:*:*:* will returns all 31 versioned Apple MacBook Pro products (and the one undefined version).

I wanted to include this CVE as an example of the variance in how nodes can be written by NVD. This configuration assumes that Tesla Model S Firmware could be running on Tesla Model 3 hardware, which is not normal.

The node matches should probably read Tesla Model Firmware running on Tesla Model , e.g. Tesla Model 3 Firmware running on Tesla Model 3. This would give 7 potential CPE match combinations.

Either way exact matches can be problematic for this reason, but more on that in part 3.

3. Advanced

The operators and structure in the previous configuration types are no different in advanced configurations. It is just the complexity of the nodes and number of nodes that makes NVD describe them as advanced.

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

CVE-2019-18939 Known Affected Software Configurations

GET https://services.nvd.nist.gov/rest/json/cve/1.0/CVE-2019-18939?apiKey=&addOns=dictionaryCpes

This response actually has 4 nodes, I am showing the first two nodes in the response below;

"nodes": [
  {
    "operator": "AND",
    "children": [],
    "cpe_match": [
      {
        "vulnerable": false,
        "cpe23Uri": "cpe:2.3:h:eq-3:homematic_ccu2:-:*:*:*:*:*:*:*",
          "cpe_name": [
            {
              "cpe23Uri": "cpe:2.3:h:eq-3:homematic_ccu2:-:*:*:*:*:*:*:*",
              "lastModifiedDate": "2020-04-10T16:04Z"
            }
          ]
      },
      {
        "vulnerable": true,
        "cpe23Uri": "cpe:2.3:o:eq-3:homematic_ccu2_firmware:2.47.20:*:*:*:*:*:*:*",
          "cpe_name": [
            {
              "cpe23Uri": "cpe:2.3:o:eq-3:homematic_ccu2_firmware:2.47.20:*:*:*:*:*:*:*",
              "lastModifiedDate": "2020-04-10T19:19Z"
            }
          ]
        },
        {
          "vulnerable": true,
          "cpe23Uri": "cpe:2.3:a:hm-print_project:hm-print:1.2a:*:*:*:*:*:*:*",
          "cpe_name": [
            {
              "cpe23Uri": "cpe:2.3:a:hm-print_project:hm-print:1.2a:*:*:*:*:*:*:*",
              "lastModifiedDate": "2020-04-10T19:19Z"
            }
          ]
        }
      ]
    },
    {
      "operator": "AND",
      "children": [],
      "cpe_match": [
        {
          "vulnerable": false,
          "cpe23Uri": "cpe:2.3:h:eq-3:homematic_ccu3:-:*:*:*:*:*:*:*",
          "cpe_name": [
            {
              "cpe23Uri": "cpe:2.3:h:eq-3:homematic_ccu3:-:*:*:*:*:*:*:*",
              "lastModifiedDate": "2020-04-10T16:04Z"
            }
          ]
        },
        {
          "vulnerable": true,
          "cpe23Uri": "cpe:2.3:o:eq-3:homematic_ccu3_firmware:3.47.18:*:*:*:*:*:*:*",
          "cpe_name": [
            {
              "cpe23Uri": "cpe:2.3:o:eq-3:homematic_ccu3_firmware:3.47.18:*:*:*:*:*:*:*",
              "lastModifiedDate": "2020-04-10T19:31Z"
            }
          ]
        },
        {
          "vulnerable": true,
          "cpe23Uri": "cpe:2.3:a:hm-print_project:hm-print:1.2:*:*:*:*:*:*:*",
          "cpe_name": [
            {
              "cpe23Uri": "cpe:2.3:a:hm-print_project:hm-print:1.2:*:*:*:*:*:*:*",
              "lastModifiedDate": "2020-04-10T19:19Z"
            }
          ]
        }
      ]
    },
    ...

In this example, each of the 4 nodes is distinct, there are no children elements inside a node (although this is possible too, like the previous Running On/With example).

Each element inside a node is considered with an AND statement. Each node is considered with an OR statement. Essentially these are 4 distinct combinations of the the product. If one of the four is running, it cause a vulnerability in some of them.

All 4 possible distinct match configurations for this CVE can be written like so (note, the final 2 nodes are omitted in the snippet above):

  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 vulnerable to CVE], 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 vulnerable to CVE], 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 vulnerable to CVE], 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 vulnerable to CVE]

Next time: User CPE configurations and Vulmatch logic

Now I have shown how node configurations are structured and how to read them logically, the next step is understanding how Vulmatch users create their own configurations and have these matched to the CVE CPE configurations shown in this post.

See you in two weeks for where I will explain all.




Our brand new Discord!

Like this blog?

Sign up to receive new posts in your inbox.


Stixify

Stixify. Extract machine readable intelligence from unstructured data.

Extract machine readable intelligence from unstructured data.

Obstracts

Obstracts

Turn any blog into structured threat intelligence.


Vulmatch

Vulmatch

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

SIEM Rules

SIEM Rules. Your detection engineering database.

View, modify, and deploy SIEM rules for threat hunting.