コンテンツに移動

PHP Web サーバールートキットを解説

Sophos X-Ops が、高度な隠蔽技術を備えたマルウェアの構造を徹底分析

Author placeholder

SophosLabs は最近、Apache および PHP のコンポーネントを使用し、セキュリティ侵害を受けた BIG-IP Access Policy Management (APM) 環境に関連する Linux インプラントを入手しました。このマルウェアは、カスタム ELF のローディング、関数フッキング、実行時コードパッチングなどの高度な手法を駆使して検知を回避しつつ、隠し Web シェルを介して永続的なアクセスを維持します。

このインプラントが提供する機能自体は、Web シェルで一般的な「オンデマンドのサーバーサイドコード実行」です。しかし、その実装には、Linux や Apache に特化した高度な攻撃手法が用いられています。

このマルウェアは、Apache、libphp、APR モジュールの読み込み、BIG-IP APM の Webtop コンポーネント、および BIG-IP のアップグレードワークフローを備えた環境を標的としていることから、特定の環境向けに開発されたことを示唆しています。F5 は、関連する c05d5254 のアクティビティを CVE-2025-53521 の影響を受ける BIG-IP APM システムに関連付けています。CVE-2025-53521 は、仮想サーバー上にアクセスポリシーが設定されている場合に、BIG-IP APM で悪用される未認証の RCE (リモートコード実行) の脆弱性です。影響を受ける BIG-IP APM バージョンを現在使用している、あるいは過去に使用していたと思われる場合は、一般的な Apache や PHP のセキュリティ強化策を適用する前に、F5 の修復および侵害評価に関するガイダンスに従ってください。

ソフォスの分析によると、ここで取り上げるサンプルは第 2 段階のペイロードであると考えられます。関連する umount サンプルの並行分析において、/usr/sbin/httpd への感染、BIG-IP アップグレードイメージ間での永続化、SELinux 設定の変更、および本記事で分析したペイロードの展開を実行する別のインストーラー/拡散コンポーネントを確認しました。第 1 段階のローダーは、例えば /mnt/tm_install などのディレクトリ下にある BIG-IP のアップグレード/インストールイメージのワークフローを検索します。特筆すべき点として、感染した httpd で使用されている悪意のあるプレフィックスのサイズ (0x5430) は、umount サンプルに埋め込まれたペイロードのサイズと一致しており、後者が前者の展開を担っていることを強く示唆しています。

第 2 段階のサンプルは、主要な攻撃用文字列を RC4 で暗号化して隠蔽し、__libc_start_main をインターセプトすることでホストアプリケーションの main() 関数が呼び出される前に実行権限を取得します。さらに、Apache Portable Runtime (APR) モジュールローダー (apr_dso_load) をフックして Apache の PHP モジュールを標的とし、PHP Web シェルをメモリに注入します。この注入の動作は、実行時に libphp 内部の mmap の動作を操作することで行われます。これにより、感染したプロセスのみが悪意のあるコンテンツを認識し、ディスクには一切書き込みが行われません。

この Web ベースのアクセスに加えて、このインプラントはローカルの UNIX ドメインソケットを作成し、接続を /bin/bash にリダイレクトすることができます。これにより、TCP リスニングポートを開放することなく対話型のアクセスが可能になります。

現在の公開されているレポートおよびソフォスの分析から判断するに、確認された標的は、一般的な Apache/PHP や CMS 環境ではなく、BIG-IP APM の Webtop 環境に集中しています。

注: この調査の過程で、ESET の研究チームがこのマルウェアの分析を実施しており、これを「PoisonedRefresh」と命名していたことを知りました。ソフォスの分析では、同様の動作を独自に確認しており、さらなる詳細情報を提供しています。

サンプルの SHA256: 26bd5b0722d1dbab5db749a063c49bc8638653ac2addfead7a9cb3d6d57bccc9

この事例が重要である理由

