Controllare una VM per rilevare segni di manomissione della memoria del kernel

Questa pagina descrive le attività che puoi eseguire per confermare la validità di un risultato di rootkit in modalità kernel finding di Virtual Machine Threat Detection. I risultati di rootkit in modalità kernel indicano che la memoria del kernel di una VM è stata potenzialmente manomessa da malware.

Quando ricevi un risultato di rootkit in modalità kernel da VM Threat Detection, ti consigliamo di eseguire questi comandi Linux sull'istanza Compute Engine interessata per verificare la presenza di punti dati che potrebbero indicare anomalie, come chiamate di sistema dirottate o moduli kernel nascosti.

In alternativa, puoi eseguire lo script di raccolta dei dati fornito sulla VM interessata. Lo script esegue i comandi descritti in questa pagina.

Salvo diversa indicazione, ogni attività di ispezione in questa pagina è pertinente a tutti i risultati di rootkit in modalità kernel.

Questo documento presuppone quanto segue:

  • Stai eseguendo le attività descritte in questo documento dopo aver ricevuto un risultato di rootkit in modalità kernel da VM Threat Detection. Per un elenco delle categorie di risultati pertinenti, consulta Risultati di minacce di rootkit in modalità kernel.

  • Hai una conoscenza degli strumenti a riga di comando Linux e del kernel Linux.

Informazioni su VM Threat Detection

Virtual Machine Threat Detection è un servizio integrato di Security Command Center. Questo servizio esegue la scansione delle macchine virtuali per rilevare applicazioni potenzialmente dannose, come software di mining di criptovalute, rootkit in modalità kernel e malware in esecuzione in ambienti cloud compromessi.

VM Threat Detection fa parte della suite di rilevamento delle minacce di Security Command Center ed è progettato per integrare le funzionalità esistenti di Event Threat Detection e Container Threat Detection.

Per informazioni su VM Threat Detection, consulta la panoramica di Virtual Machine Threat Detection. Per scoprire come visualizzare i dettagli di un risultato di VM Threat Detection, consulta Esaminare i risultati in the Google Cloud console.

Prima di iniziare

Per ottenere le autorizzazioni necessarie per visualizzare tutte le risorse e i risultati in Security Command Center e gestire l'istanza Compute Engine interessata, chiedi all'amministratore di concederti i seguenti ruoli IAM:

Per saperne di più sulla concessione dei ruoli, consulta Gestisci l'accesso a progetti, cartelle e organizzazioni.

Potresti anche riuscire a ottenere le autorizzazioni richieste tramite i ruoli personalizzati o altri ruoli predefiniti.

Identificare la VM interessata

  1. Visualizza i dettagli del risultato.
  2. Nella sezione Risorsa interessata, nel campo Nome completo della risorsa , fai clic sul link. La visualizzazione dei dettagli dell'istanza Compute Engine interessata si apre in una nuova scheda.
  3. Connettersi all'istanza. Per saperne di più, consulta Connessione alle VM Linux nella documentazione di Compute Engine .

Trovare moduli kernel imprevisti

La presenza di moduli imprevisti in una VM può indicare che la memoria del kernel della VM è potenzialmente compromessa.

Per trovare moduli kernel imprevisti:

  1. Elenca tutti i moduli kernel caricati nella VM:

    lsmod
    cat /proc/modules
    
  2. Elenca le voci sysfs per i moduli caricati e scaricati:

    ls -l /sys/module/
    
  3. Confronta i risultati di questi elenchi con quelli di altre VM nel progetto. Cerca i moduli che appaiono nella VM interessata, ma non nelle altre VM.

Cercare moduli out-of-tree in syslog

I segni che indicano che un modulo out-of-tree è stato caricato in una VM possono indicare che sono stati caricati moduli kernel atipici. Puoi cercare nel buffer dei log del kernel e nei messaggi syslog per determinare se è stato caricato un modulo out-of-tree. Nelle voci di log, un modulo out-of-tree è contrassegnato come tainted load.

Nel buffer dei log del kernel e nei messaggi syslog, cerca le voci di log simili alle seguenti:

MODULE_NAME: loading out-of-tree module taints kernel.
  • Cerca nel buffer dei log del kernel le voci di log che indicano la presenza di moduli out-of-tree:

    sudo dmesg | grep out-of-tree
    
  • Cerca in tutti i messaggi syslog le voci di log che indicano la presenza di moduli out-of-tree:

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

Verificare la presenza di livepatching

Il livepatching in una VM può interferire con i rilevamenti di VM Threat Detection e attivare risultati di falsi positivi.

Per verificare la presenza di livepatching:

  1. Controlla syslog per l'installazione e la registrazione dei moduli di livepatching. Il livepatching in genere modifica il codice del kernel installando i punti ftrace del kernel.

    sudo grep livepatch /var/log/syslog*
    
  2. Cerca i nuovi moduli kernel installati per il livepatching (in genere con il prefisso livepatch):

    sudo lsmod | grep livepatch
    
  3. Cerca i file patch:

    sudo ls -l /sys/kernel/livepatch
    

Per informazioni sul livepatching, consulta Livepatch nella documentazione del kernel Linux.

Verificare la presenza di altre attività potenzialmente dannose rilevate nella VM

  1. In Security Command Center, visualizza i dettagli del risultato di VM Threat Detection che stai esaminando.
  2. Nella sezione Risorsa interessata, nel campo Nome completo della risorsa , fai clic sulla freccia menu a discesa e poi su Mostra tutti i risultati con questo nome completo della risorsa. La query sui risultati viene aggiornata per mostrare solo i risultati per questa VM.
  3. Verifica la presenza di risultati che indicano potenziali attività di cryptomining, malware, concessioni IAM insolite e altre minacce alla sicurezza.

Verificare se il software antivirus sta causando un risultato di falso positivo

Il software antivirus può interferire con i rilevamenti di VM Threat Detection e attivare risultati di falsi positivi.

Controllare tutti i processi in esecuzione sul sistema

La presenza di processi imprevisti può indicare che il risultato di VM Threat Detection è valido e che la VM è stata compromessa.

  1. Elenca tutti i processi in esecuzione sulla VM:

    ps -eAf
    
  2. Cerca i processi di debug, come gdb, strace e pstack, che in genere non esegui su questa VM. I processi di debug possono spiare altri processi.

  3. Cerca altri processi sospetti sulla VM.

Controllare il kernel di avvio

Controlla il kernel di avvio per identificare il kernel Linux:

cat /proc/version

Se il valore restituito non è la versione kernel prevista, potrebbe indicare un attacco dirottamento eseguito sfruttando lo strumento kexec nel kernel. Lo strumento kexec può eseguire un softboot del sistema per utilizzare un kernel diverso.

Attività aggiuntiva per Unexpected system call handler

Esegui questa attività se ricevi un risultato Defense Evasion: Unexpected system call handler.

Controlla le chiamate di sistema e cerca anomalie nel loro utilizzo e nei chiamanti. I log di controllo forniscono informazioni sul processo di chiamata e sugli argomenti per le chiamate di sistema. Puoi anche eseguire attività di verifica per controllare i comportamenti previsti delle chiamate di sistema comuni. Per saperne di più, consulta Esempio di ispezione con il rootkit Diamorphine in questa pagina.

Attività aggiuntiva per Unexpected interrupt handler

Esegui questa attività se ricevi un risultato Defense Evasion: Unexpected interrupt handler.

Elenca i gestori di interruzioni live sul sistema e confronta i risultati con le informazioni di altre VM simili nel progetto. I gestori di interruzioni imprevisti possono indicare che la VM è compromessa.

Per elencare i gestori di interruzioni live, esegui il comando seguente:

cat /proc/interrupts

L'output è simile al seguente:

           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

Attività aggiuntiva per Unexpected processes in runqueue

Esegui questi passaggi se ricevi un risultato Defense Evasion: Unexpected processes in runqueue. Questa sezione ti aiuta a raccogliere punti dati aggiuntivi per esaminare i risultati. Questi punti dati potrebbero non indicare direttamente un problema di malware.

