Challenge cybersécurité : Opération Brigitte Friang (Partie 3)

Publié par Mickael Alibert le

Temps de lecture : 13 minutes

L’an dernier, la DGSE proposait un challenge sur le thème de la cybersécurité, le challenge Richelieu. Il s’agit de résoudre une suite d’énigmes faisant appel à des connaissances dans de nombreux domaines tels que la cryptographie, le hacking, la stéganographie… Je n’ai pas participé, mais j’ai suivi le parcours de Pierre-Yves et Charles-Henri, consultants à Zenika Nantes, il me trottait donc l’envie de participer de manière active à une expérience semblable si l’occasion se présentait à nouveau.

Cette année, du 24 octobre au 11 novembre, en partenariat avec l’ESIEE Paris, un nouveau challenge est proposé, l’Opération Brigitte Friang. Pris par le quotidien, j’avais laissé de côté cette information, jusqu’à ce que le second confinement français vienne libérer de la place dans mon agenda. C’est donc comme cela que je me suis lancé dans ce challenge le 30 octobre.

Ce retour d’expérience est composé de trois articles. Chacun d’entre eux vous permettra de suivre mon cheminement, mes succès et mes échecs sur les différentes épreuves du challenge. Il vous montrera également comment de petites négligences sur la sécurité peuvent avoir de lourdes conséquences, telles que des vols de données ou de l’impersonnalisation. En fin de chaque article, je ferai un retour sur quelques-unes de ces erreurs, qui sont bien plus répandues qu’on ne le pense, et sur ce qui aurait pu être mis en place pour concevoir une solution moins exploitable par des personnes malveillantes.

Si vous ne les avez pas lues, la première partie est disponible ici et vous pouvez retrouver la seconde sur ce lien.

Arène CTF

A la fin de l’épreuve de désobfuscation de javascript, nous avons trouvé un lien, qui nous emmène sur la plateforme CTF, dernière partie de l’Opération Brigitte Friang.

Accueil de l’arène CTF

Après l’inscription d’une nouvelle équipe sur la plateforme, il est possible d’accéder à l’ensemble des challenges proposés lors de ce CTF. Chaque challenge donne un nombre de points déterminés en fonction de leur difficulté, ce qui permet d’établir un classement des équipes à la fin de l’opération.

Liste des challenges disponibles


Sur les 14 challenges disponibles, j’ai réussi à en terminer 5, dont le déroulé sera présenté dans cet article. Pour le reste des solutions, des writes-up sont disponibles ici.

Alone Musks (100 Points)

Challenge Alone Musk

Ce challenge est une épreuve de conquête d’un système d’exploitation. Nous avons accès à un camion autonome, sur lequel nous devons gagner accès au système de navigation. Pour cela, on nous fournit un accès SSH avec des identifiants.

Mire d’authentification

Une fois connectés en SSH, nous tombons sur une nouvelle mire d’authentification, où les identifiants user:user ne fonctionnent pas. Un CTRL+C nous permet de couper le processus qui se charge de cette mire de login, et de visualiser lors du rapport d’arrêt que c’est le script /home/user/login.py qui est lancé. Pour vérifier que ce fichier est bien présent et voir si d’autres scripts sont également disponibles, on essaye de lister le contenu du répertoire.

Listing du répertoire

La commande ls n’est pas trouvée et nous sommes dans un rbash, session restreinte en droits, nous bloquant l’accès à la grande majorité des fichiers du système, notamment l’exécution de commandes avec un « /« . Nous savons que le script de login est un script python, qui est lui bien exécuté. Nous allons donc essayer de lancer une commande python, et si cela fonctionne, nous aurons une porte de sortie grâce à GTFOBins, un site qui regroupe un ensemble de commandes possibles notamment pour sortir d’un bash restreint.

Sortie du bash restreint

Nous sommes bien désormais dans une session bash non restreinte, nous pouvons donc modifier notre chemin d’exécution pour avoir accès à toutes les commandes sans avoir à taper leur chemin complet. Puis nous allons essayer de voir si l’on trouve le système de navigation du camion.

Identification du flag

On trouve un fichier flag.txt qui doit contenir la réponse que nous cherchons dans le dossier de l’utilisateur navigationSystem. Nous n’avons cependant pas accès à ce fichier. On remarque également un utilisateur globalSystem. Il faut que nous parvenions à nous connecter en tant que navigationSystem pour pouvoir lire le fichier. Pour cela nous allons regarder nos possibilités d’exécution en tant qu’un autre utilisateur, offertes par la commande sudo, et le cas échéant utiliser à nouveau  GTFOBins pour lancer un shell. 

Élévation de privilège

Nous sommes désormais connectés en tant que globalSystem, on peut répéter la même opération afin de voir si l’on ne peut pas atteindre notre utilisateur navigationSystem

