Qualifications NDH – Solution de l’épreuve « Slumdog Millionaire »

Olivier Chatail Writeups

Cet article présente la solution à un challenge de sécurité qui été créé pour les qualifications de la Nuit Du Hack 2017.

La Nuit Du Hack est un événement français autour des thèmes sécurité informatique / hacking. Pour sa 15e édition, il a lieu à Disneyland Paris les 24 et 25 Juin.

https://nuitduhack.com/

Deux compétitions ont lieu lors de la NDH : une privée et une publique.

La compétition privée est réservée aux 10 meilleures équipes de la phase de qualifications, qui a eu lieu le 1er Avril 2017. Quatre membres de Devoteam étaient parmi les participants.

Les qualifications proposaient différents types de challenges, des traditionnels web/exploit/forensics à la stéganographie.

The Slumdog Millionaire

Cette épreuve, dans la catégorie Web, se présente ainsi :

The PiggyBank corporation has dediced to open source its new gambling application, SlumdogMillionaire ! Since then, it has become a world phenomenon. They are particularly proud of their new algorithm and hope to prove their game is fair by giving « Carte Blanche » for anyone to audit their code !

Nous avons donc accès à un casino en ligne http://slumdogmillionaire.quals.nuitduhack.com/ et au code source de son algorithme de décision.

Le code source ne couvre bien sûr pas la totalité de l’application et n’est là que pour présenter la logique derrière le tirage des numéros gagnants.

La solution

La page ne présente qu’un formulaire d’entrée simple et quelques informations sur son fonctionnement.

La chaîne attendue doit suivre le pattern 01-23-45-67-89-01-23-45-67-89. Dix numéros sont tirés aléatoirement et comparés à l’entrée de l’utilisateur.

Si l’entrée utilisateur est incorrecte, la combinaison gagnante est affichée puis régénérée. Un historique des 10 dernières combinaisons gagnantes est aussi affiché en bas de la page.

Tandis que l’application est classée en Web, la vulnérabilité n’est pas typique de cette catégorie (injection etc) mais plus une faille de logique dans leur algorithme de décision.

Le code source fourni est le suivant :

Nous pouvons déjà observer dans la source que le code utilise la bibliothèque Python Random pour générer la combinaison gagnante.

D’un premier coup d’œil la logique a l’air OK : génération de la combinaison gagnante à chaque essai et mise en place d’un nombre maximal d’essais.

Cependant, il y a une faiblesse très typique de la génération de nombre aléatoire : le choix du seed.

Dans ce cas le seed est basé sur l’ID du processus courant (PID) et est utilisé pour généré les 10 nombres aléatoires. Un PID est un entier entre 0 et 32768 (valeur par défaut classique, qui est aussi le PID maximum sur les systèmes 32 bits).

Un seed est utilisé pour initialiser le générateur de nombre aléatoire. L’utilisation de la fonction Python randint avec le même seed générera la même sortie à chaque fois.

C’est donc sur ce point que l’algorithme montre une faiblesse, étant donné que la dernière combinaison gagnante est affichée, il est possible (avant de jouer) de pré-calculer les 32768 premières combinaisons générées.

Ces calculs permettent d’établir une liste de tous les premiers cas possibles et donc de deviner le PID utilisé par le serveur en cherchant la première combinaison gagnante dans la liste.

Pour générer la liste la fonction generate_combination() est réutilisée et les deux premières valeurs sont stockées : la première pour deviner le PID et la deuxième pour valider le challenge.

Nous avons donc une liste comme suit : 

Nous soumettons une mauvaise valeur dans le formulaire et récupérons la combinaison gagnante 22-74-39-76-48-37-79-28-13-61.

En cherchant dans la liste générée précédemment, il peut être déduit que le PID est 7729.

Il suffit donc de soumettre la deuxième valeur dans la page et… victoire !

Merci au staff de la NDH pour l’organisation de ce challenge.

 

Olivier CHATAIL