Inspecione uma VM quanto a sinais de adulteração da memória do kernel

Esta página descreve as tarefas que pode realizar para confirmar a validade de uma descoberta de rootkit no modo kernel da Deteção de ameaças da máquina virtual. As conclusões de rootkit no modo kernel indicam que a memória do kernel de uma VM foi potencialmente adulterada por software malicioso.

Quando recebe um resultado de rootkit no modo kernel da Deteção de ameaças de VMs, recomendamos que execute estes comandos Linux na instância do Compute Engine afetada para analisar o seu sistema em busca de pontos de dados que possam indicar anomalias, como chamadas de sistema roubadas ou módulos do kernel ocultos.

Em alternativa, pode executar o script de recolha de dados fornecido na VM afetada. O script executa os comandos descritos nesta página.

Salvo indicação em contrário, cada tarefa de inspeção nesta página é relevante para todas as conclusões de rootkits no modo kernel.

Este documento pressupõe o seguinte:

  • Está a realizar as tarefas neste documento depois de receber uma deteção de rootkit no modo kernel da Deteção de ameaças de VMs. Para ver uma lista das categorias de resultados relevantes, consulte o artigo Resultados de ameaças de rootkit no modo kernel.

  • Tem conhecimentos das ferramentas de linha de comandos do Linux e do kernel do Linux.

Acerca da Deteção de ameaças de VMs

A Deteção de ameaças da máquina virtual é um serviço integrado do Security Command Center. Este serviço analisa máquinas virtuais para detetar aplicações potencialmente maliciosas, como software de mineração de criptomoedas, rootkits no modo kernel e software malicioso em execução em ambientes de nuvem comprometidos.

A deteção de ameaças de VMs faz parte do conjunto de deteção de ameaças do Security Command Center e foi concebida para complementar as capacidades existentes da deteção de ameaças de eventos e da deteção de ameaças de contentores.

Para obter informações sobre a deteção de ameaças da VM, consulte a vista geral da deteção de ameaças da máquina virtual. Para saber como ver os detalhes de uma deteção de ameaças de VMs, consulte o artigo Reveja as deteções na Google Cloud consola.

Antes de começar

Para receber as autorizações de que precisa para ver todos os recursos e resultados no Security Command Center e gerir a instância do Compute Engine afetada, peça ao seu administrador que lhe conceda as seguintes funções do IAM:

Para mais informações sobre a atribuição de funções, consulte o artigo Faça a gestão do acesso a projetos, pastas e organizações.

Também pode conseguir as autorizações necessárias através de funções personalizadas ou outras funções predefinidas.

Identifique a VM afetada

  1. Veja os detalhes da descoberta.
  2. Na secção Recurso afetado, no campo Nome completo do recurso, clique no link. A vista de detalhes da instância do Compute Engine afetada é aberta num novo separador.
  3. Ligue-se à instância. Para mais informações, consulte o artigo Estabeleça ligação a VMs Linux na documentação do Compute Engine.

Encontre módulos de kernel inesperados

A presença de módulos inesperados numa VM pode indicar que a memória do kernel da VM está potencialmente comprometida.

Para encontrar módulos do kernel inesperados, siga estes passos:

  1. Liste todos os módulos do kernel carregados na VM:

    lsmod
    cat /proc/modules
    
  2. Liste as entradas sysfs para os módulos carregados e descarregados:

    ls -l /sys/module/
    
  3. Compare os resultados destas listas com listas de outras VMs no projeto. Procure módulos que apareçam na VM afetada, mas não nas outras VMs.

Pesquise syslog para módulos fora da árvore

Os sinais de que um módulo fora da árvore foi carregado numa VM podem indicar que foram carregados módulos do kernel atípicos. Pode pesquisar no buffer de registo do kernel e nas mensagens syslog para determinar se foi carregado um módulo fora da árvore. Nas entradas do registo, um módulo fora da árvore é marcado como carregamento contaminado.

No buffer do registo do kernel e nas mensagens syslog, pesquise entradas do registo que se assemelhem ao seguinte:

MODULE_NAME: loading out-of-tree module taints kernel.
  • Pesquise no buffer do registo do kernel entradas de registo que indiquem a presença de módulos externos:

    sudo dmesg | grep out-of-tree
    
  • Pesquise todas as syslog mensagens de entradas de registo que indiquem a presença de módulos externos:

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

Verifique se existem patches em direto

A aplicação de patches em tempo real numa VM pode interferir com as deteções da Deteção de ameaças de VMs e pode acionar resultados falsos positivos.

Para verificar se existe aplicação de patches em tempo real, siga estes passos:

  1. Verifique syslog para a instalação e o registo do módulo de aplicação de patches em direto. Normalmente, a aplicação de patches em direto modifica o código do kernel instalando ftrace pontos do kernel.

    sudo grep livepatch /var/log/syslog*
    
  2. Pesquise novos módulos do kernel instalados para aplicação de patches em direto (normalmente com o prefixo livepatch):

    sudo lsmod | grep livepatch
    
  3. Pesquise ficheiros de patch:

    sudo ls -l /sys/kernel/livepatch
    

Para informações sobre a aplicação de patches em tempo real, consulte o artigo Livepatch na documentação do kernel do Linux.

Verifique se existem outras atividades potencialmente maliciosas detetadas na MV

  1. No Security Command Center, veja os detalhes da deteção de ameaças de VMs que está a investigar.
  2. Na secção Recurso afetado, no campo Nome completo do recurso, clique na seta de menu pendente e, de seguida, clique em Mostrar todas as conclusões com este nome completo do recurso. A consulta de resultados é atualizada para mostrar apenas resultados para esta VM.
  3. Verifique se existem resultados que apontam para potenciais atividades de mineração de criptomoedas, software malicioso, concessões de IAM invulgares e outras ameaças de segurança.

Verifique se o software antivírus está a causar uma deteção de falso positivo

O software antivírus pode interferir com as deteções da Deteção de ameaças de VMs e pode acionar resultados falsos positivos.

Verifique todos os processos em execução no sistema

A presença de processos inesperados pode indicar que a descoberta de deteção de ameaças de VMs é válida e que a VM foi comprometida.

  1. Apresente todos os processos em execução na VM:

    ps -eAf
    
  2. Procure processos de depuração, como gdb, strace e pstack, que normalmente não executa nesta VM. Os processos do depurador podem espiar outros processos.

  3. Procure outros processos suspeitos na VM.

Verifique o kernel iniciado

Verifique o kernel iniciado para identificar o seu kernel do Linux:

cat /proc/version

Se o valor devolvido não for a versão do kernel esperada, isso pode indicar um ataque de roubo de identidade que é realizado através da exploração da ferramenta kexec no kernel. A ferramenta kexec pode reiniciar o sistema para usar um kernel diferente.

Tarefa adicional para Unexpected system call handler

Realize esta tarefa se receber uma Defense Evasion: Unexpected system call handler descoberta.

Audite as chamadas do sistema e procure anomalias na respetiva utilização e invocadores. Os registos de auditoria fornecem informações sobre o processo de invocação e os argumentos para as chamadas do sistema. Também pode realizar tarefas de validação para verificar os comportamentos esperados das chamadas do sistema comuns. Para mais informações, consulte o exemplo de inspeção com o rootkit Diamorphine nesta página.

Tarefa adicional para Unexpected interrupt handler

Realize esta tarefa se receber uma Defense Evasion: Unexpected interrupt handler descoberta.

Liste os controladores de interrupções em direto no sistema e compare os resultados com as informações de outras VMs semelhantes no projeto. Os controladores de interrupções inesperados podem indicar que a VM está comprometida.

Para apresentar uma lista dos controladores de interrupções em direto, execute o seguinte comando:

cat /proc/interrupts

O resultado é semelhante ao seguinte:

           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

Tarefa adicional para Unexpected processes in runqueue

Execute estes passos se receber uma Defense Evasion: Unexpected processes in runqueue. Esta secção ajuda a recolher pontos de dados adicionais para investigar as suas conclusões. Estes pontos de dados podem não indicar diretamente um problema de software malicioso.