Identification des élévations disponibles

On a une commande qui nous permettrait d’atteindre l’utilisateur naviationSystem, mais /usr/bin/update est un binaire obscur. Fort heureusement pour nous, le binaire est accessible en écriture pour l’utilisateur globalSystem. Nous allons donc réaliser une opération destructrice pour le binaire de mise à jour, en remplaçant son contenu par la commande de lancement d’un shell. Il ne reste maintenant plus qu’à lancer l’update, et afficher le flag.

Visualisation du flag

ChatBot (100 Points)

Challenge Chatbot

Le second challenge dans lequel je me suis lancé est le Chatbot. C’est une épreuve web, on peut donc procéder de la même manière que pour le site stockos lors de la mission pour l’agent Jeremy Nitel. Nous sommes prévenus que le ChatBot possède sûrement une faille qui permettrait d’accéder à l’intranet d’Evil Gouv. On essaye d’abord de naviguer sur le site de manière normale, pour voir si l’on trouve un fonctionnement intéressant.

Chatbot d’Evil Gouv

Nous sommes face à un robot qui répond à nos questions, avec des interactions prédéfinies possibles. Les deux premières nous apportent une réponse textuelle classique, et la dernière nous prévient qu’il est possible de candidater sur un site web, en affichant en plus de la réponse le titre du site web et son favicon. C’est cette particularité qui ouvre des possibilités d’attaque. Si le ChatBot parvient à afficher le titre et l’icône d’une page à partir d’une URL, cela signifie qu’il réalise un appel à cette page. Pour vérifier que l’appel n’est pas lancé côté client (que l’icône et le titre de la page ne sont pas chargés avec notre navigateur), il suffit d’inspecter les appels réseau réalisés par le Chatbot.

Requêtes passées au Chatbot

Quand on appuie sur le bouton “Comment candidater ?”, l’application lance un appel sur une url finissant par proxy?url=https://www.qwant.com/. Ce qui signifie que l’on peut initier des appels depuis notre ordinateur vers des sites via le proxy du ChatBot. Ce comportement dangereux ouvre un large champ de possibilités, surtout si des sites sont exposés sur le même réseau que le Proxy, tel qu’un intranet par exemple. 

On peut donc commencer à explorer le réseau pour essayer de trouver un serveur qui répond. Nous visons un intranet, CAD une machine présente uniquement sur le réseau interne de la société. Nous pouvons donc restreindre nos recherches aux classes d’IP privées. Dans chaque classe, nous allons tester les 5 premières IP pour voir si un comportement particulier se dégage, nous en profiterons également pour tester le https:

Nous pouvons concentrer tous nos efforts sur le sous-réseau 192.168.0.0/16 puisque nous obtenons une réponse sur ce dernier. Les accès interdits sur les premières IPs ne permettent pas d’être certain que l’ensemble de la plage répondra de la même manière, nous allons donc essayer d’accéder à toutes les IPs possibles du sous-réseau. Le bruteforce étant autorisé sur cette épreuve, nous allons lancer un script pour tester la réponse HTTP de chaque IP jusqu’à en trouver une pertinente.

Script de bruteforce

Le challenge n’est finalement pas si simple, puisque pour les 1000 premières adresses nous n’avons aucune réponse. En essayant avec un chemin derrière l’IP, comme /web, le comportement est identique. Il est donc nécessaire de changer de méthode et d’axe de réflexion. Dans un réseau d’entreprise très simple, les serveurs d’applications répondent sur la même zone DNS. Dans le cas d’un réseau personnel Orange, ce sous-domaine est “home”, ce qui permet d’atteindre la même page que l’on accède à l’IP de la livebox, à l’adresse http://livebox.home ou http://livebox. Nous allons utiliser ce principe pour essayer de trouver des serveurs sans connaître la zone DNS en question. Hélas, chaque essai de sites avec des noms classiques (web, webserver, home, website, test, foobar…) se solde par une erreur 404. Une bonne nuit de sommeil plus tard, je finis par accéder à une page, beaucoup trop évidente donc très complexe à trouver, qui nous renvoie une réponse: http://intranet

http://intranet

On tombe sur la page d’accueil par défaut d’un serveur web Nginx. Une maigre avancée, puisque cette dernière ne contient pas de flag. Mais puisque nous avons un serveur web, cela signifie que nous sommes sur le bon chemin, nous allons donc tenter d’explorer son contenu et les possibles sites exposés. Nous pouvons notamment tenter une attaque de type Directory Traversal qui permet d’exposer des fichiers de la machine dans le cas d’un serveur web mal configuré. Pour valider que cette attaque est potentiellement exploitable, on peut essayer d’ajouter un nom de dossier aléatoire dans l’url suivi du lien pour remonter au dossier précédent. Nous obtenons la même réponse que le lien utilisé soit celui que nous avons forgé http://intranet/toto/../ ou lien normal http://intranet. Il nous suffit donc de remonter suffisamment haut dans l’arborescence de fichier du serveur pour avoir accès aux fichiers de la machine. Pour cela, il faut ajouter une quantité non négligeable de liens pour remonter d’un dossier, suivi du chemin  absolu d’un fichier auquel on veut accéder:
http://intranet/toto/../[64 * ../] ../etc/nginx/nginx.conf

