Sometimes you need to check on the status of your applied updates and quickly. With news of the WannaCrypt/WannaCry Ransomware spreading via the MS17-010 vulnerability around the globe it’s a good idea to double check that all your updates are applied correctly.

 

The following is a quick PowerShell Execute Script monitor that you can add to Server Monitor to check for the presence of the HotFixes needed to mitigate MS17-010:

 

# KB4012598 KB4018466- Windows Server 2008
# KB4012217 KB4015551 KB4019216 - Windows Server 2012
# KB4012216 KB4015550 KB4019215 - Windows Server 2012 R2
# KB4013429 KB4019472 KB4015217 KB4015438 KB4016635 - Windows Server 2016

# List of all HotFixes containing the patch
$hotfixes = "KB4012598", "KB4018466", "KB4012217", "KB4015551", "KB4019216", "KB4012216", "KB4015550", "KB4019215", "KB4013429", "KB4019472", "KB4015217", "KB4015438", "KB4016635"

# Search for the HotFixes
$hotfix = Get-HotFix -ComputerName $mon.ComputerName | Where-Object {$hotfixes -contains $_.HotfixID} | Select-Object -property "HotFixID"

# See if the HotFix was found
if ($hotfix) {
    $mon.FireActions = $false
    $mon.Details = "Found HotFix: " + $hotfix.HotFixID
    # a blank value removes the property 
    $mon.SetComputerCustomPropByID(0, "NEEDS-MS17-010-FIX", "")
} else {
    $mon.FireActions = $true
    $mon.Details = "Didn't Find HotFix"
    $mon.SetComputerCustomPropByID(0, "NEEDS-MS17-010-FIX", "YES") 
}

 

The script should work in either Powershell v2 or v4 and contains all the Hot Fix numbers as of 5/16/2017 that contain the MS17-010 patch (each rollup update will replace the existing HotFix with a new KB number).

If you are using another version of Windows not listed above or if you’re trying to apply this to another vulnerability, the process for getting the KB numbers for the $hotfixes variable is:

  • 1 – Go to the Vulnerability’s page and locate the original KB number(s) for your systems
  • 2 – Use the original KB number(s) for the $hotfixes variable in the script above
  • 3 – Go to the Windows Update Catalog and search for the KB number
  • 4- Click the matching update(s)
  • 5 – Under the Package Details, add any KB numbers in the “This update has been replaced by the following updates” box to the $hotfixes variable
  • 6 – Repeat steps 4 and 5 for each additional Hot Fix number until you get to the Hot Fix number(s) that haven’t been replaced yet.
  • 7 – You should now have the full list of KB numbers that mitigate the vulnerability and you can deploy the script.

This is only a quick way to assess what systems are missing the fix right now. The current KB numbers will eventually be replaced as new Rollup updates get released and replace the previous ones. You can keep the HotFix List up to date by adding new KB Numbers to the $hotfixes variable, but hopefully once you know which systems are vulnerable you can make sure that they’re patched and remove the monitor entirely.

 

This script will fire alerts for each server that is missing the HotFix.  It also sets a Custom Property on the server. With the Custom Property set, you could create a Dynamic Group that will automatically contain all of the servers that need the HotFix.

 

list of servers needing MS17-010 HotFix

 

 

With the Dynamic Server List in place, you can create a Dynamic Group to easily see the servers that need to be updated.

Needs MS17-010 patch group

 

Finally, you can also run an Inventory Details report to get a list of affected server.

 

Dan is a brilliant software engineer here at Power Admin. He comes up with smart solutions that work for our customers.

Share →

