Résumé
- Censys sont incroyablement riches en détails qui passent souvent inaperçus sans un œil averti. Ce guide met en évidence la valeur de ces données hautement structurées et donne un aperçu de la manière dont nous les utilisons en interne pour détecter les infrastructures suspectes.
- Nous lançons un utilitaire gratuit appelé Censeyequi peut découvrir des pivots utiles dans les données de l'hôte Censys et (optionnellement) explorer les hôtes connexes en utilisant les données de ces découvertes.
Pivot pour le profit
Après des années de travail avec les données du site Censys , vous remarquez des schémas qui se rapprochent de l'analyse Internet. Au fil des enquêtes, votre boîte à outils s'enrichit de nouveaux utilitaires, d'une nouvelle terminologie et de nouvelles techniques qui vous permettent de passer d'un indice à l'autre en douceur. Qu'il s'agisse d'identifier un logiciel jamais vu auparavant ou de suivre de manière proactive l'infrastructure connectée à l'internet d'un criminel présumé, tout a souvent commencé par un seul fil, un indice qui, une fois exploité, a commencé à démêler une histoire plus vaste.
Vous verrez souvent des hôtes à l'aspect extrêmement générique qui ne proposent qu'une poignée de services qui ne sont parfois que ce qu'ils semblent être ; par rapport à l'ensemble de l'internet, beaucoup de ces hôtes sont, en fait, raisonnablement uniques. Prenons l'exemple de la réponse HTTP suivante :
HTTP/1.1 200 OK
Date: <REDACTED>
Server: Apache/2.4.41 (Ubuntu)
Content-Length: 0
Content-Type: text/html; charset=UTF-8
À première vue, il s'agit d'une réponse HTTP typique d'un serveur web Apache fonctionnant sous Ubuntu. Si nous filtrons les hôtes en fonction de la valeur exacte de l'en-tête Server, nous trouvons plus de 420 000 hôtes avec la même configuration, ce qui n'est pastrès unique. Cependant, lorsque nous analysons l'intégralité de la réponse à l'aide d'un hachage SHA-256 et que nous limitons notre recherche au port 80, ces 420 000 correspondances sont réduites à seulement 1 961 résultats.
Il en va de même dans l'autre sens : ce qui semble unique est souvent assez générique. Les empreintes JARM sont souvent présentées comme des indicateurs de types spécifiques de logiciels malveillants, mais en réalité, ces empreintes ne représentent pas le logiciel malveillant lui-même ; elles représentent l'API TLS sous-jacente sur laquelle le logiciel malveillant s'exécute. Par conséquent, lorsque vous recevez une empreinte JARM d'un serveur prétendument malveillant et que vous constatez qu'elle correspond à des dizaines de milliers d'hôtes en cours d'exécution(comme Metasploit JARM), vous devez la prendre avec un grain de sel.
Le point essentiel est que le diable se cache dans les détails en ce qui concerne les données d'analyse Internet. Lorsque quelque chose de très spécifique est trouvé sur un nombre limité d'hôtes, cela signifie souvent (mais pas toujours) qu'un lien peut être établi. Mais l'identification de ces éléments très spécifiques peut s'avérer difficile, et il est facile de négliger certains éléments que notre cerveau a l'habitude de voir.
Ce certificat TLS est un exemple de quelque chose de très unique que je pourrais facilement regarder sans autre contexte :
Si nous tirons le rideau un peu plus loin, nous verrons que l'organisation "Microsoft IT" ne se trouve nulle part près d'un réseau appartenant à Microsoft, et qu'il y a même quatre services Cobalt Strike vérifiés (sur deux hôtes) présentant un certificat "Microsoft IT".
Vous pouvez vous dire "Cela semble intéressant", cliquer sur les détails de l'hôte et chercher d'autres hôtes avec le même titre HTML, pour être accueilli par deux hôtes correspondants dans le même ASN mais sur des sous-réseaux différents :
Nous nous demandons donc ce qu'est "nmps" et pourquoi il n'est présent que sur deux hôtes, dont l'un est manifestement malveillant. Nous ouvrons donc à nouveau la page des détails de l'hôte et examinons l'ensemble du corps de la réponse pour comprendre ce qu'est cette chose, puisque la recherche de "nmps" sur le web ne nous permet de savoir que "New Mexico Professional Surveyors" est apparemment une chose :
Pourtant, aucune information valable ne m'aide à déterminer ce qu'est "nmps". Le HREF semble être tronqué ou peut-être corrompu, nous prenons donc un extrait du corps et le collons sur GitHub pour voir s'il fait partie d'un projet open-source, en particulier le texte "404 not found,power by" (404 non trouvé, alimenté par) :
Et maintenant, nous avons une réponse. "nmps" est un fork de "nps", qui est (je cite) un "serveur proxy de pénétration intranet léger, performant et puissant" et, à en juger par les statistiques du repo, un serveur très connu.
Le seul hôte avec "nps" qui n'exécute pas Cobalt Strike, 47.108.57.1, commence à paraître beaucoup plus suspect grâce à ces nouvelles informations. Si nous nous rendons sur VirusTotal et que nous recherchons l'IP, nous constatons que 14 fournisseurs ont signalé cette IP comme étant malveillante :
Dans l'onglet "communauté" du résultat du test VT, plusieurs utilisateurs ont signalé qu'une balise Cobalt Strike avait été trouvée sur le port 80 il y a seulement 19 jours :
Pour vérifier, nous avons consulté les données historiques associées à cet hôte et avons constaté que, oui, jusqu'au 26 octobre 2024 environ, une balise Cobalt Strike existait bel et bien sur cet hôte, tout comme l'autre serveur présentant l'erreur "NPS" à l'heure actuelle.
Malheureusement, les données d'analyse Internet ne nous permettent pas de savoir avec certitude si ces deux hôtes sont liés, mais nous savons qu'avec quelques pivots, nous avons pu identifier une infrastructure malveillante jusqu'alors inconnue.
Rapports et automatisation
Il s'agit d'une tâche que nous effectuons souvent sur Censys: utiliser une donnée suspecte pour trouver d'autres éléments tout aussi suspects. Et si vous ne savez pas dans quels champs spécifiques de nos données il est possible d'effectuer un pivot, cette tâche peut s'avérer assez lourde lorsqu'elle est effectuée manuellement. Mais le pivot est roi. Nous avons donc décidé d'automatiser certaines de ces tâches simples pour notre usage interne, ce qui s'est avéré très utile - à tel point que nous avons décidé de rendre cet outil accessible à l'ensemble de la communauté Internet.
Censys Les données de numérisation sont ce que j'appellerais "hautement structurées", en ce sens que chaque information est divisée en champs individuels - une chose se ramifie en un arbre hiérarchique, ce qui vous permet de comprendre la propriété d'un élément par rapport au suivant. Ce format structuré se prête très bien au passage d'une donnée à une autre.
Présentation de "Censeye" : un outil de reporting auto-pivotant
Censeye est un outil terminal que nous avons mis au point en quelques semaines et qui est parti d'un principe simple : prenez un seul résultat d'hôte structuré et, pour chaque champ, dites-moi combien d'autres hôtes sur Internet ont la même chose. Pour ce faire, nous avons simplement analysé un résultat de balayage et généré une expression CenQL pour toutes les paires clé/valeur. Ensuite, pour chaque requête générée, nous avons exécuté un rapport agrégé dans lequel le champ de ventilation est le nombre d'adresses IP. L'objectif était de trouver des pivots intéressants que nous aurions pu négliger en examinant manuellement un hôte.
Nous nous sommes rapidement rendu compte que tous les termes de recherche ne permettaient pas de trouver des pivots, et nous avons donc commencé à créer une liste de termes autorisés pour la génération de rapports. Nous avons également ajouté une logique simple qui mettrait en évidence les termes de recherche spécifiques qui semblent pouvoir mener à des résultats plus prometteurs. Par exemple, si une clé/valeur est trouvée sur plusieurs hôtes mais qu'elle est inférieure à un certain maximum configurable, nous voulions que ces termes de recherche soient mis en avant. Voici la sortie par défaut d'un rapport généré pour l'adresse IP "114.55.250.233".
Ici, nous voyons un tableau avec trois colonnes - la première colonne est le nombre d'adresses IP uniques qui correspondent à la clé de la colonne 1 avec la valeur de la colonne 2. Les lignes en gras indiquent les termes de recherche pour lesquels le nombre de correspondances est supérieur à un mais inférieur à 120 (valeur par défaut). Enfin, il affiche tous les termes de recherche "intéressants" qui ont été trouvés en cours de route. Si le terminal le permet, toutes les données affichées sont interactives et vous dirigent vers le résultat de la recherche Censys pour cet élément spécifique.
Des manipulations supplémentaires sont effectuées en arrière-plan pour chaque entrée ; par exemple, certains des résultats TLS génèrent en fait plusieurs rapports de différentes manières :
- Un rapport sur la clé/valeur TLS exacte : services.tls.certificates.leaf_data.subject.common_name : "example.com"
- Un autre rapport recherche (et non pas services.tls.certificates.leaf_data.subject.common_name : "example.com") et "example.com".
Il s'agit d'extraire un nom d'hôte du certificat et de voir s'il apparaît ailleurs sur l'internet.
En bref, le flux de travail de Censeye consiste en un processus en six étapes. À partir d'une adresse IP, le système récupère les données de l'hôte sur Censys, en extrayant et en affinant les paires clé-valeur des détails du service pour ne conserver que les champs les plus pertinents. Un rapport agrégé est généré à partir de Censys pour chaque paire clé-valeur sélectionnée, le nombre d'adresses IP servant de mesure de ventilation. Un seuil semi-unique est ensuite appliqué pour identifier les "termes de recherche intéressants". Si un paramètre de profondeur est spécifié, l'utilitaire récupère une liste d'hôtes correspondants, extrait leurs adresses IP et les réutilise comme données d'entrée dans l'étape initiale. Ce cycle se répète jusqu'à ce que le compteur de profondeur atteigne zéro. Rien d'extraordinaire.
Le mécanisme de signalement simple s'est avéré incroyablement utile en soi, car nous avons découvert de nombreuses nouvelles choses que nous aurions pu ignorer sans lui. En fait, un de nos cas d'utilisation quotidiens consiste à alimenter les hôtes qui ont déjà été étiquetés comme serveurs de commande et de contrôle (c2) pour trouver des connexions à d'autres hôtes qui ne sont pas des serveurs de commande et de contrôle (c2). pas pas étiquetés "c2". En d'autres termes, nous demandons s'il existe des serveurs C2 connus qui ont des liens avec des infrastructures inconnues.
Par défaut, Censeye lit à partir de stdin, il est donc facile d'utiliser d'autres outils, comme le CLI Censys , pour l'alimenter en hôtes. Dans ce cas, nous voulons regarder les hôtes qui sont déjà étiquetés comme "c2", mais lors de la génération des rapports d'hôtes pour chaque champ, exclure tous les hôtes étiquetés comme "c2" des totaux. Cela se fait avec l'option"-query-prefix" :
~$ censys search 'labels=c2' | \
jq '.[].ip' | \
python censeye.py --query-prefix 'not labels=c2'
Le même rapport tabulaire est généré pour chacun des PI d'entrée :
Vous remarquerez peut-être que plusieurs de ces lignes ont un nombre d'hôtes égal à zéro ; cela est dû à l'argument du préfixe de la requête que nous avons défini ci-dessus - cela nous indique que ces lignes n'ont été trouvées que sur des hôtes auxquels l'étiquette "c2" a déjà été appliquée, ce qui nous laisse avec trois termes de recherche "intéressants" qui ont été trouvés sur des hôtes non c2 :
Puisque nous parlons de certificats, lorsque Censeye voit une empreinte de certificat TLS qui ne se trouve que sur un seul hôte (ce qui signifie que le certificat n'a été vu que sur l'hôte que vous consultez), il tente de déterminer si ce certificat a été vu sur un autre hôte dans le passé, et si c'est le cas, cette information est mise à disposition. Prenons l'exemple de ce serveur C2 présumé de MoonBounce:
Ce certificat n'est observé que sur cet hôte actuellement, mais il est apparu sur plus de 17 hôtes différents depuis 2020. Le rapport principal met également cela en évidence en indiquant le nombre d'hôtes historiques (uniques) entre parenthèses. Il s'agit d'un moyen rapide de déterminer si un certificat unique sur un hôte a déjà été vu ailleurs. Il convient de noter que l'historique, et la distance dans le passé que vous pouvez voir, est lié aux niveaux de permission de votre compte.
Étant donné que nous indiquons déjà ce que nous considérons comme des termes de recherche "intéressants" et que nous disposons d'une liste stricte de champs à respecter, avec des limites sur la quantité de données que nous pouvons extraire, nous avons suffisamment de garde-fous pour permettre à l'outil de travailler de manière indépendante. Ainsi, au lieu d'extraire un seul rapport, d'examiner les résultats des termes de recherche trouvés, puis d'exécuter d'autres rapports basés sur ces recherches, vous pouvez demander à Censeye de le faire pour vous.
Pour illustrer cela, examinons une seule adresse IP(5.188.87.38) qui a récemment servi de serveur C2 pour le voleur d'informations Stealc. Si nous consultons l'hôte sur Censys, nous constatons qu'il n'y a pas grand-chose à dire :
Malgré cela, sous Censeye, nous pouvons immédiatement voir que le service SSH sur le port 22 a une empreinte digitale qui correspond à 45 autres hôtes.
Nous pouvons soit cliquer manuellement et regarder par nous-mêmes, soit fournir un nouveau drapeau qui indique à l'outil de générer des rapports sur tous les résultats provenant des "termes de recherche intéressants". Censeye peut agir comme une sorte de crawler - à une profondeur de zéro (par défaut), il n'affichera que les rapports sur l'hôte interrogé. Cependant, si nous augmentons cette profondeur, l'outil récupérera les hôtes correspondants pour les "termes de recherche intéressants" qu'il a trouvés sur l'hôte d'origine et exécutera le même processus de rapport sur ceux-ci.
Ici, nous modifions nos arguments d'origine avec "-depth 1". Pour tout "terme de recherche intéressant" trouvé sur 5.188.87.38, l'outil récupère une liste d'hôtes correspondant à ce terme et génère le même rapport pour chacun d'entre eux. Comme nous avons déjà vu que le seul terme de recherche partagé sur cet hôte est l'empreinte SSH, à cette profondeur, l'outil n'affichera que des informations sur les autres hôtes utilisant cette même empreinte.
Le résultat est maintenant un peu différent ; nous sommes accueillis par de nombreux autres rapports tabulaires pour tous les hôtes correspondants, mais cette fois, nous avons un nouveau résultat affichant l'"arbre pivot", qui est une représentation visuelle des hôtes que nous avons découverts et de la façon dont l'outil est arrivé là.
Dans le résultat ci-dessus, nous voyons plusieurs nouvelles adresses IP, toutes utilisant la même empreinte SSH que notre IP d'origine, 5.188.87.38. Nous remarquons également que nous avons maintenant deux "termes de recherche intéressants" affichés en haut, l'un étant l'empreinte SSH originale utilisée pour découvrir ces hôtes et une deuxième empreinte SSH (semi-unique), 6278464b, fonctionnant sur sept hôtes différents, y compris un seul hôte, 179.60.149.209.
Si nous regardons ce nouvel hôte dans Censys, nous verrons que l'empreinte SSH originale fonctionne sur le port 22, alors que cette nouvelle empreinte SSH (ainsi que sept autres hôtes) est liée au port 2222.
Avançons donc un peu et fixons notre valeur "-depth" à "3". Cela signifie que l'outil tentera de trouver des termes de recherche Censys intéressants en trois itérations. Tous ces hôtes ont une ou plusieurs connexions avec le parent ; dans ce cas, toute une série d'empreintes SSH partagées.
Dans l'exemple ci-dessus, 193.29.13.183 utilise l'empreinte SSH bd613b3b, identique au port 22 de 185.232.67.15. L'hôte 185.232.67.15 exécutait également 6278464b, la même empreinte que celle trouvée sur le port 2222 de 179.60.149.209. Ce port exécutait f95812cb, la même empreinte digitale que celle trouvée sur notre hôte original (Stealc C2), 5.188.87.38.
Note: la partie "(via : ...)" de l'arbre pivot est le terme CenQL utilisé pour trouver cet hôte.
Lors de notre recherche finale (à la profondeur 3), plusieurs nouveaux termes de recherche ont été trouvés qui pourraient fournir plus d'informations :
Par exemple, si je sais qu'il y avait un serveur Cobalt Strike sur un hôte qui a été mis hors service ou dont le service a été supprimé, et que vous connaissez la date à laquelle il a été vu pour la dernière fois sur l'hôte, vous pouvez utiliser l'option '-at-time' comme suit :
% python censeye.py 103.234.98.97 --at-time 2024-09-25
Supposons que l'outil trouve un certificat historique (comme décrit précédemment, un certificat qui n'est pas en cours d'exécution actuellement mais qui l'a été dans le passé), et que l'option "-depth" soit fournie. Dans ce cas, Censeye utilisera les données historiques de l'hôte où ce certificat a été trouvé pour trouver des pivots potentiels dans la journée en cours. Le rapport sur les hôtes et l'arbre des pivots vous indiqueront quand cela se produit en affichant la date à laquelle ces résultats ont été récupérés :
ATTENTION !
- Cet outil peut utiliser de nombreuses requêtes, ce qui signifie que l'examen d'un seul hôte peut épuiser votre quota mensuel.
- L'outil n'est pas non plus très rapide ; un rapport est généré pour chaque champ (configuré) sur un hôte, ce qui signifie que plusieurs appels d'API sont effectués en arrière-plan. Lorsque vous utilisez l'indicateur de profondeur, vous augmentez de manière exponentielle le nombre d'appels d'API effectués.
Toutefois, nous avons mis en place plusieurs couches de mise en cache afin de réduire le nombre d'appels à l'API au cours d'une même session. Tous ces éléments sont stockés dans un "espace de travail" défini par l'utilisateur (qui peut être redéfini à l'aide de l'argument "-workspace"). Mon flux de travail (personnel) consiste à conserver un espace de travail différent pour chaque "objet" que j'étudie. De cette façon, je dispose d'une version locale des données que j'ai récupérées à l'origine et je peux les revoir plus tard et passer progressivement aux différents pivots trouvés par l'outil.
Outro
Un README sur le dépôt Github de Censeye contiendra plus d'informations car il est toujours en cours de développement.