Erreur

Après quelques dizaines de tests avec des fichiers usuels, et aucune autre réponse que des erreurs 404, on peut en déduire que le serveur n’est pas si mal configuré.

Il faut donc que l’on trouve un nouvel angle d’attaque, avec les informations dont nous disposons. Les URLs qui commencent par une IP répondent en 403. Les URLs qui commencent par n’importe quoi d’autre répondent des 404, sauf pour intranet qui répond une 200 seulement sur sa home. Ces informations schématisées sur un cahier, c’est à ce moment que je me rappelle d’une RFC sur les URL et leur format. Il est possible, pour s’authentifier sur un site, de lui passer un identifiant et un mot de passe directement dans l’URL. Je pourrais donc potentiellement exploiter cette possibilité pour passer à travers le blocage des URLs commençant par une IP. Je teste ma théorie pour l’adresse suivante http://foo:bar@192.168.1.1, et j’obtiens une 404, ce qui signifie que j’ai outrepassé la règle qui renvoie des 403 ! Nous pouvons donc attaquer plus violemment le site, avec le même genre de script que la dernière fois.

Script de bruteforce

Quelques minutes plus tard, le script ressort le lien http://foo:bar@192.168.0.70, qui renvoie les données suivantes:

Page contenant le flag

Le flag est enfin trouvé, et le challenge est validé. 

Définition (50 points)

Challenge Définition

Pour ce challenge, il nous est demandé d’envoyer l’heure via netcat sur le port d’un serveur. Sur Linux, la commande pour afficher les informations de la date actuelle est date. On peut ensuite lui fournir le format désiré. Nous pouvons essayer de passer l’heure actuelle au serveur avec les commandes suivantes:

Essai d’envoi de l’heure

Si l’heure n’est pas suffisante, nous pouvons également passer l’heure, la minute et la seconde exacte au serveur. Il est aussi possible de passer la date du jour avec, ou l’heure dans un autre fuseau horaire. Sauf qu’aucune de ces solutions ne fonctionne. Finalement, la manière unique pour donner l’heure à un serveur quel que soit le fuseau est d’utiliser un timestamp Unix:

Obtention du flag

Sous l’océan (50 points)

Challenge Sous l’océan

