Petit chèque

3 vulnérabilités dans TinyCheck soutenu par Kaspersky

Dans nos dernières recherches, nous avons trouvé 3 vulnérabilités différentes dans Petit chèque, un outil open source développé et édité par Félix Aimé, l'un des GReAT experts de Kaspersky. Chacune des vulnérabilités a une gravité élevée en soi. Une fois combinés dans une chaîne, un attaquant distant pourrait l'exploiter pour obtenir un RCE (exécution de code à distance) sur la machine TinyCheck distante.

En un mot, nous avons utilisé le identifiants par défaut de TinyCheck pour modifier deux sections dans un fichier de configuration :

  • Dans le premier, nous avons ajouté une charge utile malveillante, qui sera exécutée plus tard via injection de commande vulnérabilité.
  • Dans la seconde, nous avons ajouté une URL à une liste qui provoquera SSRF, qui déclenchera plus tard la charge utile malveillante de la première section.

Qu'est-ce que TinyCheck

TinyCheck permet à l'utilisateur d'analyser le réseau d'un appareil. L'utilisateur peut connecter son appareil au WiFi proxy de TinyCheck, qui capturera l'activité du réseau. Cette activité peut être analysée pour le trafic malveillant passant par le réseau.

Puisque nous avons de l'expérience avec proxy sous Android, nous savions qu'un simple proxy ne devrait pas avoir trop de mal à gérer le trafic potentiellement malveillant. Mais TinyCheck est plus riche en fonctionnalités, offrant une meilleure capacité de détection qu'un simple script proxy. Le code source est disponible sur GitHub qui a permis de l'examiner.

TinyCheck dispose de 3 services pertinents :

  1. "Backend" - un serveur Flask ouvert au monde et protégé par nom d'utilisateur/mot de passe (authentification de base). Le serveur se concentre principalement sur l'édition de la configuration.
  2. "Frontend" - un serveur Flask qui s'exécute sur localhost, n'a pas de mot de passe et sa tâche principale consiste à démarrer/arrêter/gérer la capture réseau.
  3. "Watchers" - un service de surveillance qui itérera sur une liste d'URL et leur enverra une requête HTTP GET.

Vulnérabilité #1 – Identifiants par défaut

C'est la plus simple des 3 vulnérabilités, mais essentielle pour toute l'attaque. Par défaut, TinyCheck est livré avec les informations d'identification par défaut de "tinycheck” comme nom d'utilisateur et mot de passe.

Vulnérabilité des informations d'identification par défaut
À partir de la page Lisez-moi de GitHub

Avoir de telles informations d'identification par défaut sans obliger l'utilisateur à les modifier lors de la première utilisation présente un risque inutile.

En utilisant les informations d'identification par défaut, nous avons eu accès à une variété de points de terminaison dans le serveur "backend", ce qui nous a donné une surface d'attaque plus large.

Le point de terminaison important que nous utiliserons plus tard est celui qui modifie le fichier de configuration YAML.

https://tinycheck.local/config/edit/CATEGORY/KEY/VALUE

Plus d'informations sur la façon dont nous l'avons utilisé ci-dessous.

Vulnérabilité #2 – SSRF

L'oubli de demande côté serveur (SSRF) est toujours passionnant et souvent négligé par les développeurs ou les chercheurs en sécurité. En exploitant cette vulnérabilité, nous avons pu forcer le serveur à faire une requête HTTP. Il est utile pour contourner le pare-feu ou pour accéder au réseau interne, qui n'était pas accessible auparavant.

Nous avons constaté que le serveur dispose d'une liste d'URL stockées dans le fichier de configuration YAML sous watchers/iocs:

URL Watchers IOC
Section des observateurs TincyCheck dans le fichier YAML

En utilisant la première vulnérabilité, nous avons pu réécrire la liste et la remplacer par nos propres URL :

URL des IOC Watchers personnalisés
section des observateurs après que nous ayons réécrit avec nos propres URL

