Inspecciona una VM para detectar signos de manipulación de la memoria del kernel

En esta página, se describen las tareas que puedes realizar para confirmar la validez de un hallazgo de rootkit en modo kernel de Virtual Machine Threat Detection. Los hallazgos de rootkits en modo kernel indican que es posible que el software malicioso haya manipulado la memoria del kernel de una VM.

Cuando recibas un hallazgo de rootkit en modo kernel de VM Threat Detection, te recomendamos que ejecutes estos comandos de Linux en la instancia de Compute Engine afectada para sondear tu sistema en busca de puntos de datos que puedan indicar anomalías, como llamadas al sistema secuestradas o módulos del kernel ocultos.

Como alternativa, puedes ejecutar la secuencia de comandos de recopilación de datos proporcionada en la VM afectada. La secuencia de comandos ejecuta los comandos que se describen en esta página.

A menos que se indique lo contrario, cada tarea de inspección de esta página es pertinente para todos los hallazgos de rootkits en modo kernel.

En este documento, se da por sentado lo siguiente:

  • Realizas las tareas de este documento después de recibir un hallazgo de rootkit en modo kernel de VM Threat Detection. Para obtener una lista de las categorías de hallazgos pertinentes, consulta Hallazgos de amenazas de rootkits en modo kernel.

  • Tienes conocimientos sobre las herramientas de línea de comandos de Linux y el kernel de Linux.

Acerca de VM Threat Detection

Virtual Machine Threat Detection es un servicio integrado de Security Command Center que está disponible en los niveles Enterprise y Premium. Este servicio analiza las máquinas virtuales para detectar aplicaciones potencialmente maliciosas, como software de minería de criptomonedas, rootkits en modo kernel y software malicioso que se ejecuta en entornos de nube vulnerados.

VM Threat Detection forma parte del paquete de detección de amenazas de Security Command Center y está diseñada para complementar las capacidades existentes de Event Threat Detection y Container Threat Detection.

Para obtener información sobre VM Threat Detection, consulta la descripción general de Virtual Machine Threat Detection. Para obtener información sobre cómo ver los detalles de un resultado de VM Threat Detection, consulta Revisa los resultados en la consola deGoogle Cloud .

Antes de comenzar

Para obtener los permisos que necesitas para ver todos los recursos y hallazgos en Security Command Center y administrar la instancia de Compute Engine afectada, pídele a tu administrador que te otorgue los siguientes roles de IAM:

Para obtener más información sobre cómo otorgar roles, consulta Administra el acceso a proyectos, carpetas y organizaciones.

También puedes obtener los permisos necesarios mediante roles personalizados o cualquier otro rol predefinido.

Identifica la VM afectada

  1. Consulta los detalles del hallazgo.
  2. En la sección Recurso afectado, en el campo Nombre completo del recurso, haz clic en el vínculo. La vista de detalles de la instancia de Compute Engine afectada se abre en una pestaña nueva.
  3. Conéctate a la instancia. Para obtener más información, consulta Conéctate a VMs de Linux en la documentación de Compute Engine.

Cómo encontrar módulos de kernel inesperados

La presencia de módulos inesperados en una VM puede indicar que la memoria del kernel de la VM está potencialmente comprometida.

Para encontrar módulos del kernel inesperados, sigue estos pasos:

  1. Enumera todos los módulos del kernel cargados en la VM:

    lsmod
    cat /proc/modules
    
  2. Enumera las entradas de sysfs para los módulos cargados y descargados:

    ls -l /sys/module/
    
  3. Compara los resultados de estas listas con las de otras VMs del proyecto. Busca módulos que aparezcan en la VM afectada, pero no en las otras VMs.

Buscar módulos fuera del árbol con syslog

Los signos de que se cargó un módulo externo en una VM pueden indicar que se cargaron módulos de kernel atípicos. Puedes buscar en el búfer de registro del kernel y en los mensajes de syslog para determinar si se cargó un módulo externo al árbol. En las entradas de registro, un módulo externo al árbol se marca como carga dañada.

En el búfer de registro del kernel y los mensajes de syslog, busca entradas de registro que se parezcan a las siguientes:

