SecurityInsider
Le blog des experts sécurité Wavestone

Nuit du Hack 2016 - Write-up du challenge Intrinsec



Wavestone était présent à la 14ème édition de la Nuit du Hack, qui s’est déroulé une fois de plus au New York Hotel, Disneyland. Outre le wargame (public) et le Capture the Flag (privé), de nombreux stands, dont Wavestone et Intrinsec, ont proposé des challenges ouverts à tous.
L’article ci-dessous détaille comment nous sommes venus à bout de l’un des challenges proposés par Intrinsec.
Ce dernier était constitué de quatre étapes, mais des imprévus techniques ont forcé ses auteurs à passer sous silence la première étape (cf. @Intrinsec).

Lien vers les épreuves : https://securite.intrinsec.com/2016/07/02/challenges-intrinsec-nuit-du-hack-2016/
Challengers : @Iansus & @Sopetajo

2ème étape : Don’t feed the troll

La seconde étape du challenge était disponible à l’adresse suivante : https://isec:bl0gs3cu@isc-ndh-rss.appspot.com
L’interface web nous indique que le flag de cette étape se situe dans le fichier flag.xml, et présente un outil dont le but est le suivant :
  • Récupérer le flux RSS du blog Intrinsec
  • Filtrer les attributs des articles selon la sélection de l’utilisateur

Une analyse rapide montre que les champs du flux RSS sont filtrés en fonction de l’attribut POST attr, présent sous forme de tableau :


Les différentes valeurs proposées par l’interface web correspondent à certains des attributs des éléments du flux RSS, présenté sous le format XML :


Nous avons alors tenté de rajouter d’autres champs afin d’évaluer le degré de liberté fourni par l’outil. L’attribut « dc:creator » a provoqué l’erreur suivante :


Cette erreur nous indique que l’outil récupère le contenu du XML associé au flux RSS, parcourt les différents éléments « item » à l’aide d’une transformation XLST puis affiche les valeurs sélectionnées par l’utilisateur à l’aide d’expressions XPath. 
Le fichier contenant le flag de validation étant au format XML, nous avons directement essayé d’inclure ce dernier à l’aide de la directive XPath document(), ce qui a fourni le résultat suivant :


3ème étape : Black, with two sugars

L’URL obtenue à l’étape précédente pointe vers la troisième partie du challenge : https://ndh2k16:qMrcTvzx17OGRc5g@185.135.159.124 et présente le message suivant « Welcome ».

Nous avons tout d’abord essayé d’analyser la surface d’attaque exposée par le serveur, à l’aide de l’outil NMap :

Malheureusement, ce scan ne nous a pas apporté d’informations, puisque le port 2222 était utilisé pour la gestion du serveur (SSH), et les ports 4000 et suivants pour répartir la charge supportée par le serveur.
En nous réorientant sur l’interface HTTP exposée, nous avons alors découvert la présence du fichier robots.txt à la racine :

Grâce à ces informations, nous avons pu récupérer le fichier README.html :

Il semblerait donc que le serveur corresponde à une machine à café connectée (comme l’indique l’entête HTTP « Server : GEMINI | CS 220 PRO »). En suivant les indications du readme, nous observons le comportement suivant :


Seule la dernière requête possédant un paramètre variable, nous avons décidé d’utiliser l’outil SQLMap sur la requête suivante à la recherche d’une éventuelle injection SQL :

POST https://185.135.159.124:443 HTTP/1.1
Host: 185.135.159.124:4004
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0 Iceweasel/38.4.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Cookie: pot=true; water=true; brew=true;
Authorization: Basic bmRoMmsxNjpxTXJjVHZ6eDE3T0dSYzVn
Connection: close
Cache-Control: max-age=0
Content-Length: 10

quantity=1

SQLMap a indiqué que le serveur était vulnérable aux injections du type « Stacked queries », ce qui nous a permis de récupérer le flag depuis la base de données :


4ème étape : AES mess

La dernière étape du challenge, disponible à l’adresse https://isec:b0urr4g3@isc-ndh-token.appspot.com, se présente sous la forme d’un formulaire d’inscription. Lors de la saisie d’un nom d’utilisateur, le message d’erreur suivant apparaît :


Avec l’aide de Burp, nous avons pu identifier deux requêtes envoyées vers le serveur. La première requête, envoyée en POST, permet de récupérer un token et un vecteur d’initialisation pour le nom d’utilisateur fourni :


La seconde requête, envoyée en GET sur l’URI /status, ajoute les entêtes HTTP « Token » et « IV », contenant les paramètres précédemment retournés par le serveur. La réponse du serveur est le message d’erreur affiché sur l’interface web :


En envoyant une valeur du vecteur d’initialisation égale à « 00000000000000000000000000000000 », nous remarquons que le serveur renvoie une nouvelle erreur, indiquant que seul le premier bloc de ce qui semble être du JSON a été impacté :


Ce bloc JSON possède l’attribut « adm » fixé à la valeur « false », expliquant le message d’erreur renvoyé par le serveur. D’autre part, le type d’impact qu’a eu la modification du vecteur d’initialisation permet d’identifier de manière sûre le mode d’opération CBC.

Etant donné la structure de chaînage suivante, nous allons être en mesure de construire de toute pièce, et ce sans connaître la clé, un message JSON contenant la valeur « adm » à « true » :


En effet, en opérant depuis la fin du message, il est possible de modifier l’avant dernier bloc du texte chiffré pour obtenir n’importe quelle valeur pour le dernier bloc du texte chiffré. Cela aura bien entendu un impact sur l’avant dernier bloc du texte en clair, que nous pourrons corriger à l’aide du bloc chiffré précédent, etc. Enfin, la valeur du premier bloc du texte en clair sera corrigée à l’aide du vecteur d’initialisation.

Le format du message en clair est connu (grâce au message d’erreur), puisque la taille des blocs de l’AES est connue et est de 16 octets :



Nous pouvons en déduire avec quelle valeur nous devons réaliser l’opération XOR sur l’avant dernier texte du message chiffré pour obtenir la valeur « adm » à « true » :



En envoyant le bloc chiffré #2 modifié, nous obtenons l’erreur suivante :


Le message d’erreur nous permet également d’évaluer l’impact sur le bloc de texte clair #2 :


Nous allons pouvoir corriger ce bloc de la même manière en utilisant le bloc chiffré #1, ce qui produit désormais une erreur sur le bloc de texte clair #1 :


En appliquant une dernière fois les modifications sur le vecteur d’initialisation (considéré comme le bloc chiffré #0), nous obtenons le message suivant :


N.B. : Le flag mentionne les « padding oracles », qui sont une autre méthode de résolution de cette dernière étape. La méthode que nous avons utilisée repose sur le fait que nous connaissions l’impact de la modification des blocs chiffrés sur les blocs en clair. Les « padding oracles » font abstraction de ce message et ne reposent que sur la présentation d’un message d’erreur en lien avec un padding PKCS#1.5 incorrect.
Jean MARSAULT

Aucun commentaire:

Enregistrer un commentaire