「Web シェル」と言う言葉を耳にしたセキュリティ担当者の多くは、PHP、JSP、または ASP で書かれた短いサーバーサイドスクリプトを連想します。これらは Web からアクセス可能なディレクトリに配置され、通常の HTTP リクエストを通じて永続的なリモートコード実行を可能にします。このスクリプトはディスク上のファイルとして存在し、難読化されていたり正規コンテンツの中に隠されていたりするかもしれませんが、それでも発見は可能です。

この前提は、長年にわたる検知ロジックの基盤となってきました。アナリストは、Web ルートディレクトリで疑わしいスクリプトを探し、HTTP リクエスト内の不審なパラメーター名を精査し、ファイル整合性監視を利用して予期せぬ変更を検知しています。

一部の Web シェルファミリは、まさにその単純な攻撃モデルがいかに強力であるかを実証したことで悪名を馳せました。例えば、China Chopper はよく知られた Web シェルであり、MITRE では「Web サーバーを介してアクセスを提供し、HTTP POST コマンドの実行、ファイル操作、コマンドターミナルへのアクセスなどの動作をサポートする」と説明されています。

今回のサンプルは、以下の 3 つの点において従来のモデルに異を唱えています。

  • ファイルレスでの Web シェルの配信: Web シェル機能自体は存在しますが、ディスク上の静的なスクリプトファイルに依存しなくなっています。その代わりに、このインプラントは特定の PHP ファイルの読み込みをインターセプトし、mmap() の実行時にメモリ内表現の先頭に Web シェルを挿入します。
  • アプリケーションレベルにとどまらないプロセスレベルの侵害: このインプラントは、Apache ワーカープロセス内の特定の libc および libphp 関数呼び出しをリダイレクトします。そのため、そのプロセス内で実行されるすべての PHP ベースのコンポーネント (プラグイン、スキャナー、ローカルスクリプト) は、改ざんされたランタイム環境内で実行されます。
  • 二重のアクセスチャネル: 攻撃者は、HTTP ベースの PHP ペイロードと、リスニング TCP ポートなしで対話型シェルを提供するローカル UNIX ソケットバックドアの両方を使用できます。

その結果、攻撃者にとっては Web シェルのように機能するアクセス手法が実現しますが、ファイル中心の検知や PHP のみを対象とした検知だけでは、その検知が著しく困難になります。侵害されたホスト上では、改ざんされた libphp ランタイム環境を介して実行されるあらゆる操作が、標的となった PHP ファイルについて、ディスク上に実際に存在する内容とは異なる状態を認識してしまう可能性があります。その場合、従来のファイル検査ツールの前提が覆されることになります。

このマルウェアを特定の攻撃者に結び付けるだけの十分な証拠はありませんが、標的の選定や実装方法から、高度な能力がうかがえます。

Web シェルの概要

概念レベルでは、このサンプルは以下の 3 つのアイデアを組み合わせています。

  1. プロセスライフサイクルの初期段階で実行: このインプラントは、__libc_start_main を介して libc の起動シーケンスをインターセプトすることで、ホストアプリケーションの通常のロジックより前に実行されます。
  2. PHP が存在する場合のみ動作: apr_dso_load をはじめとする Apache Portable Runtime (APR) 関数をフックすることで、このインプラントは Apache が PHP モジュール (libphp) を読み込むまで待機してからプロセスの動作を変更します。
  3. 複数のアクセス経路を提供: libphp 内での mmap() のインターセプトを介して特定の PHP ファイルのメモリ内表現に PHP Web シェルが注入されます。また、ローカルの UNIX ドメインソケットは認証後に入力、出力、およびエラー出力を /bin/bash にリダイレクトし、ネットワークリスナーを公開することなく対話型のシェルアクセスを可能にします。

これらの手法は単体で見れば比較的単純なものですが、これらを組み合わせて、Apache/PHP の導入環境を標的とした一貫性と安定性のあるアクセスの仕組みを構築している点から、高度な手法であることがうかがえます。

ソフォスによる分析

