Re: [OE-core] Providing detailed CPE information for CVE matching capabilities

2023-08-25 Thread Jasper Orschulko via lists.openembedded.org
Hello again,

I have kept been pondering on this topic for quite some time and have
after quite some thought come to the conclusion that the mismatch in
the CPE Name Matching actually is due to a wrong interpretion of the
specification on the side of the dependencytrack maintainers and by
extension myself
(see https://github.com/DependencyTrack/dependency-track/issues/2988
for more details). So all-clear on that frontline. Sorry for the fuzz.

However, I still stand by the idea of providing more detailed CPE
information (e.g. target architecture) to avoid false positives, as
well as making openembedded-specific CVE reports possible.

Also, I believe it should be possible to gather the missing pieces of
information in an automated fashion by using a migration script for the
layers by leverage of the NIST CPE API. Using the cpeMatchString
parameter and the information we already have (product name and
version), we can attempt to guess the correct Part and Vendor
parameters:

// This might fail, if there is no CPE for current version (yet).
// However, might provide more accurate results.
if API(cpeMatchString="cpe:2.3:*:*:product_name:product_version:..."):
gather_facts_from_first_result
// If no matching CPE found:
// Reduce the product_name, which might result in less accurate results
else if API(cpeMatchString="cpe:2.3:*:*:product_name:*:..."):
gather_facts_from_first_result
// CVE unknown: Either name mismatch or no entry exists for this
product.
// Manual check required.
else:
CVE_*=unknown

This will reduce manual labor to feasibility checks, rather than
information gathering.

Leveraging the same mechanism, we could also attempt to guess the CPE_*
information when invoking the recipetool for the creation of new
recipes.

This would allow for a quick adoption and flatten out the path for
making these variables required by default, in turn improving reporting
and security for openembedded products.

Cheers, Jasper

