Aller au contenu

Détection d'actions frauduleuses avec Falco

Falco est un outil de sécurité cloud-native qui offre une protection en temps réel pour les hôtes, les conteneurs, les environnements Kubernetes et les services cloud. Il surveille les événements du noyau Linux et d'autres sources de données via des plugins, enrichissant ces événements avec des métadonnées contextuelles pour fournir des alertes en temps réel. Cela permet de détecter les comportements anormaux, les menaces potentielles et les violations de conformité.

Fonctionnalités principales de Falco

  • Détection des menaces en temps réel : Falco utilise eBPF pour surveiller l'activité du système et détecter les comportements malveillants sur les hôtes et les conteneurs, quelle que soit leur échelle.

  • Conformité réglementaire : Grâce à sa surveillance intelligente et à sa détection basée sur des règles, Falco aide à maintenir la conformité dans les systèmes cloud-native.

  • Intégration étendue : Les alertes de Falco peuvent être facilement transmises à plus de 50 systèmes tiers, facilitant l'analyse, le stockage ou les réactions appropriées.

  • Open Source : Développé au sein de la communauté cloud-native, Falco est une solution multi-fournisseurs largement adoptée, fonctionnant sur des architectures x64 et ARM, et déployable dans Kubernetes via un chart Helm officiel.

Drivers

Pour fonctionner on va devoir fournir à Falco un driver spécifique. Quand je parle de driver il faut voir derrière cela comment Falco va pouvoir collecter les informations et l'ensemble des appels système qui seront effectués. À toi de choisir ce qui correspond le mieux selon l'environnement et les restrictions que tu auras afin d'avoir l'approche la plus adaptée.

Voici un tableau récapitulatif des avantages et inconvénients des différentes méthodes de collecte des appels système pour Falco :

Méthode Avantages Inconvénients
Sonde eBPF moderne (modern_ebpf, CO-RE) - Driver par défaut des versions récentes de Falco, embarqué dans le binaire : aucune compilation ni téléchargement de driver.
- Pas de module noyau à charger, utilisable dans les environnements qui l'interdisent (GKE par exemple).
- Peut tourner en mode moindre privilège (capabilities BPF, PERFMON, SYS_RESOURCE, SYS_PTRACE) au lieu d'un conteneur privileged.
- Nécessite un noyau récent (en pratique >= 5.8) exposant BTF.
- Les fonctionnalités eBPF doivent être activées dans le noyau, ce qui n'est pas le cas sur tous les systèmes.
Module du noyau (kmod) - Solution la plus légère, avec une surcharge minimale sur le système.
- Fonctionne sur des noyaux anciens qui ne supportent pas la sonde eBPF moderne.
- Peut être construit, hébergé et installé directement sur le système hôte.
- Étroitement lié au noyau hôte, ce qui peut introduire de la complexité lors de changements de version du noyau, d'architecture ou de système d'exploitation.
- Un module défectueux peut provoquer un plantage du noyau Linux.
- Le chargement de modules noyau peut être restreint ou interdit dans certains environnements.

Drivers retirés

La sonde eBPF « legacy » (ebpf), dépréciée depuis Falco 0.43, a été retirée : le chart Helm 9.x ne propose plus que modern_ebpf et kmod (et auto pour laisser Falco choisir). L'instrumentation en espace utilisateur via ptrace(2) n'est plus maintenue non plus.

Dans l'ordre à tester je te conseille :

  1. eBPF moderne (modern_ebpf)
  2. Module du noyau (kmod), si ton noyau est trop ancien pour la sonde moderne

Mise en place

Installation du chart

On va passer par le Helm chart officiel. Je vais l'installer avec mon provider terraform argoproj-labs qui me permet d'utiliser ArgoCD.

Mais libre à toi, pour un use case plus simple, de le déployer via la CLI Helm : helm repo add falcosecurity https://falcosecurity.github.io/charts puis helm upgrade --install falco falcosecurity/falco -n falco --create-namespace.