Ce challenge est un challenge Forensic, qui nous demande d’analyser une image mémoire d’un téléphone Android pour en extraire des données de localisation. La première difficulté de ce challenge est d’exploiter un fichier de plus de 65 000 lignes de logs. Après quelques recherches dans le fichier pour des mots liés à la localisation (location, gps, latitude…), on peut déterminer de nos résultats un filtre sur les lignes contenant Location[gps. L’extraction de ces lignes nous renvoie seulement 84 résultats, simplifiant grandement le travail d’analyse.

Extrait des logs GPS d’Android

Dans ces extraits, on constate que de nombreuses informations sont nulles, identiques et superflues. Nous pouvons donc supprimer l’ensemble de ces informations.

Extrait des positions GPS

Il nous reste désormais des positions GPS en degrés décimaux. Nous pouvons commencer à vérifier les positions retournées dans le fichier.

Position 1 : Googleplex

La première d’entre elles nous amène au siège social de la petite compagnie qui développe les OR-Tools utilisés lors de la première partie du challenge. Serait-elle de mèche avec Evil Gouv ? Le reste des coordonnées nous emmène en pleine mer au Sud du continent Africain. Sauf que dans l’énoncé d’un des autres challenges, nous apprenons qu’Eve Descartes est probablement dans un sous-marin dans l’océan Atlantique. Si l’on inverse l’ordre de toutes les coordonnées, on parvient bien à des points entre les USA et la France. 

Indice

Si l’on utilise un outil pour visualiser tous les points dans l’océan, tel que l’excellent GPS Visualizer conseillé par Pierre-Yves, on obtient la carte suivante.

Carte des positions GPS

Le seul exercice restant est du niveau d’un dessin de points numérotés de 2 à 84 pour obtenir le flag qui valide ce challenge.

Obtention du Flag

Le discret Napier (150 points)

Challenge du discret Napier

Pour ce challenge, l’énoncé est clair et rapide à comprendre. Il faut simplement résoudre une équation pour trouver la valeur à insérer dans le flag. Il faudra donc résoudre un logarithme discret. Après quelques recherches, on comprend que ces équations ont une importance capitale dans la cryptographie, ce qui explique leur présence dans ce challenge. Vu la taille des nombres en jeu dans ce challenge, le souci sera de réaliser ou trouver une  implémentation capable de gérer ces nombres sans qu’elle consomme l’ensemble de la mémoire disponible. Après avoir passé les dernières heures de travail avec Pierre-Yves sur le challenge à chercher des solutions, c’est finalement l’implémentation sur le github de Efim Poberezkin, qui y a publié ses réponses à un Coursera sur la cryptographie. En utilisant son script disponible ici, nous n’avons besoin de modifier seulement 3 variables pour obtenir un résultat “697873717765” en moins de 5 secondes. Il ne reste plus qu’à former le flag avec ce résultat pour valider le challenge. 

Conclusion

Le challenge s’est terminé le 11/11/2020 à 23:59:59, permettant aux équipes de déterminer leur classement final dans l’épreuve de CTF. Sur l’ensemble des participants, 785 équipes sont parvenues à accéder à la dernière plateforme de l’Opération Brigitte Friang. Avec mes 450 points et l’épreuve du discret Napier validée dans l’après midi, j’ai réussi à atteindre la 158ème place du classement. Un grand bravo aux premières équipes, notamment celles ayant réussi à finir dans les 4 premiers jours du challenge.

Classement final
Grands gagnants de l’édition 2020

Je tiens à remercier la DGSE et l’ESIEE Paris pour la préparation de ce challenge et de sa narration, ainsi que les personnes m’ayant aidé pour le challenge ou la relecture de ces articles.

Ce challenge m’a permis de faire des découvertes lors de mes recherches (des notions mathématiques, des outils intéressants pour la cybersécurité, des moyens pour organiser mes réflexions sur plusieurs jours,…). J’ai également eu l’occasion de discuter avec des amis et des collègues à propos de la cybersécurité, des personnes techniques ou non. Ce sont notamment ces discussions qui m’ont poussé à rédiger ces articles, afin de pouvoir partager au plus grand nombre la facilité avec laquelle quelqu’un possédant des connaissances basiques et de la détermination peut exploiter des méconnaissances ou des négligences sur la cybersécurité. 

Comment limiter/éviter ces attaques ? 

Alone Musk:
La faiblesse de la sécurité mise en place repose sur les outils utilisés dans le système d’exploitation du véhicule. Utiliser un shell restreint est une bonne idée, mais ouvrir l’accès à des binaires tels que Python donne un accès tout tracé vers une exploitation. L’implémentation de sudo, bien qu’utile dans certains cas, demande une certaine maîtrise des flux ouverts, et il est préférable dans ce genre de situation d’investir un peu plus de temps pour trouver des solutions restreintes plutôt que de laisser des commandes aussi puissantes que vim à la portée de tous les utilisateurs. Dans la fin du challenge, nous avons une nouvelle fois la preuve qu’il est nécessaire de restreindre au maximum les droits d’accès aux fichiers pour éviter une utilisation malveillante.

Chatbot:
Ce chatbot offre par son fonctionnement un point de départ d’attaque conséquent. La requête de pages web par l’application côté serveur plutôt que depuis l’ordinateur de l’utilisateur n’a aucune plus-value, et représente un vrai risque d’exploitation.
Le positionnement du serveur, exposé sur le web mais capable de joindre les machines dans le data-center d’Evil Gouv pose lui aussi de gros problèmes. Il est préférable, pour toute application exposée publiquement, de la déployer au sein d’une zone démilitarisée, qui permettra d’isoler complètement la machine et de la rendre inintéressante pour un utilisateur malveillant.
Enfin, deux paramétrages auraient permis de ralentir les tentatives d’exploitation, jusqu’à décourager la majorité des attaquants.
La première méthode est là même que celle décrite dans la partie 2. Configurer le serveur web pour limiter le nombre de requêtes possibles dans un laps de temps déterminé permettrait de ralentir fortement les possibilités d’attaques. Ici, les requêtes attendues étant censée atteindre un site unique (qwant), il est possible d’utiliser un logiciel tel que fail2ban pour bannir complètement l’utilisateur au bout de quelques tentatives sur une autre adresse.
Il serait également pertinent dans ce cas d’utilisation de renvoyer toujours le même type d’erreur au client quelle que soit l’erreur rencontrée côté serveur. Ainsi, nous n’aurions pas pu identifier le filtrage sur les IPs, et l’exploitation aurait semblé impossible.

Si vous avez des questions sur cet article, ou que vous souhaitez plus de détails techniques sur l’un des sujets abordés, n’hésitez pas à me contacter sur Twitter @Alibert_m.

Catégories : Sécurité

Mickael Alibert

Practice leader - Lead SRE