Inspecter une VM pour détecter les signes de falsification de la mémoire du noyau

Cette page décrit les tâches que vous pouvez effectuer pour confirmer la validité d'un résultat de rootkit en mode noyau de Virtual Machine Threat Detection. Les résultats de rootkit en mode noyau indiquent que la mémoire du noyau d'une VM a potentiellement été falsifiée par un logiciel malveillant.

Lorsque vous recevez un résultat de détection de rootkit en mode noyau de VM Threat Detection, nous vous recommandons d'exécuter ces commandes Linux sur l'instance Compute Engine concernée pour analyser votre système et rechercher des points de données pouvant indiquer des anomalies, comme des appels système piratés ou des modules de noyau masqués.

Vous pouvez également exécuter le script de collecte de données fourni sur la VM concernée. Le script exécute les commandes décrites sur cette page.

Sauf indication contraire, chaque tâche d'inspection de cette page concerne toutes les conclusions relatives aux rootkits en mode noyau.

Ce document suppose que vous avez déjà :

  • Vous effectuez les tâches décrites dans ce document après avoir reçu un résultat de détection de rootkit en mode noyau de VM Threat Detection. Pour obtenir la liste des catégories de résultats pertinentes, consultez Résultats de menace de rootkit en mode noyau.

  • Vous comprenez les outils de ligne de commande Linux et le noyau Linux.

À propos de VM Threat Detection

Virtual Machine Threat Detection est un service intégré de Security Command Center disponible dans les niveaux Enterprise et Premium. Ce service analyse les machines virtuelles pour détecter les applications potentiellement malveillantes, telles que les logiciels de minage de cryptomonnaie, les rootkits en mode noyau et les logiciels malveillants exécutés dans des environnements cloud compromis.

VM Threat Detection fait partie de la suite de détection des menaces de Security Command Center. Il est conçu pour compléter les fonctionnalités existantes d'Event Threat Detection et de Container Threat Detection.

Pour en savoir plus sur VM Threat Detection, consultez la présentation de Virtual Machine Threat Detection. Pour savoir comment afficher les détails d'un résultat VM Threat Detection, consultez Examiner les résultats dans la consoleGoogle Cloud .

Avant de commencer

Pour obtenir les autorisations nécessaires pour afficher toutes les ressources et tous les résultats dans Security Command Center et gérer l'instance Compute Engine concernée, demandez à votre administrateur de vous accorder les rôles IAM suivants :

Pour en savoir plus sur l'attribution de rôles, consultez Gérer l'accès aux projets, aux dossiers et aux organisations.

Vous pouvez également obtenir les autorisations requises avec des rôles personnalisés ou d'autres rôles prédéfinis.

Identifier la VM concernée

  1. Affichez les détails du résultat.
  2. Dans la section Ressource concernée, cliquez sur le lien dans le champ Nom complet de la ressource. La vue détaillée de l'instance Compute Engine concernée s'ouvre dans un nouvel onglet.
  3. Se connecter à l'instance Pour en savoir plus, consultez la section Se connecter à des VM Linux dans la documentation Compute Engine.

Rechercher les modules de noyau inattendus

La présence de modules inattendus dans une VM peut indiquer que la mémoire du noyau de la VM est potentiellement compromise.

Pour identifier les modules de noyau inattendus, procédez comme suit :

  1. Répertoriez tous les modules du noyau chargés dans la VM :

    lsmod
    cat /proc/modules
    
  2. Répertoriez les entrées sysfs pour les modules chargés et déchargés :

    ls -l /sys/module/
    
  3. Comparez les résultats de ces listes avec ceux des listes d'autres VM du projet. Recherchez les modules qui apparaissent dans la VM concernée, mais pas dans les autres VM.

Rechercher syslog des modules hors arbre

Les signes indiquant qu'un module hors arbre a été chargé dans une VM peuvent indiquer que des modules de noyau atypiques ont été chargés. Vous pouvez rechercher dans le tampon de journal du noyau et les messages syslog pour déterminer si un module hors arbre a été chargé. Dans les entrées de journal, un module hors arbre est marqué comme charge contaminée.

Dans le tampon du journal du noyau et les messages syslog, recherchez les entrées de journal qui ressemblent à ce qui suit :

