Dans la dernière analyse du Lab Threat & Detection de SEKOIA.IO nous avons fait face à une attaque de phishing de type « Man-in-the-middle« , révélant Evilginx2. Il s’agit d’un outil offensif permettant d’outre-passer l’authentification deux facteurs. Nous nous attaquons ici à une menace bien plus importante étant donné sa fréquence d’utilisation par les acteurs de la menace.
Dans ce blogpost, nous décrivons pas à pas comment déployer une défense proactive face à Cobalt Strike. Ils s’agit de l’un des plus puissant outils de pentesting détourné par des attaquants dans de nombreuses campagnes.
En nous concentrant sur les certificats SSL et réponse HTTP, nous présentons des exemples sur la manière de traquer les serveurs Command and Control (C2) de Cobalt Strike et Malleable Profiles.
Nous décrivons également comment détecter :
- Les charges utiles de Cobalt Strike telle que la balise DNS fondée sur la nature et le volume des requêtes DNS ;
- L’escalade de privilèges de Cobalt Strike avec le service svc-exe intégré,
- Les mouvements latéraux de Cobalt Strike avec le service intégré PsExec et
- La communication des balises Cobalt Strike via les canaux désignés.
Pourquoi les défenseurs devraient-ils se concentrer sur la traque et la détection de Cobalt Strike ?
Qu’ont APT29, APT 32, APT 41, APT 19, UNC2453, FIN6, Wizard Spider et la plupart des cybercriminels en commun dans leur boîte à outils ?
Comme montré ci-dessus, la réponse est Cobalt Strike.
Cobalt Strike est un agent post-exploitation commercial pensé pour permettre aux pentesters d’éxcuter des attaques et émuler des actions post-exploitation sur des menaces avancées. Son objectif est d’imiter les tactiques, techniques et procédures des acteurs de la menaces pour tester les défenses de la cible. Cependant, ces dernières années, la raison d’être de Cobalt Strike a été détournée par des attaquants ayant réussi à cracker ses versions officielles. Ils ont ainsi pu les utiliser dans leurs attaques et tirer parti de l’accès distant de Cobalt Strike et de sa capacité à contourner les défenses.
Cobalt Strike est désormais largement utilisé par les acteurs de la menace, peu importe leurs capacités, compétences, la complexité ou les objectifs de leurs campagnes. Par exemple, CS a été remarqué récemment dans les attaques sur SolarWinds [1], ainsi que dans les campagnes fréquemment menées par des groupes criminels comme Wizard Spider [2], [3] et le groupe Egregor [4] délivrant des charges utiles de rançongiciels.
En 2020, Cobalt Strike a été l’outil de pentesting le plus utilisé par les attaquants aux côtés de Mimikatz et Powershell Empire [5]. Au total, 66% des attaques par rançongiciels intégraient des charges utiles de Cobalt Strike sur le 4ème trimestre de 2020 [6].
Par conséquent, ces données mettent en évidence notre besoin, en tant que défenseur, d’être à jour de la menace représentée par l’usage de Cobalt Strike pour des usages malveillants.
Comment fonctionne Cobalt strike, en quelques mots
Cobalt Strike fonctionne sur un mode client/serveur. Le serveur est connu sous le nom de Team Server, tournant sous Linux, contrôlant la balise de charge utile et recevant toutes les informations de l’hôte infecté. Le logiciel client (connu sous le nom de Agressor) fonctionne sur plusieurs OS et permet à l’utilisateur de se connecter sur différents Team Servers pour configurer la balise, délivrer la charge utile et utiliser toutes les fonctionnalités de Cobalt Strike à distance.
La balise est la charge utile de Cobalt Strike, personnalisable via « Malleable C2 profiles », lui permettant de communiquer avec son serveur via HTTP, HTTPS ou DNS. Il fonctionne en mode asynchrone et peut compiler des charges utiles avec ou sans étapes, offrant une flexibilité considérable.
Une fois connecté à son serveur C2, l’utilisateur configure un « listener » (HTTP, DNS…) et une balise avec ou sans étapes (Windows PE, PowerShell…). La livraison des balises peut être réalisée directement à partir du serveur Cobalt Strike ou via un autre outil utilisateur.
Il s’agit d’un outil simple à utiliser et bien documenté [7] expliquant ainsi sa popularité.
Nous adoptons une posture proactive pour protéger nos clients d’attaques utilisant Cobalt Strike. Pour cela, nous nous concentrons sur le tracking des serveurs Cobalt Strike et l’implémentation de règles capables d’en détecter chaque version.
Les attaques utilisant Cobalt Strike s’appuient généralement sur d’anciennes version ayant fuité. Nous utilisons ici la version 4.2 (déployée le 06/11/2020), ayant fuité sur des forums pirates et facile à trouver.
La dernière version (4.3) vient d’être déployée (03/03/2021). En dehors de nouvelles fonctionnalités et corrections usuelles, nous avons remarqué les efforts faits pour réparer les détails techniques aidant à la détection de Cobalt Strike. Nous évoquons certains d’entre eux, mais c’est probablement un jeu sans fin.
Voici comment nous traquons les serveurs C2 de Cobalt Strike
Nous disposons actuellement de plus de 50 trackers pour les serveurs C2 Cobalt Strike et Malleable profiles. Ils nous ont permis d’alimenter notre base de renseignements avec plus de 10 000 IPs en 2020. Cliquez sur ce lien pour en savoir davantage sur les résultats de notre traque.
Vous trouverez ci-dessous un exemple de trois fonctionnalités que vous pouvez suivre pour repérer les serveurs Cobalt Strike. Plusieurs trackers sont valables pour les anciennes versions de Cobalt Strike. Mais comme vous le remarquerez en considérant le nombre de serveurs que nous détectons encore grâce à ces trackers, ils sont toujours efficaces. Comme nous l’avons dit précédemment, les auteurs de menaces utilisent habituellement des versions qui ont fait l’objet d’une fuite et qui ne sont pas nécessairement les plus récentes.
Garder un oeil sur les certificats par défaut
Comme montré ci-dessous, les serveurs Cobalt Strike ont un certificat par défaut affichant des valeurs spécifiques pour le numéro de série, l’émetteur, le sujet et le certificat de validité.
S’ils n’ont pas été modifiés par les attaquants, ces serveurs peuvent être facilement repérés à l’aide d’une requête Shodan. Au moment de l’écriture, 700 serveurs correspondent à ce numéro de série de certificat.
Que nous dit la réponse HTTP ?
Les versions de Cobalt Strike précédant la 3.13 ont une réponse http affichant un espace extérieur à la fin du statut http.
Au moment où nous écrivons cela, nous pouvons encore détecter 30 serveurs en utilisant ce tracker. La même détection peut être faite via des règles Snort.
Examinons un Malleable C2 profile
Comme mentionné plus tôt, les Malleable C2 Profiles permettent de personnaliser Cobalt Strike. En conséquence, les configurations publiques peuvent servir à traquer les serveurs C2.
Voici un exemple d’un Malleable C2 Profile, au certificat auto-signé [8], que l’on peut rechercher sur Shodan.
Les information de l’émetteur du certificat corrrespondaient à 116 serveurs en ligne en 2020 (nom, organisation, équipe, lieu, pays).
Comment notre SIEM nous permet de le détecter ?
Nous avons réalisé des attaques utilisant des balises Cobalt Strike en laboratoire pour savoir comment détecter Cobalt Strike avec notre SIEM SEKOIA.IO.
Pour cet article, nous avons choisi de nous concentrer sur une attaque utilisant une balise DNS comme auditeur de premier niveau et la balise SMB pour les mouvements latéraux. Nous avons détecté chaque étape en utilisant le code source de Cobalt Strike ou les logs générés.
Pour détecter Cobalt Strike en utilisant les règles suivantes, vous devrez avoir accès à ces registres :
- Microsoft-Windows-Sysmon/Operational (et la configuration symon pertinente Named Pipe)
- Microsoft-Windows-Windows Defender/Operational (ou tout autre log d’antivirus)
- DNS et logs de Proxy
Voici quelques règles que vous pouvez intégrer à votre SIEM pour détecter cette attaque en particulier.
Le balisage DNS est une fonctionnalité très utile, permettant d’outre-passer n’importe quel autre filtrage HTTP ou inspection de proxy existant chez la cible.
Le code source de Cobalt Strike (version 4.0) a fuité l’année dernière. Un chercheur y a repéré des caractéristiques intéressante pour le balisage DNS :
From the CobaltStrike source code, you can now build nice query rules for your local Passive DNS database or NIDS.
— Alexandre Dulaunoy (@adulau) November 12, 2020
https://t.co/EzLrBljp8b pic.twitter.com/wqOTew28u1
Le code source mentionné révèle que Cobalt Strike utilise trois étiquettes DNS constantes en paire avec le type de question DNS : « cdn » pour le type A, « api » pour le type TXT et « www6 » pour le type AAAA. Cela signifie qu’à un moment donné, lorsque la balise tentera d’atteindre son serveur C2, outre deux étiquettes aléatoires et celle choisie par l’utilisateur, cette chaîne constante sera utilisée : elle est très pratique en termes de détection et nous permet de construire ce genre de règle :
(dnsquery.value LIKE ‘www6.%’ AND dnsquery.type = ‘AAAA’) OR (dnsquery.value LIKE ‘cdn.%’ AND dnsquery.type = ‘A’) OR (dnsquery.value LIKE ‘api.%’ AND dnsquery.type = ‘TXT’)
Cette règle nous a permis de détecter la première étape de l’attaque, mettant en évidence la balise DNS.
La règle nécessite quelques exeptions (e.g cdn.onenote.net, cdn.fwup.org) pour éviter les faux positifs sur votre trafic réseaux, mais semble fiable. La version 4.3 de Cobalt Strike amène de nouvelles options pour outrepasser les valeurs par défaut à travers un Malleable C2 profile [9]. Les précédentes versions obligeront les attaquants à modifier le code source ou patcher les balises binaires.
Baliser le trafic réseau
Un autre comportement qui peut être détecté dépend de la valeur de l’intervalle entre deux requêtes réseau de balises, qui n’a pas de temps de veille par défaut. Cette configuration peut être modifiée avec un Malleable C2 profile.
Par conséquent, travailler avec Cobalt Strike en mode interactif générera une quantité considérable de requêtes réseau, en particulier avec certaines balises (par ex. DNS) lorsqu’il s’agit de télécharger/téléverser des fichiers. Cela pourrait être utilisé pour la détection en utilisant des règles de comportement classiques.
Lors de notre attaque, nous avons observé que pour les balises DNS et HTTP, même avec seulement l’activité des balises (pas d’exfiltration ou de commande), le total des requêtes DNS/HTTP de l’hôte infecté dépassait 200 requêtes par minutes.
La règle prendrait cette forme :
selection DNS/HTTP requests | count() by minute src_ip > 200
Détecter lorsqu’un attaquant élève ses privilèges à l’aide de svc-exe et se déplace latéralement à l’aide de PsExec
Nous avons pu élever nos privilèges dans le SI de la victime. Nous y sommes parvenus en utilisant svc.exe, une faille intégrée à Cobalt Strike.
Il va déposer un exécutable de charge utile, créer un service pour l’exécuter, contrôler la charge et les nettoyer. Cela nous permet d’accéder au système.
Ensuite, nous voulions effectuer un mouvement latéral et passer nouvel hôte ciblé. Nous avons choisi de tirer parti d’une balise SMB, fréquemment utilisée dans les attaques.
Nous avons exécuté une commande sur Cobalt Strike qui exploite psexec64 comme suit :
$ jump psexec64 <host-ip> <name-of-our-SMB-beacon-listener>
C’est l’une des fonctionnalités qui fait de Cobalt Strike un outil puissant et efficace. Il s’appuie sur les API natives de Windows et non sur une pile de protocoles tiers, augmentant ainsi ses capacités d’évasion de défense. Ainsi, Cobalt Strike a un PsExec intégré, dont la force réside dans sa capacité à lancer des commandes interactives sur des systèmes distants. Il peut être exécuté sur le système de la victime car il utilise des composants natifs de Windows.
Nous avons constaté que ces opérations ont donné lieu à la création d’un service. Ils ont tous deux lancé rundll32.exe qui a lancé une connexion réseau, qui est l’événement ID 3 du journal Microsoft-Windows-Sysmon/Operational. Ce qui le rend différent du comportement habituel de rundll32, c’est que la dll est exécutée sans arguments en ligne de commande.
Ce comportement est ancré dans Cobalt Strike. A moins que les attaquants ne décident de changer la configuration dans le code source, cela détectera de nombreuses autres attaques.
Des pipes pour les détecter tous
Un pipe est une section de mémoire partagée qui traite l’utilisation pour la communication. Le processus qui crée un pipe est le pipe serveur. Celui qui s’y connecte, c’est le pipe client. Un processus écrit l’information au pipe, tandis que l’autre processus en lit l’information.
Il y a deux types de pipes: nommés ou anonymes
Les nommés sont unidirectionnels ou duplex et sont utilisés pour la communication interprocess réseau qui peut avoir lieu entre un pipe serveur et un ou plusieurs pipe client. Plusieurs pipes clients peuvent utiliser le même pipe nommé simultanément dans la même instance.
Les anonymes sont unidirectionnels, utilisés pour les communications interprocess entre un parent et un processus enfant, uniquement sur un ordinateur local.
Cobalt Strike a la capacité de pivoter sur les pipes nommés. Il les utilise pour permettre à une balise de recevoir ses commandes et d’envoyer les siennes à une autre balise. Dans cette situation, les deux balises communiqueront au-dessus des canaux de pipes, comme le souligne la flèche orange dans le graphique de ci-dessous. Cobalt Strike utilise également des sockets TCP et des sessions SSH pour connecter une session beacon à une autre.
Par conséquent, lorsque nous avons connecté un auditeur (par ex. une balise DNS) avec une autre balise (par ex. une balise SMB) pour effectuer un mouvement latéral, nous avons observé la création de l’événement sysmon ID 17 « Pipe created », dans nos journaux.
Lors de nos différents tests, nous avons observé que le pipe créé affichait le même motif qui peut être détecté par ce regex :
MSSE-[0-9]{4}-server
Les utilisateurs de Cobalt Strike ne peuvent pas modifier la valeur par défaut de ces pipes sans accéder et modifier la configuration du code source de Cobalt Strike.
Il est important de distinguer les pipes qui sont créés pour permettre aux balises de communiquer, des pipes nommées qui sont générés spécifiquement pour la balise SMB, et dont la valeur par défaut est sous la forme de : msagent_39 comme indiqué ci-dessous. Contrairement aux pipes MSSE, la valeur par défaut du nom de pipe de la balise SMB peut être facilement modifiée sur l’interface d’attaque.
Charge utile par défaut
Pour de nombreuses interactions avec les utilisateurs, Cobalt Strike affiche une valeur par défaut, et en particulier pour le nommage de la charge utile. Bien sûr, c’est un indicateur de détection très faible, mais une erreur est toujours possible et les défenseurs n’en ont besoin que d’une.
Lors de nos tests de laboratoire avec différents cas d’utilisation, nous avons eu ces noms binaires par défaut :
beacon.{bin|exe|dll|ps1}, artifact.{dll|exe}, payload.{java|ps1|py|rb|vba}
Les journaux anti-virus à ce stade pourraient également être une victoire facile : la plupart des AV ont des signatures spécifiques qui pourraient être utilisées pour déclencher une alerte dans votre SIEM, et détecter un attaquant qui a oublié d’utiliser sa charge utile personnalisée.
Plus globalement, les autres caractéristiques des binaires (sur disque ou en mémoire) pourraient également être utilisées comme indicateurs de détection. C’est pourquoi l’éditeur de Cobalt Strike conseille de le personnaliser avec un Malleable C2 Profile ou le kit Artifact [10].
De nombreuses règles yara publiques existent pour le faire précisément, et essayer de suivre la charge utile existante disponible dans la nature [11]. Ceci est recommandé si vous avez une capacité EDR.
Comment mitiger Cobalt Strike ?
Comme indiqué précédemment, la plupart des caractéristiques des balises Cobalt Strike peuvent être personnalisées. Soit directement sur l’interface utilisateur pour certains d’entre eux, via un Malleable Profile ou en inversant directement le code source. Par conséquent, il est essentiel d’être aussi exhaustif que possible en ce qui concerne la capacité de détection.
En outre, il semble que le concepteur de Cobalt Strike ait fait de l’une de ses priorités de toujours s’assurer que son outil ne puisse pas être détecté, publiant une nouvelle version chaque fois que la dernière version était bien documentée par les défenseurs. Souligner pour nous la nécessité d’être à jour concernant les caractéristiques des nouvelles versions. Depuis, les attaquants ont principalement utilisé les versions divulguées, nous sommes toujours un pas en avant dans la détection des dernières menaces.
Compte tenu des volumes d’attaques effectuées avec Cobalt Strike, combiner la chasse au serveur Cobalt Strike C2 et la détection de balises comme montré dans cet article, est certainement un bon moyen d’assurer la meilleure protection et de resserrer le filet autour de cette menace.
Pour être protégé contre cela, nous vous recommandons fortement de vous appuyer sur une solution de détection en temps réel alimentée par l’intelligence des cybermenaces.
En plus d’avoir un SIEM à jour, il y a aussi ces actions évidentes que les défenseurs pourraient utiliser :
- Cobalt Strike peut être abandonné dans les systèmes de victimes suite à des campagnes d’hameçonnage utilisant des scripts VBS. Il est recommandé de désactiver la macro document dans MS Office. La formation des utilisateurs à remarquer les courriels malveillants devrait également être effectuée sur une base régulière.
- La charge utile de Cobalt Strike peut être livrée sous forme de script Powershell. Il est recommandé de restreindre l’exécution du script Powershell pour autoriser uniquement les scripts signés.
- Certaines signatures de charge utile Cobalt Strike peuvent être identifiées par un antivirus. Il est recommandé d’avoir un bon produit antivirus.
- Les balises Cobalt Strike génèrent des comportements anormaux qui peuvent être traqués à l’aide des journaux Sysmon, Security, PowerShell et WMI.
- Il est recommandé de chasser les processus parents qui engendrent des processus enfants inattendus.
- Surveiller les modifications suspectes aux clés de registre, dossiers de démarrage, planificateur de tâches et exécution de service.
Si vous avez été infecté par Cobalt Strike, il est recommandé de procéder à des analyses de mémoire. L’outil CobaltStrikeScan disponible sur GitHub scanne les fichiers et la mémoire de traitement des balises Cobalt Strike et analyse leur configuration [12]. Il analyse la mémoire du processus Windows pour la preuve de l’injection DLL.
Vous pouvez lire aussi sur le blog :