Unquoted Service Paths

Manual and Automated Process to resolve Unquote Service Path issues

The Risk

The remote Windows host contains services installed that use unquoted service paths, which contains at least one whitespace. A local attacker can gain elevated privileges by inserting an executable file in the path of the affected service.

The Fix

  1. Open the registry editor in Administrator Mode
  2. Goto HKLM\System\CurrentControlSet\Services
  3. Locate the service which has been highlighted as the issue

    e.g.

    • OpenVPNConnectorService
      Value name: ImagePath
      Value data: C:\Program Files\OpenVPN Connect\ovpnconnector.exe run
  4. Enclose the path in quote marks

    e.g.

    • OpenVPNConnectorService
      Value name: ImagePath
      Value data: "C:\Program Files\OpenVPN Connect\ovpnconnector.exe" run

Also

You can search for any "Unquoted Path" issues using the following command

wmic service get name,displayname,pathname,startmode |findstr /i “auto” |findstr /i /v “c:\windows\\” |findstr /i /v “””

You can also run a script to change any identified paths, either as a one-off or as a repeating task inside an RMM tool or similar

#Check we are running in admin mode
function Test-Administrator
{
$user = [Security.Principal.WindowsIdentity]::GetCurrent();
(New-Object Security.Principal.WindowsPrincipal $user).IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)
}
cls
If(Test-Administrator)
{
Write-Host "Running in Admin Mode" -ForegroundColor Yellow
Write-Host "Checking for Unquoted Service Paths" -ForegroundColor Cyan
}
else
{
Write-Host "Not Running in Admin Mode - Please execute in Admin Mode"
Exit
}
#Collect a list of IndividualServices running on the machine being checked
$InstalledServices = Get-ChildItem "HKLM:\SYSTEM\CurrentControlSet\Services"
#Check each and every service
foreach($IndividualService in $InstalledServices)
{
$ImagePathExists = $false
foreach($Property in $IndividualService.Property)
{
#Does the service have an image path?
if($Property -eq "ImagePath")
{
$ImagePathExists = $true
break;
}
}
#If we cannot find an Image Path on the service we can move on and ignore
if(-not($ImagePathExists))
{
continue
}

#Copy the image path variable so we can work with it in the scipt
$ImagePathCopy = [string]$IndividualService.GetValue("ImagePath")

# If the ImagePathCopy has no spaces we can ignore it
if(-not ($ImagePathCopy.Contains(" ")))
{ continue }

#Variables for executable and parameters
$executables = ""
$parameters = ""

#Is this a driver with .SYS extension
if($ImagePathCopy.Contains('.sys'))
{
# Split executable path and arguments for drivers
if($ImagePathCopy.Contains('.sys"'))
{
$splitPoint = $ImagePathCopy.IndexOf(".sys")+5
$executables = $ImagePathCopy.Substring(0,$splitPoint)
$arguments = ($ImagePathCopy.Substring($splitPoint-1))
} else
{
$splitPoint = $ImagePathCopy.IndexOf(".sys")+4
$executables = $ImagePathCopy.Substring(0,$splitPoint)
$arguments = ($ImagePathCopy.Substring($splitPoint))
}
#Is this an executable file with a .exe extension
} elseif($ImagePathCopy.Contains('.exe'))
{
# Split executable path and arguments for drivers
if($ImagePathCopy.Contains('.exe"'))
{
$splitPoint = $ImagePathCopy.IndexOf(".exe")+5
$executables = $ImagePathCopy.Substring(0,$splitPoint)
$arguments = ($ImagePathCopy.Substring($splitPoint-1))
} else
{
$splitPoint = $ImagePathCopy.IndexOf(".exe")+4
$executables = $ImagePathCopy.Substring(0,$splitPoint)
$arguments = ($ImagePathCopy.Substring($splitPoint))
}
}

#Check for spaces in the executable path
If($executables.Contains(' '))
{
#Are there spaced and no quotes
if(-not(($executables.StartsWith('"') -and $executables.EndsWith('"'))))
{
# Add quotes
"$($Individualservice.name) was identified with an unquoted path ($imagePathCopy)"
$executables = "`"$executables`""
$NewImagePath = "$executables$arguments"
# Change registry path to add the quotes
$IndividualServicePath = $IndividualService.Name.Replace("HKEY_LOCAL_MACHINE","HKLM:")
# Update the ImagePath
"changing to $NewImagePath"
Set-ItemProperty -Path $IndividualServicePath -Name "ImagePath" -Value $newImagePath
}
}
}
Write-Host "Completed Unquoted Service Path Checking" -ForegroundColor Green