Inspecionar uma VM para verificar se há sinais de adulteração da memória do kernel

Nesta página, descrevemos as tarefas que podem ser realizadas para confirmar a validade de uma descoberta de rootkit no modo kernel da Detecção de ameaças a máquinas virtuais. As descobertas de rootkit no modo kernel indicam que a memória do kernel de uma VM pode ter sido adulterada por malware.

Quando você recebe uma descoberta de rootkit no modo kernel da VM Threat Detection, recomendamos que execute estes comandos do Linux na instância afetada do Compute Engine para investigar seu sistema em busca de pontos de dados que possam indicar anomalias, como chamadas de sistema sequestradas ou módulos de kernel ocultos.

Como alternativa, execute o script de coleta 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 descobertas de rootkit no modo kernel.

Neste documento, partimos do princípio que você:

  • Você está realizando as tarefas neste documento depois de receber uma descoberta de rootkit no modo kernel da VM Threat Detection. Para conferir uma lista das categorias de descobertas relevantes, consulte Descobertas de ameaças do rootkit no modo kernel.

  • Você tem conhecimento das ferramentas de linha de comando do Linux e do kernel do Linux.

Sobre a VM Threat Detection

A Detecção de ameaças a máquinas virtuais é um serviço integrado do Security Command Center disponível nos níveis Enterprise e Premium. Esse serviço verifica máquinas virtuais para detectar aplicativos potencialmente maliciosos, como software de mineração de criptomoedas, rootkits no modo kernel e malware em execução em ambientes de nuvem comprometidos.

A VM Threat Detection faz parte do pacote de detecção de ameaças do Security Command Center e foi projetada para complementar os recursos atuais do Event Threat Detection e do Container Threat Detection.

Para informações sobre a detecção de ameaças a máquinas virtuais, consulte Visão geral da detecção de ameaças a máquinas virtuais. Para saber como acessar os detalhes de uma descoberta da detecção de ameaças à VM, consulte Analisar descobertas no console Google Cloud .

Antes de começar

Para ter as permissões necessárias para visualizar todos os recursos e descobertas no Security Command Center e gerenciar a instância afetada do Compute Engine, peça ao administrador para conceder a você os seguintes papéis do IAM:

Para mais informações sobre a concessão de papéis, consulte Gerenciar o acesso a projetos, pastas e organizações.

Também é possível conseguir as permissões necessárias por meio de papéis personalizados ou de outros papéis predefinidos.

Identificar a VM afetada

  1. Confira os detalhes da descoberta.
  2. Na seção Recurso afetado, no campo Nome completo do recurso, clique no link. A visualização de detalhes da instância afetada do Compute Engine é aberta em uma nova guia.
  3. Conecte-se à instância. Para mais informações, consulte Conectar-se a VMs do Linux na documentação do Compute Engine.

Encontrar módulos de kernel inesperados

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

Para encontrar módulos do kernel inesperados, siga estas etapas:

  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 dessas listas com as de outras VMs no projeto. Procure módulos que aparecem na VM afetada, mas não nas outras.

Pesquisar módulos fora da árvore em syslog

Sinais de que um módulo fora da árvore foi carregado em uma VM podem indicar que módulos de kernel atípicos foram carregados. Você pode pesquisar o buffer de registro do kernel e as mensagens syslog para determinar se um módulo fora da árvore foi carregado. Nas entradas de registro, um módulo fora da árvore é marcado como carga contaminada.

No buffer de registro do kernel e nas mensagens syslog, procure entradas de registro semelhantes a estas:

MODULE_NAME: loading out-of-tree module taints kernel.
  • Pesquise no buffer de registro do kernel entradas de registro que indicam a presença de módulos fora da árvore:

    sudo dmesg | grep out-of-tree
    
  • Pesquise todas as mensagens syslog para encontrar entradas de registro que indiquem a presença de módulos fora da árvore:

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

Verificar o livepatching

O Livepatching em uma VM pode interferir nas detecções da VM Threat Detection e acionar descobertas de falsos positivos.

Para verificar se o livepatching está ativado, siga estas etapas:

  1. Confira syslog para instalação e registro do módulo de livepatching. O patch dinâmico normalmente modifica o código do kernel instalando pontos de ftrace do kernel.

    sudo grep livepatch /var/log/syslog*
    
  2. Procure novos módulos do kernel instalados para livepatching (normalmente com o prefixo livepatch):

    sudo lsmod | grep livepatch
    
  3. Pesquisar arquivos de patch:

    sudo ls -l /sys/kernel/livepatch
    

Para informações sobre o livepatching, consulte Livepatch na documentação do kernel do Linux.

Verificar outras atividades potencialmente maliciosas detectadas na VM

  1. No Security Command Center, veja os detalhes da descoberta da VM Threat Detection que você está investigando.
  2. Na seção Recurso afetado, no campo Nome completo do recurso, clique na seta suspensa e em Mostrar todas as descobertas com este nome completo do recurso. A consulta de descobertas é atualizada para mostrar apenas as descobertas dessa VM.
  3. Verifique se há descobertas que apontam para possíveis atividades de criptomineração, malware, concessões incomuns do IAM e outras ameaças à segurança.

Verificar se o software antivírus está causando um falso positivo

O software antivírus pode interferir nas detecções da VM Threat Detection e acionar descobertas de falsos positivos.