バイナリはストリップ処理され、静的リンクされていたため、インポート分析や単純な文字列検索といった従来のトリアージ手法の有効性は、最初から限定的でした。また、このサンプルは通常の動的リンカーの起動パスを迂回し、独自のローダーロジックと起動フックを持ち込んでいます。

ソフォスは、インポートの分析から始めるのではなく、以下の点に着目しました。

  • 制御フローのピボット (特にプロセスの起動時におけるもの)
  • 実行時の文字列の復号ルーチン
  • シンボルの解決およびフック設置のロジック
  • /proc を介した Linux プロセスのイントロスペクションの使用
  • 暗号化されたデータや不透明なデータが平文となり実行可能になる転換点

Linux マルウェアがこれまでのディスク上の単純なインプラントから、カスタムローダー、実行時コード生成、メモリ内実行、およびプロセス操作へと移行し続ける中で、このスタイルの分析はますます重要性を増しています。

これらの手法では、防御側が観測できるシグナルは依然として生成されますが、多くの場合、明らかなファイルシステム上の痕跡は、より多くのコンテキストや詳細な検査がなければ特定することができない一連の動作へと置き換えられてしまいます。

このサンプルはその分かりやすい例で、従来の Web シェルを通常の方法で配置するのではなく、特定の PHP ファイルが実行中プロセスにどのように提示されるかを実行時に改変しています。攻撃者が悪用可能なこの機能自体は従来の Web シェルと似ていますが、その実装によって防御側が通常依存している痕跡の多くが排除されます。これは、ファイルシステム、メモリ、プロセス、および動作の可視化を組み合わせた多層防御の重要性を浮き彫りにしています。

RC4 文字列: 手がかりを追う

このサンプルを理解する上での最初のハードルの一つは、実行時に文字列復号が多用されているでした。最も重要な文字列の多くは .rodata セクションに暗号化された状態で格納されており、コンパクトな RC4 ルーチンを使用して必要な場合にのみ復号されます。

このマルウェアは、ハードコードされた以下の 16 バイトのキーを用いた RC4 ストリーム暗号を使用します。TrswBWIl90Z5e38n

これにより、動作に関連する主要な文字列が単純な静的解析では見えなくなり、従来の文字列抽出だけではサンプルの機能を理解することがより困難になります。ソフォスは分析の過程で、関数名、ライブラリ名、標的ファイル名など、数多くの異なる暗号化文字列を特定し、復号しました。

これらの文字列が実行時に復号されると、インプラントの真の対象範囲と意図が明らかになります。

  • プロセスの自己検査に使用される /proc/self/exe および /proc/self/maps
  • libc の起動ルーチンである __libc_start_main
  • Apache 内の APR 関数である apr_dso_load および apr_time_now
  • Apache プロセス内で標的とされる PHP モジュールである libphp
  • open、close、mmap などのファイルおよびメモリ API
  • pthread_create や pthread_detach などのスレッド処理の基本機能

個々の文字列だけを見れば特に注目すべき点はありませんが、これらを総合すると、このサンプルが Linux プロセスの内部構造、Apache の実行環境、および PHP の実行モデルを理解していることがうかがえます。

防御のヒント: このサンプルでは、RC4 は主に難読化メカニズムとして機能しているようです。つまり、動作に関連する文字列を単純な静的抽出から隠し、分析を実行時まで遅らせる役割を果たしています。ここで留意すべきは、他のサンプルと同様に、一見無害に見える文字列の出力が、必ずしもバイナリが無害であることを意味するわけではないという点です。Linux サーバーの調査においては、実行時の文字列復号、動的な API 解決、および設定データの段階的な開示が、より高度な機能を持つ Linux マルウェアファミリで一般的になりつつあります。

実行のための「main」の呼び出し

Linux では、ほとんどのプログラムは main を直接呼び出しません。実行フローは libc の初期化コードを経由し、これがプロセス環境を準備した上で main を呼び出します。このシーケンスの重要な構成要素が __libc_start_main であり、これが初期化を実行し、プログラムのエントリポイントを呼び出します。

