检查虚拟机是否存在内核内存篡改迹象

本页介绍了您可以执行的任务,以确认 Virtual Machine Threat Detection 发现的内核模式 rootkit 发现结果的有效性。内核模式 rootkit 发现结果表明,虚拟机的内核内存可能已被恶意软件篡改。

如果您从 VM Threat Detection 收到内核模式 rootkit 发现结果,我们建议您在受影响的 Compute Engine 实例上运行这些 Linux 命令,以便在系统中探测可能表明存在异常(例如被劫持的系统调用或隐藏的内核模块)的数据点。

或者,您也可以在受影响的虚拟机上运行提供的数据收集脚本。该脚本会执行本页面中所述的命令。

除非另有说明,否则本页上的每个检查任务都与所有内核模式 rootkit 发现结果相关。

本文档假定您满足以下条件:

  • 您是在收到来自虚拟机威胁检测的根模式 rootkit 发现结果后执行本文档中的任务。如需查看相关发现类别的列表,请参阅内核模式 rootkit 威胁发现结果

  • 您了解 Linux 命令行工具和 Linux 内核。

关于 VM Threat Detection

Virtual Machine Threat Detection 是 Security Command Center 内置的一项服务,可在 Enterprise 层级和 Premium 层级中使用。此服务会扫描虚拟机以检测潜在恶意应用,例如加密货币挖矿软件、内核模式 rootkit 以及在遭入侵的云环境中运行的恶意软件。

VM Threat Detection 是 Security Command Center 威胁检测套件的一部分,旨在补充 Event Threat DetectionContainer Threat Detection 的现有功能。

如需了解 VM Threat Detection,请参阅虚拟机威胁检测概览。如需了解如何查看 VM Threat Detection 发现结果的详细信息,请参阅在Google Cloud 控制台中查看发现结果

准备工作

如需获得在 Security Command Center 中查看所有资源和发现结果以及管理受影响的 Compute Engine 实例所需的权限,请让您的管理员为您授予以下 IAM 角色:

如需详细了解如何授予角色,请参阅管理对项目、文件夹和组织的访问权限

您也可以通过自定义角色或其他预定义角色来获取所需的权限。

确定受影响的虚拟机

  1. 查看发现结果的详细信息
  2. 受影响的资源部分的资源完整名称字段中,点击链接。系统会在新标签页中打开受影响的 Compute Engine 实例的详细信息视图。
  3. 连接到实例。如需了解详情,请参阅 Compute Engine 文档中的连接到 Linux 虚拟机

查找意外的内核模块

虚拟机中存在意外模块可能表示虚拟机的内核内存可能已遭到破坏。

如需查找意外的内核模块,请按以下步骤操作:

  1. 列出虚拟机中已加载的所有内核模块:

    lsmod
    cat /proc/modules
    
  2. 列出已加载和已卸载模块的 sysfs 条目:

    ls -l /sys/module/
    
  3. 将这些列表的结果与项目中其他虚拟机的列表进行比较。查找在受影响的虚拟机中显示但在其他虚拟机中不显示的模块。

syslog 中搜索树外模块

树外模块已加载到虚拟机中的迹象可能表明已加载非典型内核模块。您可以搜索内核日志缓冲区和 syslog 消息,以确定是否已加载树外模块。在日志条目中,树外模块会被标记为污染加载。

在内核日志缓冲区和 syslog 消息中,搜索类似于以下内容的日志条目:

MODULE_NAME: loading out-of-tree module taints kernel.
  • 在内核日志缓冲区中搜索日志条目,以指明是否存在树外模块:

    sudo dmesg | grep out-of-tree
    
  • 搜索所有 syslog 消息,查找指示存在树外模块的日志条目:

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

检查实时修补

虚拟机中的实时修补可能会干扰 VM Threat Detection 检测,并可能会触发误报发现结果。

如需检查实时修补功能,请按以下步骤操作:

  1. 检查 syslog 以了解实时修补模块安装和日志记录。实时补丁通常通过安装内核 ftrace 点来修改内核代码。

    sudo grep livepatch /var/log/syslog*
    
  2. 搜索已安装用于实时修补的内核模块(通常以 livepatch 为前缀):

    sudo lsmod | grep livepatch
    
  3. 搜索补丁文件:

    sudo ls -l /sys/kernel/livepatch
    

如需了解实时修补,请参阅 Linux 内核文档中的 Livepatch

检查虚拟机中是否检测到其他可能的恶意活动

  1. 在 Security Command Center 中,查看您正在调查的 VM Threat Detection 发现结果的详细信息
  2. 受影响的资源部分的资源全名字段中,点击下拉箭头,然后点击显示使用此资源全名的所有发现结果。更新了发现结果查询,以仅显示此虚拟机的发现结果。
  3. 检查是否有指向潜在挖矿活动、恶意软件、异常 IAM 授权和其他安全威胁的发现结果。

检查防病毒软件是否导致误报发现结果

杀毒软件可能会干扰 VM Threat Detection 检测,并可能会触发误报发现结果。

检查系统上所有正在运行的进程

出现意外进程可能表明 VM Threat Detection 发现结果有效且虚拟机已遭入侵。

  1. 列出在虚拟机上运行的所有进程:

    ps -eAf
    
  2. 查找您通常不会在此虚拟机上运行的调试程序进程,例如 gdbstracepstack。调试程序进程可以监视其他进程。

  3. 在虚拟机上查找其他可疑进程。