MODULE_NAME: loading out-of-tree module taints kernel.
  • Recherchez dans le tampon de journal du noyau les entrées de journal indiquant la présence de modules hors arbre :

    sudo dmesg | grep out-of-tree
    
  • Recherchez dans tous les messages syslog les entrées de journal indiquant la présence de modules hors arbre :

    grep "out-of-tree" /var/log/syslog*
    

Vérifier le livepatching

Le live patching dans une VM peut interférer avec les détections de VM Threat Detection et déclencher des faux positifs.

Pour vérifier si le correctif en direct est disponible, procédez comme suit :

  1. Consultez syslog pour l'installation et la journalisation du module Livepatch. Le correctif en direct modifie généralement le code du noyau en installant des points ftrace du noyau.

    sudo grep livepatch /var/log/syslog*
    
  2. Recherchez les nouveaux modules de noyau installés pour le correctif dynamique (ils sont généralement précédés du préfixe livepatch) :

    sudo lsmod | grep livepatch
    
  3. Recherchez des fichiers de correctif :

    sudo ls -l /sys/kernel/livepatch
    

Pour en savoir plus sur le correctif à chaud, consultez Livepatch dans la documentation du noyau Linux.

Recherchez d'autres activités potentiellement malveillantes détectées dans la VM.

  1. Dans Security Command Center, affichez les détails du résultat VM Threat Detection que vous examinez.
  2. Dans la section Ressource concernée, dans le champ Nom complet de la ressource, cliquez sur la flèche du menu déroulant, puis sur Afficher tous les résultats avec ce nom complet de la ressource. La requête de résultats est mise à jour pour n'afficher que les résultats pour cette VM.
  3. Recherchez les résultats qui indiquent des activités potentielles de minage de cryptomonnaie, des logiciels malveillants, des octrois IAM inhabituels et d'autres menaces de sécurité.

Vérifier si un logiciel antivirus est à l'origine d'un faux positif

Les logiciels antivirus peuvent interférer avec les détections VM Threat Detection et déclencher des faux positifs.

Vérifier tous les processus en cours d'exécution sur le système

La présence de processus inattendus peut indiquer que le résultat VM Threat Detection est valide et que la VM a été compromise.

  1. Répertoriez tous les processus en cours d'exécution sur la VM :

    ps -eAf
    
  2. Recherchez les processus de débogueur (comme gdb, strace et pstack) que vous n'exécutez pas habituellement sur cette VM. Les processus du Debugger peuvent espionner d'autres processus.

  3. Recherchez d'autres processus suspects sur la VM.

Vérifier le noyau démarré

Vérifiez le noyau démarré pour identifier votre noyau Linux :

cat /proc/version

Si la valeur renvoyée ne correspond pas à la version du noyau attendue, cela peut indiquer une attaque par piratage qui exploite l'outil kexec dans le noyau. L'outil kexec peut redémarrer le système en mode softboot pour utiliser un autre noyau.

Tâche supplémentaire pour Unexpected system call handler

Effectuez cette tâche si vous obtenez un résultat Defense Evasion: Unexpected system call handler.

Auditez les appels système et recherchez les anomalies dans leur utilisation et leurs appelants. Les journaux d'audit fournissent des informations sur le processus d'appel et les arguments des appels système. Vous pouvez également effectuer des tâches de validation pour vérifier les comportements attendus des appels système courants. Pour en savoir plus, consultez la section Exemple d'inspection avec le rootkit Diamorphine sur cette page.

Tâche supplémentaire pour Unexpected interrupt handler

Effectuez cette tâche si vous obtenez un résultat Defense Evasion: Unexpected interrupt handler.

Listez les gestionnaires d'interruptions en direct sur le système et comparez les résultats avec les informations d'autres VM similaires du projet. Les gestionnaires d'interruptions inattendus peuvent indiquer que la VM est compromise.

Pour lister les gestionnaires d'interruption actifs, exécutez la commande suivante :

cat /proc/interrupts