Fait intéressant, nous avons maintenant pu faire en sorte que le service « observateurs » fasse une requête HTTP GET à n'importe quelle URL que nous choisissons. Plus important encore, nous pourrions toucher le serveur "frontend" tel qu'il s'exécute dans localhost une fois le service « watchers » rechargé.
Encore une fois, cela nous a donné une surface d'attaque plus large pour atteindre plus de points finaux et plus de logique que nous pouvions exploiter.

Vulnérabilité #3 – Injection de commandes

Nous avons commencé à enquêter sur le serveur "frontend". Ne soyez pas confus par le nom, il s'agit d'un serveur Flask, pas seulement d'un frontal JS.

Ayant un tout nouveau monde de points de terminaison de la vulnérabilité SSRF, nous avons examiné les classes de service, les fonctions et les utilitaires qui pourraient être exploitables.
Après avoir lu le code source et approfondi la pile des appels de fonction, nous sommes tombés sur ce code :

Popen("tshark -i {}".format(self.iface), shell=True)

Popen est le moyen d'appeler un sous-processus en Python. La shell=True et par format sont les parties exploitables, c'est-à-dire que la commande qui s'exécutera sera interprétée comme une chaîne. Bien que l'intention originale ici fonctionne si self.iface est juste une chaîne comme "eth0", nous avons réalisé que si nous pouvions injecter une chaîne conçue de manière malveillante, nous serions capables d'exécuter du code arbitraire.

Heureusement pour nous, le self.iface a été réellement lu à partir du fichier de configuration sous le network/in section, sa valeur d'origine suppose qu'elle pointe vers une interface réseau.

self.iface = read_config("network/in")

Comme pour la vulnérabilité SSRF, nous avons injecté notre charge utile en utilisant le même point de terminaison de modification de configuration.

L'injection elle-même était simple:

; whoami>/tmp/exploit.out

Cela signifie qu'avec notre charge utile, la commande d'origine sera formatée comme suit :

Popen("tshark -i ; whoami>/tmp/exploit.out", shell=True)

En effet, le fichier contenait le mot root, ce qui signifie que nous pourrions prendre le contrôle du système, car le serveur s'exécute en tant que root et non en tant qu'utilisateur dédié à faibles privilèges.

Mais nous devions déclencher ce code. À l'heure actuelle, notre charge utile a été exécutée juste au moment où l'utilisateur commence à capturer l'activité du réseau via l'interface utilisateur.

La chaîne d'exploitation complète

Pour tout lier, nous avions besoin d'un moyen de déclencher notre charge utile.

Notre charge utile malveillante qui a été injectée dans la configuration du réseau

Nous l'avons fait en tirant parti du SSRF pour appeler l'un des points de terminaison "frontaux" locaux, qui démarre la fonction de capture du réseau afin que nous n'ayons pas à attendre que l'utilisateur le fasse.

Réseau de capture SSRF
Injecté le point de terminaison du serveur frontal pour déclencher la fonctionnalité de capture réseau

Cela a appelé le code vulnérable du service "watchers" et pour que l'injection de commande soit exécutée avec notre charge utile malveillante.

Divulgation à l'équipe de sécurité de Kaspersky

La divulgation de la vulnérabilité à l'équipe de sécurité de Kaspersky a été une expérience remarquablement bonne pour nous. Je les remercie de nous avoir contactés très rapidement et d'avoir pris la tête du produit, Félix Aimé, impliqué qui a résolu toutes les vulnérabilités en un jour ou deux.

Chronologie de la divulgation

  • 2020-12-14 : Rapport détaillé envoyé à [email protected]
  • 2020/12/15 : première réponse de l'équipe de sécurité des produits de Kaspersky
  • 2020/12/18 : Toutes les vulnérabilités corrigées + du conseil pour passer à la version corrigée
  • 2021-01-22 : émissions de CVE
  • 2021/02/11 : publication d'un article de blog
Passer au contenu