通常の Linux ELF バイナリは、確立された経路をたどります。つまり、カーネルがバイナリを読み込み、動的リンカー (ld.so) が依存関係を解決した後、libc の起動コードが環境を準備して main を呼び出します。多くのセキュリティツールや可観測性ツールは、このシーケンスに便乗して、プロセスの起動状況を可視化しています。

今回のサンプルは、2 つの点においてこの流れから逸脱しています。第一に、本来のエントリポイントにおいて、通常のように __libc_start_main を呼び出すのではなく、カスタムローダールーチンへと直接ジャンプします。このローダーは、単に追加のコードを実行するのではなく、/proc/self/exe を介して自身のイメージを再度開き、保存されている元の実行ファイルが始まるオフセットまでシークし、埋め込まれたその ELF を手動でメモリにロードします。

A screenshot of a typical _start routine in a disassembler

図 1: ストリップ処理された、静的リンク済みの 32 ビット ELF における典型的な _start ルーチン。シンボルがなくても、エントリポイントにはスタックの調整、起動引数の設定、libc の起動ルーチンへの呼び出しといった、一般的な C ランタイムの起動動作が存在します。このため、感染した httpd のエントリポイントに目が留まりました。なぜなら、このパターンに従う代わりに、本来のスタックを直接カスタムローダーに渡しており、そのルーチンが復帰した場合は実行を停止していたからです。

A screenshot of a custom loader routine in a disassembler

図 2: プログラムのエントリポイント (_start) は、実行権限をカスタムローダールーチンに直接引き渡します。従来の Linux 実行ファイルでは、_start は通常 __libc_start_main へと進み、最終的に main() を呼び出します。この馴染みのある起動シーケンスが欠如しているという点が、分析中に目を引き、このインプラントのカスタム ELF ローディングおよび起動フックのロジックの発見につながりました。

その後、ローダーは埋め込まれた ELF を解析し、その PT_LOAD セグメントを巡回して新しいメモリ領域をマッピングし、セグメントの内容を適切な場所にコピーし、適切なメモリ保護を適用し、必要に応じて元のインタプリタを処理し、独自の __libc_start_main ラッパーを介して実行をリダイレクトします。

A routine in the malicious sample, shown in a disassembler screenshot図 3: このインプラントは __libc_start_main を復号して解決し、元の libc 起動ルーチンを保持した上で、ラッパー (フックされた __libc_start_main) で上書きします。これにより、プログラムの実際の main より前にインプラントのコードが実行されます。

この「独自ローダーを持ち込む」という手法は、攻撃者に次のようなメリットをもたらします。

  • 従来の動的リンカーの起動パスを回避できるため、そのシーケンスを監視ポイントとしているコントロールからの視認性を低減できる可能性があります。
  • 攻撃者は、libc の起動をいつ、どのようにインターセプトするかを、高い精度で制御できるようになります。
  • インプラントの残りの部分への明確なピボットポイントが提供されます。

防御側の視点で見ると、これは、より高度な Linux 脅威に対しては、もはや通常のローダーパスをインターセプトのポイントとして用いるだけでは不十分であることを改めて示唆するものです。

このサンプルは、明示的に __libc_start_main を標的とし、ラッパー関数に置き換えています。概念的には、フローは以下のように変化します。

_start -> __libc_start_main(main, ...) -> main()

to:

_start -> custom loader -> real __libc_start_main(wrapper, ...) -> wrapper() -> real main()
wrapper() runs implant initialization
wrapper() then calls the real main

これにより、ホストアプリケーションが実質的な処理を行う前に、インプラントは早期かつ確実に実行できる時間を確保できます。また、アプリケーションの残りの部分がどのように動作するかにかかわらず、安定したピボットポイントが提供されるため、マルウェアは一度初期化を行うだけで、その後は正規のプロセスに紛れ込むことができます。

