with one click
sql-injection
Hunt SQL injection (CWE-89) via source-level taint tracking. Covers string concat, format-string, ORM raw queries, second-order injection, and NoSQL injection in MongoDB/DynamoDB.
Menu
Hunt SQL injection (CWE-89) via source-level taint tracking. Covers string concat, format-string, ORM raw queries, second-order injection, and NoSQL injection in MongoDB/DynamoDB.
Author and deploy an evilginx2 phishlet to reverse-proxy a real login and capture the post-authentication session cookie, defeating MFA via session-token theft.
Build and launch a tracked phishing campaign with the GoPhish REST API — sending profile, groups, email template, landing page, launch, and event polling.
Register and provision a lookalike / Punycode phishing domain with DNS and TLS so GoPhish and evilginx2 lures resolve and pass modern mail + browser checks.
Harvest and replay O365 / Entra ID access via the OAuth device-code flow and captured tokens (TokenTactics-style), skipping the password + MFA prompts.
Design a credible phishing pretext and target shortlist from OSINT before any campaign is built — sender persona, scenario, timing, and the minimal target set.
Phishing / social-engineering catalog for the Phisher agent. Use ONLY when the engagement RoE authorizes a phishing engagement. Covers pretext design, GoPhish campaigns, evilginx2 MFA-bypass proxying, O365 credential/token harvest, lookalike domains, and the mandatory blue-team deconfliction handshake.
| name | sql-injection |
| description | Hunt SQL injection (CWE-89) via source-level taint tracking. Covers string concat, format-string, ORM raw queries, second-order injection, and NoSQL injection in MongoDB/DynamoDB. |
| metadata | {"subdomain":"web-exploitation","when_to_use":"sql injection sqli cwe-89 taint tracking string concat format orm raw second order nosql mongodb dynamodb"} |
Classic, still the king. Modern ORMs reduce the surface area but every codebase has escape hatches (raw queries, dynamic table names, LIKE fragments) where taint tracking pays off.
Anything accepting untrusted input: query params, form bodies, headers, cookies, JWT claims, file contents parsed as config, message-queue payloads.
| Language | Safe API | Dangerous API |
|---|---|---|
| Python | cursor.execute(sql, params) | cursor.execute(f"... {user}"), %-format |
| Python | SQLAlchemy text().bindparams | text(f"... {user}"), raw_sql |
| Python | Django ORM filter kwargs | Model.objects.raw(...), .extra(where=[...]) |
| Node | pg.query(text, params) | Template literals with user data |
| Node | Prisma $queryRaw\...`` | $queryRawUnsafe(userString) |
| Java | PreparedStatement | Statement.executeQuery(string + user) |
| Java | JPA criteria | entityManager.createNativeQuery(user + sql) |
| Go | db.Query(text, args...) | fmt.Sprintf → db.Query |
| Ruby | Rails where("col = ?", x) | where("col = '#{x}'"), find_by_sql(interp) |
| PHP | PDO prepared | mysqli_query($conn, $user . $sql) |
# Semgrep covers 80% of obvious cases
semgrep --config p/sql-injection /workspace/src --sarif -o /workspace/sem-sqli.sarif
kg_ingest_sarif("/workspace/sem-sqli.sarif", "semgrep")
# Grep for the high-signal patterns semgrep misses (dynamic order/group by)
grep -rE 'ORDER BY.*\$|LIMIT.*\$|GROUP BY.*\$' /workspace/src
grep -rE 'execute\s*\(.*f["\']|execute\s*\(.*%.*%' /workspace/src
# Django raw + extra (scanner blind spot)
grep -rE '\.raw\(|\.extra\(' /workspace/src
# Second-order: anything that stores user input then queries by it unescaped
grep -rE 'INSERT INTO.*VALUES.*\?|UPDATE.*SET' /workspace/src
ORMs parameterize values but NOT identifiers. If the code does:
cursor.execute(f"SELECT * FROM {tenant}_users WHERE id=%s", (uid,))
the table name is user-controlled. Check whether tenant is validated
against an allowlist. If not, this is trivial RCE on Postgres
(; DROP ... ; COPY ... TO PROGRAM 'bash -c ...' --).
| DB | Dangerous | Safe |
|---|---|---|
| MongoDB | db.users.find({name: req.body.name}) | find({name: String(req.body.name)}) |
| Firebase | db.ref(req.query.path) | path allowlist |
| Dynamo | Filter expressions built from strings | ExpressionAttributeValues |
Classic Mongo bypass: {"username": "admin", "password": {"$ne": null}}.
Most dangerous variant. The sink query reads from a previously stored value that was user-controlled. Missed by 90% of scanners because the taint breaks at the DB boundary.
Audit approach: any column that stores user input and is later concatenated into another query is a candidate. Grep for the column name across the repo.
# Blind time-based
curl "https://target.com/search?q=1' AND SLEEP(5)-- -"
# Success: response time > 5s
# Error-based
curl "https://target.com/search?q=1' AND (SELECT 1 FROM (SELECT COUNT(*),CONCAT(version(),FLOOR(RAND(0)*2))x FROM information_schema.tables GROUP BY x)a)-- -"
# Success: mysql error with version string reflected
validate_finding contract:
version\(\), mysql, postgres, sleep.*5,
syntax error near, ORA-01756q=1 (no payload)| Variant | Score | Notes |
|---|---|---|
| Authenticated read-only SQLi | 6.5 | C:L I:N A:N, PR:L |
| Unauth blind SQLi | 7.5 | C:H I:N A:N, PR:N |
| Unauth error-based SQLi | 8.6 | C:H I:L A:N |
| Unauth → OS command (xp_cmdshell, COPY TO PROGRAM) | 9.8 | C:H I:H A:H |
Vector for the 9.8: AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H.
SQL injection often enables:
auth_as edge → internal user nodeleaks edge → secret node (config.php, .env)enables edge → new shell/rce node