Verificar todos os processos em execução no sistema

A presença de processos inesperados pode indicar que a descoberta da VM Threat Detection é válida e que a VM foi comprometida.

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

    ps -eAf
    
  2. Procure processos de depurador, como gdb, strace e pstack, que você normalmente não executa nessa VM. Os processos do depurador podem espionar outros processos.

  3. Procure outros processos suspeitos na VM.

Verificar o kernel inicializado

Verifique o kernel inicializado para identificar seu kernel do Linux:

cat /proc/version

Se o valor retornado não for a versão esperada do kernel, isso pode indicar um ataque de sequestro feito explorando a ferramenta kexec no kernel. A ferramenta kexec pode fazer uma reinicialização parcial do sistema para usar um kernel diferente.

Tarefa adicional para Unexpected system call handler

Faça isso se você receber uma descoberta Defense Evasion: Unexpected system call handler.

Audite as chamadas do sistema e procure anomalias no uso e nos invocadores. Os registros de auditoria fornecem informações sobre o processo de invocação e os argumentos para as chamadas do sistema. Você também pode realizar tarefas de verificação para conferir os comportamentos esperados das chamadas de sistema comuns. Para mais informações, consulte Exemplo de inspeção com o rootkit Diamorphine nesta página.

Tarefa adicional para Unexpected interrupt handler

Faça isso se você receber uma descoberta Defense Evasion: Unexpected interrupt handler.

Liste os manipuladores de interrupção ativos no sistema e compare os resultados com informações de outras VMs semelhantes no projeto. Manipuladores inesperados de interrupção podem indicar que a VM está comprometida.

Para listar os manipuladores de interrupção ativos, execute o seguinte comando:

cat /proc/interrupts

A saída será assim:

           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

Siga estas etapas se você receber uma descoberta Defense Evasion: Unexpected processes in runqueue. Esta seção ajuda você a coletar outros pontos de dados para investigar suas descobertas. Esses pontos de dados podem não indicar diretamente um problema de malware.

Nesta tarefa, você vai analisar a fila do programador por CPU. Embora alguns processos possam ser de curta duração, ainda é possível avaliar o comportamento da fila do programador com os processos em execução por CPU para procurar comportamentos anômalos.

  1. Mostra detalhes sobre a quantidade de tempo que cada processo em execução gasta por CPU. Isso ajuda a saber se uma CPU específica está muito ocupada. É possível correlacionar os resultados com interrupções fixadas na CPU de /proc/interrupts.

    cat /proc/schedstat
    

    Para mais informações sobre esse comando, consulte Estatísticas do Scheduler na documentação do kernel do Linux.

  2. Liste todas as tarefas executáveis atuais e detalhes sobre as trocas de contexto para cada CPU.

    cat /proc/sched_debug
    

    A saída será assim:

    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 de processos em execução.
    • Número de trocas de contexto por CPU. Verifique se um processo está gerando poucas ou muitas trocas na CPU.
    • Tempo de CPU gasto (tempo não ocioso).

Exemplo de inspeção com o rootkit Diamorphine

Esta seção demonstra uma inspeção de uma VM com o rootkit Diamorphine instalado. A diamorfina é um módulo do kernel carregável (LKM, na sigla em inglês) conhecido. Esse rootkit aciona as seguintes categorias de descoberta:

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

Para mais informações sobre essas categorias de descobertas, consulte Descobertas de ameaças de rootkit no modo kernel.

As etapas de inspeção realizadas e os sintomas observados na VM são os seguintes:

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

    1. Pesquise o buffer de registro 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 para encontrar falhas na verificação de módulos (não disponível em todas as distribuições do Linux).

    1. Pesquise o buffer de registro 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 se o módulo está oculto dos comandos /proc/modules e lsmod.

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

    Nenhum resultado foi mostrado.

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

    sudo cat /sys/module/diamorphine/coresize
    

    Saída:

    16384
    
  5. Acesse 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
    

    Faça auditorias para detectar anomalias em chamadas de sistema, como kill e getdents, que geralmente são adulteradas por rootkits.

  6. Para verificar se houve adulteração do manipulador de chamadas do sistema, faça uma auditoria das chamadas e procure comportamentos anômalos. Esses comportamentos variam de acordo com cada chamada de sistema.

    Uma chamada de sistema que geralmente é invadida é a kill. Você pode verificar se a chamada de sistema kill foi ignorada. No exemplo a seguir, a chamada de sistema kill foi auditada.

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

      Nesse ponto da inspeção, o rootkit Diamorphine já estava instalado. As próximas etapas mostram o comportamento da VM após a instalação do rootkit.

    2. Confirme se uma entrada de registro de auditoria para o indicador não está mais presente depois que o rootkit Diamorphine foi instalado:

      $ sudo ausearch -k audit_kill | grep -A 3 "pid=1158"
      $ sleep 600 &
      [2] 1167
      
    3. Confira os detalhes na entrada de registro de auditoria do indicador. Neste exemplo, embora esse sinal específico não tenha sido totalmente sequestrado 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"
      

Depurar o script de coleta de dados

O script a seguir executa muitas das tarefas de depuração descritas nesta página. É possível executar esse script no modo sudo ou root. O script lê apenas 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 "=================================================="

A seguir