25 Responses to How to check for MS17-010 and other HotFixes

  1. Gil says:

    Hi, thank you for this. it looks very useful.
    one question though, when i try to run it it fails with the message below. it seems to have some kind of a problem with the expression $mon. am i missing something? thanks

    Get-HotFix : Cannot validate argument on parameter ‘ComputerName’. The argument is null or empty. Provide an argument that is not null or empty,
    and then try the command again.
    At line:10 char:36
    + $hotfix = Get-HotFix -ComputerName $mon.ComputerName | Where-Object { …
    + ~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidData: (:) [Get-HotFix], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.GetHotFixCommand

    The property ‘FireActions’ cannot be found on this object. Verify that the property exists and can be set.
    At line:17 char:5
    + $mon.FireActions = $true
    + ~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : PropertyNotFound

    The property ‘Details’ cannot be found on this object. Verify that the property exists and can be set.
    At line:18 char:5
    + $mon.Details = “Didn’t Find HotFix”
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : PropertyNotFound

    • Doug N Doug N says:

      This script is specifically for PA Server Monitor’s Execute Script monitor. That is where $mon is defined. But you could remove that reference, and replace the computer name with a string and it will still work.

      • Allen Crist says:

        If you figure out how to make it work w/o PowerAdmin, can you please post here?

        • Doug N Doug N says:

          Sure. You can use the following, but change {your_servername_here}.

          $hotfixes = "KB4012212", "KB4012217", "KB4015551", "KB4019216", "KB4012216", "KB4015550", "KB4019215", "KB4013429", "KB4019472", "KB4015217", "KB4015438", "KB4016635"
          $hotfix = Get-HotFix -ComputerName "{your_servername_here}"| Where-Object {$hotfixes -contains $_.HotfixID} | Select-Object -property "HotFixID"
          if ($hotfix)
          {
          "Found HotFix: " + $hotfix.HotFixID
          } else {
          "Didn't Find HotFix"
          }

          (Note: The text is wrapping onto separate lines – it should be formatted the same as the original shown above)

          • Gil says:

            Perfect. works like a charm 🙂
            i think the next smart step for system admins would be to export a list of all of their AD server\workstation and somehow have the script run remotely against every single server\workstation to create a report

          • phil says:

            Or you could substitute $env:computername in place of {your_servername_here} instead of the actual server name and make the script server independent. :-}

  2. Allen Crist says:

    $hotfix = Get-HotFix -ComputerName $mon.ComputerName | Where-Object {$hotfixes -contains $_.HotfixID} | Select-Object -property “HotFixID”

    Yeilds “Get-Hotfix : Cannont validate argument on paramater ‘ComputerName’

  3. Brian says:

    Where do you find a comprehensive list of HotFixes that contain MS17-010 as more are released?

  4. Srinivas says:

    Thank you for the script this helped a lot and had a good learning playing around the KB checks. however if even one hotfix is installed. It might say required KB’s are installed.
    They are chances that not all KB’s Installed on the systems. requires to validate specific kb and get it installed.

  5. […] I updated a script I found on the internet so that it can be simply pasted into a PowerShell to check a […]

  6. Delvin says:

    Thank you, Doug, for such a useful script. I make some improvements for it.
    Added list of computers from txt file and a cycle to check this list.
    $hotfixes = “KB4012212”, “KB4012217”, “KB4015551”, “KB4019216”, “KB4012216”, “KB4015550”, “KB4019215”, “KB4013429”, “KB4019472”, “KB4015217”, “KB4015438”, “KB4016635”

    #This variant is for manual entry server names
    #$Computername = “server1”, “server2″,”server3″,”server4″,”server5”

    #This variant is for reading from file. Change the filename and fill it with the list of servers/workstations you want to check
    $Computername = Get-Content .\ListOfMachines.txt

    foreach ($comp in $Computername) {
    $hotfix = Get-HotFix -ComputerName “$Comp”| Where-Object {$hotfixes -contains $_.HotfixID} | Select-Object -property “HotFixID”
    if (Get-HotFix | Where-Object {$hotfixes -contains $_.HotfixID})
    {
    “Found HotFix on $Comp : ” + $hotfix.HotFixID
    } else {
    “Didn’t Find HotFix on $Comp”
    }
    }

  7. Paul says:

    Hey, Thanks for your help, but I have an other issue. When I launch the script (even on my local machine) I got :
    Get-HotFix : The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)

    I have use your script w/o PA and change your_servername_here for sur 😉
    Thanks

    • Paul says:

      My bad… for this error…
      But it do not find update installed…

      • Paul says:

        In fact it does not work across network but on the machine itself, it’s work.
        Thanks anyway for this script.

  8. Rob de Haan says:

    Just a quick one, if a server (2008 R2) does not have KB12215 (Monthly rollup March) installed, but it has KB19264 (Monthly rollup May) installed, can I assume it is covered?

    • Rob de Haan says:

      I meant KB4012215 and KB4019264

    • Dan H says:

      Yes, each rollup replaces the previous one, so includes the fixes from the previous one, but changes the KB number to look for.

      The process for working out all the KB numbers for a given fix is detailed in the numbered list in the article. You have to go through each update and see what KB numbers replace it. Then keep following the KB numbers until you get to one that hasn’t been replaced yet.

  9. Anonymous says:

    Shouldn’t the “if” be against $hotfix instead of Get-Hotfix?

    if ($hotfix | Where-Object {$hotfixes -contains $_.HotfixID})

  10. Ravi says:

    Thank you for the original script. There was bug in it and has been modified as follows and it can be run against an OU.
    $hotfixes = “KB4019472″,”KB4015217″,”KB4015438″,”KB4016635″,”KB4019215″,”KB4019216″,”KB4019263″,”KB4019264″,”KB4015549″,”KB4015550″,”KB4015551″,”KB4012216″,”KB4012217″,”KB4012598″,”KB4012213″,”KB4012214″,”KB4012215″,”KB4012212″,”KB4013429″,”KB4012606″,”KB4013198″

    #This variant is for manual entry server names
    # $Computernames = @([pscustomobject]@{Name=”VPOINTTEEST01″},[pscustomobject]@{Name=”VPOINT01”})

    #This variant is for reading from file. Change the filename and fill it with the list of servers/workstations you want to check
    $Computers = Get-Content .\ListOfMachines.txt
    $Computernames = @()
    ForEach ($computer in $Computers) {
    $object = New-Object System.Object
    $object | Add-Member -MemberType NoteProperty -Name ‘Name’ -Value $computer
    $Computernames += $object
    }

    # AD OU query
    #Import-Module ActiveDirectory
    #$Computernames = Get-ADComputer -Filter * -SearchBase “OU=Hosted_Servers,DC=hosted,DC=local” |Sort Name |Select Name

    foreach ($comp in $Computernames) {
    Try{
    $hotfix = Get-HotFix -ComputerName $Comp.Name | Where-Object {$hotfixes -contains $_.HotfixID} | Select-Object -First 1 -property “HotFixID”
    #if (Get-HotFix | Where-Object {$hotfixes -contains $_.HotfixID})
    if ($hotfix | Where-Object {$hotfixes -contains $_.HotfixID})
    {
    “Found HotFix on $($Comp.Name) : ” + $hotfix.HotFixID
    } else {
    “DID NOT Find HotFix on : $($Comp.Name)”
    }
    }
    Catch {“Unable to collect hotfix list for : $($Comp.Name)”}
    }

  11. Ravi says:

    Thank you for the script. There was a minor bug that has been fixed.
    $hotfixes = “KB4019472″,”KB4015217″,”KB4015438″,”KB4016635″,”KB4019215″,”KB4019216″,”KB4019263″,”KB4019264″,”KB4015549″,”KB4015550″,”KB4015551″,”KB4012216″,”KB4012217″,”KB4012598″,”KB4012213″,”KB4012214″,”KB4012215″,”KB4012212″,”KB4013429″,”KB4012606″,”KB4013198″

    #This variant is for manual entry server names
    # $Computernames = @([pscustomobject]@{Name=”VPOINTTEEST01″},[pscustomobject]@{Name=”VPOINT01”})

    #This variant is for reading from file. Change the filename and fill it with the list of servers/workstations you want to check
    $Computers = Get-Content .\ListOfMachines.txt
    $Computernames = @()
    ForEach ($computer in $Computers) {
    $object = New-Object System.Object
    $object | Add-Member -MemberType NoteProperty -Name ‘Name’ -Value $computer
    $Computernames += $object
    }

    # AD OU query
    #Import-Module ActiveDirectory
    #$Computernames = Get-ADComputer -Filter * -SearchBase “OU=YOUR_Servers,DC=YOUR,DC=local” |Sort Name |Select Name

    foreach ($comp in $Computernames) {
    Try{
    $hotfix = Get-HotFix -ComputerName $Comp.Name | Where-Object {$hotfixes -contains $_.HotfixID} | Select-Object -First 1 -property “HotFixID”
    #if (Get-HotFix | Where-Object {$hotfixes -contains $_.HotfixID})
    if ($hotfix | Where-Object {$hotfixes -contains $_.HotfixID})
    {
    “Found HotFix on $($Comp.Name) : ” + $hotfix.HotFixID
    } else {
    “DID NOT Find HotFix on : $($Comp.Name)”
    }
    }
    Catch {“Unable to collect hotfix list for : $($Comp.Name)”}
    }

  12. Swami says:

    AWESOME AWESOME.. Great job. keep it up..

  13. Wolle says:

    Hi,

    the script work in nework by changing the if statemant to:
    if ($hotfix) ….

    Thanks for the script, have a nice day
    Wolle

  14. Fanaz says:

    # Supress errors
    $ErrorActionPreference = “SilentlyContinue”

    # List of KB’s
    $hotfixes = “KB4012212”, “KB4012213”, “KB4012214”, “KB4012215”, “KB4012216”, “KB4012217”, “KB4012219”, “KB4012220”, “KB4012598”, “KB4012606”, “KB4013198”, “KB4013429”, “KB4015217”, “KB4015438”, “KB4015549”, “KB4015550”, “KB4015551”, “KB4015552”, “KB4015553”, “KB4015554”, “KB4016635”, “KB4019215”, “KB4019216”, “KB4019264”, “KB4019472”

    # Get Computers list from AD
    $ComputerList = Get-ADComputer -Filter * | Select-Object -ExpandProperty ‘Name’

    # Check every Computer for a list of KB’s
    foreach ($computer in $ComputerList)
    {
    if (-not (Test-Connection $computer -Count 1 -quiet)) { Write-Warning “$computer is offline”
    continue }

    $hotfix = Get-HotFix -ComputerName $computer | Where-Object -FilterScript { $hotfixes -contains $_.HotfixID } | Select-Object -ExpandProperty ‘HotFixID’

    if ($hotfix) { Write-Warning “$computer has: $hotfix” }
    else { Write-Warning “$computer has: NONE” }
    }

  15. Andrew says:

    Many thanks for this script.

    FYI, the latest KB for Windows Server 2008 is not included above. It is: KB4018466

  16. Stom says:

    Here is the script as a powershell function:
    ———————————————————
    Function Check-HotFix
    {
    param
    (
    [string]
    $computer = (Get-Childitem env:computername).Value
    )

    BEGIN
    {
    # KB4012598 KB4018466 – Windows Server 2008
    # KB4012217 KB4015551 KB4019216 – Windows Server 2012
    # KB4012216 KB4015550 KB4019215 – Windows Server 2012 R2
    # KB4013429 KB4019472 KB4015217 KB4015438 KB4016635 – Windows Server 2016
    # KB4012212 KB4012215 – Windows 7

    # List of all HotFixes containing the patch
    $hotfixes = “KB4012212”, “KB4012215”, “KB4012598”, “KB4018466”, “KB4012217”, “KB4015551”, “KB4019216”, “KB4012216”, “KB4015550”, “KB4019215”, “KB4013429”, “KB4019472”, “KB4015217”, “KB4015438”, “KB4016635”
    }

    PROCESS
    {
    # Search for the HotFixes
    $hotfix = Get-HotFix -ComputerName $computer | Where-Object {$hotfixes -contains $_.HotfixID} | Select-Object -property “HotFixID”

    # See if the HotFix was found
    if ($hotfix)
    {
    $result = “Found HotFix: ” + $hotfix.HotFixID
    }
    else
    {
    $result = “Didn’t Find HotFix!”
    }

    return $result
    }
    }

(ec2)