Script Powershell para verificação remota do Spectre e Meltdown em uma lista de computadores.

 

Nesta publicação, daremos uma olhada no  SpeculationControl PowerShell module que foi lançado recentemente pela Microsoft Security Response Center para ajudar a verificar as proteções Spectre e Meltdown.
SpeculationControl pode ser econtrado no PowerShell Gallery conforme link abaixo link: https://www.powershellgallery.com/packages/SpeculationControl

Ao instalar este módulo em um sistema será adiciona uma nova função chamada Get-SpeculationControlSettings e esta função pode ser executada em um sistema para fornecer detalhes para verificar se as proteções contra Spectre e Meltdown estão habilitadas.

 

E se você quisesse executar isso remotamente contra vários sistemas?

Para rodar a funçao Get-SpeculationControlSettings em multiplos sistemas, veja o exemplo abaixo.

(Credit goes to Keith Hitchcock for his help on this)

Import-Module SpeculationControl
$scriptstring = Get-Content Path (Get-Module SpeculationControl).Path | % { if (-not ($_ -match “^\# “)) { $_ }} | Out-String
$scriptstring +=
function Write-Host {}
$scriptstring += ‘Get-SpeculationControlSettings’
$script=[scriptblock]::create($scriptstring)
Invoke-Command ComputerName localhost, system2, system3 ScriptBlock $script

Esse exemplo requer que você tenha o módulo SpeculationControl instalado no sistema que será executado esse código. Por causa da forma como a função Get-SpeculationControlSettings está estruturada, podemos simplesmente carregar a função remotamente como parte da chamada para Invoke-Command.

Para executar este código de exemplo em um ambiente, a única atualização necessária é a lista de máquinas que seguem -ComputerName. Se você preferir passar em uma lista de sistemas em um arquivo de texto, o código de exemplo pode ser facilmente modificado para receber um arquivo de texto de entrada utilizando o cmdlet Get-Content.

Import-Module SpeculationControl
$scriptstring = Get-Content Path (Get-Module SpeculationControl).Path | % { if (-not ($_ -match “^\# “)) { $_ }} | Out-String
$scriptstring +=
function Write-Host {}
$scriptstring += ‘Get-SpeculationControlSettings’
$script=[scriptblock]::create($scriptstring)
$InputFile = “C:\Temp\computers.txt”
$RemoteComputers = Get-Content $InputFile
Invoke-Command ComputerName $RemoteComputers ScriptBlock $script

Exemplo de saída

Embora seja bom, podemos dar um passo adiante, lançando os resultados para o CSV, o que tornará as coisas mais fáceis de consumir, especialmente quando começamos a adicionar mais sistemas à lista.
Examplo abaixo:

Import-Module SpeculationControl
$scriptstring = Get-Content Path (Get-Module SpeculationControl).Path | % { if (-not ($_ -match “^\# “)) { $_ }} | Out-String
$scriptstring +=
function Write-Host {}
$scriptstring += ‘Get-SpeculationControlSettings’
$script=[scriptblock]::create($scriptstring)
$results = Invoke-Command ComputerName localhost, system2, system3 ScriptBlock $script
$results | Export-Csv .\SpeculationControlSettings.csv NoTypeInformation

Exemplo de saída

Isso agora é mais fácil de digerir e podemos classificar e aplicar filtros conforme necessário.

Neste ponto, usamos o módulo SpeculationControl para executá-lo através de alguns exemplos que o levam além da execução local e nos ajudam a revisar sistemas remotos em um ambiente.
Em seguida, analisaremos o uso do módulo SpeculationControl junto com outro módulo PowerShell chamado DSCEA. O DSCEA fornece testes de configuração e recursos de relatórios para sistemas baseados no Windows, e analisaremos como podemos usá-lo para obter alguma inteligência a partir dos dados que podemos reunir remotamente.
Por exemplo, digamos que sua equipe de gerenciamento está procurando por números, especificamente, quantas máquinas existem em seu ambiente que ainda não foram corrigidas para a vulnerabilidade CVE-2017-5754 de carga de cache de dados (Meltdown).

Embora pudéssemos pedir a alguém que olhe através do arquivo CSV e compare sistemas em várias colunas, eu prefiro que um computador forneça essa informação.

Há alguns pontos a fazer antes de seguir o caminho do DSCEA. O DSCEA requer uma versão mínima do PowerShell 5.0, com 5.1 sendo recomendado. Além disso, o DSCEA exigiria que o módulo SpeculationControl fosse instalado em todos os pontos finais que estão sendo digitalizados. Embora existam algumas maneiras fáceis de lidar com isso, incluindo a inclusão de uma configuração DSC que utiliza o recurso DSC File, ou apenas um script de cópia de arquivo, para este exemplo, eu incluo toda a função Get-SpeculationControlSettings como parte da minha configuração DSC personalizada . Isso torna isso muito mais fácil de demonstrar, mas exige atualizações de código se houver atualizações no módulo SpeculationControl no futuro.
Esta seção assumirá que você baixou o DSCEA e tem algum conhecimento sobre seu uso. Se você não fizer isso, clique aqui para saber mais.

 

Copiei a configuração DSC no final desta publicação que será usada para verificar se os sistemas foram corrigidos para Meltdown. Você usará essa configuração para criar um arquivo MOF que você usará com o DSCEA para escanear sistemas para ver se eles possuem as atualizações e configurações adequadas habilitadas.

A configuração vem com a seguinte lógica definida para determinar se um sistema foi configurado corretamente em relação ao Meltdown:

$compliance = $false
$SpeculationControlSettings = Get-SpeculationControlSettings
if ($SpeculationControlSettings.KVAShadowRequired -eq $False) {
$compliance = $True
}
elseif ($SpeculationControlSettings.KVAShadowRequired -eq $True -and `
$SpeculationControlSettings.KVAShadowWindowsSupportPresent -eq $True -and `
$SpeculationControlSettings.KVAShadowWindowsSupportEnabled -eq $True -and `
$SpeculationControlSettings.KVAShadowPcidEnabled -eq $True) {
$compliance = $True
}
return $compliance

DSCEA HTML Exemplo de relatório
Nesse caso, todos os 3 sistemas não são compatíveis, o que significa que precisam ser revisados ​​para obter as atualizações e configurações adequadas.

 

DSC – Configuração

configuration VerifySpeculationControlSettings {
Import-DscResource ModuleName PSDesiredStateConfiguration
Node ‘localhost’ {
Script ‘SpeculationControlSettings’ {
GetScript = {
#Not used
}
TestScript = {
function Get-SpeculationControlSettings {
<#
.SYNOPSIS
This function queries the speculation control settings for the system.
.DESCRIPTION
This function queries the speculation control settings for the system.
Version 1.3.
#>
[CmdletBinding()]
param (
)
process {
$NtQSIDefinition = @’
[DllImport(“ntdll.dll”)]
public static extern int NtQuerySystemInformation(uint systemInformationClass, IntPtr systemInformation, uint systemInformationLength, IntPtr returnLength);
‘@
$ntdll = Add-Type MemberDefinition $NtQSIDefinition Name ‘ntdll’ Namespace ‘Win32’ PassThru
[System.IntPtr]$systemInformationPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal(4)
[System.IntPtr]$returnLengthPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal(4)
$object = New-Object TypeName PSObject
try {
#
# Query branch target injection information.
#
Write-Host “Speculation control settings for CVE-2017-5715 [branch target injection]” ForegroundColor Cyan
Write-Host
$btiHardwarePresent = $false
$btiWindowsSupportPresent = $false
$btiWindowsSupportEnabled = $false
$btiDisabledBySystemPolicy = $false
$btiDisabledByNoHardwareSupport = $false
[System.UInt32]$systemInformationClass = 201
[System.UInt32]$systemInformationLength = 4
$retval = $ntdll::NtQuerySystemInformation($systemInformationClass, $systemInformationPtr, $systemInformationLength, $returnLengthPtr)
if ($retval -eq 0xc0000003 -or $retval -eq 0xc0000002) {
# fallthrough
}
elseif ($retval -ne 0) {
throw ((“Querying branch target injection information failed with error {0:X8}” -f $retval))
}
else {
[System.UInt32]$scfBpbEnabled = 0x01
[System.UInt32]$scfBpbDisabledSystemPolicy = 0x02
[System.UInt32]$scfBpbDisabledNoHardwareSupport = 0x04
[System.UInt32]$scfHwReg1Enumerated = 0x08
[System.UInt32]$scfHwReg2Enumerated = 0x10
[System.UInt32]$scfHwMode1Present = 0x20
[System.UInt32]$scfHwMode2Present = 0x40
[System.UInt32]$scfSmepPresent = 0x80
[System.UInt32]$flags = [System.UInt32][System.Runtime.InteropServices.Marshal]::ReadInt32($systemInformationPtr)
$btiHardwarePresent = ((($flags -band $scfHwReg1Enumerated) -ne 0) -or (($flags -band $scfHwReg2Enumerated)))
$btiWindowsSupportPresent = $true
$btiWindowsSupportEnabled = (($flags -band $scfBpbEnabled) -ne 0)
if ($btiWindowsSupportEnabled -eq $false) {
$btiDisabledBySystemPolicy = (($flags -band $scfBpbDisabledSystemPolicy) -ne 0)
$btiDisabledByNoHardwareSupport = (($flags -band $scfBpbDisabledNoHardwareSupport) -ne 0)
}
if ($PSBoundParameters[‘Verbose’]) {
Write-Host “BpbEnabled :” (($flags -band $scfBpbEnabled) -ne 0)
Write-Host “BpbDisabledSystemPolicy :” (($flags -band $scfBpbDisabledSystemPolicy) -ne 0)
Write-Host “BpbDisabledNoHardwareSupport :” (($flags -band $scfBpbDisabledNoHardwareSupport) -ne 0)
Write-Host “HwReg1Enumerated :” (($flags -band $scfHwReg1Enumerated) -ne 0)
Write-Host “HwReg2Enumerated :” (($flags -band $scfHwReg2Enumerated) -ne 0)
Write-Host “HwMode1Present :” (($flags -band $scfHwMode1Present) -ne 0)
Write-Host “HwMode2Present :” (($flags -band $scfHwMode2Present) -ne 0)
Write-Host “SmepPresent :” (($flags -band $scfSmepPresent) -ne 0)
}
}
Write-Host “Hardware support for branch target injection mitigation is present:”($btiHardwarePresent) ForegroundColor $(If ($btiHardwarePresent) { [System.ConsoleColor]::Green } Else { [System.ConsoleColor]::Red })
Write-Host “Windows OS support for branch target injection mitigation is present:”($btiWindowsSupportPresent) ForegroundColor $(If ($btiWindowsSupportPresent) { [System.ConsoleColor]::Green } Else { [System.ConsoleColor]::Red })
Write-Host “Windows OS support for branch target injection mitigation is enabled:”($btiWindowsSupportEnabled) ForegroundColor $(If ($btiWindowsSupportEnabled) { [System.ConsoleColor]::Green } Else { [System.ConsoleColor]::Red })
if ($btiWindowsSupportPresent -eq $true -and $btiWindowsSupportEnabled -eq $false) {
Write-Host ForegroundColor Red “Windows OS support for branch target injection mitigation is disabled by system policy:”($btiDisabledBySystemPolicy)
Write-Host ForegroundColor Red “Windows OS support for branch target injection mitigation is disabled by absence of hardware support:”($btiDisabledByNoHardwareSupport)
}
$object | Add-Member MemberType NoteProperty Name BTIHardwarePresent Value $btiHardwarePresent
$object | Add-Member MemberType NoteProperty Name BTIWindowsSupportPresent Value $btiWindowsSupportPresent
$object | Add-Member MemberType NoteProperty Name BTIWindowsSupportEnabled Value $btiWindowsSupportEnabled
$object | Add-Member MemberType NoteProperty Name BTIDisabledBySystemPolicy Value $btiDisabledBySystemPolicy
$object | Add-Member MemberType NoteProperty Name BTIDisabledByNoHardwareSupport Value $btiDisabledByNoHardwareSupport
#
# Query kernel VA shadow information.
#
Write-Host
Write-Host “Speculation control settings for CVE-2017-5754 [rogue data cache load]” ForegroundColor Cyan
Write-Host
$kvaShadowRequired = $true
$kvaShadowPresent = $false
$kvaShadowEnabled = $false
$kvaShadowPcidEnabled = $false
$cpu = Get-WmiObject Win32_Processor
if ($cpu.Manufacturer -eq “AuthenticAMD”) {
$kvaShadowRequired = $false
}
elseif ($cpu.Manufacturer -eq “GenuineIntel”) {
$regex = [regex]‘Family (\d+) Model (\d+) Stepping (\d+)’
$result = $regex.Match($cpu.Description)
if ($result.Success) {
$family = [System.UInt32]$result.Groups[1].Value
$model = [System.UInt32]$result.Groups[2].Value
$stepping = [System.UInt32]$result.Groups[3].Value
if (($family -eq 0x6) -and
(($model -eq 0x1c) -or
($model -eq 0x26) -or
($model -eq 0x27) -or
($model -eq 0x36) -or
($model -eq 0x35))) {
$kvaShadowRequired = $false
}
}
}
else {
throw (“Unsupported processor manufacturer: {0}” -f $cpu.Manufacturer)
}
[System.UInt32]$systemInformationClass = 196
[System.UInt32]$systemInformationLength = 4
$retval = $ntdll::NtQuerySystemInformation($systemInformationClass, $systemInformationPtr, $systemInformationLength, $returnLengthPtr)
if ($retval -eq 0xc0000003 -or $retval -eq 0xc0000002) {
}
elseif ($retval -ne 0) {
throw ((“Querying kernel VA shadow information failed with error {0:X8}” -f $retval))
}
else {
[System.UInt32]$kvaShadowEnabledFlag = 0x01
[System.UInt32]$kvaShadowUserGlobalFlag = 0x02
[System.UInt32]$kvaShadowPcidFlag = 0x04
[System.UInt32]$kvaShadowInvpcidFlag = 0x08
[System.UInt32]$flags = [System.UInt32][System.Runtime.InteropServices.Marshal]::ReadInt32($systemInformationPtr)
$kvaShadowPresent = $true
$kvaShadowEnabled = (($flags -band $kvaShadowEnabledFlag) -ne 0)
$kvaShadowPcidEnabled = ((($flags -band $kvaShadowPcidFlag) -ne 0) -and (($flags -band $kvaShadowInvpcidFlag) -ne 0))
if ($PSBoundParameters[‘Verbose’]) {
Write-Host “KvaShadowEnabled :” (($flags -band $kvaShadowEnabledFlag) -ne 0)
Write-Host “KvaShadowUserGlobal :” (($flags -band $kvaShadowUserGlobalFlag) -ne 0)
Write-Host “KvaShadowPcid :” (($flags -band $kvaShadowPcidFlag) -ne 0)
Write-Host “KvaShadowInvpcid :” (($flags -band $kvaShadowInvpcidFlag) -ne 0)
}
}
Write-Host “Hardware requires kernel VA shadowing:”$kvaShadowRequired
if ($kvaShadowRequired) {
Write-Host “Windows OS support for kernel VA shadow is present:”$kvaShadowPresent ForegroundColor $(If ($kvaShadowPresent) { [System.ConsoleColor]::Green } Else { [System.ConsoleColor]::Red })
Write-Host “Windows OS support for kernel VA shadow is enabled:”$kvaShadowEnabled ForegroundColor $(If ($kvaShadowEnabled) { [System.ConsoleColor]::Green } Else { [System.ConsoleColor]::Red })
if ($kvaShadowEnabled) {
Write-Host “Windows OS support for PCID performance optimization is enabled: $kvaShadowPcidEnabled [not required for security]” ForegroundColor $(If ($kvaShadowPcidEnabled) { [System.ConsoleColor]::Green } Else { [System.ConsoleColor]::Blue })
}
}
$object | Add-Member MemberType NoteProperty Name KVAShadowRequired Value $kvaShadowRequired
$object | Add-Member MemberType NoteProperty Name KVAShadowWindowsSupportPresent Value $kvaShadowPresent
$object | Add-Member MemberType NoteProperty Name KVAShadowWindowsSupportEnabled Value $kvaShadowEnabled
$object | Add-Member MemberType NoteProperty Name KVAShadowPcidEnabled Value $kvaShadowPcidEnabled
#
# Provide guidance as appropriate.
#
$actions = @()
if ($btiHardwarePresent -eq $false) {
$actions += “Install BIOS/firmware update provided by your device OEM that enables hardware support for the branch target injection mitigation.”
}
if ($btiWindowsSupportPresent -eq $false -or $kvaShadowPresent -eq $false) {
$actions += “Install the latest available updates for Windows with support for speculation control mitigations.”
}
if (($btiHardwarePresent -eq $true -and $btiWindowsSupportEnabled -eq $false) -or ($kvaShadowRequired -eq $true -and $kvaShadowEnabled -eq $false)) {
$guidanceUri = “”
$guidanceType = “”
$os = Get-WmiObject Win32_OperatingSystem
if ($os.ProductType -eq 1) {
# Workstation
$guidanceUri = “https://support.microsoft.com/help/4073119”
$guidanceType = “Client”
}
else {
# Server/DC
$guidanceUri = “https://support.microsoft.com/help/4072698”
$guidanceType = “Server”
}
$actions += “Follow the guidance for enabling Windows $guidanceType support for speculation control mitigations described in $guidanceUri
}
if ($actions.Length -gt 0) {
Write-Host
Write-Host “Suggested actions” ForegroundColor Cyan
Write-Host
foreach ($action in $actions) {
Write-Host ” *” $action
}
}
return $object
}
finally
{
if ($systemInformationPtr -ne [System.IntPtr]::Zero) {
[System.Runtime.InteropServices.Marshal]::FreeHGlobal($systemInformationPtr)
}
if ($returnLengthPtr -ne [System.IntPtr]::Zero) {
[System.Runtime.InteropServices.Marshal]::FreeHGlobal($returnLengthPtr)
}
}
}
}
$compliance = $false
$SpeculationControlSettings = Get-SpeculationControlSettings
if ($SpeculationControlSettings.KVAShadowRequired -eq $False) {
$compliance = $True
}
elseif ($SpeculationControlSettings.KVAShadowRequired -eq $True -and `
$SpeculationControlSettings.KVAShadowWindowsSupportPresent -eq $True -and `
$SpeculationControlSettings.KVAShadowWindowsSupportEnabled -eq $True -and `
$SpeculationControlSettings.KVAShadowPcidEnabled -eq $True) {
$compliance = $True
}
return $compliance
}
SetScript = {
#Not used
}
}
}
}
VerifySpeculationControlSettings OutputPath .\