Outils

Faisabilité d’un réseau décentralisé - Introduction

Après avoir lu les articles sur le "démantèlement" de certains botnets comme mariposa  et waledac, nous nous sommes intéressés à la détection de ces réseaux ainsi qu'aux faiblesses inhérentes à leurs modes de communication.

Dans le cas de ces réseaux, nous pouvons remarquer un élément commun, et pas des moindres : leurs modes de communication reposent sur  le protocole DNS.

Grâce au travail de Defense Intelligence sur mariposa, nous savons aujourd'hui qu'une certaine quantité de serveurs DNS contrôlaient le réseau. Même si  ces adresses évoluaient au fur et à mesure de la mise à jour des bots, elles restaient le référentiel de toutes les mises à jour du réseau. Pour preuve, après avoir mis la main sur les domaines ils ont pu contrôler à leur tour le réseau et récolter des données volées depuis les bots venant de plus de 190 pays.

De même dernièrement, Microsoft a annoncé qu'il avait "démantelé" le réseau waledac qui base lui aussi une partie de sa communication sur des technologies à base de DNS en demandant la fermeture temporaire de 277 noms de domaines.

Dans les deux cas la méthode utilisée par ces botnets est bien connue. Elle utilise la fonctionnalité de round robin DNS  qui consiste en l'ajout d'une grosse quantité d'IP avec un TTL très bas sur un même host, on l'appelle Fast-Flux.

Elle a la propriété de changer continuellement les adresses IP attachées à un même nom DNS. Elle permet ainsi de cacher rapidement le destinataire par un effet de bord intéressant du TTL bas, le changement d'adresse IP rapide. Ces dernières font ainsi office de "reverse proxy" pour la communication avec le reste du réseau (lien Wikipedia).

Regardons maintenant les méthodes de communication décentralisées, utilisées massivement ces dernières années, comme par exemple les DHT (tables de hachages distribuées) utilisées dans des protocoles P2P, par exemple, BitTorrent.

Essayons de nous mettre dans la peau d'un "Bot Master" (contrôleur du botnet) pour imaginer un concept qui ne se base plus sur des référents fixes tels que les services DNS, HTTP, IRC, ... mais sur le réseau lui même.

Pour la communication réseau, il est judicieux d'utiliser une DHT de type Chord, qui permet de d'associer chaque représentant du réseau à un hash unique. Cela permet de faire du calcul de distance, de simplifier la communication, et de baser les messages sur un système d'évènements totalement asynchrone afin de créer ce qu'on appelle un overlay network.

Il existe une implémentation de l'algorithme de Chord en langage C, le projet Chimera.

Du fait des faibles dépendances de cette bibliothèque il est possible de la porter assez simplement sur plusieurs architectures et OS différents, pouvant être aussi exotiques que certaines appliances/routeurs ou encore certains téléphones  (utilisant une µ/glibc).

L'overlay network peut ainsi être décomposé en quatre primitives indispensables à la vie du réseau :

- set // qui permet d'ajouter une ressource (peer, chunk)
- get // qui permet de récuperer une ressource
- del // qui supprime une ressource
- route // qui route le message vers la ressource

L'avantage direct de ce type de technologie est la non divulgation des adresses des destinataires, et surtout le fait de se passer des problématiques de routage entre les différents noeuds.

Le principe d'une DHT étant pour un peer de ne connaître qu'une petite portion du réseau, une personne voulant récupérer les adresses IP de tout le réseau n'aura que la vision du peer qu'il contrôle avec ses voisins, sa "leaf" pour reprendre les termes liés à la bibliothèque chimera.

Le routage est automatique, les problématiques de routage sont négociées par la DHT elle-même.

Le principal problème de ce mode de communication provient du NAT. En effet, un client, situé derrière un routeur, possédant une adresse privée ne pourra pas directement communiquer avec le reste du réseau, la passerelle ne relayant pas les messages entrants.

Il existe cependant plusieurs méthodes pour traverser les NAT, la plus efficace pour ce type de réseau étant l'utilisation de Peer spéciaux dits points de rendez-vous. Il prennent en charge les connexions sortantes d'un client NATé lui permettant de communiquer avec le reste du réseau.

L'utilisation de l'UDP hole punching fiabilise cette méthode en assurant une connexion directe une fois la négociation avec le point de rendez-vous effectuée.

Un bon exemple est le botnet Conficker qui utilise des points de rendez-vous, mais là encore en utilisant des listes de domaines générés par le bot toutes les 3h, et surtout prédictibles.

Il existe également une autre solution, moins fiable, de communiquer directement avec des clients derrières des NAT, en profitant de l'état stateless de l'UDP. Depuis un Peer A, nous pouvons faire envoyer en continu des paquets sur un Peer B qui ne s'attendra pas à recevoir le flux. Si le NAT ne modifie pas le port source du Peer A, B peut envoyer à son tour un flux UDP en direction de A sur ce même port source et ainsi assurer la connexion. Cette méthode est en effet peu fiable car le port source peut se retrouver modifié par l'équipement réseau en amont.

Revenons à notre DHT. Une attaque peut mettre en péril l'intégrité d'une DHT : le fait d'ajouter une énorme quantité de bot afin de la polluer et après un certain temps, de tous les déconnecter en même temps pour couper le routage entre nodes. Ces "tainted Peer" doivent être identique en tout point aux autres peers du réseau. La réussite de cette attaque est liée à la taille du réseau. Plus le réseau est grand et plus il sera difficile de polluer la DHT.