MODULE_NAME: loading out-of-tree module taints kernel.
  • Busca en el búfer de registro del kernel entradas de registro que indiquen la presencia de módulos externos al árbol:

    sudo dmesg | grep out-of-tree
    
  • Busca todos los mensajes de syslog para encontrar entradas de registro que indiquen la presencia de módulos externos al árbol:

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

Cómo verificar si se aplicó una actualización en vivo

La aplicación de parches en vivo en una VM puede interferir en las detecciones de VM Threat Detection y activar resultados de falsos positivos.

Para verificar si se aplicó la corrección en vivo, sigue estos pasos:

  1. Verifica syslog para el registro y la instalación del módulo de livepatching. Por lo general, la aplicación de parches en vivo modifica el código del kernel instalando puntos ftrace del kernel.

    sudo grep livepatch /var/log/syslog*
    
  2. Busca los módulos de kernel nuevos instalados para la aplicación de parches en vivo (generalmente, tienen el prefijo livepatch):

    sudo lsmod | grep livepatch
    
  3. Sigue estos pasos para buscar archivos de parche:

    sudo ls -l /sys/kernel/livepatch
    

Para obtener información sobre la aplicación de parches en vivo, consulta Livepatch en la documentación del kernel de Linux.

Verifica si se detectaron otras actividades potencialmente maliciosas en la VM

  1. En Security Command Center, consulta los detalles del resultado de VM Threat Detection que estás investigando.
  2. En la sección Recurso afectado, en el campo Nombre completo del recurso, haz clic en la flecha desplegable y, luego, en Mostrar todos los resultados con este nombre completo del recurso. La búsqueda de resultados se actualiza para mostrar solo los resultados de esta VM.
  3. Verifica si hay hallazgos que indiquen posibles actividades de criptominería, software malicioso, otorgamientos de IAM inusuales y otras amenazas a la seguridad.

Comprueba si el software antivirus está generando un resultado falso positivo

El software antivirus puede interferir en las detecciones de VM Threat Detection y activar resultados de falsos positivos.

Verifica todos los procesos en ejecución en el sistema

La presencia de procesos inesperados puede indicar que el hallazgo de VM Threat Detection es válido y que la VM se vulneró.

  1. Enumera todos los procesos que se ejecutan en la VM:

    ps -eAf
    
  2. Busca procesos de depurador, como gdb, strace y pstack, que no suelas ejecutar en esta VM. Los procesos del Debugger pueden espiar otros procesos.

  3. Busca otros procesos sospechosos en la VM.

Verifica el kernel iniciado

Comprueba el kernel de arranque para identificar tu kernel de Linux:

cat /proc/version

Si el valor que se devuelve no es la versión del kernel esperada, esto puede indicar un ataque de secuestro que se realiza aprovechando la herramienta kexec en el kernel. La herramienta kexec puede realizar un reinicio parcial del sistema para usar un kernel diferente.

Tarea adicional para Unexpected system call handler

Realiza esta tarea si obtienes un resultado Defense Evasion: Unexpected system call handler.

Audita las llamadas al sistema y busca anomalías en su uso y en los invocadores. Los registros de auditoría proporcionan información sobre el proceso de invocación y los argumentos de las llamadas al sistema. También puedes realizar tareas de verificación para comprobar los comportamientos esperados de las llamadas al sistema comunes. Para obtener más información, consulta Ejemplo de inspección con el rootkit Diamorphine en esta página.

Tarea adicional para Unexpected interrupt handler

Realiza esta tarea si obtienes un resultado Defense Evasion: Unexpected interrupt handler.

Enumera los controladores de interrupciones en vivo del sistema y compara los resultados con la información de otras VMs similares del proyecto. Los controladores de interrupción inesperados pueden indicar que la VM está en riesgo.

Para enumerar los controladores de interrupciones activos, ejecuta el siguiente comando:

cat /proc/interrupts

El resultado se ve de la manera siguiente:

           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

Tarea adicional para Unexpected processes in runqueue

Sigue estos pasos si obtienes un hallazgo de Defense Evasion: Unexpected processes in runqueue. En esta sección, se te ayuda a recopilar puntos de datos adicionales para investigar tus hallazgos. Es posible que estos datos no indiquen directamente un problema de software malicioso.

