Outils pour utilisateurs

Outils du site


ctf:public:sthack2016:fleur

Fleur - French version only

Challenge

Ce challenge se présente sous la forme d'une interface web dont le code est fourni. Après une première et brève lecture du code, on s’aperçoit que le but est de se connecter en tant que admin à cette interface de façon à inclure dans la page un fichier "flag.php" qui requiert une telle "connexion".

Analyse

Vues de l'interface

L'interface présente les vues suivantes:

  • index : pour se connecter ou voir une page blanche si déjà connecté
  • inscription : pour s'inscrire
  • lostpassword : pour demander la récupération de son mot de passe
  • crypt : pour modifier l'algorithme de hachage associé à l'utilisateur de la session courante

Session

L'utilisateur courant est déterminé à chaque requête à l'aide d'un cookie en base64 contenant l'identifiant et le mot de passe de l'utilisateur. Ils sont rangés dans les variables globales $user et $pwd. Si le couple correspond à un jeu d'identifiants valides, la variable globale $authenticated vaut vrai, elle vaut faux sinon.

Mot de passe perdu

Récupération du mot de passe

Lorsqu'une demande récupération de mot de passe est faite, les opérations suivantes sont effectuées :

  • récupération dans la BDD des données relatives au mail fourni
  • hachage de ces données avec de multiple sels dont :
    • le numéro d'interface gateway du serveur
    • l'heure du serveur à la minute près
  • envoi d'un lien par mail avec le hash en paramètre GET

L'utilisateur doit alors cliquer sur le mail dans la minute, le serveur effectuant à nouveau ces opérations pour vérifier la correspondance des hashs.

Le hash

$data étant le résultat de la requête SQL contenant les informations de l'utilisateur, le hash est ainsi effectué :

    md5(md5(date('Y-m-d H:i').$_SERVER['GATEWAY_INTERFACE'].$data[0].crypt($data[1], $data[2])))

On devine, à partir de la signature de crypt et du schéma désordonné (on ne connait pas excplicitement l'ordre des colonnes) de la BDD que l'on peut trouver dans inscription.php que $data[1] représente le mot de passe de l'utilisateur et que $data[2] représente son algorithme de hachage.

On observe aussi que le serveur n'est pas à l'heure, mais à H-2.

Enfin pour la suite on considérera que l'interface gateway du serveur vaut la valeur la plus fréquente et qui est aussi celle présente sur notre serveur apache local (le cas contraire il suffirait de la faire varier).

Les failles

=== Les failles de crypt.php

Session

Contrairement aux autres pages du site, qui si l'utilisateur n'est pas correctement authentifié alors qu'il le devrait le redirige vers la page de connexion, crypt.php ne le fait pas et prend pour utilisateur courant celui présent dans la variable globale $user. On peut donc, en modifiant le cookie de connexion, modifier l'algorithme de hachage de chaque utilisateur.

Choix des algorithmes de hachage

En plus de permettre à chaque utilisateur de modifier l'algorithme de hachage des autres, le serveur ne prend pas non plus soin de s'assurer que les algorithmes demandés sont exclusivement ceux de la liste proposée. On peut donc choisir celui qu'on veut pour l'utilisateur qu'on veut, sachant comme on l'a vu précédemment que celui-ci sera utilisé pour effectuer un hash du mot de passe à l'aide de crypt lorsque l'on voudra récupérer son mot de passe.

Les failles de ''crypt''

Fonctionnement de ''crypt''

La fonction `crypt` de PHP prend en premier paramètre la valeur à hacher et en deuxième paramètre une chaîne permettant de choisir l'algorithme à utiliser et de le paramétrer. Par exemple pour utiliser l'algorithme MD5 il faut que cette chaîne soit composée :

  • du préfixe $5$
  • d'un sel de 25 caractères
  • du suffixe $
La faille

Cette fonction présente le désavantage de retourner la même valeur de "*1" dans le cas où l'algorithme de hachage qu'on lui demande d'utiliser n'est pas correctement paramétré (dans certains cas elle retournera une valeur légèrement différente voir lancera une erreur mais cela est peu important ici).

Attention cela ne fonctionne donc pas sur des algorithmes dont les paramètres sont suffisamment souples pour pouvoir prendre toutes les valeurs imaginables, la fonction crypt effectuant de part ailleurs des troncatures de la chaîne pour éviter certains dépassements.

Solution

La résolution de ce challenge va donc consister à :

  • modifier l'algorithme de hachage de l'utilisateur "admin" pour lui en donner un erroné et qui retournera la même valeur quel que soit son mot de passe
  • générer un hash valide à partir des données l'utilisateur admin
  • demander une récupération de mot de passe à partir de ce hash en générant la requête GET de récupération
  • afficher l'index pour voir s'afficher le contenu de flag.php.

Modification de l'algorithme de hashage

Effectuer la requête suivante :

    url: <host>/crypt.php
    method: POST
    body_params: {'update', '$577='} (ou toute autre valeur invalide)
    cookie: base64('admin:mdp')
Génération du hash valude

Générer un hash valide :

    md5(md5(date('Y-m-d H:i', time() - 2 * 60 * 60).'CGI/1.1'.'admin'.crypt('mdp', '$577=')))
Récupération du mot de passe

Effectuer la requête suivante :

    url: <host>/lostpassword.php?t=<hash>&user=admin
    method: GET
ctf/public/sthack2016/fleur.txt · Dernière modification: 2016/10/06 07:13 par arthaum