Via the main SCCM Management Console
- Click on Assets and Compliance Section
- Click on Compliance Settings, Configuration Items
- Click on Create Configuration Item ( I won't detail all the screens here - skipping to the "Settings" section - specify name, description, supported platforms etc as you see fit.
- You want to create a new Settings with a Setting Type of Script and a Data type of String.
Now we'll specify the Discovery Script and the Remediation Script
Discovery Script (Script Language : Powershell)
$Services = Get-WmiObject -Class Win32_Service
$Compliant = ""
$Services | % {
#Check the path of each service, locate .exe in the path string, then check if any spaces in the path
#Also check if any " in the path before the EXE. If no " and a space exists, then its not compliant
$ServiceName = $_.Name
$ServiceEXEPath = $_.PathName
#$RegKey = Get-ChildItem "HKLM:\SYSTEM\CurrentControlSet\Services\$ServiceName"
$RegPath = (Get-itemproperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\$ServiceName").ImagePath
$IndexOfSpace = $RegPath.IndexOf(" ")
$IndexOfEXE = $RegPath.IndexOf(".exe")
$IndexOfQuote = $RegPath.IndexOf("`"")
if (($IndexOfSpace -ne -1) -and ($IndexOfSpace -lt $IndexOfEXE) -and ($IndexOfQuote -ne 0))
{
$newpath = "`"" + $Regpath.substring(0,$IndexofEXE+4) + "`""
#Write-Host "[$ServiceName][$ServiceEXEPath][$RegPath][$IndexOfSpace][$IndexOfEXE][$IndexOfQuote][$NewPath]"
$Compliant += "[$ServiceName][$ServiceEXEPath]`n"
}
}
if ($Compliant.length -eq 0)
{
$Compliant = "Compliant"
}
$Compliant
Remediation Script (Script Language : Powershell)
$Services = Get-WmiObject -Class Win32_Service
$Services | % {
#Check the path of each service, locate .exe in the path string, then check if any spaces in the path
#Also check if any " in the path before the EXE. If no " and a space exists, then its not compliant
$ServiceName = $_.Name
$ServiceEXEPath = $_.PathName
#$RegKey = Get-ChildItem "HKLM:\SYSTEM\CurrentControlSet\Services\$ServiceName"
$RegPath = (Get-itemproperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\$ServiceName").ImagePath
$IndexOfSpace = $RegPath.IndexOf(" ")
$IndexOfEXE = ($RegPath.toupper()).IndexOf(".EXE")
$IndexOfQuote = $RegPath.IndexOf("`"")
if (($IndexOfSpace -ne -1) -and ($IndexOfSpace -lt $IndexOfEXE) -and ($IndexOfQuote -ne 0))
{
$newpath = "`"" + $Regpath.substring(0,$IndexofEXE+4) + "`""
if (($RegPath.length) -gt ($IndexOfEXE+4))
{
$newpath += $RegPath.substring($IndexOfEXE+4,($Regpath.length - $IndexofEXE - 4))
}
#Write-Host "[$ServiceName]`n[$ServiceEXEPath]`n[$IndexOfSpace][$IndexOfEXE][$IndexOfQuote]`n[$NewPath]"
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\$ServiceName" -Name ImagePath -Value $newpath
}
}
$Services | % {
#Check the path of each service, locate .exe in the path string, then check if any spaces in the path
#Also check if any " in the path before the EXE. If no " and a space exists, then its not compliant
$ServiceName = $_.Name
$ServiceEXEPath = $_.PathName
#$RegKey = Get-ChildItem "HKLM:\SYSTEM\CurrentControlSet\Services\$ServiceName"
$RegPath = (Get-itemproperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\$ServiceName").ImagePath
$IndexOfSpace = $RegPath.IndexOf(" ")
$IndexOfEXE = ($RegPath.toupper()).IndexOf(".EXE")
$IndexOfQuote = $RegPath.IndexOf("`"")
if (($IndexOfSpace -ne -1) -and ($IndexOfSpace -lt $IndexOfEXE) -and ($IndexOfQuote -ne 0))
{
$newpath = "`"" + $Regpath.substring(0,$IndexofEXE+4) + "`""
if (($RegPath.length) -gt ($IndexOfEXE+4))
{
$newpath += $RegPath.substring($IndexOfEXE+4,($Regpath.length - $IndexofEXE - 4))
}
#Write-Host "[$ServiceName]`n[$ServiceEXEPath]`n[$IndexOfSpace][$IndexOfEXE][$IndexOfQuote]`n[$NewPath]"
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\$ServiceName" -Name ImagePath -Value $newpath
}
}
This should allow you to scan and check all the services across your entire estate for the unqouted service path vulnerability, and when you enable the Remediate option, automatically fix any misconfigured services.
the if ($Compliant.length -eq 0) test will always equal 0 unless the last service tested has an unquoted services path.
ReplyDeleteI ended up adding a $count variable and incrementing it in the loop if the service being tested ended up having an unquoted services path.
I changed the set of the variable $Compliant = "" to $Compliant = "Compliant"
and then changed the:
if ($Compliant.length -eq 0)
to
if ($Count-gt 0) {$Compliant = "NotCompliant"
this resolved the always "true" test I was having issue with.