Nesta tarefa, revê a fila do agendador por CPU. Embora alguns processos possam ser de curta duração, ainda pode avaliar o comportamento da fila do agendador com os processos em execução por CPU para procurar um comportamento anómalo.

  1. Apresente detalhes sobre a quantidade de tempo que cada processo em execução gasta por CPU. Isto ajuda a ver se uma CPU específica está extremamente ocupada. Pode correlacionar os resultados com as interrupções fixadas na CPU a partir de /proc/interrupts.

    cat /proc/schedstat
    

    Para mais informações sobre este comando, consulte Scheduler Statistics na documentação do kernel do Linux.

  2. Liste todas as tarefas executáveis atuais e os detalhes sobre as comutações de contexto para cada CPU.

    cat /proc/sched_debug
    

    O resultado é semelhante ao seguinte:

    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. Procure o seguinte:

    • Nomes dos processos em execução.
    • Número de mudanças de contexto por CPU. Verifique se um processo está a incorrer em comutações demasiado poucas ou demasiadas na CPU.
    • Tempo da CPU gasto (tempo não inativo).

Exemplo de inspeção com o rootkit Diamorphine

Esta secção demonstra uma inspeção de uma MV que tem o rootkit Diamorphine instalado. O Diamorphine é um módulo do kernel carregável (LKM) popular. Este rootkit aciona as seguintes categorias de resultados:

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

Para mais informações sobre estas categorias de deteção, consulte o artigo Deteções de ameaças de rootkit no modo kernel.

Os passos de inspeção realizados e os sintomas observados na VM são os seguintes:

  1. Pesquise syslog todos os módulos do kernel fora da árvore que estão carregados.

    1. Pesquise o buffer do registo do kernel:

      sudo dmesg | grep out-of-tree
      

      Saída:

      diamorphine: loading out-of-tree module taints kernel.
      
    2. Pesquise as mensagens de syslog:

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

      Saída:

      /var/log/syslog: diamorphine: loading out-of-tree module taints kernel.
      
  2. Pesquise syslog falhas de validação de módulos (não disponível em todas as distribuições do Linux).

    1. Pesquise o buffer do registo do kernel:

      sudo dmesg | grep "module verification failed"
      

      Saída:

      diamorphine: module verification failed: signature and/or required key missing - tainting kernel
      
    2. Pesquise as mensagens de syslog:

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

      Saída:

      /var/log/syslog: diamorphine: module verification failed: signature and/or required key missing - tainting kernel
      
  3. Confirme que o módulo está oculto dos comandos /proc/modules e lsmod.

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

    Não foram apresentados resultados.

  4. Confirme se o módulo tem uma entrada em sysfs.

    sudo cat /sys/module/diamorphine/coresize
    

    Saída:

    16384
    
  5. Obtenha a tabela de chamadas do sistema para a arquitetura:

    sudo ausyscall --dump
    

    Saída:

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

    Auditoria de anomalias nas chamadas do sistema, como kill e getdents, que são normalmente adulteradas por rootkits.

  6. Para verificar se existem adulterações do controlador de chamadas do sistema, audite as chamadas do sistema e verifique se existem comportamentos anómalos. Estes comportamentos variam para cada chamada do sistema.

    Uma chamada de sistema que é normalmente pirateada é a chamada kill. Pode verificar se a chamada do sistema kill foi ignorada. No exemplo seguinte, a chamada de sistema kill foi auditada.

    1. Instale o auditd e observe o comportamento da MV sem o 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"
      

      Neste ponto da inspeção, o rootkit Diamorphine foi instalado. Os passos seguintes mostram o comportamento da MV após a instalação do rootkit.

    2. Confirme que uma entrada do registo de auditoria para o sinal está agora ausente após a instalação do rootkit Diamorphine:

      $ sudo ausearch -k audit_kill | grep -A 3 "pid=1158"
      $ sleep 600 &
      [2] 1167
      
    3. Verifique os detalhes na entrada do registo de auditoria do sinal. Neste exemplo, embora este sinal específico não tenha sido completamente roubado pelo rootkit, as informações sobre o processo de invocação estão disponíveis.

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

Depure o script de recolha de dados

O script seguinte executa muitas das tarefas de depuração descritas nesta página. Pode executar este script no modo sudo ou root. O script apenas lê informações de depuração do 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 "=================================================="

O que se segue?