2020 a confirmé que Cobalt Strike était bel et bien entré dans la boîte à outils de la plupart des groupes d’attaquants. D’Ocean Lotus au groupe derrière les attaques de Solar Winds, Cobalt Strike est partout. Que vous travaillez en SOC ou en threat intelligence, il est probable que vous allez rencontrer ce malware dans votre activité. Cet article fournit quelques clés afin d’analyser une attaque utilisant Cobalt Strike.
En décembre 2020, le monde de la sécurité informatique se réveille groggy devant l’ampleur de l’attaque Solar Winds. Un groupe d’attaquants a infiltré les systèmes informatiques de l’entreprise américaine Solar Winds (qui vend des solutions de supervision de réseau), et a utilisé les systèmes de mises à jour logiciels pour infiltrer certains de ses clients. Immédiatement, la chasse aux malwares commence, on découvre ainsi Teardrop ou encore Sunburst, et au milieu de tout ça, des samples Cobalt Strike [SW]. Cela ne devrait pas nous étonner, depuis plusieurs années, on a vu cette suite d’outils être utilisée de plus en plus souvent par des groupes d’attaquants comme Ocean Lotus [OL] ou encore MuddyWater [MW]. La voir apparaître dans ce qui est sans doute l’attaque la plus importante de 2020 confirme cette tendance, et on peut s’attendre à voir Cobalt Strike très régulièrement dans les prochaines années. L’entreprise Recorded Future notait récemment que plus de 13 % des serveurs de commande et contrôle (C&C) identifiés en 2020 étaient des serveurs CS [RF].
Cobalt Strike (abrégé CS dans la suite de cet article) est une suite d’outils d’attaque pour tests d’intrusion vendue par l’entreprise américaine Strategic Cyber LLC. Sans rouvrir le débat sur la publication d’outils offensifs, il devient indispensable dans n’importe quel SOC de connaître le fonctionnement de Cobalt Strike et d’avoir mis en place les règles qui vont bien pour le détecter au plus vite. Cet article vise à donner un aperçu de la suite Cobalt Strike ainsi que des astuces et techniques pour analyser une attaque l’utilisant.
1. Modes d’infection
Cobalt Strike offre plusieurs moyens de compromettre un système, par exemple via une application HTML (HTA) contenant du code VBScript, ou encore une macro VisualBasic à intégrer dans votre plus beau leurre. Ces outils ne semblent pas faire la joie des groupes d’attaques probablement en raison de leur forte détection par les solutions de sécurité.
La plupart des attaques préfèrent embarquer directement CS dans un loader fait maison (programme qui ne fait que lancer le programme malveillant final), comme les récents loaders Teardrop et Raindrop [SW] utilisés dans l’attaque SolarWinds, ou le loader KerrDown du groupe Ocean Lotus [OL]. Pour simplifier cette tâche, Cobalt Strike fournit un générateur de payloads permettant de récupérer le code en différents langages pour l’intégrer facilement à un exploit ou un loader. Il est également possible d’exporter un loader CS sous format EXE ou DLL utilisable de la même façon. Ces derniers sont par défaut des « stagers », c’est-à-dire des binaires de petite taille qui vont télécharger et exécuter le maliciel final ; mais ils peuvent également inclure le maliciel CS (appelé « beacon ») directement (ils sont alors appelés « stageless » par CS).
Le loader fourni par CS utilise des « named pipes » pour éviter la détection par les moteurs comportementaux de certains antivirus qui ne les implémentent pas [CS1]. Au lancement, un « named pipe » \\.\pipe\MSSE-XXXX-server (où XXXX est un nombre aléatoire) est créé avec deux threads, un qui écrit la charge utile dans ce pipe et l’autre qui la lit. Si ce transfert est effectué correctement, la charge utile est alors déchiffrée et exécutée.
2. Identifier un serveur Cobalt Strike
Lorsqu’on trouve un loader CS obfusqué, il est généralement plus rapide pour l’analyste de regarder si le serveur distant avec lequel communique ce loader est un serveur Cobalt Strike. Les beacons CS peuvent communiquer avec le serveur de C&C en TCP, par DNS ou en HTTP(s). Ce dernier protocole est le plus souvent préféré, car il passe inaperçu dans la masse de trafic web des entreprises. Nous allons nous focaliser exclusivement sur HTTP(s) dans la suite de cet article.
Le serveur web CS utilise un algorithme de checksum appelé checksum8 sur l’URL et répond avec le beacon 32 bit ou 64 bits en fonction de ce checksum (cet algorithme est également utilisé par Metasploit). Nous pouvons voir cette fonction dans le code décompilé de CS :
Un script permet de trouver des URL répondant à cet algorithme pour la version 32 bits (comme /aaa9 ou /aab8) ou 64 bits (comme /aab9 ou /aac8) et de tester si un serveur web répond à ces URL. Le serveur Cobalt Strike filtre les requêtes avec des user-agent inhabituels, il faut donc rajouter un entête User-Agent courant, ce que l’ont peut faire simplement avec HTTPie :
Par défaut, un serveur CS utilise un certificat autosigné n’ayant aucun Common Name ou Issuer Name et avec le numéro de série 146473198 (0x8bb00ee) :
Il est également possible d’utiliser les empreintes JARM pour identifier un serveur CS [JARM]. JARM est un système d’empreintes TLS actif qui se base sur la configuration TLS en dehors du certificat (listes de chiffrements acceptés et extensions TLS) pour générer une empreinte. Il permet d’identifier le web serveur Java utilisé par CS :
L’empreinte 07d14d16d21d21d07c07d14d07d21d9b2f5869a6985368a9dec764186a9175 correspond à la configuration TLS d’un serveur web Java 1.8.0 utilisé la plupart du temps par CS (également utilisé par d’autres applications comme Burp Intruder). Un serveur CS utilisant Java 11 donnerait l’empreinte 07d14d16d21d21d07c42d41d00041d24a458a375eef0c576d23a7bab9a9fb1 [CSJ].
Bien sûr, des attaquants scrupuleux vont probablement changer le certificat par défaut, ou mettre le serveur web Java derrière un reverse proxy. Néanmoins, une recherche sur Shodan en février 2021 montre 564 IP avec le certificat par défaut et plus de 35000 IP avec cette empreinte JARM. Tout le monde ne semble donc pas lire la documentation Cobalt Strike en détail.
3. Analyse du beacon
3.1 Extraire le beacon
Dans la plupart des cas, le fichier délivré par le serveur ne sera pas un exécutable de type PE, mais un beacon chiffré contenant un entête de position-independent code en charge du déchiffrement et de l’exécution du beacon. On peut voir rapidement la routine de déchiffrement de cet entête sur la figure 1.
Les premières instructions permettent de récupérer l’adresse après la routine de déchiffrement, la succession CALL / POP EBX mettant l’adresse suivant le CALL sur la pile avant de la récupérer avec POP. À partir de loc_20, la clé de déchiffrement située juste après l’entête est copiée dans EDX, puis la taille du fichier stocké juste après est copiée dans EAX et déchiffrée par un XOR avec EDX. La routine de déchiffrement en loc_2e va ensuite déchiffrer par un XOR avec enchaînement de blocs (Cipher Block Chaining ou CBC).
Une fois l’entête déchiffré, nous trouvons alors le beacon qui peut être sous la forme d’un position-independent code, mais plus souvent sous la forme d’un fichier PE qui est également exécutable (ce que CS appelle « raw stageless artifact » [CS2]). Pour ce faire, CS utilise un entête PE valide, mais avec un entête DOS modifié (voir la figure 2) qui va aller appeler la fonction exportée _ReflectiveLoader@4 qui implémente un loader de PE minimaliste basé sur ReflectiveDLLInjection [REF]. Une fois le PE chargé, le code dans l’entête DOS n’a plus qu’à appeler le point d’entrée.
3.2 Extraire la configuration
La configuration du beacon est stockée directement dans le binaire sous la forme d’une liste d’entrées type-taille-valeur, le tout « xoré » soit avec la valeur 0x69 pour CS v3 ou 0x2E pour CS v4 (dans de rares binaires, la configuration est stockée en clair). Par exemple, sur la figure 3, on voit la première entrée de type 1 pour short, de taille 2 qui donne l’information SSL/DNS (ici, 8 indique une communication en HTTP avec TLS).
Il est donc assez simple avec une expression régulière d’identifier le début de la configuration, puis de la déchiffrer et décoder :
La valeur « watermark » est intéressante, il s’agit d’un nombre généré à partir de la licence de l’utilisateur et inclus dans la configuration, afin d’identifier une utilisation malveillante de CS. La plupart des versions crackées de CS mettent cette valeur à zéro comme dans la configuration ci-dessus. La licence d’évaluation de CS met également cette valeur à zéro, mais elle désactive aussi le chiffrement des communications du beacon, chiffrement qui est actif ici (valeur « cryptoscheme » à 0), nous avons donc bien une version crackée de CS. Si un groupe utilise une valeur unique non nulle, cela peut permettre de pivoter et identifier de nouveaux beacons (cela a été, par exemple, utilisé pour traquer le maliciel Trickbot [TRICKBOT]).
4. Communications réseau
CS implémente des « profils C&C malléables » [CS3] permettant de configurer en détail le comportement du beacon. La configuration permet notamment de définir précisément les requêtes GET et POST, ou encore le user-agent utilisé. La plupart des groupes d’attaques essaient d’imiter au plus près des services existants, comme le groupe Ocean Lotus qui utilise des URL proches du service Google Safe Browsing.
Un beacon CS communique avec son serveur C&C après un nombre de millisecondes défini dans la configuration (.sleep) avec une variance aléatoire (.jitter). À chaque intervalle, le beacon communique avec le serveur via une requête GET HTTP ou HTTPs. Cette requête utilise l’URL et user-agent définis par la configuration, la valeur par défaut étant définie aléatoirement au lancement du serveur CS. Les métadonnées de la machine sont passées chiffrées dans l’entête Cookie.
La réponse du serveur fournit la commande chiffrée que doit exécuter le beacon (dans l’exemple ci-dessus, aucun contenu signifie que le beacon n’a aucune commande à exécuter). Une fois cette tâche réalisée sur le système compromis, le beacon renvoie alors le résultat de cette tâche, cette fois-ci via une requête POST.
La configuration par défaut utilise l’URL /submit.php pour les requêtes POST, les données utilisées sont ensuite passées chiffrées dans le corps de la requête.
Les configurations C&C permettent de configurer tous les paramètres de ces requêtes HTTP. CS fournit également la possibilité de définir un protocole fait maison en intégrant un programme « ExternalC2 » dans le beacon. Dans ces cas-là, le beacon intègre ce programme et va lui envoyer les données via un named pipe. C’est le programme « ExternalC2 » qui acheminera les données reçues à un service tiers qui les enverra à son tour au serveur C&C final. [EC2].
Conclusion
Nous avons vu quelques exemples d’utilisation de Cobalt Strike et de sa façon de communiquer avec le serveur de C&C. Une fois le mode de fonctionnement de CS connu par l’analyste, il est relativement aisé de reconnaître un serveur CS, d’en extraire les beacons ainsi que leurs configurations. L’analyste pourra alors consacrer son temps à identifier les mouvements latéraux dans son réseau, et les différentes portes dérobées laissées ci et là par les attaquants. Une suite de scripts permettant de réaliser ces opérations est disponible sur GitHub [SCRIPTS]. Je recommande également la lecture de l’excellent « The art and science of detecting Cobalt Strike » [TALOS].
En termes de détection, MITRE fournit une liste détaillée des techniques ATT&CK sur son site [MITRE]. Rien de très original, la meilleure solution pour un SOC consiste toujours à s’assurer de couvrir l’ensemble du périmètre en termes de détection, et à intégrer des flux de menaces (de plus en plus faciles à trouver pour CS), des règles de détection de binaires (comme Yara), de comportement (comme Sigma) ou de trafic réseau (voir les conseils de Sekoia là-dessus [SEKOIA]) propres à Cobalt Strike. Le dépôt Awesome-CobaltStrike-Defence [ACSD] vous permettra de trouver toutes les ressources nécessaires sur ce sujet.
Références
[SW] Symantec, « Raindrop: New Malware Discovered in SolarWinds Investigation », janvier 2021, https://symantec-enterprise-blogs.security.com/blogs/threat-intelligence/solarwinds-raindrop-malware
[OL] Palo Alto, « Tracking OceanLotus’ new Downloader, KerrDown », février 2019, https://unit42.paloaltonetworks.com/tracking-oceanlotus-new-downloader-kerrdown/
[MW] Bleeping Computer, « GitHub-hosted malware calculates Cobalt Strike payload from Imgur pic », décembre 2020, https://www.bleepingcomputer.com/news/security/github-hosted-malware-calculates-cobalt-strike-payload-from-imgur-pic/
[CS1] Cobalt Strike, « Learn Pipe Fitting for all of your Offense Projects », février 2021, https://blog.cobaltstrike.com/2021/02/09/learn-pipe-fitting-for-all-of-your-offense-projects/
[RF] Recorded Future, « Adversary Infrastructure Report 2020: A Defender’s View », janvier 2021, https://www.recordedfuture.com/2020-adversary-infrastructure-report/
[JARM] John Althouse, « Easily Identify Malicious Servers on the Internet with JARM », novembre 2020, https://engineering.salesforce.com/easily-identify-malicious-servers-on-the-internet-with-jarm-e095edac525a
[CSJ] Cobalt Strike, « A Red Teamer Plays with JARM », décembre 2020, https://blog.cobaltstrike.com/2020/12/08/a-red-teamer-plays-with-jarm/
[CS2] Cobalt Strike, « What is a stageless payload artifact? », juin 2016, https://blog.cobaltstrike.com/2016/06/15/what-is-a-stageless-payload-artifact/
[REF] Stephen Fewer, ReflectiveDLLInjection, https://github.com/stephenfewer/ReflectiveDLLInjection
[CS3] Cobalt Strike, « Malleable Command and Control », https://www.cobaltstrike.com/help-malleable-c2
[TRICKBOT] Sentinel Labs, « Enter the Maze: Demystifying an Affiliate Involved in Maze (SNOW) », juillet 2020, https://labs.sentinelone.com/enter-the-maze-demystifying-an-affiliate-involved-in-maze-snow/
[EC2] Cobalt Strike, « External C2 », https://www.cobaltstrike.com/help-externalc2
[SCRIPTS] Étienne Maynier, scripts pour Cobalt Strike, https://github.com/Te-k/cobaltstrike
[TALOS] Nick Mavis, Cisco Talos, « The art and science of detecting Cobalt Strike », septembre 2021, https://talos-intelligence-site.s3.amazonaws.com/production/document_files/files/000/095/031/original/Talos_Cobalt_Strike.pdf
[MITRE] MITRE, Cobalt Strike, https://attack.mitre.org/software/S0154/
[SEKOIA] Sekoia, « Hunting and detecting Cobalt Strike », https://www.sekoia.io/en/hunting-and-detecting-cobalt-strike/
[ACSD] Michael Koczwara, Awesome CobaltStrike Defence, https://github.com/MichaelKoczwara/Awesome-CobaltStrike-Defence