In questa attività esaminerai la coda dello scheduler per CPU. Sebbene alcuni processi possano essere di breve durata, puoi comunque valutare il comportamento della coda dello scheduler con i processi in esecuzione per CPU per cercare comportamenti anomali.

  1. Visualizza i dettagli sulla quantità di tempo che ogni processo in esecuzione trascorre per CPU. In questo modo puoi verificare se una determinata CPU è estremamente occupata. Puoi correlare i risultati alle interruzioni associate alla CPU da /proc/interrupts.

    cat /proc/schedstat
    

    Per saperne di più su questo comando, consulta Statistiche dello scheduler nella documentazione del kernel Linux.

  2. Elenca tutte le attività eseguibili correnti e i dettagli sui cambi di contesto per ogni CPU.

    cat /proc/sched_debug
    

    L'output è simile al seguente:

    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. Cerca quanto segue:

    • Nomi dei processi in esecuzione.
    • Numero di cambi di contesto per CPU. Verifica se un processo sta subendo troppi o troppo pochi cambi sulla CPU.
    • Tempo di CPU trascorso (tempo non inattivo).

Esempio di ispezione con il rootkit Diamorphine

Questa sezione mostra un'ispezione di una VM in cui è installato il rootkit Diamorphine. Diamorphine è un modulo kernel caricabile (LKM) diffuso. Questo rootkit attiva le seguenti categorie di risultati:

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

Per saperne di più su queste categorie di risultati, consulta Risultati di minacce di rootkit in modalità kernel.

I passaggi di ispezione eseguiti e i sintomi osservati sulla VM sono i seguenti:

  1. Cerca in syslog tutti i moduli kernel out-of-tree caricati.

    1. Cerca nel buffer dei log del kernel:

      sudo dmesg | grep out-of-tree
      

      Output:

      diamorphine: loading out-of-tree module taints kernel.
      
    2. Cerca nei messaggi syslog:

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

      Output:

      /var/log/syslog: diamorphine: loading out-of-tree module taints kernel.
      
  2. Cerca in syslog eventuali errori di verifica dei moduli (non disponibile su tutte le distribuzioni Linux).

    1. Cerca nel buffer dei log del kernel:

      sudo dmesg | grep "module verification failed"
      

      Output:

      diamorphine: module verification failed: signature and/or required key missing - tainting kernel
      
    2. Cerca nei messaggi syslog:

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

      Output:

      /var/log/syslog: diamorphine: module verification failed: signature and/or required key missing - tainting kernel
      
  3. Verifica che il modulo sia nascosto dai comandi /proc/modules e lsmod.

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

    Non sono stati visualizzati risultati.

  4. Verifica che il modulo abbia una voce in sysfs.

    sudo cat /sys/module/diamorphine/coresize
    

    Output:

    16384
    
  5. Ottieni la tabella delle chiamate di sistema per l'architettura:

    sudo ausyscall --dump
    

    Output:

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

    Controlla la presenza di anomalie nelle chiamate di sistema, come kill e getdents, che in genere vengono manomesse dai rootkit.

  6. Per verificare la manomissione del gestore delle chiamate di sistema, controlla le chiamate di sistema e verifica la presenza di comportamenti anomali. Questi comportamenti variano per ogni chiamata di sistema.

    Una chiamata di sistema che in genere viene compromessa è la chiamata kill. Puoi verificare se la chiamata di sistema kill è stata bypassata. Nell'esempio seguente, la chiamata di sistema kill è stata controllata.

    1. Installa auditd e osserva il comportamento della VM senza il 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"
      

      A questo punto dell'ispezione, è stato installato il rootkit Diamorphine. I passaggi successivi mostrano il comportamento della VM dopo l'installazione del rootkit.

    2. Verifica che una voce di log di controllo per il segnale sia ora assente dopo l'installazione del rootkit Diamorphine:

      $ sudo ausearch -k audit_kill | grep -A 3 "pid=1158"
      $ sleep 600 &
      [2] 1167
      
    3. Controlla i dettagli nella voce di log di controllo per il segnale. In questo esempio, sebbene questo particolare segnale non sia stato completamente dirottato dal rootkit, sono disponibili informazioni sul processo chiamante.

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

Eseguire il debug dello script di raccolta dei dati

Lo script seguente esegue molte delle attività di debug descritte in questa pagina. Puoi eseguire questo script in modalità sudo o root. Lo script legge solo le informazioni di debug dal sistema.

$ 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 "=================================================="

Passaggi successivi