このように起動ロジックをインターセプトすることで、攻撃者には以下のメリットももたらされます。

  • 安定した単一の実行ポイント
  • アプリケーションのスレッドが開始される前に API を解決し、フックを設置する能力
  • 後続の悪意のある動作を、そのプロセス本来の動作のように見せる手法

フォレンジックの観点から見ると、これによって痕跡がプロセスタイムラインのより早い段階 (多くの場合、ログのフレームワークが完全初期化される前) に現れるようになります。

防御のヒント: プロセスのライフサイクルの非常に早い段階における異常な動作 (/proc へのアクセスやメモリ権限の変更など) は、その後のアクティビティよりも有用な情報となる場合があります。

APR を介した Apache への攻撃

早期の実行権限を獲得した後、このインプラントはプロセス内のすべてを直ちに操作しようとはしません。その代わりに、特定の条件、すなわち Apache が PHP モジュール (libphp) をロードするのを待ちます。

APR は動的モジュールローディングのための API を提供しており、その中には実行時に共有オブジェクトを読み込む apr_dso_load も含まれます。この関数をフックすることにより、インプラントはロードする順序を推測したりハードコーディングしたりすることなく、モジュール初期化を監視できるポイントを得ることができます。マルウェアは、すべての Apache プロセスを無差別に書き換えるのではなく、標的とする環境が整うまで待機してから活動を開始することができます。

今回のサンプルは apr_dso_load をフックし、ロードされるモジュールのパスを検査します。マルウェアは libphp を検知すると、そのモジュール内の動作を変更します。

A hook in the implant, shown in a screenshot of a disassembler

図 4: このインプラントは APR の apr_dso_load をフックし、その動作を明示的に PHP モジュールに限定します。libphpがロードされていない場合は、直ちに終了します。

同時に、このサンプルは APR の「現在時刻」関数である apr_time_now をフックします。この API は一見すると無害ですが、稼働中の Apache プロセスでは頻繁に呼び出されます。

ソフォスの分析によると、このインプラントは、頻繁に呼び出されるこの API を、ローカルの UNIX ソケットバックドアを担当するワーカーの起動など、後続アクションを遅延させて実行するトリガーとして利用しています。

このアプローチは、以下の点から、運用面での成熟度の高さを示しています。

  • インプラントが自身の対象範囲を、設計で定められた環境のみに限定している
  • 早期すぎる、あるいは広範すぎる動作によってサービスを不安定化させることを避けている
  • 標的プラットフォームの実行時の抽象化機能に抗うのではなく、その機能を活用している

このように選択的に起動するのは、インプラント全体を通じて繰り返される特徴です。このマルウェアは、プロセスの開始直後に変更を加えるのではなく、特定のランタイム条件が満たされるのを繰り返し待ち、その後で追加機能を有効にしています。

防御のヒント: Apache プロセスにおいて、libphp がロードされた直後に発生するメモリ保護の変更や、実行ページの改ざんを調査してください。

メモリ内の libphp の位置特定

PHP が読み込まれると、インプラントはそれがプロセスメモリのどこに位置しているかを知る必要があります。Linux では、この情報は /proc/self/maps 通じて公開されており、ここにはすべてのメモリマッピングと、そのアドレス範囲および対応するファイルが一覧表示されています。

インプラントはこのファイルを解析し、libphp マッピングの開始アドレスと終了アドレスを特定します。その後、特定したアドレスを使用して、標的モジュールに対するその後の改変を制限します。インプラントはメモリをやみくもに書き換えるのではなく、実行可能な libphp マッピングを特定し、変更をその領域内に限定します。これは、以下の手順を実行することで達成されます。

/proc/self/maps の読み取り -> libphp の特定 -> RWX の mprotect -> リロケーションのパッチング -> RX の mprotect

/proc/self/maps の読み取り自体は本質的に悪意のあるものではありません。デバッガー、プロファイラー、メモリ管理ツールなどは、正規の目的でプロセスマッピングを検査することがあります。しかし、その直後にメモリ権限の変更、リロケーションのパッチング、標的となった共有ライブラリの実行可能領域への書き込みが続く場合、その動作は極めて疑わしいものになります。

