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

本页介绍了您可以执行的任务,以确认 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 内置的一项服务。此服务会扫描虚拟机以检测潜在恶意应用,例如加密货币挖矿软件、内核模式 rootkit 以及在遭入侵的云环境中运行的恶意软件。

VM Threat Detection 是 Security Command Center 威胁检测套件的一部分,旨在补充 Event Threat Detection 和 Container 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. 查找您通常不会在此虚拟机上运行的调试程序进程,例如 gdb、strace 和 pstack。调试程序进程可以监视其他进程。

  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/modules 和 lsmod 命令中隐藏。

    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
    

    审核系统调用中的异常情况(例如 kill 和 getdents),这些异常情况通常是由 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"
      

调试数据收集脚本

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

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

后续步骤