En esta tarea, revisarás la cola del programador por CPU. Aunque algunos procesos pueden ser de corta duración, puedes evaluar el comportamiento de la cola del programador con los procesos en ejecución por CPU para buscar comportamientos anómalos.

  1. Muestra detalles sobre la cantidad de tiempo que cada proceso en ejecución dedica por CPU. Esto te ayuda a ver si una CPU en particular está extremadamente ocupada. Puedes correlacionar los resultados con las interrupciones fijadas en la CPU desde /proc/interrupts.

    cat /proc/schedstat
    

    Para obtener más información sobre este comando, consulta Estadísticas del programador en la documentación del kernel de Linux.

  2. Enumera todas las tareas ejecutables actuales y los detalles sobre los cambios de contexto para cada CPU.

    cat /proc/sched_debug
    

    El resultado se ve de la manera siguiente:

    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. Busca lo siguiente:

    • Nombres de los procesos en ejecución
    • Cantidad de cambios de contexto por CPU. Comprobar si un proceso genera demasiados o muy pocos cambios en la CPU
    • Tiempo de CPU empleado (tiempo no inactivo).

Ejemplo de inspección con el rootkit Diamorphine

En esta sección, se muestra una inspección de una VM que tiene instalado el rootkit Diamorphine. La diamorfina es un módulo del kernel cargable (LKM) popular. Este rootkit activa las siguientes categorías de hallazgos:

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

Para obtener más información sobre estas categorías de hallazgos, consulta Hallazgos de amenazas de rootkits en modo kernel.

A continuación, se indican los pasos de inspección que se llevaron a cabo y los síntomas que se observaron en la VM:

  1. Busca syslog para todos los módulos de kernel externos al árbol que estén cargados.

    1. Busca en el búfer de registro del kernel:

      sudo dmesg | grep out-of-tree
      

      Resultado:

      diamorphine: loading out-of-tree module taints kernel.
      
    2. Busca los mensajes de syslog:

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

      Resultado:

      /var/log/syslog: diamorphine: loading out-of-tree module taints kernel.
      
  2. Busca syslog para detectar cualquier falla en la verificación del módulo (no disponible en todas las distribuciones de Linux).

    1. Busca en el búfer de registro del kernel:

      sudo dmesg | grep "module verification failed"
      

      Resultado:

      diamorphine: module verification failed: signature and/or required key missing - tainting kernel
      
    2. Busca los mensajes de syslog:

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

      Resultado:

      /var/log/syslog: diamorphine: module verification failed: signature and/or required key missing - tainting kernel
      
  3. Confirma que el módulo esté oculto en los comandos /proc/modules y lsmod.

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

    No se mostraron resultados.

  4. Confirma que el módulo tenga una entrada en sysfs.

    sudo cat /sys/module/diamorphine/coresize
    

    Resultado:

    16384
    
  5. Obtén la tabla de llamadas al sistema para la arquitectura:

    sudo ausyscall --dump
    

    Resultado:

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

    Audita las anomalías en las llamadas al sistema, como kill y getdents, que suelen ser manipuladas por los rootkits.

  6. Para verificar si se manipuló el controlador de llamadas del sistema, audita las llamadas del sistema y busca comportamientos anómalos. Estos comportamientos varían para cada llamada al sistema.

    La llamada al sistema que se suele hackear es la llamada kill. Puedes verificar si se omitió la llamada al sistema kill. En el siguiente ejemplo, se auditó la llamada al sistema kill.

    1. Instala auditd y observa el comportamiento de la VM sin el 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"
      

      En este punto de la inspección, se instaló el rootkit Diamorphine. En los siguientes pasos, se muestra el comportamiento de la VM después de la instalación del rootkit.

    2. Confirma que ahora no hay una entrada de registro de auditoría para el indicador después de que se instaló el rootkit de diamorfina:

      $ sudo ausearch -k audit_kill | grep -A 3 "pid=1158"
      $ sleep 600 &
      [2] 1167
      
    3. Verifica los detalles de la entrada de registro de auditoría para el indicador. En este ejemplo, aunque el rootkit no secuestró por completo este indicador en particular, la información sobre el proceso de invocación está disponible.

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

Depura la secuencia de comandos de recopilación de datos

La siguiente secuencia de comandos realiza muchas de las tareas de depuración que se describen en esta página. Puedes ejecutar esta secuencia de comandos en el modo sudo o root. La secuencia de comandos solo lee información de depuración del 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 "=================================================="

¿Qué sigue?