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:)

Configure the firewall profile with DSC (Part 3)

The third part deals with the most advanced or modern way of creating custom DSC resources.
Sorry, this time, there’s no helper module😦 but there’s an excellent documentation on MSDN on this page😀

mkdir 'C:\Program Files\WindowsPowerShell\Modules\xFirewallProfile'

$Manifest = @{
    Path = 'C:\Program Files\WindowsPowerShell\Modules\xFirewallProfile\xFirewallProfile.psd1'
    RootModule = 'xFirewallProfile.psm1'
    Guid = ([guid]::NewGuid().Guid) ;
    Author  = 'Emin Atac' ;
    CompanyName  = 'Emin Atac'
    Copyright = 'Free to use'
    ModuleVersion = '1.0.0'
    PowerShellVersion = '5.0'
    DscResourcesToExport = 'ClassFirewallProfile'
New-ModuleManifest @Manifest -Verbose

psedit "C:\Program Files\WindowsPowerShell\Modules\xFirewallProfile\xFirewallProfile.psm1"

NB: Notice that the RootModule and DscResourcesToExport statements added to the manifest.

Now here’s what to paste into the xFirewallProfile.psm1 file.

Let’s first examine the syntax.

Looks good. Let’s create a configuration to test it. This isn’t much different from what we saw in part 2.

If my machine is already configured as expected, I’ll get:

If I change the domain profile and reapply my configuration, it’s set back to its desired state

Configure the firewall profile with DSC (Part 2)

The 2nd part deals with the classic way of creating custom DSC resources.
To help demo that, there’s actually an xDSCResourceDesginer module available in the PowerShell Gallery (a.k.a. PSGallery).

Here’s what I run if it’s not installed

# 1. Get the module and load it
Find-Module -Name xDSCResourceDesigner -Repository PsGallery -Verbose
Install-Module -Name xDSCResourceDesigner -Repository PsGallery -Verbose
Import-Module -Name xDSCResourceDesigner -Force -Verbose

There are only a few steps required to get started

# 2. Create the resource
$resource = @{
    Name = 'cFirewallProfile';
    Property  = (New-xDscResourceProperty -Name 'Name' -Type 'String' -Attribute = 'Key' -ValidateSet 'Domain','Public','Private'),
                (New-xDscResourceProperty -Name "Enabled" -Type "String" -Attribute Required -ValidateSet 'True','False','NotConfigured'),
                (New-xDscResourceProperty -Name DefaultInboundAction -Type "String" -Attribute Required -ValidateSet 'Allow','Block','NotConfigured'),
                (New-xDscResourceProperty -Name DefaultOutboundAction -Type "String" -Attribute Required -ValidateSet 'Allow','Block','NotConfigured')
    Path = 'C:\Program Files\WindowsPowerShell\Modules\cFirewallProfile';
    ClassVersion = '1.0' ;
    FriendlyName = 'cFirewallProfile' ;
    Force = $true ;
New-xDscResource @resource

# 3. Create its manifest
$Manifest = @{
    Path = 'C:\Program Files\WindowsPowerShell\Modules\cFirewallProfile\cFirewallProfile.psd1'
    Guid = ([guid]::NewGuid().Guid) ;
    Author  = 'Emin Atac' ;
    CompanyName  = 'Emin Atac'
    Copyright = 'Free to use'
    ModuleVersion = '1.0.0'
    PowerShellVersion = '4.0'
    FunctionsToExport = 'Get-TargetResource','Test-TargetResource','Set-TargetResource'
New-ModuleManifest @Manifest -Verbose

# 4. Ready to edit the resource
psedit 'C:\Program Files\WindowsPowerShell\Modules\cFirewallProfile\DSCResources\cFirewallProfile\cFirewallProfile.psm1'

All the parameters of the 3 functions have been populated automatically thanks to the New-xDscResource and New-xDscResourceProperty cmdlets and we only have to focus and create the body of these functions. Nice isn’t it?

Here’s what to paste inside the cFirewallProfile.psm1 file.

Now, I can use the above custom DSC resource to configure the firewall profiles:

Configuration TestFirewallProfileConfig {

    Param (
        [string[]]$NodeName = 'localhost'

    Import-DscResource -Name * -ModuleName 'cFirewallProfile';

    Node $NodeName
        Foreach ($fw in @('Domain','Public','Private'))
            cFirewallProfile "$($fw)"
                Name = "$($fw)"
                Enabled = 'True'
                DefaultInboundAction = 'Block' ;
                DefaultOutboundAction = 'Allow' ;

The last step consists in compiling the configuration into a MOF file and applying it like this:

if (-not(test-path -Path C:\DSC -PathType Container)){
    mkdir C:\DSC
# Compile into MOF file
TestFirewallProfileConfig -OutputPath C:\DSC 

# Apply
Start-DscConfiguration -Path C:\DSC -ComputerName localhost -Verbose -Force -Wait

To be able to test it, I’ll set the exact opposite way I want it to be. Don’t do that on a production server.

Set-NetFirewallProfile -All -DefaultInboundAction Allow -DefaultOutboundAction Block  -Enabled false

When I apply the configuration, we can see all the 3 profiles being configured:

If I ask whether the system is in its desired state with the Test-DscConfiguration cmdlet, I get:
If I refresh the wf.msc MMC snap-in I’ve actually restored back the defaults thanks to my DSC configuration.

Let’s say I only mess up the Domain profile.

When I (re)apply the configuration, there’s only one profile that is being reconfigured before the Test-DscConfiguration cmdlet tells me it’s compliant again😀


Configure the firewall profile with DSC (Part 1)

I was preparing a DSC configuration for a new server this week and after configuring firewall rules with the xNetworking DSC resources available on the PowerShell Gallery, I realized that having only rules without configuring the firewall profiles is wrong.

Keep in mind DSC is for compliance not security.
In my opinion, we should first configure the firewall rules AND then the firewall profiles.
If you’ve got the rules and an admin turns the firewall off, DSC will either tell you and/or fix the problem depending on the way you configured the ConfigurationMode of the LCM (Local Configuration Manager)
In this case, I’d suggest that the xfirewall DSC should be renamed to xFirewallRule and a new DSC resource xFirewallProfile should be added.

As I was in a hurry, here is the quick and dirty way I used to configure the firewall profiles:

As you can see, I had to explicitly use scopes inside the TestScript block.
In the meantime, I’ve discovered what scopes can be used inside a Tescript block. Using the global or local scope worked but not the script scope.
Using the Set-Variable to define the problem variable in the parent scope didn’t work either.

You may also have noticed that I’ve hardcoded the firewall state, its DefaultInboundAction and DefaultOutboundAction properties.
We’ll see in Part 2 how to create a proper DSC resource and use these as parameters.

WMF 5.0 RTM republished

I’ve already announced on my blog that WMF 5.0 is RTM but I also kept the post updated with comments about the issue with the PSModulePath environment variable raised on the UserVoice site than led to the removal of KB3094174, KB3094175, and KB3094176 packages published by the end of December.

Now, I’m very pleased to announce that Windows Management Framework (WMF) 5.0 RTM packages has been republished. The PowerShell Team deserves a big thank you for fixing the issue and also for keeping us in touch along their journey. Drum roll😀

All the reasons I exposed in my previous blog post explaining why WMF5 is such a huge milestone are still valid.
The only update required is the table that listed package names, their download link and their SHA256 checksums.
So, here we go:

Operating System Architecture Package Name SHA256
Windows Server 2012 R2 x64 Win8.1AndW2K12R2-KB3134758-x64.msu BB6AF4547545B5D10D8EF239F47D59DE76DAFF06F05D0ED08C73EFF30B213BF2
Windows Server 2012 x64 W2K12-KB3134759-x64.msu 6E59CEC4BD30C505F426A319673A13C4A9AA8D8FF69FD0582BFA89F522F5FF00
Windows Server 2008 R2 x64 Win7AndW2K8R2-KB3134760-x64.msu 077E864CC83739AC53750C97A506E1211F637C3CD6DA320C53BB01ED1EF7A98B
Windows 8.1 x64 Win8.1AndW2K12R2-KB3134758-x64.msu BB6AF4547545B5D10D8EF239F47D59DE76DAFF06F05D0ED08C73EFF30B213BF2
Windows 8.1 x86 Win8.1-KB3134758-x86.msu F9EE4BF2D826827BC56CD58FABD0529CB4B49082B2740F212851CC0CC4ACBA06
Windows 7 SP1 x64 Win7AndW2K8R2-KB3134760-x64.msu 077E864CC83739AC53750C97A506E1211F637C3CD6DA320C53BB01ED1EF7A98B
Windows 7 SP1 x86 Win7-KB3134760-x86.msu 0486901B4FD9C41A70644E3A427FE06DD23765F1AD8B45C14BE3321203695464

Here’s WMF 5.0 RTM republished on Windows 7