Using the SANS DShield REST API

The SANS announced the availability of the Microsoft Patch Data on the 5th of April.
They have actually added both a REST API and a new web interface.

I’ve written a tiny module that uses the 3 Dshield REST API methods and made sure you can bind the resulting functions together. The last piece of the puzzle is a function to get the 2nd Tuesday of a month.

The module is available in a github repository and in the PowerShell Gallery

To get a nice display of Microsoft security bulletins, you can do:

(Get-SecondTuesday -Year 2016 -Month 04).ToString('yyyy-MM-dd') |
Get-SansMSPatchDay | Select @{l='Bulletin';e={$_.Id}},title,
 @{l='Components Affected';e={$_.affected}},
 @{l='kb';e={$_.kb -as [string]}},
 @{l='Known Exploits';e={
  switch($_.exploits) {
   'yes' { $true}
   'no'  {$false}
   default {}
}},severity,clients,servers | Out-GridView -Title "April, 2016"

NB1: The long select properties list aims only to force the KB property to be displayed as a string by Out-GridView. There’s no problem in the console with the raw json format.
NB2: Next month, you can also omit the -Year and -Month parameters of the Get-SecondTuesday function. By default this function returns the second Tuesday of the current month as a datetime object.

Now that we have seen how to use the functions each month.

Let’s say we want to do something more complicated and get an overview of what happened last year.

First store dates formatted the way the REST API expects them:

# Summary for 2015
$2015BTDates = 1..12 | ForEach-Object {
    (Get-SecondTuesday -Year 2015 -Month $_).ToString('yyyy-MM-dd')


Pull all the bulletins from 2015 and store the info in a variable:

# Get Bulletins
$2015Bulletins = $2015BTDates | Get-SansMSPatchDay

We also see above the first bulletin MS15-001 and the last one MS15-135.

Sure there were 135 bulletins in 2015? Actually No! The following tells us that there were only 133 bulletins 😎

# Total bulletins in 2015
$2015Bulletins.Id | Measure


How many bulletins have addressed one or more known vulnerabilities exploited in the wild?

# Only known exploits
$2015Bulletins | Where 'exploits' -eq 'yes' |
Select -Property Id | Measure


19 known exploits over how many vulnerabilities fixed by these bulletins?

# Get CVEs
$2015CVEs  = $2015Bulletins | Get-SansMSPatchCVE

# Total CVEs
$2015CVEs | Select -expand cve | Sort -Unique | Measure


"{0:P2}" -f $(19/220)

That makes 8.64%

What months got the most bulletins released?:

# Total bulletins per month in 2015
1..12 | ForEach-Object {
        Month = $_ ;
        Bulletins = $(
            (Get-SecondTuesday -Year 2015 -Month $_).ToString('yyyy-MM-dd') | 
            Get-SansMSPatchDay | Select -Expand Id 
} | Select Month,Bulletins,
@{l='Count';e={ $_.Bulletins | Measure-Object | Select -Expand Count}}


How many vulnerabilities were addressed each month?

# Total CVEs per month in 2015
1..12 | ForEach-Object {
        Month = $_ ;
        CVEs = $(
            (Get-SecondTuesday -Year 2015 -Month $_).ToString('yyyy-MM-dd') | 
            Get-SansMSPatchDay | Get-SansMSPatchCVE | Select -Expand cve
} | Select Month,CVEs,
@{l='Count';e={ $_.CVEs |  Sort -Unique | Measure-Object | Select -Expand Count}}


Let’s go crazy and retrieve from all the SANS data (almost 10 years) and filter out what bulletins were rated “PATCH NOW” by the SANS:

2006..2016 | ForEach-Object {
    $Y = $_
    1..12 | ForEach-Object {
        $M = $_
        Get-SecondTuesday -Year $Y -Month $M
} | ForEach-Object {

    Write-Verbose -Message "Query MS Patch Day API of SANS for date: $($_.ToString('yyyy-MM-dd'))" -Verbose
    $_.ToString('yyyy-MM-dd') | Get-SansMSPatchDay
} | Where { $_.clients -eq 'patch now' -or $_.servers -eq 'patch now' } | 
Select Id,Title,affected,
    @{l='kb';e={$_.kb -as [string]}},
    @{l='Known Exploits';e={
        switch($_.exploits) {
            'yes' { $true}
            'no'  {$false}
            default {}
    }},severity,clients,servers | ogv

NB1: you’ll see inconsistencies when affected components get named. You’ve got for example: IE, MSIE or Internet Explorer.
NB2: the SANS bulletin id’s are not numbered the same way Microsoft did before 2010. You’ve got MS90-32 instead of MS09-032 for example.

Don’t blame the SANS, they did a nice job by providing these REST API methods.

Bye Bye Makecert.exe

One of the goodness of PowerShell 5.0 on Windows 10 is that you can totally get rid of our brave old makecert.exe to create certificates. No more pain trying to remember where to download makecert.exe. You’ve now built in Windows 10 the New-SelfSignedCertificate cmdlet.

You can actually see the great improvements brought to the New-SelfSignedCertificate cmdlet if you compare its documentation for Windows 8.1 and its documenation page for Windows 10. Isn’t that awesome?

I’ll share 2 basic examples that will only scratch the surface of the extended capabilities of this cmdlet.

Here is an example to create a self-signed certificate used for code signing:

$HT = @{
 Subject = '';
 KeyLength = 2048;
 HashAlgorithm = 'SHA256';
 KeyUsage = 'DigitalSignature';
 KeyExportPolicy = 'Exportable';
 KeySpec = 'Signature';
 NotAfter = (Get-Date).AddYears(1) ;
 TextExtension = '{text}'
New-SelfSignedCertificate @HT

I’ve used the above code to create a certificate to sign PPKG files in a Windows 10 lab.

Here is a second example to create a self-signed certificate used for document/message encryption:

$HT = @{
 Subject = 'CN=me@contoso';
 KeyLength = 2048; 
 KeySpec = 'KeyExchange';
 HashAlgorithm = 'SHA1';
 KeyExportPolicy = 'Exportable';
 KeyUsage = 'KeyEncipherment','DataEncipherment' ;
 NotAfter = (Get-Date).AddYears(1);
 TextExtension = '{text}';
New-SelfSignedCertificate @HT

Now, you can start playing with the other goodness: the Protect-CmsMessage cmdlet

Here are a few links I bookmarked to get started on this topic:

Test-DSCConfiguration exceeds the maximum envelope size

I’ve recently encountered an error while I was using the Test-DSCConfiguration cmdlet:

The WS-Management service cannot process the request. The computed response packet size (519056) exceeds the maximum envelope size that is allowed (512000).


The Get-DscConfigurationStatus -All worked well and indicated that I had more than 400 resources in my config.

To fix it, I…

Set-WSManInstance -ValueSet @{MaxEnvelopeSizekb = "1000"} -ResourceURI winrm/config
dir WSMan:\localhost

…doubled the default value of 500KB and the Test-DSCConfiguration cmdlet worked back again as expected 🙂