この一連の動作は、Apache のワーカープロセスにおいて特に異例です。なぜなら、ワーカープロセスが自身のメモリマッピングを検査し、その直後に実行可能ページを変更する理由はほとんどないからです。

防御のヒント: /proc/self/maps へのアクセスに続いて、mprotect() の実行、リロケーションのパッチング、または実行可能メモリ領域への書き込みが行われる場合は、(特に Apache ワーカープロセスにおいては) 調査の対象とすべきです。

libphp 内部での実行権限のリダイレクト

多くの防御担当者は、LD_PRELOAD を介したマルウェアのフックや、PLT/GOT エントリの改ざんについてご存知かと思います。今回のサンプルはより緻密な手法をとっており、リロケーションベースのフックと libphp 内部の呼び出し先への直接的な書き換えを組み合わせています。これにより、特定の操作がまずインプラントの制御下にあるコードへと迂回されるようになります。

これらの変更を適用する前に、インプラントは標的となった libphp のマッピングに対するメモリ保護を一時的に変更し、選択したリロケーションおよび呼び出し先をパッチングした後、元の保護状態に戻します。

実装の観点から見ると、このサンプルは libphp に関連付けられたリロケーションデータを巡回し、ごく少数の関数について PC 相対の呼び出し先を調整します。防御担当者の観点からは、正確なリロケーションメカニズムよりも、その結果の方が重要です。

PHP モジュールのコンテキストにおいて、このサンプルは通常であれば open、close、mmap、__fxstat といったファイルおよびメモリ API を呼び出す処理を密かにリダイレクトします。その結果、PHP が標的スクリプトファイルをどのように開き、サイズを測定し、マッピングし、最終的に実行するかを制御できるようになります。これらのフックは、次に説明するメモリ内の Web シェル配信メカニズムの基盤となっています。これによって攻撃者には、「通常のローダーパスに新しい共有ライブラリを注入する必要がない」という別のメリットをもたらします。

メモリマッピングによる Web シェルの配信

ソフォスの見解では、これがこのサンプルの最も特徴的な点でした。このインプラントは、PHP が以下の 3 つのスクリプトファイルを開こうとする試みをインターセプトします。

  • apm_css.php3
  • full_wt.php3
  • webtop_popup_css.php3

これらのファイル名は、標的となった BIG-IP APM Webtop 環境内に存在していたことから選ばれた可能性が高く、そのため不審に思われにくいと考えられます。

PHP がこのうちのいずれかのファイルを開くと、インプラントはファイル記述子を記録します。その後、そのファイルがメモリマッピングされる際、インプラントは、埋め込まれた Web シェルと元のスクリプトコンテンツの両方を含む、改ざんされたメモリ内のビューを作成します。

ディスク上のファイルには、最終的な Web シェルのコンテンツが含まれている必要は一切ありません。実行は、実行時にインプラントによって作成された、メモリ内の変更済み表現に基づいて行われます。

The mmap() hook in the implant, shown in a screenshot of a disassembler

図 5: mmap() フックは、マッピングが追跡対象の PHP スクリプトのファイル記述子に属しているかどうかを確認します。属している場合、元の mmap() を呼び出し、埋め込まれた PHP Web シェルをメモリ内のマッピングされたコンテンツの先頭に追加します。これにより、ディスク上のファイルは変更されなくなります。

埋め込まれた PHP ペイロードは、従来の Web シェルのように動作しますが、次のような顕著な特徴があります。

  • php://input から未加工のリクエストバイトを読み取る
  • リクエスト本体の先頭にある短いマジックプレフィックス (BSOHAzPB) をチェックする
  • 小型ストリーム暗号を使用して、残りの部分を復号する
  • eval を介して復号されたコンテンツを実行する
  • HTTP status 201 を返し、Content-Type: text/css; charset=utf-8 を設定して、通常のアセットリクエストに紛れ込む

