Skip to content

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 :

  1. Reconnaissance réseau

  2. Identification d’un service vulnérable

  3. Exploitation de la vulnérabilité

  4. 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

minikube start 

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

kubectl get pods -n falco
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:

kubectl port-forward service/falco-falcosidekick-ui -n falco 2802:2802 & > /dev/null 2>&1
Accédez à : http://localhost:2802

Nom d'utilisateur : admin Mot de passe : admin

Déploiement des workloads

  1. Déployer le conteneur cible

    kubectl apply -f target-pod.yaml
    

  2. Déployer le conteneur attaquant

    kubectl apply -f attacker-pod-manual.yaml
    

  3. Vérifier l’état du cluster

    kubectl get pods -A
    

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:

kubectl exec -it malicious-attacker-manual -- sh

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 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

curl 10.244.0.9:8000 # modifier l'adresse IP en cas de besoin
<!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.

curl 10.244.0.9:8000/etc/passwd # modifier l'adresse IP en cas de besoin
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:

Falco dashboard

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

kubectl apply -f attacker-pod-complex.yaml

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

kubectl delete -f attacker-pod-complex.yaml && kubectl apply -f attacker-pod-complex.yaml

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.