resource "argocd_application" "falco" {
  metadata {
    name      = "falco"
    namespace = "argocd"
  }

  spec {

    destination {
      server    = "https://kubernetes.default.svc"
      namespace = kubernetes_namespace.security.metadata[0].name
    }

    sync_policy {
      automated {
        prune       = false
        self_heal   = true
        allow_empty = true
      }

      sync_options = ["Validate=true"]
      retry {
        limit = "5"
        backoff {
          duration     = "30s"
          max_duration = "2m"
          factor       = "2"
        }
      }
    }

    source {
      repo_url        = "https://falcosecurity.github.io/charts"
      chart           = "falco"
      target_revision = "9.2.0"

      helm {
        release_name = "falco"
      }
    }
  }
}

Mise en place des métriques

On va compléter le bloc helm {} de notre application avec ces values-ci. Les métriques seront accessibles via le webserver de Falco sur le port 8765 (http://localhost:8765/metrics après un kubectl port-forward).

values = yamlencode({
    metrics = {
        enabled = true
    }
    driver = {
        kind = "modern_ebpf"
        modernEbpf = {
            leastPrivileged = true
        }
    }
    falco = {
        webserver = {
            prometheus_metrics_enabled = true
        }
    }
})

À toi de gérer selon ta stack de monitoring pour récupérer les logs et/ou métriques afin de te créer ton propre système d'alertes qui t'avertissent lors de potentielles attaques.

Exemple pour trigger Falco

Mise en place

J'ai créé un simple pod que voici :

apiVersion: v1
kind: Pod
metadata:
  name: alpine-pod
spec:
  containers:
    - name: alpine-container
      image: alpine:latest
      command: ["/bin/sh", "-c", "sleep 3600"]
      securityContext:
        runAsUser: 0
        allowPrivilegeEscalation: true
  restartPolicy: Never

Ici le but est d'avoir un pod qui se lance sous l'user root avec la possibilité d'acquérir des privilèges supplémentaires (su, sudo...), tels que l'ajout de capacités ou l'exécution de commandes nécessitant des privilèges élevés.

Exemple 1 : Alerte d'utilisation d'un terminal

On va avoir une première alerte remontée de la part de Falco, qui va me prévenir qu'un terminal a été ouvert sur un pod.

2025-01-06T14:52:30.037679658+01:00 13:29:16.039605364: Notice
  A shell was spawned in a container with an attached terminal
  evt_type=execve
  user=root
  user_uid=0
  user_loginuid=-1
  process=sh
  proc_exepath=/bin/busybox
  parent=containerd-shim
  command=sh -c command -v bash >/dev/null && exec bash || exec sh
  terminal=34816
  exe_flags=EXE_WRITABLE|EXE_LOWER_LAYER
  container_id=d857035a621a
  container_image=<NA>
  container_image_tag=<NA>
  container_name=<NA>
  k8s_ns=<NA>
  k8s_pod_name=<NA>

Exemple 2 : Alerte d'exécution d'un binaire

Dans le terminal je vais exécuter la commande sudo touch momo.sh. Ici je veux imiter le fait de réaliser une commande sous les pleins pouvoirs avec le sudo

2025-01-06T14:02:03.338144717: Critical
  Executing binary not part of base image
  proc_exe=sudo
  proc_sname=sh
  gparent=sh
  proc_exe_ino_ctime=1736173475640000634
  proc_exe_ino_mtime=1733128624000000000
  proc_exe_ino_ctime_duration_proc_start=18446742721407406491
  proc_cwd=/
  container_start_ts=1736171734240852034
  evt_type=execve
  user=root
  user_uid=0
  user_loginuid=-1
  process=sudo
  proc_exepath=/usr/bin/sudo
  parent=sh
  command=sudo touch momo.sh
  terminal=34816
  exe_flags=EXE_WRITABLE|EXE_UPPER_LAYER
  container_id=d60da3400589
  container_image=<NA>
  container_image_tag=<NA>
  container_name=<NA>
  k8s_ns=<NA>
  k8s_pod_name=<NA>

Pour situer Falco face à Tetragon, KubeArmor ou KubeHound, vois le comparatif des solutions pour sécuriser ton cluster.