このペイロードはテンプレート化されており、主要な文字列は実行時に書き換えられるため、静的シグネチャマッチングがさらに困難になります。ソフォスのサンプルでは、リクエストマーカー (BSOHAzPB) と Web シェルキー (wSLjN1beuR) は、最終的な形で直接格納されるのではなく、実行時に PHP に埋め込まれていました。

防御のヒント: Web シェルの検知メカニズムには、ファイルスキャンだけでなく、実行時の動作やメモリ検査を含める必要があります。この種の脅威では、ディスク上の PHP ファイルが無害に見えたとしても、メモリ内のマッピングに悪意のあるコードが含まれている可能性が十分にあります。

apr_time_now を利用した起動の遅延

このインプラントは、初期起動時にスレッドや重いルーチンを生成するのではなく、apr_time_now に対するフックを遅延トリガーとして利用します。

Apache プロセスが通常の time 関数呼び出しを開始すると、インプラントはローカル UNIX ソケットバックドアの生成を担当するワーカースレッドを生成して切り離します。このタイミングにより、サービスを不安定化させるリスクが最小限に抑えられ、また、インプラントは通常の実行時動作に紛れ込みやすくなります。また、プロセス開始直後の短時間にしか確認できない動的解析環境にとって解析を難しくさせる効果もあります。

HTTP ベースの Web シェルに加えて、このインプラントは従来の TCP リスナーを公開するのではなく、/run/bigtlog.pipe にローカルの AF_UNIX ソケットを確立します。

32 ビット Linux では、ソケット操作は一般的に、昔からある socketcall システムコールを介して多重化されており、このシステムコールは socket、bind、listen、accept などの操作を処理します。このインプラントは、x86-32 環境に合わせてこのインターフェースを使用しています。

トークン Kzwd6jM5 に基づく簡単な認証チェックの後、このインプラントは標準の入力、出力、エラー出力をソケットにリダイレクトし、/bin/bash を実行します。これにより、TCP リスニングポートを開くことなく対話型シェルへのアクセスが可能になり、ネットワークベースの監視だけでの検知が困難になります。認証成功後もリスナーはアクティブな状態を維持し、fork() を使用して別のシェルプロセスを作成しながら、追加の接続を受け入れ続けます。

興味深いことに、攻撃者がこのソケットに接続することを可能にする組み込みのメカニズムは確認できませんでした。クライアント側のソケットコードは存在せず、認証トークンへの追加の参照もなかったことから、2 つの方法 (Web シェルとソケット) は独立した機能であると考えられます。攻撃者が Web シェルを介してソケットとやり取りできる可能性はありますが、現時点ではそれを裏付ける証拠も否定する証拠もありません。

Screenshot of a disassembler, showing the implant handing a local socket connection to /bin/bash

図 6: インプラントは、標準ストリームをリダイレクトしてシェルバイナリを実行することにより、ローカルソケット接続を /bin/bash に直接引き渡します。

防御のヒント: サーバーサイドの侵害においては、ローカル IPC エンドポイント (特に /bin/bash 配下にあるもの) を精査する必要があります。

保護機能と防御機能

ソフォスはこの脅威を Linux/Agnt-IC として検知します。

脅威ハンティング

以下の動作は、単独で確定の材料として使用するのではなく、調査の手がかりとして扱い、ファイルの整合性、プロセス、メモリ、および BIG-IP 特有の証拠と照合する必要があります。

Web レイヤーのシグナル

以下の点を確認してください。

  • 上記の..php3 エンドポイントへのリクエスト (特にお使いの環境ではめったに見られない場合)。
  • CSS であると主張しながら (Content-Type: text/css; charset=utf-8)、HTTP 201 を返す PHP エンドポイント。
  • 一貫した構造または不審なボディサイズを持つ、CSS に似た PHP パスに対して繰り返される POST リクエスト。

ホストレベルのシグナル