Le résultat se présente comme suit :

           CPU0       CPU1
  0:         44          0   IO-APIC   0-edge      timer
  1:          9          0   IO-APIC   1-edge      i8042
  4:      17493          0   IO-APIC   4-edge      ttyS0
  8:          0          0   IO-APIC   8-edge      rtc0
  9:          0          0   IO-APIC   9-fasteoi   acpi
 12:          0        152   IO-APIC  12-edge      i8042
 24:         16          0   PCI-MSI 81920-edge      virtio2-config
 25:          0      40194   PCI-MSI 81921-edge      virtio2-inflate
 26:      58528          0   PCI-MSI 81922-edge      virtio2-deflate
 27:          0     966356   PCI-MSI 81923-edge      virtio2-stats
 28:          0          0   PCI-MSI 49152-edge      virtio0-config
 29:          0          0   PCI-MSI 49153-edge      virtio0-control
 30:          0          0   PCI-MSI 49154-edge      virtio0-event
 31:          0     555807   PCI-MSI 49155-edge      virtio0-request
 32:          0          0   PCI-MSI 98304-edge      virtio3-config
 33:        184          0   PCI-MSI 98305-edge      virtio3-input
 34:          0          0   PCI-MSI 65536-edge      virtio1-config
 35:     556203          0   PCI-MSI 65537-edge      virtio1-input.0
 36:     552746          1   PCI-MSI 65538-edge      virtio1-output.0
 37:          1     426036   PCI-MSI 65539-edge      virtio1-input.1
 38:          0     408475   PCI-MSI 65540-edge      virtio1-output.1

Tâche supplémentaire pour Unexpected processes in runqueue

Suivez ces étapes si vous obtenez un résultat Defense Evasion: Unexpected processes in runqueue. Cette section vous aide à collecter des points de données supplémentaires pour examiner vos résultats. Ces points de données n'indiquent pas forcément un problème de logiciel malveillant.

