Skip to main content

Windows Unquoted Search Path Remediation

  • September 14, 2020
  • 4 replies
  • 1048 views

jack.smith
Forum|alt.badge.img+1

This worklet will search for Windows Unquoted Search Path under uninstall and services in registry and add quotes. This addresses a vulnerability detected by some tools like Rapid7 or Nessus. All changes made by the script are logged under C:\windows\temp\unquoted-search-path-changes.csv.


#Evaluation Code


$i = 0

$BaseKeys = "HKLM:\System\CurrentControlSet\Services",                                  #Services

            "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall",                #32bit Uninstalls

            "HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall"     #64bit Uninstalls

#Blacklist for keys to ignore

$BlackList = $Null

#Create an ArrayList to store results in

$Values = New-Object System.Collections.ArrayList

#Discovers all registry keys under the base keys

$DiscKeys = Get-ChildItem -Recurse -Directory $BaseKeys -Exclude $BlackList -ErrorAction SilentlyContinue |

            Select-Object -ExpandProperty Name | %{($_.ToString().Split('\') | Select-Object -Skip 1) -join '\'}

#Open the local registry

$Registry = [Microsoft.Win32.RegistryKey]::OpenBaseKey('LocalMachine', 'Default')

ForEach ($RegKey in $DiscKeys)

{

    #Open each key with write permissions

    Try { $ParentKey = $Registry.OpenSubKey($RegKey, $True) }

    Catch { Write-Debug "Unable to open $RegKey" }

    #Test if registry key has values

    If ($ParentKey.ValueCount -gt 0)

    {

        $MatchedValues = $ParentKey.GetValueNames() | ?{ $_ -eq "ImagePath" -or $_ -eq "UninstallString" }

        ForEach ($Match in $MatchedValues)

        {

            #RegEx that matches values containing .exe with a space in the exe path and no double quote encapsulation

            $ValueRegEx = '(^(?!\u0022).*\s.*\.[Ee][Xx][Ee](?<!\u0022))(.*$)'

            $Value = $ParentKey.GetValue($Match)

            #Test if value matches RegEx

            If ($Value -match $ValueRegEx)

            {

                $RegType = $ParentKey.GetValueKind($Match)

                #Uses the matches from the RegEx to build a new entry encapsulating the exe path with double quotes

                $Correction = "$([char]34)$($Matches[1])$([char]34)$($Matches[2])"



                #Attempt to correct the entry

                $i++

            }

        }

    }

    $ParentKey.Close()

}

$Registry.Close()



IF($i -eq 0){ Exit 0 }else{ Exit 1 }


#Remediation Code


$BaseKeys = "HKLM:\System\CurrentControlSet\Services",                                  #Services

            "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall",                #32bit Uninstalls

            "HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall"     #64bit Uninstalls

#Blacklist for keys to ignore

$BlackList = $Null

#Create an ArrayList to store results in

$Values = New-Object System.Collections.ArrayList

#Discovers all registry keys under the base keys

$DiscKeys = Get-ChildItem -Recurse -Directory $BaseKeys -Exclude $BlackList -ErrorAction SilentlyContinue |

            Select-Object -ExpandProperty Name | %{($_.ToString().Split('\') | Select-Object -Skip 1) -join '\'}

#Open the local registry

$Registry = [Microsoft.Win32.RegistryKey]::OpenBaseKey('LocalMachine', 'Default')

ForEach ($RegKey in $DiscKeys)

{

    #Open each key with write permissions

    Try { $ParentKey = $Registry.OpenSubKey($RegKey, $True) }

    Catch { Write-Debug "Unable to open $RegKey" }

    #Test if registry key has values

    If ($ParentKey.ValueCount -gt 0)

    {

        $MatchedValues = $ParentKey.GetValueNames() | ?{ $_ -eq "ImagePath" -or $_ -eq "UninstallString" }

        ForEach ($Match in $MatchedValues)

        {

            #RegEx that matches values containing .exe with a space in the exe path and no double quote encapsulation

            $ValueRegEx = '(^(?!\u0022).*\s.*\.[Ee][Xx][Ee](?<!\u0022))(.*$)'

            $Value = $ParentKey.GetValue($Match)

            #Test if value matches RegEx

            If ($Value -match $ValueRegEx)

            {

                $RegType = $ParentKey.GetValueKind($Match)

                #Uses the matches from the RegEx to build a new entry encapsulating the exe path with double quotes

                $Correction = "$([char]34)$($Matches[1])$([char]34)$($Matches[2])"

                #Attempt to correct the entry

                Try { $ParentKey.SetValue("$Match", "$Correction", [Microsoft.Win32.RegistryValueKind]::$RegType) }

                Catch { Write-Debug "Unable to write to $ParentKey" }

                #Add a hashtable containing details of corrected key to ArrayList

                $Values.Add((New-Object PSObject -Property @{

                "Name" = $Match

                "Type" = $RegType

                "Value" = $Value

                "Correction" = $Correction

                "ParentKey" = "HKEY_LOCAL_MACHINE\$RegKey"

                })) | Out-Null

            }

        }

    }

    $ParentKey.Close()

}

$Registry.Close()

$Values | Select-Object @{l='Timestamp';e={"$((Get-Date).ToShortDateString()) $((Get-Date).ToShortTimeString())"}},ParentKey,Value,Correction,Name,Type | export-csv C:\windows\temp\unquoted-search-path-changes.csv -NoTypeInformation -Append

That is a fantastic Worklet! @jack.smith, thank’s for sharing, this is great.


Forum|alt.badge.img

Hi Jack,

If the file comes out empty, does it mean there are no unquoted search path? How do we solve this vulnerability?

If the paths are identified?

Eg: 

Service Name Image Path
IntelAudioService %SystemRoot%\system32\cAVS\Intel(R)_Audio_Service\IntelAudioService.exe

  • Rookie
  • October 15, 2024

Hi,

i’d like to share my experiencie. We’d like to implant this to check this vulnerability. I used intune creating two ps1 files one for evalutation code and the other one for remediation code and both were saved with PS1 file. After that i attached to the intune option scripts and remediation. How do i know that it works? 
 

 


  • Rookie
  • October 15, 2024

@Arunchandar N how did you get it the file? i tried to run both scripts with powershell ISE but i’m not seeing that is doing something.
 

 


Reply


Cookie policy

We use cookies to enhance and personalize your experience. If you accept you agree to our full cookie policy. Learn more about our cookies.

 
Cookie settings