On Fri, 2023-08-25 at 09:57 -1000, Steve Sakoman wrote:
> On Fri, Aug 25, 2023 at 9:18 AM Jasper Orschulko via
> lists.openembedded.org
>  wrote:
> > 
> > Hi Richard,
> > hi all,
> > 
> > I want to address a flaw in the current CPE generation
> > functionality in
> > openembedded, which renders the CPEs unusable in regards to the
> > minimal
> > requirements of the NIST CPE Name Matching Specification standard
> > (https://nvlpubs.nist.gov/nistpubs/Legacy/IR/nistir7696.pdf).
> > 
> > This makes working with the generated CPEs in thirdparty software
> > close
> > to impossible, as it would require the thirdparty software to
> > implement
> > matching logic beyond the requirements defined in the NIST
> > standard.
> > 
> > 
> > Status quo:
> > 
> > Currently, the CPE is generated from the optional CVE_PRODUCT
> > (optionally including the vendor) and CVE_VERSION variables. If
> > neither
> > are provided, CPE generation will fall back on the BPN and PV of
> > the
> > recipe.
> > 
> > As a result, the generated CPE will usually look as follows:
> > 
> > cpe:2.3:*:*:${BPN}:${PV}:*:*:*:*:*:*:*:*
> > 
> > Or, if the CVE_PRODUCT includes a vendor:
> > 
> > cpe:2.3:*:${vendor}:${product}:${PV}:*:*:*:*:*:*:*:*
> > 
> > 
> > 
> > The Issue (The TL;DR):
> > 
> > This will return zero¹ matches when doing CPE matching against CVE
> > CPEs
> > in accordance with the minimal requirements of the NIST Name
> > Matching
> > Specification. For reliable matches the components CPE should be as
> > precise as possible, i.e. not containing any "*" (ANY) values for
> > vital
> > attributes, such as: Part, Vendor, Product, Version, Target_HW.
> > 
> > 
> > 
> > The Issue (In detail):
> > 
> > To understand the issue in full detail, in depth knowledge of the
> > NIST
> > specification is required. However, I will try to provide a
> > comprehensive summary below:
> > 
> > CPE matching is done using a source CPE and target CPE. Due to
> > limitations (see Table 6-2, cases 4 & 11), using the CVE CPE as a
> > source and the component CPE as a target is the only sensible way
> > (otherwise a CVE CPE containing wildcards would lead to undefined
> > behavior).
> > 
> > Each attribute of the CVE CPE, will then be matched against the
> > component CPE, setting the relationship of each source attribute to
> > the
> > corresponding target attribute to either superset (⊃), equal (=),
> > subset (⊂) or disjoint (≠) (see Table 6-1, example: Table 6-3).
> > 
> > The NIST standard then defines 4 required CPE Name Comparison
> > Relations
> > (see Table 6-4), with two of them relevant for what we would
> > consider a
> > "match" between a CVE CPE and a component CPE:
> > 
> > If all attribute relations are EQUAL (=) -> Then CPE name relation
> > is
> > EQUAL (=) -> match
> > 
> > If all attribute relations are SUPERSET (⊃) or
> > EQUAL (=) -> Then CPE name relation is SUPERSET (⊃) -> match
> > 
> > Let's take a look at this, based on a real-world example:
> > 
> > CVE CPE: 

Re: [OE-core] Providing detailed CPE information for CVE matching capabilities

2023-08-25 Thread Jasper Orschulko via lists.openembedded.org
Hi Steve,

I don't think it makes much of a difference at this point. When looking
at the recipes in openembedded core (master), only a handful of recipes
provide the CVE vendor:

➜  meta git:(master) pwd
/home/jasper/git/openembedded-core/meta   
➜  meta git:(master) grep -rP 'CVE_PRODUCT\s*=\s*"\w+:\w+'
recipes-support/curl/curl_8.2.1.bb:CVE_PRODUCT = "haxx:curl
haxx:libcurl curl:curl curl:libcurl libcurl:libcurl
daniel_stenberg:curl"
recipes-support/boost/boost.inc:CVE_PRODUCT = "boost:boost"
recipes-extended/ed/ed_1.19.bb:CVE_PRODUCT = "gnu:ed"
recipes-extended/tar/tar_1.35.bb:CVE_PRODUCT = "gnu:tar"
recipes-devtools/flex/flex_2.6.4.bb:CVE_PRODUCT = "flex_project:flex"
recipes-devtools/subversion/subversion_1.14.2.bb:CVE_PRODUCT =
"apache:subversion"
recipes-connectivity/openssl/openssl_3.1.2.bb:CVE_PRODUCT =
"openssl:openssl"

Without the patch these few recipes will indeed match _some_ CVEs.

Everything other recipe is missing a vendor attribute and will
therefore not match according to the NIST specification regardless of
the provided "a" or "*".

But yes, for what it's worth it probably does not make sense to
backport the patch at the moment, since it will just replace one
erroneous behaviour with another. I only realized this after submitting
the patch, as in my use-case (integration with dependencytrack) there
were indeed more "matches" (1 CVE on Kernel vs. 300+), but after closer
inspection it turned out that was only due to an optional fuzzy
matching feature in dependencytrack and not because the results
actually improved. Sorry for the trouble.

Cheers, Jasper

On Fri, 2023-08-25 at 09:57 -1000, Steve Sakoman wrote:
> On Fri, Aug 25, 2023 at 9:18 AM Jasper Orschulko via
> lists.openembedded.org
>  wrote:
> > 
> > Hi Richard,
> > hi all,
> > 
> > I want to address a flaw in the current CPE generation
> > functionality in
> > openembedded, which renders the CPEs unusable in regards to the
> > minimal
> > requirements of the NIST CPE Name Matching Specification standard
> > (https://nvlpubs.nist.gov/nistpubs/Legacy/IR/nistir7696.pdf).
> > 
> > This makes working with the generated CPEs in thirdparty software
> > close
> > to impossible, as it would require the thirdparty software to
> > implement
> > matching logic beyond the requirements defined in the NIST
> > standard.
> > 
> > 
> > Status quo:
> > 
> > Currently, the CPE is generated from the optional CVE_PRODUCT
> > (optionally including the vendor) and CVE_VERSION variables. If
> > neither
> > are provided, CPE generation will fall back on the BPN and PV of
> > the
> > recipe.
> > 
> > As a result, the generated CPE will usually look as follows:
> > 
> > cpe:2.3:*:*:${BPN}:${PV}:*:*:*:*:*:*:*:*
> > 
> > Or, if the CVE_PRODUCT includes a vendor:
> > 
> > cpe:2.3:*:${vendor}:${product}:${PV}:*:*:*:*:*:*:*:*
> > 
> > 
> > 
> > The Issue (The TL;DR):
> > 
> > This will return zero¹ matches when doing CPE matching against CVE
> > CPEs
> > in accordance with the minimal requirements of the NIST Name
> > Matching
> > Specification. For reliable matches the components CPE should be as
> > precise as possible, i.e. not containing any "*" (ANY) values for
> > vital
> > attributes, such as: Part, Vendor, Product, Version, Target_HW.
> > 
> > 
> > 
> > The Issue (In detail):
> > 
> > To understand the issue in full detail, in depth knowledge of the
> > NIST
> > specification is required. However, I will try to provide a
> > comprehensive summary below:
> > 
> > CPE matching is done using a source CPE and target CPE. Due to
> > limitations (see Table 6-2, cases 4 & 11), using the CVE CPE as a
> > source and the component CPE as a target is the only sensible way
> > (otherwise a CVE CPE containing wildcards would lead to undefined
> > behavior).
> > 
> > Each attribute of the CVE CPE, will then be matched against the
> > component CPE, setting the relationship of each source attribute to
> > the
> > corresponding target attribute to either superset (⊃), equal (=),
> > subset (⊂) or disjoint (≠) (see Table 6-1, example: Table 6-3).
> > 
> > The NIST standard then defines 4 required CPE Name Comparison
> > Relations
> > (see Table 6-4), with two of them relevant for what we would
> > consider a
> > "match" between a CVE CPE and a component CPE:
> > 
> > If all attribute relations are EQUAL (=) -> Then CPE name relation
> > is
> > EQUAL (=) -> match
> > 
> > If all attribute relations are SUPERSET (⊃) or
> > EQUAL (=) -> Then CPE name relation is SUPERSET (⊃) -> match
> > 
> > Let's take a look at this, based on a real-world example:
> > 
> > CVE CPE: cpe:2.3:o:linux:linux_kernel:5.15.37:*:*:*:*:*:x86:*:*
> > Component CPE: cpe:2.3:*:*:linux_kernel:5.15.37:*:*:*:*:*:*:*:*
> > 
> > In this example the CVE CPE has the attributes "Part" ("o"),
> > "Vendor"
> > ("linux") and "Target_HW" defined, while the Component CPE sets
> > these
> > attributes to "ANY", thus the CVE CPE attributes are subsets of the
> > component CPEs (see 

Re: [OE-core] Providing detailed CPE information for CVE matching capabilities

2023-08-25 Thread Steve Sakoman
On Fri, Aug 25, 2023 at 9:18 AM Jasper Orschulko via
lists.openembedded.org
 wrote:
>
> Hi Richard,
> hi all,
>
> I want to address a flaw in the current CPE generation functionality in
> openembedded, which renders the CPEs unusable in regards to the minimal
> requirements of the NIST CPE Name Matching Specification standard
> (https://nvlpubs.nist.gov/nistpubs/Legacy/IR/nistir7696.pdf).
>
> This makes working with the generated CPEs in thirdparty software close
> to impossible, as it would require the thirdparty software to implement
> matching logic beyond the requirements defined in the NIST standard.
>
>
> Status quo:
>
> Currently, the CPE is generated from the optional CVE_PRODUCT
> (optionally including the vendor) and CVE_VERSION variables. If neither
> are provided, CPE generation will fall back on the BPN and PV of the
> recipe.
>
> As a result, the generated CPE will usually look as follows:
>
> cpe:2.3:*:*:${BPN}:${PV}:*:*:*:*:*:*:*:*
>
> Or, if the CVE_PRODUCT includes a vendor:
>
> cpe:2.3:*:${vendor}:${product}:${PV}:*:*:*:*:*:*:*:*
>
>
>
> The Issue (The TL;DR):
>
> This will return zero¹ matches when doing CPE matching against CVE CPEs
> in accordance with the minimal requirements of the NIST Name Matching
> Specification. For reliable matches the components CPE should be as
> precise as possible, i.e. not containing any "*" (ANY) values for vital
> attributes, such as: Part, Vendor, Product, Version, Target_HW.
>
>
>
> The Issue (In detail):
>
> To understand the issue in full detail, in depth knowledge of the NIST
> specification is required. However, I will try to provide a
> comprehensive summary below:
>
> CPE matching is done using a source CPE and target CPE. Due to
> limitations (see Table 6-2, cases 4 & 11), using the CVE CPE as a
> source and the component CPE as a target is the only sensible way
> (otherwise a CVE CPE containing wildcards would lead to undefined
> behavior).
>
> Each attribute of the CVE CPE, will then be matched against the
> component CPE, setting the relationship of each source attribute to the
> corresponding target attribute to either superset (⊃), equal (=),
> subset (⊂) or disjoint (≠) (see Table 6-1, example: Table 6-3).
>
> The NIST standard then defines 4 required CPE Name Comparison Relations
> (see Table 6-4), with two of them relevant for what we would consider a
> "match" between a CVE CPE and a component CPE:
>
> If all attribute relations are EQUAL (=) -> Then CPE name relation is
> EQUAL (=) -> match
>
> If all attribute relations are SUPERSET (⊃) or
> EQUAL (=) -> Then CPE name relation is SUPERSET (⊃) -> match
>
> Let's take a look at this, based on a real-world example:
>
> CVE CPE: cpe:2.3:o:linux:linux_kernel:5.15.37:*:*:*:*:*:x86:*:*
> Component CPE: cpe:2.3:*:*:linux_kernel:5.15.37:*:*:*:*:*:*:*:*
>
> In this example the CVE CPE has the attributes "Part" ("o"), "Vendor"
> ("linux") and "Target_HW" defined, while the Component CPE sets these
> attributes to "ANY", thus the CVE CPE attributes are subsets of the
> component CPEs (see Table 6-2, case 13), making the entire CVE CPE a
> subset of the component CPE, thus causing a false-negative.
>
>
>
> Proposed solution:
>
> Openembedded should, in accordance with the CPE Naming Specification
> (https://nvlpubs.nist.gov/nistpubs/Legacy/IR/nistir7695.pdf), provide
> complete and accurate CPE information (at least: Part, Vendor, Product,
> Version, Target_HW) for recipes in order to avoid false-negatives
> during CVE CPE comparison and ensure compatibility with other tools.
>
> A component CPE could then look like this (something I came up with in
> 5 minutes, enjoy with a grain of salt):
>
> cpe:2.3:o:linux:linux_kernel:5.15.37::*:open
> embedded:::en_US (is there a bitbake
> variable for this?):*
>
> Setting attributes such as SW_Edition = "openembbeded" and Target_SW =
> "" also has the positive side-effect of allowing
> for the registration of openembedded-specific CVEs, e.g.
> vulnerabilities in patches within recipes.
>
> Of course, this is easier said than done, as some of the required
> information, especially "Part" and "Vendor" is missing from existing
> recipes.
>
> I therefore, suggest the following approach:
>
> Step 1 (non-intrusive):
>
> Introduce a new, optional variable CVE_PART, which is set to "a"
> (application) by default but may be overridden in a recipe (e.g. for
> linux_kernel)
>
> For consistency: Introduce the new, optional variable CVE_VENDOR as a
> replacement for the CVE_PRODUCT "double role" (for backwards
> compatibility, we can evaluate CVE_VENDOR first, then check for a
> vendor within CVE_PRODUCT).
>
> Adding already existing information from the build (e.g. Target_HW) to
> the CPE.
>
> Start filling in CVE_VENDOR for core recipes (openembedded-core).
>
> Optional: Step 2 (enforcement):
>
> Once a certain threshold of recipes with complete information is
> reached, we might want to consider enforcing explicit CVE_* variable
> declaration by default, with an