De même, pour vérifier si une information est valide ou pas il n'existe actuellement aucune méthode fiable de vérification des messages, un tainted peer peut envoyer de fausses informations.

Généralement le bot master possède une clef privée permettant de signer ses messages, ce qui handicape les messages autonomes entre peers, à l'exception des messages de type keepalives et les forward de messages signés.

Pour conclure, il semble évident que l'émergence d'une solution totalement décentralisée, actuellement possible avec des outils et des bibliothèques open-source, serait plus difficile à éradiquer. Il existe aujourd'hui des solutions concrètes pour fabriquer des réseaux décentralisés indépendant de l'OS et de l'architecture, qui ne font appel à aucun référant fixe en dehors du réseau lui-même et capable de faire du NAT traversal. Contrairement aux exemples précédant cités en début d'article, il sera extrêmement difficile dans les années à venir de supprimer ce type de réseau.

Pour vous donner un ordre d'idée, le plus gros "cloud" n'appartient pas à Microsoft, Google ou Amazon, mais aux propriétaires du ver Conficker.

 

Domptage de Firefox à l'aide de Chickenfoot

chickenfoot1

Lors d'un test d'intrusion, nous avons eu à faire une recherche exhaustive sur des comptes Webmail, plus précisément des identifiants valides, en laissant le minimum de traces dans les logs. Typiquement simuler une action humaine. Nous nous sommes orienté vers l'extension Firefox, Chickenfoot.

Chickenfoot (développée par le User Interface Design Group du MIT) est une interface qui permet de contrôler son navigateur au moyen de scripts.

Ses principaux atouts :

- Les scripts créés tournent dans l'espace chrome (au delà du DOM de la page, on est au niveau des extensions, on peut donc intéragir avec le code de Firefox).

- De nombreuses fonctions et bibliothèques extrêmement utiles sont fournies.

- C'est le juste milieu entre la macro de souris/clavier extrêmement imprécise (en particulier lorsqu'il s'agit de gérer les erreurs) et le script curl ou équivalent, détectable et limité (comportement non classique, non exécution du javascript, non téléchargement des images, etc.).

Chickenfoot permet donc d'automatiser un comportement utilisateur sans avoir à émuler un navigateur.

Nous nous sommes uniquement intéressés à l'aspect automatisation d'actions, mais il est à noter que ses fonctionnalités sont aussi orientées sur la présentation de contenu (la plupart des tutoriaux le présente d'ailleurs sous cet aspect).

chickenfoot2Comme un code source parle bien souvent plus qu'un long discours, vous trouverez - ici - un code exemple permettant le bruteforce d'un SquirrelMail français.

Deux blocs de fonctions, Utils et Squirrel, avec pour Utils :

Utils.Output pour la création de logs, qui donne un exemple de manipulation de fichiers (grâce à l'include fileio.js, jetez un oeil aux bibliothèques documentées, et n'hésitez pas à fouiller les sources de Chickenfoot pour trouver des petits trésors comme screenshot.js qui porte bien son nom).

Elle est suivie par Utils.CloseBoxWindow pour détruire toute forme de messages d'alerte (on notera ici la manipulation d'objets du navigateur).

Dans le bloc de fonctions Squirrel vous avez les exemples de base :

go(url);
retvalue = find("Identifiant:");
if (retvalue.count == 1) {
Util.Output("Init OK");
} else {
Util.Output("Can't verify if it's a good login page");
return (null);
}

go(url) envoie l'onglet courant sur la page url. Le find permet de faire de l'évènementiel, il sert de wait. Il attend que la page soit chargée, puis y cherche ensuite la chaine "Identifiant:". On peut ensuite effectuer un test dessus.

Par la suite, les identifiants et mots de passe sont extraits des fichiers sur le disque (un exemple d'expression régulière permettant de scinder le contenu de ces derniers).

On continue avec la fonction Squirrel.Check, appelée pour tester un couple d'identifiants :

enter("Identifiant :", login);
enter("Mot de passe :", pass);
click("Messagerie button");
retvalue = find("Utilisateur inconnu ou mot de passe incorrect.");
if (retvalue.count == 1) {
[...]
}

La simplicité de cette extension apparait très clairement sur cet exemple. On est loin du POST, du GET, des input type=hidden, des redirections de pages, des problèmes d'XMLHTTPRequest, etc. On demande simplement de remplir des champs, de cliquer sur un bouton, puis de regarder une fois la page chargée si une chaine est présente.

L'appel à sleep() qui suit, permet de temporiser, à noter que cette implémentation fait partie des fonctions fournies par l'extension, et souffre de problèmes sous certains systèmes exploitations (FreeBSD entre autre). Dans un soucis de portabilité, il est conseillé de rester sur les classiques rappels par setTimeout() bien connus des développeurs Javascript.

Je vous renvoie à la documentation officielle et à son wiki (courts et incomplets), au peu de posts tiers mais surtout aux sources (pour ceux qui souhaitent approfondir). Le mode record est à voir aussi, qui permet de générer très facilement les enter(xx,xx) et click(xx) (il suffit de cocher la case "Record actions").

Ce billet est une brève introduction de l'outil. Nous publierons prochainement une documentation plus avancée accompagnée de sources.