microsoft / MSRC-Microsoft-Security-Updates-API

Repo with getting started projects for the Microsoft Security Updates API (msrc.microsoft.com/update-guide)
https://msrc.microsoft.com/update-guide
MIT License
365 stars 115 forks source link

Getting DownloadURL Issues #91

Open DerikPlanSys opened 3 years ago

DerikPlanSys commented 3 years ago

I'm trying to use the API to generate an automated report for the months updates, based on a JSON file with all our known products. Creating an Excel report is not currently the problem. I'm having an issue with getting the correct Download URL. The closest I can get is a link to the KB Download. So https://www.catalog.update.microsoft.com/Search.aspx?q=KB5000808 for example. But then I have to still go and select which one of THOSE I need to download.

I am wanting to get the specific download URL for the update "2021-03 Cumulative Update for Windows 10 Version 1909 for x64-based Systems (KB5000808)".

I was hoping Get-KBDownloadUrl would be what I'm after, but no matter what I pipe into it, it always spits out

So this returns essentially nothing. $MonthlyUpdateDownload = Get-MsrcCvrfDocument -ID $MonthofInterest -Verbose | Get-MsrcCvrfAffectedSoftware | Where-Object { $_.FullProductName -in $(Get-SamsAffectedProducts).name } | Get-KBDownloadUrl

I didn't include the variables, but it should be self explanatory how it's working. Looks like I need to figure out Markdown...

p0w3rsh3ll commented 3 years ago

Get-KBDownloadUrl is a public function in the module but it's only consumed by Get-MsrcVulnerabilityReportHtml that uses input from Get-MsrcCvrfAffectedSoftware to insert a clickable link into the html report created.

It appears that you're looking for a way to parse a page from the catalog like https://www.catalog.update.microsoft.com/Search.aspx?q=KB5000808 to get to the MSU file http://download.windowsupdate.com/d/msdownload/update/software/secu/2021/03/windows10.0-kb5000808-x64_e574cea84cade2730bfdd398cc341dbe0b864cbe.msu

This module doesn't do that. You need to write your own code/function for that. There are other modules that do that like MSCatalog or LatestUpdate

Here's something that worked from me while I was testing and trying to get the download URL from the catalog. (You should test the above modules, they do a better job than this sample test code:)

$MonthlyUpdateDownload = Get-MsrcCvrfDocument -ID '2021-Jun' -Verbose 

$MonthlyUpdateDownload  | Get-MsrcCvrfAffectedSoftware | 
Where-Object { $_.FullProductName -in 'Windows 10 Version 1909 for x64-based Systems' } |
Select-Object -ExpandProperty KBArticle | Sort-Object -Property ID -Unique

Function Get-MSCatalogLink {
[CmdletBinding()]
[OutputType([System.String])]
Param (
    [Parameter(Mandatory,ValueFromPipeline)]
    $InputObject
)
Begin {}
Process {
    $HT = @{ ErrorAction = 'Stop' }
    $InputObject |
    ForEach-Object {
        if ($_.ID) {
            Write-Verbose -Message "Looking for KB $($_.ID)"
            try {
                Invoke-WebRequest -UseBasicParsing -Uri ( 'https://catalog.update.microsoft.com/v7/site/Search.aspx?q=KB{0}' -f $_.ID) @HT |
                Select-Object -ExpandProperty Links |
                Where-Object {$_.onclick -match 'goToDetails' } |
                ForEach-Object {
                    [PSCustomObject]@{
                        KB = ($_.outerHTML -split "`n")[1].Trim()
                        ID = ([regex]'goToDetails\("(?<ID>.+)"\);').Match($_.onclick) | Select-Object -ExpandProperty Groups | Select-Object -Last 1 -ExpandProperty Value
                    }
                }|
                ForEach-Object {
                    $post = @{ size = 0; updateID = $_.ID; uidInfo = $_.ID } | ConvertTo-Json -Compress
                    $Body = @{ updateIDs = "[$post]" } 
                    $r = Invoke-WebRequest -Uri 'https://www.catalog.update.microsoft.com/DownloadDialog.aspx' -Method Post -Body $Body -UseBasicParsing @HT
                    $r.Content | Select-String -Pattern "(http[s]?\://download\.windowsupdate\.com\/[^\'\""]*)" -AllMatches |
                    ForEach-Object {
                        $_.matches.value
                    }
                }
            } catch {
                Throw $_
            }
        }
    }
}
End {}
}

$test = [PSCustomObject]@{
ID = '5003635'
URL  ='https://catalog.update.microsoft.com/v7/site/Search.aspx?q=KB5003635'
SubType = 'Security Update'
}

$test | Get-MSCatalogLink