以下の点を確認してください。

  • /proc/self/maps を読み取る Apache ワーカープロセス。
  • libphp 周辺の PHP モジュールマッピングに対するメモリ権限の一時的な変更 (RWX から RX への変更)。
  • /run/bigtlog.pipe における UNIX ドメインソケットの作成。
  • Stdio をリダイレクトし /bin/bash を実行する Apache 系統のプロセス。

防御担当者向けガイダンス

インシデント対応ガイダンス

このインプラントが疑われる場合:

  1. 揮発性証拠を最初に収集する。
  2. 二重アクセスを想定する。
  3. サービス再起動だけでは保証にならない。

強化と検知

環境はそれぞれ異なっていても、以下の幅広い対策を導入することで、リスクの低減や可視性の向上が図れます。

攻撃対象領域の縮小

  • お使いの環境内で .php3 の実行が必要でない場合は、変更管理とアプリケーションへの影響評価を行った上で無効化を検討してください。F5 のガイダンスに従わずに、この方法を BIG-IP APM システムに対する包括的な緩和策として適用しないでください。
  • 可能な限り、長期間存続している PHP 実行パスを最小限に抑える設定を優先してください。
  • ptrace を制限してください (これにより、プロセス間検査や注入の機会をある程度減らすことができますが、プロセス内のローダーやパッチングに対する緩和策になるとは限りません)。
echo 1 > /proc/sys/kernel/yama/ptrace_scope
  • Apache の設定に以下を追加してください。
<FilesMatch "\.php3$">
    Require all denied
</FilesMatch>
  • 不必要な PHP 実行機能を最小限に抑え、必要に応じて危険な関数を制限することによる運用上の影響を検証してください。

動作監視

  • 以下のような Apache ワーカーの異常なアクティビティの組み合わせに対してアラートを設定してください。
    • proc/self/maps の読み取り
    • libphp のメモリ保護の変更
    • run 配下での UNIX ソケットのバインド
    • /bin/bash の生成
  • PHP エンドポイントからの HTTP 201 + text/css レスポンスが通常のアプリケーション動作の一部でない場合、不審なものとして扱います。
  • メモリを意識した対応策の策定:
    • 重要な Web サーバーのインシデント対応プレイブックに、プロセスメモリの収集、およびディスク上とメモリ内のモジュールコンテンツの比較を組み込んでください。

結論

このインプラントは、最新の Linux マルウェアが、高度な配信メカニズムを通じて攻撃者にとって見慣れた機能を提供できることを示しています。埋め込まれた PHP は最終的には従来の Web シェルと同様に動作しますが、それを取り巻くインフラストラクチャは、カスタム ELF ロード、起動初期段階でのインターセプト、APR 対応モジュールの監視、リロケーションパッチング、メモリ限定のペイロード配信など、はるかに高度なものとなっています。

関連する umount および感染した httpd サンプルの分析に基づき、ソフォスはこのキャンペーンでは段階的なアーキテクチャが採用されていると判断しています。インストーラーコンポーネントが展開、永続化、および拡散を担う一方で、感染した httpd コンポーネントは実行時機能、プロセス操作、Web シェル配信、および対話型アクセスに重点を置いています。

おそらく最も重要な発見は、Web シェルがディスク上に最終的な形で存在する必要がないという点です。代わりに、インプラントは標的となった PHP ファイルが実行中のプロセスにどのように提示されるかを改変します。これは、Apache や PHP によって認識されるコンテンツが、従来のファイルベースの検査で可視化されるコンテンツと異なる可能性があることを意味します。結果として、ファイルシステムにのみ注目していると、対応担当者は重要な証拠を見落としてしまう可能性があります。

今回のサンプルは、ディスク上の明らかな痕跡よりも、実行時の操作に依存する、より広範な Linux 脅威の一例です。このような場合、防御担当者はレイヤー間の相関関係に焦点を当てる必要があります。ファイルシステムの検査だけでは侵害を明らかにできない可能性があります。しかし、ネットワークテレメトリ、プロトコル検査、プロセス監視、メモリ分析、および整合性検証のそれぞれによって、攻撃チェーンのさまざまな部分を明らかにすることができます。