「これ、なんですか」——レンタルサーバーからの一斉警告メールで発覚した。
数ヶ月前に運用保守を引き継いだばかりの、複数拠点を持つ士業事務所のコーポレートサイト。 契約中のレンタルサーバー事業者から「不審なファイルを検知しました」という一斉スキャン警告メールが届き、担当者様からご相談をいただいた。 調査に入ると、サイト全体に拡張子を持たない実行可能ファイルが 大量に散布されていることが判明。とは異なる手口の、実行バイナリ型の侵害だった。
運用保守を引き継いだばかりのサイトについて、契約中のレンタルサーバー事業者から届いた 一斉マルウェア警告メールをきっかけにご相談をいただきました。 調査の先で見えてきたのは、数の多さそのものより、駆除作業の「やり方」に潜む見落としでした。
※ 守秘義務契約のため、サイト名・業種・URL は非公開とさせていただいています。
※ 本ケースは特定事例の実績です。所要時間・被害範囲はサイト規模・侵害深度・サーバ環境により大きく変動します。守秘義務契約のためサイト名・業種・URLは非公開とさせていただいています。
これは、運用保守を引き継いだばかりのサイトで、サーバー事業者からの一斉警告をきっかけに調査に入った記録です。 駆除そのものより、駆除の「やり方」に潜む見落としにこそ、注意が必要でした。

300個以上を消して終わりでは、
まだ足りなかった。
数ヶ月前に運用保守を引き継いだばかりの、複数拠点を持つ士業事務所のコーポレートサイト。 契約中のレンタルサーバー事業者から「不審なファイルを検知しました」という一斉スキャン警告メールが届き、担当者様からご相談をいただいた。 調査に入ると、サイト全体に拡張子を持たない実行可能ファイルが 大量に散布されていることが判明。とは異なる手口の、実行バイナリ型の侵害だった。
300個以上のファイルは、レンタルサーバー事業者側のマルウェアスキャン機構が検知と同時に 自身への読み書き権限すら持たない「権限000」へ自動的に無害化していた状態で、正規のCSS・JSファイルと同じ場所に紛れていた。 検体を確認すると静的リンク済みの実行可能ELFバイナリで、 ファイル名は既存ディレクトリ名から一文字も外れない偽装が施されていた。 さらに、既存プラグイン・テーマの正規PHPファイル4本にも難読化された条件分岐コードが注入されており、 うち1本はオリジナルのコードが跡形もなく置き換わっていた。
全ての不正ファイルを証拠保全のうえ隔離・完全削除し、コア・全プラグイン・全テーマを公式配布元から総入れ替えする方針を選択。 ここで気づいたのが、配布パッケージに含まれないファイルの扱いという盲点だった。 差分同期の除外リストの設計次第では、駆除作業そのものが既存の防御設定を巻き添えにしてしまう。 作業中にこの挙動に気づき、直前のバックアップ設定を基にその場で復元。サイト全体の主要動線を一つずつ手動確認してから作業を完了させた。
駆除完了後、外部セキュリティスキャナーによる第三者診断を実施。 管理者アカウント名がURLパラメータ経由で特定できてしまう設定や、APIエンドポイント経由でユーザー一覧が 誰でも取得できる状態など、侵害とは別系統の設定不備7件が見つかり、 フォーム送信などの正常機能を壊さない範囲ですべて是正。最後にサイト全体を既知の攻撃パターンで再スキャンし、 新たな混入がないことを確認したうえで、ファイル整合性監視の基準値を駆除後のクリーンな状態で再構築した。
「総入れ替えで駆除した」という対応自体は正しくても、その手順の中に防御設定を巻き添えにする分岐点が 潜んでいることがあります。駆除の直後に主要な動線を一つずつ手動で確認する工程を省かないことが、 結果的に復旧の質を左右します。
— 本ケースからの教訓(WATRIX による分析)
このケースで実際に検出された3つのアーティファクトです。 いずれも「駆除しただけ」では見落としたままになっていた可能性があるものでした。

パーミッション000は、レンタルサーバー事業者の検知機構による自動無害化の痕跡。実行や書き込みはできない状態になっていたが、それはあくまで「無力化」であって「除去」ではない。ファイルが残っている限り、権限が復元されれば再び動き出すリスクは消えない。
$ ls -la wp-admin/css/colors/ocean/
-rw-r--r-- colors.css
-rw-r--r-- colors.min.css
---------- dutch_mimes ← パーミッション 000
$ file dutch_mimes
dutch_mimes: ELF 64-bit LSB executable, x86-64,
statically linked, stripped
# サーバー事業者側のマルウェアスキャン機構が
# 検知と同時に自動で実行権限を剥奪した痕跡
# → 実害の拡大は止まっていたが、
# 除去されずファイル自体はまだ残っていた他の3本は「正規コードの先頭に悪性コードを継ぎ足す」手口だったが、この1本だけはオリジナルが跡形もなく上書きされていた。同じキャンペーン内でも手口の粒度が一様ではない。
<?php if(isset($_POST)&&isset($_POST["ho\154der"])):
$_0=$_POST["\x68o\154d\145r"];$_0=eXPloDE(".",$_0);
$_1="";$_2="abcdef\x67hi\152klmn\x6fpqrstuvw...";
// ファイル全体がこの1行のみ
// 本来あるはずの正規コードは一切残っていない
$ wc -l hooks/hook-*.php
0 hooks/hook-*.php ← 改行なしの1行に収まっている差分同期による総入れ替えは「余分なファイルを残さない」という意味では正しい手法。ただし除外リストの設計を誤ると、既存の防御設定ごと消してしまう。駆除の直後に主要ページへ実際にアクセスして確認する工程は省略できない。
$ rsync -av --delete \
--exclude="wp-content" \
--exclude="wp-config.php" \
/path/to/official-package/ ./
# 公式配布パッケージには同梱されない設定ファイルが、
# 除外リストに入っていなかったため
# --delete の対象に巻き込まれて消失
# → 直前に導入していた防御設定がまとめて無効化「消しました」だけでは、再発しない保証にはなりません。
18体の AI エージェントが、駆除作業そのものが生む副作用まで含めて機械的にダブルチェックする—— これが WP-AIレスキューのアプローチです。