Tchotchke Tchotchke - 3 months ago 38
PowerShell Question

Regex to capture CVEs from Nessus plugin output

I have a block of output that looks like this:

- KB3167679 (MS16-101) (2 vulnerabilities)The following CVEs would be covered: 
CVE-2016-3300, CVE-2016-3237
- KB3114340 (MS16-099) (16 vulnerabilities)The following CVEs would be covered:
CVE-2016-3313, CVE-2016-3315, CVE-2016-3316, CVE-2016-3317, CVE-2016-3318,
CVE-2016-3313, CVE-2016-3315, CVE-2016-3316, CVE-2016-3317, CVE-2016-3318,
CVE-2016-3313, CVE-2016-3315, CVE-2016-3316, CVE-2016-3317, CVE-2016-3318,
CVE-2014-6362


I'm able to get the KB and MS values easily but I'm having a harder time pulling all the CVE numbers that follow. Is it possible to split my output based on the string "- " so that I'll get strings like this:

- KB3167679 (MS16-101) (2 vulnerabilities)The following CVEs would be covered: 
CVE-2016-3300, CVE-2016-3237


- KB3114340 (MS16-099) (16 vulnerabilities)The following CVEs would be covered: 
CVE-2016-3313, CVE-2016-3315, CVE-2016-3316, CVE-2016-3317, CVE-2016-3318,
CVE-2016-3313, CVE-2016-3315, CVE-2016-3316, CVE-2016-3317, CVE-2016-3318,
CVE-2016-3313, CVE-2016-3315, CVE-2016-3316, CVE-2016-3317, CVE-2016-3318,
CVE-2014-6362


From here I think I could do a regex with
-AllMatches
to get what I want.

Answer

I assume you'd want to preserve the relationship between the KB/MS identifier and the CVE codes.

For that purpose, I would populate a hashtable, by simply reading the text line by line, updating the key every time a KB line is encountered:

# This hashtable will hold our data
$CVECoverage = @{}

$KB = 'Unknown'

# Read file line by line
Get-Content D:\test\nessus.txt |ForEach-Object {

    # Check if line is a "header" line, grab the KB/MS ID
    if($_ -like '- *')
    {
        $KB = $_.Substring(2, $_.IndexOf(')') - 1)

        # If we don't already have a record of CVEs for this KB, create a new array
        if(-not $CVECoverage.ContainsKey($KB)){
            $CVECoverage[$KB] = @()
        }
    }
    else
    {
        # Find CVEs and add to respective hashtable entry
        foreach($CVE in $_ | Select-String -Pattern 'CVE-\d{4}-\d{4,}' -AllMatches)
        {
            $CVECoverage[$KB] += $CVE.Matches.Value
        }
    }
}