regexpowershellnessus

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.


Solution

  • 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
            }
        }
    }
    

    If the input is already one big string, use the following to split it into individual lines:

    $bigString -split "`r?`n" |ForEach-Object { ... }