このページでは、Virtual Machine Threat Detection のカーネルモード ルートキットの検出結果の有効性を確認するために実行できるタスクについて説明します。カーネルモード ルートキットの検出結果は、VM のカーネルメモリがマルウェアによって改ざんされている可能性があることを示します。
VM Threat Detection からカーネルモード ルートキットの検出結果が返された場合は、影響を受ける Compute Engine インスタンスで次の Linux コマンドを実行して、システム呼び出しの不正使用や隠れたカーネル モジュールなど、異常を示す可能性のあるデータポイントを探すことをおすすめします。
また、影響を受ける VM で提供されているデータ収集スクリプトを実行することもできます。このスクリプトは、このページで説明するコマンドを実行します。
特に記載のない限り、このページの各検査タスクは、すべてのカーネルモード ルートキットの検出結果に関連しています。
このドキュメントの前提条件は次のとおりです。
このドキュメントで説明するタスクは、VM Threat Detection からカーネルモードのルートキットの検出結果を受け取った後に行います。関連する検出結果のカテゴリのリストについては、カーネルモード ルートキットの脅威の検出をご覧ください。
Linux コマンドライン ツールと Linux カーネルを理解している。
VM Threat Detection について
Virtual Machine Threat Detection は、エンタープライズ ティアとプレミアム ティアで利用できる Security Command Center の組み込みサービスです。このサービスは、Compute Engine インスタンスをスキャンして、侵害されたクラウド環境で実行されている、悪質な可能性のあるアプリケーション(暗号通貨マイニング ソフトウェア、カーネルモード ルートキット、マルウェアなど)を検出します。
VM Threat Detection は、Security Command Center の脅威検出スイートの一部であり、Event Threat Detection と Container Threat Detection の既存の機能を補完するように設計されています。
VM Threat Detection の詳細については、Virtual Machine Threat Detection の概要をご覧ください。VM Threat Detection の検出結果の詳細を表示する方法については、Google Cloud コンソールで検出結果を確認するをご覧ください。
始める前に
Security Command Center ですべてのリソースと検出結果を表示し、影響を受ける Compute Engine インスタンスを管理するために必要な権限を取得するには、管理者に次の IAM ロールを付与するよう依頼してください。
-
組織に対するセキュリティ センター管理閲覧者 (
roles/securitycenter.adminViewer
) -
Compute Engine インスタンスに対する Compute インスタンス管理者(v1) (
roles/compute.instanceAdmin.v1
)
ロールの付与については、プロジェクト、フォルダ、組織へのアクセス権の管理をご覧ください。
必要な権限は、カスタムロールや他の事前定義ロールから取得することもできます。
影響を受ける VM を特定する
- 検出結果の詳細を表示する。
- [影響を受けるリソース] セクションの [リソースの完全な名前] フィールドで、リンクをクリックします。影響を受ける Compute Engine インスタンスの詳細ビューが新しいタブで開きます。
- インスタンスに接続します。詳細については、Compute Engine のドキュメントの Linux VM に接続するをご覧ください。
予期しないカーネル モジュールを見つける
VM に予期しないモジュールが存在する場合、VM のカーネル メモリが侵害されている可能性があります。
予期しないカーネル モジュールを確認する手順は次のとおりです。
VM に読み込まれたすべてのカーネル モジュールを一覧表示します。
lsmod cat /proc/modules
読み込まれたモジュールとアンロードされたモジュールの
sysfs
エントリを一覧表示します。ls -l /sys/module/
これらのリストの結果を、プロジェクト内の他の VM のリストと比較します。影響を受ける VM に表示され、他の VM に表示されないモジュールを探します。
syslog
でツリー外のモジュールを検索する
ツリー外のモジュールが VM に読み込まれた兆候は、異常なカーネル モジュールが読み込まれたことを示している可能性があります。カーネル ログ バッファと 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 でのライブパッチ適用は、VM Threat Detection の検出を妨げ、誤検出の検出結果をトリガーする可能性があります。
ライブパッチ適用を確認する手順は次のとおりです。
syslog
で、ライブパッチ モジュールのインストールとロギングを確認します。通常、ライブ パッチ適用は、カーネルftrace
ポイントをインストールしてカーネル コードを変更します。sudo grep livepatch /var/log/syslog*
ライブパッチ適用用にインストールされた新しいカーネル モジュールを検索します(通常は
livepatch
が接頭辞として付いています)。sudo lsmod | grep livepatch
パッチファイルを検索します。
sudo ls -l /sys/kernel/livepatch
ライブパッチ適用の詳細については、Linux カーネルのドキュメントのLivepatchをご覧ください。
VM で検出されたその他の悪意のあるアクティビティを確認する
- Security Command Center で、調査中の VM Threat Detection の検出結果の詳細を表示します。
- [影響を受けるリソース] セクションの [リソースの完全な名前] フィールドで、プルダウン矢印をクリックし、[このリソースの完全な名前を含むすべての検出結果を表示] をクリックします。検出結果クエリが更新され、この VM の検出結果のみが表示されます。
- クリプトマイニングのアクティビティ、マルウェア、異常な IAM 付与、その他のセキュリティ脅威を示す検出結果を確認します。
ウイルス対策ソフトウェアが偽陽性検出の原因となっているかどうかを確認する
ウイルス対策ソフトウェアは VM Threat Detection の検出を妨げ、誤検出をトリガーする可能性があります。
システムで実行されているすべてのプロセスを確認する
予期しないプロセスが存在する場合、VM Threat Detection の検出結果が有効で、VM が侵害されていることを示している可能性があります。
VM で実行されているすべてのプロセスを一覧表示します。
ps -eAf
この VM で通常は実行されないデバッガ プロセス(
gdb
、strace
、pstack
など)を探します。デバッガ プロセスは他のプロセスをスヌープできます。VM で他の不審なプロセスを探します。
起動したカーネルを確認する
起動したカーネルを確認して、Linux カーネルを特定します。
cat /proc/version
返された値が想定されるカーネル バージョンと異なる場合は、カーネル内の kexec
ツールを悪用した不正使用攻撃が行われている可能性があります。kexec
ツールを使用すると、システムをソフトブートして別のカーネルを使用できます。
Unexpected kernel code modification
の検出結果の追加タスク
このセクションのタスクは、Defense Evasion: Unexpected
kernel code modification
検出結果カテゴリに固有のものです。次のセクションのタスクを実行して、このカテゴリの検出結果の有効性を確認します。
これらのセクションでは、VM がデバッガ API を使用しているかどうかを確認します。デバッガ API は、実行中のカーネルのコード領域を変更できるため、誤検出の検出結果をトリガーする可能性があります。
通常、VM Threat Detection は、デバッガ API の使用を検出しても検出結果を生成しません。ただし、VM が VM Threat Detection に認識されていないデバッガ API を使用している場合、誤検出が発生する可能性があります。
有効になっているデバッグ トレーサーを確認する
トレーサー(nop
トレーサーを除く)は、カーネル コードの変更を引き起こす可能性があります。これらは VM Threat Detection の検出を妨げ、偽陽性の検出結果をトリガーする可能性があります。通常、VM Threat Detection がトレーサーの存在を検出しても、Defense Evasion: Unexpected kernel code
modification
検出結果は送信されません。
有効になっているデバッグ トレーサーを確認する手順は次のとおりです。
使用可能なトレーサーを確認します。
cat /sys/kernel/debug/tracing/available_tracers
出力は次のようになります。
hwlat blk mmiotrace function_graph wakeup_dl wakeup_rt wakeup function nop
現在のトレーサーを確認します。
cat /sys/kernel/debug/tracing/current_tracer
結果は、前のコマンドで返された使用可能なトレーサーの 1 つです。
システムでトレースが有効になっているかどうかを確認します。
cat /sys/kernel/debug/tracing/tracing_on
値
1
は、システムでトレースが有効になっていることを示します。トレースが無効になっている CPU を一覧表示します。
cat /sys/kernel/debug/tracing/tracing_cpumask
トレース詳細を表示します。
cat /sys/kernel/debug/tracing/trace_stat/function*
出力は次のようになります。
Function Hit Time Avg s^2
デバッグ トレーサー イベントを確認する
カーネルのイベント モニタリングにより、カーネルコードが変更され、VM Threat Detection の検出結果が誤検出される可能性があります。多くのデバッグツールとパフォーマンス モニタリング ツールでは、イベント モニタリングを自動的に有効にできます。
イベント モニタリングが有効になっているかどうかを確認するには、次のコマンドを実行します。
cat /sys/kernel/debug/tracing/events/enable
cat /sys/kernel/debug/tracing/events/*/enable
出力が 0
の場合、イベント モニタリングが無効になっています。出力が 1
の場合、イベント モニタリングが有効になっています。
イベント モニタリングを無効にして、VM Threat Detection が同じ検出結果を出力するかどうかを確認することを検討してください。検出結果が減った場合は、最初の検出結果の一部が誤検出だった可能性があります。
kprobe、eBPF ルール、netfilter を確認する
Netfilter、kprobe、eBPF ルールは、カスタム コールバックへの呼び出し転送をトリガーするため、コード変更をトリガーする可能性があります。VM Threat Detection は、これらのプローブの存在を検出し、それらを変更されたコードページにマッピングします。偽陽性をトリガーするプローブは考慮されません。
kprobe、eBPF ルール、netfilter を確認するには、次のコマンドを実行します。
iptable -L
cat /sys/kernel/debug/kprobes/enabled
cat /sys/kernel/debug/kprobes/list
cat /sys/kernel/debug/kprobes/blacklist
cat /sys/kernel/debug/tracing/enabled_functions
sudo apt-get update && sudo apt-get install bpftrace
bpftrace -l
sudo apt install linux-tools-`uname -r`
bpftool prog
早期デバッグ トレーサーを確認する
起動時に有効になっている早期デバッグ トレーサーが存在すると、VM Threat Detection の検出が妨げられ、誤検出が発生する可能性があります。
早期デバッグ トレーサーを確認するには、次のコマンドを実行します。
cat /proc/cmdline
使用可能なアーリーデバッグ トレーサーの一覧については、Linux カーネルのドキュメントの起動時のトレースをご覧ください。
Unexpected system call handler
の追加タスク
Defense Evasion: Unexpected system call handler
の検出結果が返された場合に、このタスクを実行します。
システム呼び出しを監査し、使用状況と呼び出し元の異常を探します。監査ログには、呼び出しプロセスとシステム呼び出しの引数に関する情報が記録されます。検証タスクを実行して、一般的なシステム呼び出しの想定される動作を確認することもできます。詳細については、このページのDiamorphine ルートキットを使用した検査の例をご覧ください。
Unexpected interrupt handler
の追加タスク
Defense Evasion: Unexpected interrupt handler
の検出結果が返された場合に、このタスクを実行します。
システム上のライブ割り込みハンドラを一覧表示し、結果をプロジェクト内の他の同様の VM の情報と比較します。予期しない割り込みハンドラは、VM が侵害されていることを示している可能性があります。
ライブ割り込みハンドラを一覧表示するには、次のコマンドを実行します。
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 あたりの実行プロセスを使用してスケジューラ キューの動作を評価し、異常な動作を探すことができます。
実行中の各プロセスが CPU ごとに費やした時間の詳細を表示します。これにより、特定の CPU が非常にビジー状態かどうかを確認できます。結果を、
/proc/interrupts
から CPU に固定された割り込みに関連付けることができます。cat /proc/schedstat
このコマンドの詳細については、Linux カーネルのドキュメントのスケジューラ統計情報をご覧ください。
現在の実行可能なタスクと、各 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 /
次のものを確認します。
- 実行中のプロセス名。
- CPU あたりのコンテキスト切り替え数。プロセスが CPU でスイッチをあまり行っていないか、またはあまり行いすぎていないかを確認します。
- 使用した CPU 時間(アイドル状態ではない時間)。
Diamorphine ルートキットを使用した検査の例
このセクションでは、Diamorphine ルートキットがインストールされている VM の検査について説明します。Diamorphine は、一般的な読み込み可能なカーネル モジュール(LKM)です。このルートキットは、次の検出結果カテゴリをトリガーします。
Defense Evasion: Unexpected system call handler
Defense Evasion: Unexpected kernel modules
Defense Evasion: Unexpected kernel read-only data modification
これらの検出結果カテゴリの詳細については、カーネルモード ルートキットの脅威の検出結果をご覧ください。
実施した検査手順と VM で確認された症状は次のとおりです。
読み込まれているすべてのツリー外カーネル モジュールを
syslog
で検索します。カーネル ログ バッファを検索します。
sudo dmesg | grep out-of-tree
出力:
diamorphine: loading out-of-tree module taints kernel.
syslog
メッセージを検索します。grep "out-of-tree" /var/log/syslog*
出力:
/var/log/syslog: diamorphine: loading out-of-tree module taints kernel.
syslog
でモジュールの検証エラーがないか検索します(一部の Linux ディストリビューションでは使用できません)。カーネル ログ バッファを検索します。
sudo dmesg | grep "module verification failed"
出力:
diamorphine: module verification failed: signature and/or required key missing - tainting kernel
syslog
メッセージを検索します。sudo grep "module verification failed" /var/log/syslog*
出力:
/var/log/syslog: diamorphine: module verification failed: signature and/or required key missing - tainting kernel
モジュールが
/proc/modules
コマンドとlsmod
コマンドから非表示になっていることを確認します。sudo grep diamorphine /proc/modules sudo lsmod | grep diamorphine
結果は表示されませんでした。
モジュールに
sysfs
にエントリがあることを確認します。sudo cat /sys/module/diamorphine/coresize
出力:
16384
アーキテクチャのシステム コール テーブルを取得します。
sudo ausyscall --dump
出力:
Using x86_64 syscall table: 0 read 1 write 2 open 3 close
通常は rootkit によって改ざんされるシステム呼び出し(
kill
やgetdents
など)の異常を監査します。システムコール ハンドラの改ざんを確認するには、システムコールを監査して異常な動作がないか確認します。これらの動作は、システム呼び出しごとに異なります。
通常ハッキングされるシステムコールは
kill
呼び出しです。kill
システム呼び出しがバイパスされたかどうかを確認できます。次の例では、kill
システム呼び出しが監査されました。auditd
をインストールし、Diamorphine ルートキットのない VM の動作を確認します。$ 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 ルートキットがインストールされていました。次の手順では、ルートキットのインストール後の VM の動作を示します。
Diamorphine ルートキットがインストールされた後、シグナルの監査ログエントリが存在しないことを確認します。
$ sudo ausearch -k audit_kill | grep -A 3 "pid=1158" $ sleep 600 & [2] 1167
シグナルの監査ログエントリの詳細を確認します。この例では、この特定のシグナルは 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 "=================================================="