检查已启动的内核

检查已启动的内核以识别您的 Linux 内核:

cat /proc/version

如果返回的值不是您预期的内核版本,则可能表明存在通过利用内核中的 kexec 工具进行的劫持攻击。kexec 工具可以软启动系统以使用其他内核。

针对 Unexpected system call handler 的额外任务

如果您收到 Defense Evasion: Unexpected system call handler 发现结果,请执行此任务。

审核系统调用,并查找其用法和调用方中的异常情况。审核日志提供有关系统调用的调用进程和参数的信息。您还可以执行验证任务,以检查常见系统调用的预期行为。如需了解详情,请参阅本页上的使用 Diamorphine rootkit 的检查示例

针对 Unexpected interrupt handler 的额外任务

如果您收到 Defense Evasion: Unexpected interrupt handler 发现结果,请执行此任务。

列出系统上的实时中断处理程序,并将结果与项目中其他类似虚拟机中的信息进行比较。意外的中断处理程序可能表明虚拟机遭到入侵。

如需列出实时中断处理程序,请运行以下命令:

cat /proc/interrupts

输出将类似以下内容:

           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

针对 Unexpected processes in runqueue 的额外任务

如果您收到 Defense Evasion: Unexpected processes in runqueue 发现结果,请执行以下步骤。本部分可帮助您收集更多数据点,以调查您的发现结果。这些数据点可能不会直接指明存在恶意软件问题。

在此任务中,您将查看每个 CPU 的调度器队列。尽管某些进程可能生命周期短,但您仍然可以使用每个 CPU 的运行进程来评估调度器队列行为,以查找异常行为。

  1. 显示每个正在运行的进程在每个 CPU 上所用时间的详细信息。这有助于您了解特定 CPU 是否非常繁忙。您可以将结果与从 /proc/interrupts 固定到 CPU 的中断相关联。

    cat /proc/schedstat
    

    如需详细了解此命令,请参阅 Linux 内核文档中的调度器统计信息

  2. 列出每个 CPU 的所有当前可运行任务和上下文切换的详细信息。

    cat /proc/sched_debug
    

    输出将类似以下内容:

    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. 查找以下项:

    • 正在运行的进程名称。
    • 每个 CPU 的上下文切换次数。查看进程在 CPU 上是否发生了过少或过多的切换。
    • 所花费的 CPU 时间(非空闲时间)。

使用 Diamorphine rootkit 的检查示例

本部分演示了对安装了 Diamorphine rootkit 的虚拟机进行检查。Diamorphine 是一种常用的可加载内核模块 (LKM)。此 rootkit 会触发以下发现发现结果类别:

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

如需详细了解这些发现类别,请参阅内核模式 rootkit 威胁发现结果

所采取的检查步骤和在虚拟机上观察到的症状如下:

  1. 搜索 syslog 以查找已加载的所有树外内核模块。

    1. 搜索内核日志缓冲区:

      sudo dmesg | grep out-of-tree
      

      输出:

      diamorphine: loading out-of-tree module taints kernel.
      
    2. 搜索 syslog 消息:

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

      输出:

      /var/log/syslog: diamorphine: loading out-of-tree module taints kernel.
      
  2. 搜索 syslog 以查找任何模块验证失败情况(并非所有 Linux 发行版都支持此命令)。

    1. 搜索内核日志缓冲区:

      sudo dmesg | grep "module verification failed"
      

      输出:

      diamorphine: module verification failed: signature and/or required key missing - tainting kernel
      
    2. 搜索 syslog 消息:

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

      输出:

      /var/log/syslog: diamorphine: module verification failed: signature and/or required key missing - tainting kernel
      
  3. 确认模块已从 /proc/moduleslsmod 命令中隐藏。

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

    未显示任何结果。

  4. 确认该模块在 sysfs 中具有条目。

    sudo cat /sys/module/diamorphine/coresize
    

    输出:

    16384
    
  5. 获取架构的系统调用表:

    sudo ausyscall --dump
    

    输出:

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

    审核系统调用中的异常情况(例如 killgetdents),这些异常情况通常是由 rootkit 篡改的。

  6. 如需检查系统调用处理程序是否遭到篡改,请审核系统调用并检查是否存在异常行为。这些行为因系统调用而异。

    通常被黑的系统调用是 kill 调用。您可以检查是否绕过了 kill 系统调用。在以下示例中,对 kill 系统调用进行了审核。

    1. 安装 auditd,并在没有 Diamorphine rootkit 的情况下观察虚拟机的行为:

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

      在检查的此阶段,安装了 Diamorphine rootkit。接下来的步骤将展示 rootkit 安装后的虚拟机行为。

    2. 确认在安装了 Diamorphine rootkit 后,信号的审核日志条目现在不存在:

      $ sudo ausearch -k audit_kill | grep -A 3 "pid=1158"
      $ sleep 600 &
      [2] 1167
      
    3. 查看该信号的审核日志条目中的详细信息。在此示例中,虽然此特定信号未被 rootkit 完全劫持,但调用程序进程的信息是可用的。

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

调试数据收集脚本

以下脚本会执行本页面中所述的许多调试任务。您可以在 sudoroot 模式下运行此脚本。该脚本仅从系统读取调试信息。

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

后续步骤