Dans cette tâche, vous allez examiner la file d'attente du planificateur par processeur. Bien que certains processus puissent être de courte durée, vous pouvez toujours évaluer le comportement de la file d'attente du planificateur avec les processus en cours d'exécution par processeur pour rechercher un comportement anormal.

  1. Affichez des informations sur le temps passé par chaque processus en cours d'exécution par processeur. Cela vous permet de voir si un processeur particulier est extrêmement occupé. Vous pouvez corréler les résultats aux interruptions épinglées au processeur à partir de /proc/interrupts.

    cat /proc/schedstat
    

    Pour en savoir plus sur cette commande, consultez Statistiques du planificateur dans la documentation du noyau Linux.

  2. Liste toutes les tâches exécutables en cours et les détails sur les changements de contexte pour chaque CPU.

    cat /proc/sched_debug
    

    Le résultat se présente comme suit :

    Sched Debug Version: v0.11, 5.4.0-1081-gke #87-Ubuntu
    ktime                                   : 976187427.733850
    sched_clk                               : 976101974.761097
    cpu_clk                                 : 976101973.335113
    jiffies                                 : 4538939132
    sched_clock_stable()                    : 1
    
    sysctl_sched
      .sysctl_sched_latency                    : 12.000000
      .sysctl_sched_min_granularity            : 1.500000
      .sysctl_sched_wakeup_granularity         : 2.000000
      .sysctl_sched_child_runs_first           : 0
      .sysctl_sched_features                   : 2059067
      .sysctl_sched_tunable_scaling            : 1 (logarithmic)
    
    cpu#0, 2199.998 MHz
      .nr_running                    : 0
      .nr_switches                   : 16250401
      .nr_load_updates               : 0
      .nr_uninterruptible            : 12692
      .next_balance                  : 4538.939133
      .curr->pid                     : 0
      .clock                         : 976101971.732857
      .clock_task                    : 976101971.732857
      .avg_idle                      : 880408
      .max_idle_balance_cost         : 500000
    
    runnable tasks:
     S           task   PID         tree-key  switches  prio     wait-time             sum-exec        sum-sleep
    -----------------------------------------------------------------------------------------------------------
     S        systemd     1     51740.602172    326778   120         0.000000    165741.786097         0.000000 0 0 /init.scope
     S       kthreadd     2   1482297.917240      1361   120         0.000000       112.028205         0.000000 0 0 /
     I      rcu_sched    11   1482642.606136   1090339   120         0.000000     17958.156471         0.000000 0 0 /
     S        cpuhp/1    15       537.058588         8   120         0.000000         2.275927         0.000000 0 0 /
     S  idle_inject/1    16        -2.994953         3    49         0.000000         0.012780         0.000000 0 0 /
     S    migration/1    17         0.000000    245774     0         0.000000      5566.508869         0.000000 0 0 /
     S    ksoftirqd/1    18   1482595.656315     47766   120         0.000000      1235.099147         0.000000 0 0 /
     I   kworker/1:0H    20       536.961474         5   100         0.000000         0.043908         0.000000 0 0 /
     S      kdevtmpfs    21     11301.343465       177   120         0.000000         3.195291         0.000000 0 0 /
     I          netns    22         6.983329         2   100         0.000000         0.021870         0.000000 0 0 /
     Srcu_tasks_kthre    23        10.993528         2   120         0.000000         0.010200         0.000000 0 0 /
     S        kauditd    24   1482525.828948       319   120         0.000000        14.489652         0.000000 0 0 /
    
  3. Recherchez les éléments suivants :

    • Noms des processus en cours d'exécution.
    • Nombre de changements de contexte par processeur. Vérifiez si un processus entraîne trop ou trop peu de changements de contexte sur le processeur.
    • Temps CPU utilisé (temps d'activité).

Exemple d'inspection avec le rootkit Diamorphine

Cette section montre comment inspecter une VM sur laquelle le rootkit Diamorphine est installé. Diamorphine est un module de noyau chargeable (LKM) populaire. Ce rootkit déclenche les catégories de résultats suivantes :

  • Defense Evasion: Unexpected system call handler
  • Defense Evasion: Unexpected kernel modules
  • Defense Evasion: Unexpected kernel read-only data modification

Pour en savoir plus sur ces catégories de résultats, consultez Résultats concernant les menaces de rootkit en mode noyau.

Voici les étapes d'inspection effectuées et les symptômes observés sur la VM :

  1. Recherchez syslog pour trouver tous les modules du noyau hors arbre qui sont chargés.

    1. Recherchez dans le tampon du journal du noyau :

      sudo dmesg | grep out-of-tree
      

      Sortie :

      diamorphine: loading out-of-tree module taints kernel.
      
    2. Recherchez les messages syslog :

      grep "out-of-tree" /var/log/syslog*
      

      Sortie :

      /var/log/syslog: diamorphine: loading out-of-tree module taints kernel.
      
  2. Recherchez syslog pour détecter les échecs de validation des modules (non disponible sur toutes les distributions Linux).

    1. Recherchez dans le tampon du journal du noyau :

      sudo dmesg | grep "module verification failed"
      

      Sortie :

      diamorphine: module verification failed: signature and/or required key missing - tainting kernel
      
    2. Recherchez les messages syslog :

      sudo grep "module verification failed" /var/log/syslog*
      

      Sortie :

      /var/log/syslog: diamorphine: module verification failed: signature and/or required key missing - tainting kernel
      
  3. Vérifiez que le module est masqué dans les commandes /proc/modules et lsmod.

    sudo grep diamorphine /proc/modules
    sudo lsmod | grep diamorphine
    

    Aucun résultat ne s'est affiché.

  4. Vérifiez que le module comporte une entrée dans sysfs.

    sudo cat /sys/module/diamorphine/coresize
    

    Sortie :

    16384
    
  5. Obtenez le tableau des appels système pour l'architecture :

    sudo ausyscall --dump
    

    Sortie :

    Using x86_64 syscall table:
    0       read
    1       write
    2       open
    3       close
    

    Auditez les appels système (comme kill et getdents) qui sont généralement falsifiés par les rootkits pour détecter les anomalies.

  6. Pour vérifier si le gestionnaire d'appels système a été falsifié, auditez les appels système et recherchez les comportements anormaux. Ces comportements varient pour chaque appel système.

    L'appel système généralement piraté est l'appel kill. Vous pouvez vérifier si l'appel système kill a été contourné. Dans l'exemple suivant, l'appel système kill a été audité.

    1. Installez auditd et observez le comportement de la VM sans le rootkit Diamorphine :

      $ sudo apt-get update && sudo apt-get install auditd
      $ # Add audit rules for specific system calls
      $ sudo echo "-a exit,always -F arch=b64 -S kill -k audit_kill" >> /etc/audit/rules.d/audit.rules
      $  sudo /etc/init.d/auditd restart
      Restarting auditd (via systemctl): auditd.service.
      
      $ # Behavior observed without rootkit
      $ sleep 600 &
      [1] 1119
      $ sudo kill -9 1119
      $ sudo ausearch -k audit_kill | grep -A 3 "pid=1119"
      type=OBJ_PID msg=audit(1677517839.523:198): opid=1119 oauid=1001 ouid=0 oses=1 obj=unconfined ocomm="sleep"
      type=SYSCALL msg=audit(1677517839.523:198): arch=c000003e syscall=62 success=yes exit=0 a0=45f a1=9 a2=0 a3=7f61c64b2ac0 items=0 ppid=1034 pid=1035 auid=1001 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0
      tty=pts0 ses=1 comm="bash" exe="/usr/bin/bash" subj=unconfined key="audit_kill"
      $ sleep 600 &
      [1] 1087
      $ sudo kill -31 1087
      $ sudo ausearch -k audit_kill | grep -A 3 "pid=1087"
      type=OBJ_PID msg=audit(1677517760.844:168): opid=1087 oauid=1001 ouid=0 oses=1 obj=unconfined ocomm="sleep"
      type=SYSCALL msg=audit(1677517760.844:168): arch=c000003e syscall=62 success=yes exit=0 a0=43f a1=1f a2=0 a3=7f61c64b2ac0 items=0 ppid=1034 pid=1035 auid=1001 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0        ses=1 comm="bash" exe="/usr/bin/bash" subj=unconfined key="audit_kill"
      

      À ce stade de l'inspection, le rootkit Diamorphine a été installé. Les étapes suivantes montrent le comportement de la VM après l'installation du rootkit.

    2. Vérifiez qu'une entrée de journal d'audit pour le signal est désormais absente après l'installation du rootkit Diamorphine :

      $ sudo ausearch -k audit_kill | grep -A 3 "pid=1158"
      $ sleep 600 &
      [2] 1167
      
    3. Consultez les détails de l'entrée de journal'audit pour le signal. Dans cet exemple, bien que ce signal particulier n'ait pas été complètement piraté par le rootkit, des informations sur le processus d'appelant sont disponibles.

      $ sudo kill -9 1167
      $ sudo ausearch -k audit_kill | grep -A 3 "pid=1167"
      type=OBJ_PID msg=audit(1677518008.586:237): opid=1167 oauid=1001 ouid=0 oses=1 obj=unconfined ocomm="sleep"
      type=SYSCALL msg=audit(1677518008.586:237): arch=c000003e syscall=62 success=yes exit=0 a0=48f a1=9 a2=0 a3=7f61c64b2ac0 items=0 ppid=1034 pid=1035 auid=1001 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0
      tty=pts0 ses=1 comm="bash" exe="/usr/bin/bash" subj=unconfined key="audit_kill"
      

Déboguer le script de collecte de données

Le script suivant effectue la plupart des tâches de débogage décrites sur cette page. Vous pouvez exécuter ce script en mode sudo ou root. Le script ne lit que les informations de débogage du système.

$ cat kprot.sh
#!/bin/bash

echo "Boot command line"
cat /proc/cmdline
echo "=================================================="
echo "Loaded modules"
cat /proc/modules
echo "=================================================="
echo "Current tracer"
cat /sys/kernel/debug/tracing/current_tracer
echo "=================================================="
echo "Tracing event enable"
cat /sys/kernel/debug/tracing/events/enable
echo "=================================================="
echo "Tracing sub events enable"
for en in `find /sys/kernel/debug/tracing/events/*/enable`; do printf "\b$en\n"; cat $en; done
echo "=================================================="
echo "IP table rules"
iptables -L
echo "=================================================="
echo "Ftrace list"
cat /sys/kernel/debug/tracing/enabled_functions
echo "=================================================="
echo "Kprobes enabled"
cat /sys/kernel/debug/kprobes/enabled
echo "=================================================="
echo "Kprobes list"
cat /sys/kernel/debug/kprobes/list
echo "=================================================="
echo "Kprobes blocklist"
cat /sys/kernel/debug/kprobes/blacklist
echo "=================================================="
echo "BPF trace"
sudo apt update && sudo apt-get update && sudo apt-get install bpftrace
bpftrace -l
echo "=================================================="
echo "BPF prog list"
sudo apt update && sudo apt install linux-tools-`uname -r`
bpftool prog
echo "=================================================="

Étapes suivantes