Add resolved_in_version for Windows OS Vulns (#16546)

This commit is contained in:
Tim Lee 2024-02-07 06:19:59 -07:00 committed by GitHub
parent a9e837afaf
commit 6d1eee6279
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 83905 additions and 135 deletions

View file

@ -0,0 +1 @@
- Windows OS Vulnerabilities now include a `resolved_in_version` in the `/os_versions` API response

View file

@ -269,7 +269,7 @@ func checkWinVulnerabilities(
}
start := time.Now()
r, err := msrc.Analyze(ctx, ds, o, vulnPath, collectVulns)
r, err := msrc.Analyze(ctx, ds, o, vulnPath, collectVulns, logger)
elapsed := time.Since(start)
level.Debug(logger).Log(
"msg", "msrc-analysis-done",

View file

@ -18,7 +18,8 @@ func (ds *Datastore) ListOSVulnerabilitiesByOS(ctx context.Context, osID uint) (
SELECT
operating_system_id,
cve,
resolved_in_version
resolved_in_version,
source
FROM operating_system_vulnerabilities
WHERE operating_system_id = ?
`

View file

@ -59,9 +59,9 @@ func testListOSVulnerabilitiesByOS(t *testing.T, ds *Datastore) {
t.Run("returns matching", func(t *testing.T) {
expected := []fleet.OSVulnerability{
{CVE: "cve-1", OSID: 1, ResolvedInVersion: ptr.String("1.2.3")},
{CVE: "cve-3", OSID: 1, ResolvedInVersion: ptr.String("10.14.2")},
{CVE: "cve-2", OSID: 1, ResolvedInVersion: ptr.String("8.123.1")},
{CVE: "cve-1", OSID: 1, ResolvedInVersion: ptr.String("1.2.3"), Source: fleet.MSRCSource},
{CVE: "cve-3", OSID: 1, ResolvedInVersion: ptr.String("10.14.2"), Source: fleet.MSRCSource},
{CVE: "cve-2", OSID: 1, ResolvedInVersion: ptr.String("8.123.1"), Source: fleet.MSRCSource},
}
actual, err := ds.ListOSVulnerabilitiesByOS(ctx, 1)
@ -197,9 +197,15 @@ func testInsertOSVulnerabilities(t *testing.T, ds *Datastore) {
require.NoError(t, err)
require.Equal(t, int64(3), c)
expected := []fleet.OSVulnerability{
{CVE: "cve-1", OSID: 1, Source: fleet.MSRCSource},
{CVE: "cve-3", OSID: 1, Source: fleet.MSRCSource},
{CVE: "cve-2", OSID: 1, Source: fleet.MSRCSource},
}
actual, err := ds.ListOSVulnerabilitiesByOS(ctx, 1)
require.NoError(t, err)
require.ElementsMatch(t, vulns, actual)
require.ElementsMatch(t, expected, actual)
}
func testInsertOSVulnerability(t *testing.T, ds *Datastore) {
@ -232,10 +238,13 @@ func testInsertOSVulnerability(t *testing.T, ds *Datastore) {
require.NoError(t, err)
require.Equal(t, false, didInsert)
expected := vulnsUpdate
expected.Source = fleet.MSRCSource
list1, err := ds.ListOSVulnerabilitiesByOS(ctx, 1)
require.NoError(t, err)
require.Len(t, list1, 1)
require.Equal(t, vulnsUpdate, list1[0])
require.Equal(t, expected, list1[0])
}
func testDeleteOSVulnerabilitiesEmpty(t *testing.T, ds *Datastore) {
@ -275,8 +284,8 @@ func testDeleteOSVulnerabilities(t *testing.T, ds *Datastore) {
actual, err := ds.ListOSVulnerabilitiesByOS(ctx, 1)
require.NoError(t, err)
require.ElementsMatch(t, []fleet.OSVulnerability{
{CVE: "cve-1", OSID: 1},
{CVE: "cve-3", OSID: 1},
{CVE: "cve-1", OSID: 1, Source: fleet.MSRCSource},
{CVE: "cve-3", OSID: 1, Source: fleet.MSRCSource},
}, actual)
}

View file

@ -94,7 +94,11 @@ func (ov OSVulnerability) String() string {
// If we have a list of os vulnerabilities, the Key can be used
// as a discrimator for unique entries.
func (ov OSVulnerability) Key() string {
return fmt.Sprintf("os:%d:%s", ov.OSID, ov.CVE)
var rv string
if ov.ResolvedInVersion != nil {
rv = *ov.ResolvedInVersion
}
return fmt.Sprintf("os:%d:%s:%s", ov.OSID, ov.CVE, rv)
}
func (ov OSVulnerability) GetCVE() string {

View file

@ -2,7 +2,6 @@ package msrc
import (
"context"
"errors"
"fmt"
"strconv"
"strings"
@ -10,9 +9,12 @@ import (
"github.com/fleetdm/fleet/v4/server/contexts/ctxerr"
"github.com/fleetdm/fleet/v4/server/fleet"
"github.com/fleetdm/fleet/v4/server/ptr"
"github.com/fleetdm/fleet/v4/server/vulnerabilities/io"
msrc "github.com/fleetdm/fleet/v4/server/vulnerabilities/msrc/parsed"
utils "github.com/fleetdm/fleet/v4/server/vulnerabilities/utils"
kitlog "github.com/go-kit/log"
"github.com/go-kit/log/level"
)
const (
@ -25,6 +27,7 @@ func Analyze(
os fleet.OperatingSystem,
vulnPath string,
collectVulns bool,
logger kitlog.Logger,
) ([]fleet.OSVulnerability, error) {
bulletin, err := loadBulletin(os, vulnPath)
if err != nil {
@ -51,17 +54,21 @@ func Analyze(
// Run vulnerability detection for all hosts in this batch (hIDs)
// and store the results in 'found'.
var found []fleet.OSVulnerability
for cve, v := range bulletin.Vulnerabities {
// Check if this vulnerability targets the OS
if !utils.ProductIDsIntersect(v.ProductIDs, matchingPIDs) {
continue
}
// Check if the vulnerability is patched by referencing the OS version number
if patched(os, bulletin, v, matchingPIDs) {
continue
// Check if the OS is vulnerable to the vulnerability by referencing the OS kernel version
isVuln, riv := isOSVulnerable(os.KernelVersion, bulletin, v, matchingPIDs, cve, logger)
if isVuln {
found = append(found, fleet.OSVulnerability{
OSID: os.ID,
CVE: cve,
Source: fleet.MSRCSource,
ResolvedInVersion: ptr.String(riv),
})
}
found = append(found, fleet.OSVulnerability{OSID: os.ID, CVE: cve})
}
// Fetch all stored vulnerabilities for the current batch
@ -114,18 +121,21 @@ func Analyze(
return inserted, nil
}
// patched returns true if the vulnerability (v) is patched by the any of the provided Windows
// updates.
func patched(
os fleet.OperatingSystem,
// isOSVulnerable returns true if the OS is vulnerable to the given vulnerability.
// If the OS is vulnerable, the function returns the version in which the vulnerability
// was resolved.
func isOSVulnerable(
osKernel string,
b *msrc.SecurityBulletin,
v msrc.Vulnerability,
matchingPIDs map[string]bool,
) bool {
cve string,
logger kitlog.Logger,
) (isVulnerable bool, resolvedInVersion string) {
for KBID := range v.RemediatedBy {
fix := b.VendorFixes[KBID]
// Check if this vendor fix targets the OS
// Check if the MSRC FixedBuild version targets the OS version
if !utils.ProductIDsIntersect(fix.ProductIDs, matchingPIDs) {
continue
}
@ -138,14 +148,38 @@ func patched(
continue
}
isGreater, err := winBuildVersionGreaterOrEqual(build, os.KernelVersion)
// Return true on errors to prevent false positives
if err != nil || isGreater {
return true
fixedBuild, feedParts, err := getBuildNumber(build)
if err != nil {
level.Debug(logger).Log("msg", "invalid msrc feed version", "cve", cve, "err", err)
continue
}
osBuild, osParts, err := getBuildNumber(osKernel)
if err != nil {
continue
}
// skip if the product version number does not match
// ie. 10.0.22000.X vs 10.0.22631.X
if isProductVersionMismatch(feedParts, osParts) {
continue
}
if osBuild < fixedBuild {
return true, build
}
}
}
return
}
func isProductVersionMismatch(feedVersion, osVersion []string) bool {
for i := 0; i < 3; i++ {
if feedVersion[i] != osVersion[i] {
return true
}
}
return false
}
@ -162,31 +196,8 @@ func loadBulletin(os fleet.OperatingSystem, dir string) (*msrc.SecurityBulletin,
return msrc.UnmarshalBulletin(latest)
}
func winBuildVersionGreaterOrEqual(feed, os string) (bool, error) {
if feed == "" {
return false, errors.New("empty feed version")
}
feedBuild, feedParts, err := getBuildNumber(feed)
if err != nil {
return false, fmt.Errorf("invalid feed version: %w", err)
}
osBuild, osParts, err := getBuildNumber(os)
if err != nil {
return false, fmt.Errorf("invalid os version: %w", err)
}
for i := 0; i < 3; i++ {
if feedParts[i] != osParts[i] {
// comparing different product versions
return false, nil
}
}
return osBuild >= feedBuild, nil
}
// getBuildNumber expects a version string in the format "10.0.22000.194" and
// returns the final part (build number) as an integer and the parts as a slice of strings.
func getBuildNumber(version string) (int, []string, error) {
if version == "" {
return 0, nil, fmt.Errorf("empty version string %s", version)

View file

@ -1,6 +1,7 @@
package msrc
import (
"context"
"encoding/json"
"os"
"path/filepath"
@ -8,13 +9,15 @@ import (
"time"
"github.com/fleetdm/fleet/v4/server/fleet"
"github.com/fleetdm/fleet/v4/server/mock"
"github.com/fleetdm/fleet/v4/server/ptr"
"github.com/fleetdm/fleet/v4/server/vulnerabilities/io"
"github.com/fleetdm/fleet/v4/server/vulnerabilities/msrc/parsed"
"github.com/go-kit/log"
"github.com/stretchr/testify/require"
)
func TestAnalyzer(t *testing.T) {
func TestIsVulnPatched(t *testing.T) {
op := fleet.OperatingSystem{
Name: "Microsoft Windows 11 Enterprise Evaluation",
DisplayVersion: "21H2",
@ -25,35 +28,6 @@ func TestAnalyzer(t *testing.T) {
}
prod := parsed.NewProductFromOS(op)
t.Run("#patched", func(t *testing.T) {
// TODO: this tests a nil vulnerability, which should never happen
// maybe return an error instead?
t.Run("no updates", func(t *testing.T) {
b := parsed.NewSecurityBulletin(prod.Name())
b.Products["123"] = prod
b.Vulnerabities["cve-123"] = parsed.NewVulnerability(nil)
pIDs := map[string]bool{"123": true}
require.False(t, patched(op, b, b.Vulnerabities["cve-123"], pIDs))
})
t.Run("remediated by build", func(t *testing.T) {
b := parsed.NewSecurityBulletin(prod.Name())
b.Products["123"] = prod
pIDs := map[string]bool{"123": true}
vuln := parsed.NewVulnerability(nil)
vuln.RemediatedBy[456] = true
b.Vulnerabities["cve-123"] = vuln
vfA := parsed.NewVendorFix("10.0.22000.794")
vfA.Supersedes = ptr.Uint(123)
vfA.ProductIDs["123"] = true
b.VendorFixes[456] = vfA
require.True(t, patched(op, b, b.Vulnerabities["cve-123"], pIDs))
})
})
t.Run("#loadBulletin", func(t *testing.T) {
t.Run("dir does not exists", func(t *testing.T) {
bulletin, err := loadBulletin(op, "over_the_rainbow")
@ -84,82 +58,373 @@ func TestAnalyzer(t *testing.T) {
})
}
func TestWinBuildVersionGreaterOrEqual(t *testing.T) {
func TestIsOSVulnerable(t *testing.T) {
b := parsed.SecurityBulletin{
Vulnerabities: map[string]parsed.Vulnerability{
"CVE-Win11": {
RemediatedBy: map[uint]bool{
123: true,
},
},
"CVE-too-many-parts": {
RemediatedBy: map[uint]bool{
124: true,
},
},
"CVE-too-few-parts": {
RemediatedBy: map[uint]bool{
125: true,
},
},
"CVE-empty-feed-version": {
RemediatedBy: map[uint]bool{
126: true,
},
},
"CVE-wrong-build-version": {
RemediatedBy: map[uint]bool{
127: true,
},
},
"CVE-multiple-fixed-builds": {
RemediatedBy: map[uint]bool{
128: true,
},
},
},
VendorFixes: map[uint]parsed.VendorFix{
123: {
FixedBuilds: []string{"10.0.22000.794"},
ProductIDs: map[string]bool{"123": true},
},
124: {
FixedBuilds: []string{"10.0.22000.794.9999"},
ProductIDs: map[string]bool{"123": true},
},
125: {
FixedBuilds: []string{"10.0.22000"},
ProductIDs: map[string]bool{"123": true},
},
126: {
FixedBuilds: []string{""},
ProductIDs: map[string]bool{"123": true},
},
127: {
FixedBuilds: []string{"10.0.22621.795"}, // bug in the feed
ProductIDs: map[string]bool{"123": true},
},
128: {
FixedBuilds: []string{"10.0.22000.794", "10.0.22631.795"},
ProductIDs: map[string]bool{"123": true, "124": true},
},
},
}
tc := []struct {
name string
feed string
os string
result bool
errMessage string
name string
feed string
os string
isVulnerable bool
resolvedIn string
}{
{
name: "equal",
feed: "10.0.22000.795",
os: "10.0.22000.795",
result: true,
errMessage: "",
name: "os version equals fixed build",
feed: "CVE-Win11",
os: "10.0.22000.795",
isVulnerable: false,
resolvedIn: "",
},
{
name: "greater",
feed: "10.0.22000.795",
os: "10.0.22000.796",
result: true,
errMessage: "",
name: "os version greater than fixed build",
feed: "CVE-Win11",
os: "10.0.22000.796",
isVulnerable: false,
resolvedIn: "",
},
{
name: "less",
feed: "10.0.22000.795",
os: "10.0.22000.794",
result: false,
errMessage: "",
name: "os version less than fixed build",
feed: "CVE-Win11",
os: "10.0.22000.793",
isVulnerable: true,
resolvedIn: "10.0.22000.794",
},
{
name: "too many parts in feed version",
feed: "10.0.22000.795.9999",
os: "10.0.22000.794",
result: false,
errMessage: "invalid feed version",
name: "too many parts in feed version",
feed: "CVE-too-many-parts",
os: "10.0.22000.794",
isVulnerable: false,
resolvedIn: "",
},
{
name: "too many parts in os version",
feed: "10.0.22000.795",
os: "10.0.22000.794.9999",
result: false,
errMessage: "invalid os version",
name: "too many parts in os version",
feed: "CVE-Win11",
os: "10.0.22000.794.9999",
isVulnerable: false,
resolvedIn: "",
},
{
name: "too few parts in feed version",
feed: "10.0.22000",
os: "10.0.22000.794",
result: false,
errMessage: "invalid feed version",
name: "too few parts in feed version",
feed: "CVE-too-few-parts",
os: "10.0.22000.794",
isVulnerable: false,
resolvedIn: "",
},
{
name: "empty feed version",
feed: "",
os: "10.0.22000.794",
result: false,
errMessage: "empty feed version",
name: "empty feed version",
feed: "CVE-empty-feed-version",
os: "10.0.22000.794",
isVulnerable: false,
resolvedIn: "",
},
{
name: "comparing different product versions",
feed: "10.0.22000.795",
os: "10.0.22621.795",
result: false,
errMessage: "",
name: "comparing different product versions",
feed: "CVE-wrong-build-version",
os: "10.0.22000.794",
isVulnerable: false,
resolvedIn: "",
},
{
name: "vulnerable with multiple fixed builds",
feed: "CVE-multiple-fixed-builds",
os: "10.0.22000.793",
isVulnerable: true,
resolvedIn: "10.0.22000.794",
},
{
name: "not vulnerable with multiple fixed builds",
feed: "CVE-multiple-fixed-builds",
os: "10.0.22000.794",
isVulnerable: false,
resolvedIn: "",
},
}
for _, c := range tc {
t.Run(c.name, func(t *testing.T) {
result, err := winBuildVersionGreaterOrEqual(c.feed, c.os)
require.Equal(t, c.result, result)
if c.errMessage != "" {
require.Error(t, err)
require.ErrorContains(t, err, c.errMessage)
} else {
require.NoError(t, err)
}
isVuln, resolvedIn := isOSVulnerable(c.os, &b, b.Vulnerabities[c.feed], map[string]bool{"123": true}, c.feed, log.NewNopLogger())
require.Equal(t, c.isVulnerable, isVuln)
require.Equal(t, c.resolvedIn, resolvedIn)
})
}
}
func TestAnalyze(t *testing.T) {
ctx := context.Background()
ds := new(mock.Store)
vulnPath := "./testdata"
tc := []struct {
name string
osName string
osVersion string
displayVersion string
vulns []fleet.OSVulnerability
}{
{
name: "OS With No Display Version",
osName: "Microsoft Windows 11 Enterprise",
osVersion: "10.0.22000.2652",
displayVersion: "",
vulns: []fleet.OSVulnerability{
{CVE: "CVE-2024-21320", ResolvedInVersion: ptr.String("10.0.22000.2713"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-21307", ResolvedInVersion: ptr.String("10.0.22000.2713"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-21306", ResolvedInVersion: ptr.String("10.0.22000.2713"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-21305", ResolvedInVersion: ptr.String("10.0.22000.2713"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20692", ResolvedInVersion: ptr.String("10.0.22000.2713"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20687", ResolvedInVersion: ptr.String("10.0.22000.2713"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20683", ResolvedInVersion: ptr.String("10.0.22000.2713"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-21316", ResolvedInVersion: ptr.String("10.0.22000.2713"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20660", ResolvedInVersion: ptr.String("10.0.22000.2713"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20658", ResolvedInVersion: ptr.String("10.0.22000.2713"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20653", ResolvedInVersion: ptr.String("10.0.22000.2713"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20652", ResolvedInVersion: ptr.String("10.0.22000.2713"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20674", ResolvedInVersion: ptr.String("10.0.22000.2713"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20666", ResolvedInVersion: ptr.String("10.0.22000.2713"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-21314", ResolvedInVersion: ptr.String("10.0.22000.2713"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-21313", ResolvedInVersion: ptr.String("10.0.22000.2713"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-21311", ResolvedInVersion: ptr.String("10.0.22000.2713"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-21310", ResolvedInVersion: ptr.String("10.0.22000.2713"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-21309", ResolvedInVersion: ptr.String("10.0.22000.2713"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20700", ResolvedInVersion: ptr.String("10.0.22000.2713"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20699", ResolvedInVersion: ptr.String("10.0.22000.2713"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20698", ResolvedInVersion: ptr.String("10.0.22000.2713"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20696", ResolvedInVersion: ptr.String("10.0.22000.2713"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20694", ResolvedInVersion: ptr.String("10.0.22000.2713"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20691", ResolvedInVersion: ptr.String("10.0.22000.2713"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20690", ResolvedInVersion: ptr.String("10.0.22000.2713"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20682", ResolvedInVersion: ptr.String("10.0.22000.2713"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20681", ResolvedInVersion: ptr.String("10.0.22000.2713"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20680", ResolvedInVersion: ptr.String("10.0.22000.2713"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20664", ResolvedInVersion: ptr.String("10.0.22000.2713"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20663", ResolvedInVersion: ptr.String("10.0.22000.2713"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20661", ResolvedInVersion: ptr.String("10.0.22000.2713"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20657", ResolvedInVersion: ptr.String("10.0.22000.2713"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20654", ResolvedInVersion: ptr.String("10.0.22000.2713"), OSID: 1, Source: fleet.MSRCSource},
},
},
{
name: "OS With Display Version",
osName: "Microsoft Windows 11 Enterprise 22H2",
osVersion: "10.0.22621.2861",
displayVersion: "22H2",
vulns: []fleet.OSVulnerability{
{CVE: "CVE-2024-21320", ResolvedInVersion: ptr.String("10.0.22621.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-21307", ResolvedInVersion: ptr.String("10.0.22621.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-21306", ResolvedInVersion: ptr.String("10.0.22621.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-21305", ResolvedInVersion: ptr.String("10.0.22621.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20697", ResolvedInVersion: ptr.String("10.0.22621.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20692", ResolvedInVersion: ptr.String("10.0.22621.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20687", ResolvedInVersion: ptr.String("10.0.22621.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20683", ResolvedInVersion: ptr.String("10.0.22621.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-21316", ResolvedInVersion: ptr.String("10.0.22621.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20660", ResolvedInVersion: ptr.String("10.0.22621.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20658", ResolvedInVersion: ptr.String("10.0.22621.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20653", ResolvedInVersion: ptr.String("10.0.22621.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20652", ResolvedInVersion: ptr.String("10.0.22621.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20674", ResolvedInVersion: ptr.String("10.0.22621.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20666", ResolvedInVersion: ptr.String("10.0.22621.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-21314", ResolvedInVersion: ptr.String("10.0.22621.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-21313", ResolvedInVersion: ptr.String("10.0.22621.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-21311", ResolvedInVersion: ptr.String("10.0.22621.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-21310", ResolvedInVersion: ptr.String("10.0.22621.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-21309", ResolvedInVersion: ptr.String("10.0.22621.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20700", ResolvedInVersion: ptr.String("10.0.22621.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20699", ResolvedInVersion: ptr.String("10.0.22621.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20698", ResolvedInVersion: ptr.String("10.0.22621.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20696", ResolvedInVersion: ptr.String("10.0.22621.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20694", ResolvedInVersion: ptr.String("10.0.22621.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20691", ResolvedInVersion: ptr.String("10.0.22621.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20690", ResolvedInVersion: ptr.String("10.0.22621.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20682", ResolvedInVersion: ptr.String("10.0.22621.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20681", ResolvedInVersion: ptr.String("10.0.22621.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20680", ResolvedInVersion: ptr.String("10.0.22621.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20664", ResolvedInVersion: ptr.String("10.0.22621.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20663", ResolvedInVersion: ptr.String("10.0.22621.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20661", ResolvedInVersion: ptr.String("10.0.22621.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20657", ResolvedInVersion: ptr.String("10.0.22621.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20654", ResolvedInVersion: ptr.String("10.0.22621.3007"), OSID: 1, Source: fleet.MSRCSource},
},
},
{
name: "OS With Display Version and No Vulnerabilities",
osName: "Microsoft Windows 11 Enterprise 22H2",
osVersion: "10.0.22621.3007",
displayVersion: "22H2",
vulns: []fleet.OSVulnerability{},
},
{
name: "Vulnerable 23H2 Version",
osName: "Microsoft Windows 11 Enterprise 23H2",
osVersion: "10.0.22631.2861",
displayVersion: "23H2",
vulns: []fleet.OSVulnerability{
{CVE: "CVE-2024-20697", ResolvedInVersion: ptr.String("10.0.22631.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-21320", ResolvedInVersion: ptr.String("10.0.22631.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-21307", ResolvedInVersion: ptr.String("10.0.22631.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-21306", ResolvedInVersion: ptr.String("10.0.22631.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-21305", ResolvedInVersion: ptr.String("10.0.22631.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20692", ResolvedInVersion: ptr.String("10.0.22631.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20687", ResolvedInVersion: ptr.String("10.0.22631.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20683", ResolvedInVersion: ptr.String("10.0.22631.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-21316", ResolvedInVersion: ptr.String("10.0.22631.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20660", ResolvedInVersion: ptr.String("10.0.22631.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20658", ResolvedInVersion: ptr.String("10.0.22631.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20653", ResolvedInVersion: ptr.String("10.0.22631.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20652", ResolvedInVersion: ptr.String("10.0.22631.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20674", ResolvedInVersion: ptr.String("10.0.22631.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20666", ResolvedInVersion: ptr.String("10.0.22631.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-21314", ResolvedInVersion: ptr.String("10.0.22631.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-21313", ResolvedInVersion: ptr.String("10.0.22631.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-21311", ResolvedInVersion: ptr.String("10.0.22631.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-21310", ResolvedInVersion: ptr.String("10.0.22631.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-21309", ResolvedInVersion: ptr.String("10.0.22631.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20700", ResolvedInVersion: ptr.String("10.0.22631.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20699", ResolvedInVersion: ptr.String("10.0.22631.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20698", ResolvedInVersion: ptr.String("10.0.22631.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20696", ResolvedInVersion: ptr.String("10.0.22631.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20694", ResolvedInVersion: ptr.String("10.0.22631.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20691", ResolvedInVersion: ptr.String("10.0.22631.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20690", ResolvedInVersion: ptr.String("10.0.22631.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20682", ResolvedInVersion: ptr.String("10.0.22631.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20681", ResolvedInVersion: ptr.String("10.0.22631.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20680", ResolvedInVersion: ptr.String("10.0.22631.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20664", ResolvedInVersion: ptr.String("10.0.22631.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20663", ResolvedInVersion: ptr.String("10.0.22631.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20661", ResolvedInVersion: ptr.String("10.0.22631.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20657", ResolvedInVersion: ptr.String("10.0.22631.3007"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20654", ResolvedInVersion: ptr.String("10.0.22631.3007"), OSID: 1, Source: fleet.MSRCSource},
},
},
{
name: "Windows 10 22H2",
osName: "Microsoft Windows 10 Enterprise 22H2",
osVersion: "10.0.19045.3803",
displayVersion: "22H2",
vulns: []fleet.OSVulnerability{
{CVE: "CVE-2024-21320", ResolvedInVersion: ptr.String("10.0.19045.3930"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-21307", ResolvedInVersion: ptr.String("10.0.19045.3930"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-21306", ResolvedInVersion: ptr.String("10.0.19045.3930"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-21305", ResolvedInVersion: ptr.String("10.0.19045.3930"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2022-35737", ResolvedInVersion: ptr.String("10.0.19045.3930"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20692", ResolvedInVersion: ptr.String("10.0.19045.3930"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20687", ResolvedInVersion: ptr.String("10.0.19045.3930"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20683", ResolvedInVersion: ptr.String("10.0.19045.3930"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-21316", ResolvedInVersion: ptr.String("10.0.19045.3930"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20660", ResolvedInVersion: ptr.String("10.0.19045.3930"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20658", ResolvedInVersion: ptr.String("10.0.19045.3930"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20653", ResolvedInVersion: ptr.String("10.0.19045.3930"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20652", ResolvedInVersion: ptr.String("10.0.19045.3930"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20674", ResolvedInVersion: ptr.String("10.0.19045.3930"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20666", ResolvedInVersion: ptr.String("10.0.19045.3930"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-21314", ResolvedInVersion: ptr.String("10.0.19045.3930"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-21313", ResolvedInVersion: ptr.String("10.0.19045.3930"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-21311", ResolvedInVersion: ptr.String("10.0.19045.3930"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-21310", ResolvedInVersion: ptr.String("10.0.19045.3930"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20700", ResolvedInVersion: ptr.String("10.0.19045.3930"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20699", ResolvedInVersion: ptr.String("10.0.19045.3930"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20698", ResolvedInVersion: ptr.String("10.0.19045.3930"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20696", ResolvedInVersion: ptr.String("10.0.19045.3930"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20694", ResolvedInVersion: ptr.String("10.0.19045.3930"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20691", ResolvedInVersion: ptr.String("10.0.19045.3930"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20690", ResolvedInVersion: ptr.String("10.0.19045.3930"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20682", ResolvedInVersion: ptr.String("10.0.19045.3930"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20681", ResolvedInVersion: ptr.String("10.0.19045.3930"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20680", ResolvedInVersion: ptr.String("10.0.19045.3930"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20664", ResolvedInVersion: ptr.String("10.0.19045.3930"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20663", ResolvedInVersion: ptr.String("10.0.19045.3930"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20661", ResolvedInVersion: ptr.String("10.0.19045.3930"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20657", ResolvedInVersion: ptr.String("10.0.19045.3930"), OSID: 1, Source: fleet.MSRCSource},
{CVE: "CVE-2024-20654", ResolvedInVersion: ptr.String("10.0.19045.3930"), OSID: 1, Source: fleet.MSRCSource},
},
},
}
for _, c := range tc {
t.Run(c.name, func(t *testing.T) {
fos := fleet.OperatingSystem{
ID: uint(1),
Name: c.osName,
DisplayVersion: c.displayVersion,
Version: c.osVersion,
Arch: "64-bit",
KernelVersion: c.osVersion,
Platform: "windows",
}
ds.ListOSVulnerabilitiesByOSFunc = func(ctx context.Context, osID uint) ([]fleet.OSVulnerability, error) {
return nil, nil
}
ds.DeleteOSVulnerabilitiesFunc = func(ctx context.Context, vulnerabilities []fleet.OSVulnerability) error {
return nil
}
ds.InsertOSVulnerabilitiesFunc = func(ctx context.Context, vulnerabilities []fleet.OSVulnerability, source fleet.VulnerabilitySource) (int64, error) {
return int64(len(c.vulns)), nil
}
results, err := Analyze(ctx, ds, fos, vulnPath, true, log.NewNopLogger())
require.NoError(t, err)
require.ElementsMatch(t, c.vulns, results)
})
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff