Détection de conteneurs malveillants avec runtime analysis
Falco est un outil qui détecte en temps réel les processus et les appels système dans le système ou dans les conteneur.
Warning
Veuillez noter que tous les outils et le code source peuvent être utilisés en toute sécurité dans le cadre de ce laboratoire.
Scénario
Ce laboratoire démontre un scénario réaliste de détection d’attaque dans un environnement Kubernetes.
Dans cet environnement :
- Un conteneur compromis agit comme attaquant
- Un conteneur vulnérable agit comme victime
- Falco outil pour la detection des attaques
Le conteneur malveillant réalise plusieurs étapes typiques d’une attaque :
-
Reconnaissance réseau
-
Identification d’un service vulnérable
-
Exploitation de la vulnérabilité
-
Exfiltration de données
Ce type de scénario reproduit un comportement que l’on observe souvent dans des attaques réelles dans des clusters Kubernetes mal sécurisés.
Infrastructure
graph TD;
A[Kubernetes Cluster] --> B[Malicious Pod];
B --> D[nmap];
B --> E[exploit script];
A --> F[Target Pod];
F --> G[Vulnerable service];
A --> H[Falco];
H --> I[Syscall monitoring];
H --> J[Detection rules];
style A fill:#f9f,stroke:#333,stroke-width:2px;
style B fill:#fbb,stroke:#333,stroke-width:1px;
style F fill:#bbf,stroke:#333,stroke-width:1px;
style H fill:#bfb,stroke:#333,stroke-width:1px;
Composants du cluster Kubernetes
Conteneur malveillant (Attaquant)
Objectif: Simuler un comportement réel de malware dans un conteneur.
Dans de nombreux incidents de sécurité, les attaquants obtiennent un accès initial à un conteneur puis utilisent cet accès pour :
- explorer le réseau interne
- identifier d'autres services
- exploiter des vulnérabilités
- récupérer des données
Conteneur cible (Victime)
Objectif: Fournir un service volontairement vulnérable.
Le conteneur cible expose un service HTTP avec une vulnérabilité exploitable: Traversal de répertoire
Falco Deployment
Objectif: Détecter les comportements malveillants pendant l’exécution.
Fonctionnement
Falco observe:
- les appels système du noyau
- les processus exécutés
- les accès fichiers
- l’activité réseau
Il applique ensuite des règles de détection.
Mise en place de l’environnement
Prérequis
Assurez-vous d’avoir installé:
- minikube
- helm
- docker
Start cluster
Installation de Falco
helm repo add falcosecurity https://falcosecurity.github.io/charts
helm repo update
helm install --replace falco falcosecurity/falco \
--namespace falco \
--create-namespace \
--set tty=true \
--set falcosidekick.enabled=true \
--set falcosidekick.webui.enabled=true
Vérifier le déploiement
Attendez que toutes les Pods soient "Running":NAME READY STATUS RESTARTS AGE
falco-7gvx9 2/2 Running 0 101s
falco-falcosidekick-6c7cd9b5c5-459rc 1/1 Running 0 100s
falco-falcosidekick-6c7cd9b5c5-qnwz9 1/1 Running 0 100s
falco-falcosidekick-ui-58bfb74947-58rxs 1/1 Running 0 100s
falco-falcosidekick-ui-58bfb74947-x9nd4 1/1 Running 0 100s
falco-falcosidekick-ui-redis-0 1/1 Running 0 100s
Falco UI
Dans une nouvelle fenêtre de terminal, exécutez:
Accédez à :http://localhost:2802
Nom d'utilisateur : admin
Mot de passe : admin
Déploiement des workloads
-
Déployer le conteneur cible
-
Déployer le conteneur attaquant
-
Vérifier l’état du cluster
Phase 1: Exécution de l’attaque
Dans ce premier exercice, nous allons jouer manuellement le rôle de l'attaquant.
Vous répondrez aux commandes fournies (en les adaptant à vos adresses IP), puis vous verrez les résultats dans l'interface utilisateur.
Cela imite l'accès initial au système par l'attaquant:
1. Recon + Lateral movement
L'attaquant examine les interfaces :
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN qlen 1000
link/ipip 0.0.0.0 brd 0.0.0.0
3: gre0@NONE: <NOARP> mtu 1476 qdisc noop state DOWN qlen 1000
link/gre 0.0.0.0 brd 0.0.0.0
4: gretap0@NONE: <BROADCAST,MULTICAST> mtu 1462 qdisc noop state DOWN qlen 1000
link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff
5: erspan0@NONE: <BROADCAST,MULTICAST> mtu 1450 qdisc noop state DOWN qlen 1000
link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff
6: ip_vti0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN qlen 1000
link/ipip 0.0.0.0 brd 0.0.0.0
7: ip6_vti0@NONE: <NOARP> mtu 1428 qdisc noop state DOWN qlen 1000
link/tunnel6 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00 brd 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00
8: sit0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN qlen 1000
link/sit 0.0.0.0 brd 0.0.0.0
9: ip6tnl0@NONE: <NOARP> mtu 1452 qdisc noop state DOWN qlen 1000
link/tunnel6 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00 brd 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00
10: ip6gre0@NONE: <NOARP> mtu 1448 qdisc noop state DOWN qlen 1000
link/[823] 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00 brd 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00
11: eth0@if22: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
link/ether 06:aa:a4:ae:f9:0d brd ff:ff:ff:ff:ff:ff
inet 10.244.0.10/16 brd 10.244.255.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::4aa:a4ff:feae:f90d/64 scope link
valid_lft forever preferred_lft forever
Il n'y a qu'une seule interface avec une adresse IP valide : 10.244.0.10. L'attaquant l'utilise pour l'énumération du réseau :
/ # nmap 10.244.0.10/24 -n -T5 --disable-arp-ping
Nmap scan report for 10.244.0.1
Host is up (0.0000020s latency).
Not shown: 998 closed tcp ports (reset)
PORT STATE SERVICE
22/tcp open ssh
8443/tcp open https-alt
MAC Address: 00:00:40:01:95:88 (Applicon)
Nmap scan report for 10.244.0.2
Host is up (0.0000030s latency).
All 1000 scanned ports on 10.244.0.2 are in ignored states.
Not shown: 1000 closed tcp ports (reset)
MAC Address: 00:00:40:01:DE:A9 (Applicon)
Nmap scan report for 10.244.0.3
Host is up (0.0000020s latency).
Not shown: 997 closed tcp ports (reset)
PORT STATE SERVICE
53/tcp open domain
8080/tcp open http-proxy
8181/tcp open intermapper
MAC Address: 00:00:40:01:EC:19 (Applicon)
Nmap scan report for 10.244.0.4
Host is up (0.0000020s latency).
All 1000 scanned ports on 10.244.0.4 are in ignored states.
Not shown: 1000 closed tcp ports (reset)
MAC Address: 00:00:40:01:47:9C (Applicon)
Nmap scan report for 10.244.0.5
Host is up (0.0000020s latency).
All 1000 scanned ports on 10.244.0.5 are in ignored states.
Not shown: 1000 closed tcp ports (reset)
MAC Address: 00:00:40:01:17:19 (Applicon)
Nmap scan report for 10.244.0.6
Host is up (0.0000020s latency).
All 1000 scanned ports on 10.244.0.6 are in ignored states.
Not shown: 1000 closed tcp ports (reset)
MAC Address: 00:00:40:01:F4:2B (Applicon)
Nmap scan report for 10.244.0.7
Host is up (0.0000030s latency).
All 1000 scanned ports on 10.244.0.7 are in ignored states.
Not shown: 1000 closed tcp ports (reset)
MAC Address: 00:00:40:01:9A:6F (Applicon)
Nmap scan report for 10.244.0.8
Host is up (0.0000030s latency).
Not shown: 999 closed tcp ports (reset)
PORT STATE SERVICE
8001/tcp open vcom-tunnel
MAC Address: 00:00:40:01:12:3A (Applicon)
Nmap scan report for 10.244.0.9
Host is up (0.0000020s latency).
Not shown: 999 closed tcp ports (reset)
PORT STATE SERVICE
8000/tcp open http-alt
MAC Address: 00:00:40:01:31:52 (Applicon)
Nmap scan report for 10.244.0.10
Host is up (0.0000010s latency).
All 1000 scanned ports on 10.244.0.10 are in ignored states.
Not shown: 1000 closed tcp ports (reset)
Nmap done: 256 IP addresses (10 hosts up) scanned in 25.74 seconds
L'attaquant remarque que 8000/tcp open http-alt est un serveur web.
2. Attack
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Directory listing for /</title>
</head>
<body>
<h1>Directory listing for /</h1>
<hr>
<ul>
<li><a href=".dockerenv">.dockerenv</a></li>
<li><a href="bin/">bin/</a></li>
<li><a href="dev/">dev/</a></li>
<li><a href="etc/">etc/</a></li>
<li><a href="home/">home/</a></li>
<li><a href="lib/">lib/</a></li>
<li><a href="media/">media/</a></li>
<li><a href="mnt/">mnt/</a></li>
<li><a href="opt/">opt/</a></li>
<li><a href="proc/">proc/</a></li>
<li><a href="root/">root/</a></li>
<li><a href="run/">run/</a></li>
<li><a href="sbin/">sbin/</a></li>
<li><a href="srv/">srv/</a></li>
<li><a href="sys/">sys/</a></li>
<li><a href="tmp/">tmp/</a></li>
<li><a href="usr/">usr/</a></li>
<li><a href="var/">var/</a></li>
</ul>
<hr>
</body>
</html>
L'attaquant remarque qu'une attaque par traversée de chemin est possible et l'exploite pour exfiltrer le mot de passe de la victime.
root:x:0:0:root:/root:/bin/sh
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/mail:/sbin/nologin
news:x:9:13:news:/usr/lib/news:/sbin/nologin
uucp:x:10:14:uucp:/var/spool/uucppublic:/sbin/nologin
cron:x:16:16:cron:/var/spool/cron:/sbin/nologin
ftp:x:21:21::/var/lib/ftp:/sbin/nologin
sshd:x:22:22:sshd:/dev/null:/sbin/nologin
games:x:35:35:games:/usr/games:/sbin/nologin
ntp:x:123:123:NTP:/var/empty:/sbin/nologin
guest:x:405:100:guest:/dev/null:/sbin/nologin
nobody:x:65534:65534:nobody:/:/sbin/nologin
Phase 2: Detection & Analysis
Regardez maintenant le tableau de bord. Vous devriez voir quelque chose de similaire à l'image suivante:

Question
Quels appels système et processus sont marqués comme critiques?
Quelles informations pouvons-nous obtenir à partir des tags ?
Phase 3: Attaque complexe
Dans le scénario précédent, nous avons usurpé l'identité d'un utilisateur malveillant qui a obtenu l'accès à un conteneur. Nous allons maintenant passer à un scénario plus complexe, dans lequel l'image du conteneur est déjà compromise. C'est le cas, par exemple, lorsque l'utilisateur télécharge un conteneur malveillant.
Voici le fichier Dockerfile utilisé pour créer l'image de l'attaquant:
FROM alpine:latest
RUN apk add --no-cache nmap curl
# Create a script file
RUN printf '#!/bin/sh\n\
while true; do \n\
echo "Starting attack simulation..."; \n\
echo "1. Scanning network for vulnerable services..."; \n\
nmap -sn vulnerable-target/27; \n\
echo "2. Identifying vulnerable service..."; \n\
sleep 2; \n\
echo "3. Exploiting vulnerability..."; \n\
sleep 2; \n\
echo "4. Retrieving file..."; \n\
curl http://vulnerable-target/etc/passwd; \n\
echo "Attack completed."; \n\
sleep 20; \n\
done' > /usr/local/bin/attack-script.sh
RUN chmod +x /usr/local/bin/attack-script.sh
CMD ["/usr/local/bin/attack-script.sh"]
1. Lancer l'attaque
Exécutez la commande et attendez que l'attaque se déroule. Rendez-vous ensuite sur le tableau de bord de Falco et consultez les événements.
Question
Quels appels système ne sont pas détectés ?
Pourquoi ne voyons-nous plus les événements critiques ?
2. Améliorer les règles Falco
Falco utilise un ensemble de règles par défaut créées par la communauté FOSS. Elles sont disponibles ici.
Nous devons créer une nouvelle règle pour enregistrer l'état critique du logiciel nmap. Vous trouverez ici la documentation sur la manière de créer des règles.
On va créer une règle Falco avec un niveau de gravité CRITICAL qui se déclenche lorsqu'un conteneur utilise la commande nmap.
Une fois que vous avez terminé, ajoutez la règle à un fichier appelé extra-rules.yaml en suivant le schéma suivant:
# extra-rules.yaml
customRules:
rules-nmap.yaml: |-
- macro: nmap_execution
condition: spawned_process and proc.name = "nmap"
- rule: Nmap execution detected
desc: Detects execution of nmap network scanning tool on the system
condition: nmap_execution
output: CRITICAL - Nmap network scan detected (command=%proc.cmdline pid=%proc.pid user=%user.name container=%container.name image=%container.image)
priority: CRITICAL
Ensuite, vous réinstallerez falco avec les règles mises à jour:
helm uninstall -nfalco && helm install --replace falco falcosecurity/falco -f extra-rules.yaml --namespace falco --create-namespace --set tty=true --set falcosidekick.enabled=true --set falcosidekick.webui.enabled=true
Déclencher à nouveau l'attaque
Question
Fournissez une capture d'écran du tableau de bord mis à jour avec la nouvelle règle.
Question
Discutez des risques liés à l'utilisation exclusive des règles par défaut.
Question
Discutez des risques liés à l’utilisation du nom du processus comme règle et proposez des solutions.
Question
Imaginez le cas d'un conteneur exécutant le programme python. Quel type de règles de détection créeriez-vous pour surveiller un tel conteneur?
Question
Expliquez pourquoi il est plus facile d'ajouter une surveillance basée sur les appels système à une application connue qu'à des applications tierces.
Bonus (optional)
Pour l'instant, l'application affiche uniquement les problèmes dans une interface utilisateur. Pour obtenir une visibilité sur ces alertes, vous pouvez configurer des notifications (par exemple, Telegram).
Pour ce faire, vous pouvez modifier le fichier chart values.yaml à l'aide de ce guide et configurer un bot Telegram à l'aide de cet autre guide.