サイレントバックドアの悪夢
侵害されたサーバーを目の前にして目を覚ますのは、非常にストレスの高い経験だ。数年前、深夜3時にブルートフォース攻撃で最初の本番サーバーがやられた後、私はSSHの堅牢化に執念を燃やすようになった。しかし、最も明白な侵入口を見落としがちだ:Webアプリケーション自体だ。パッチ未適用のプラグイン1つや、脆弱なファイルアップロードフォームがあれば、攻撃者はわずか数秒でWebシェルを設置できてしまう。
Webシェルとは、PHP、Python、JSPといった言語で書かれた悪意のあるスクリプトだ。リモート管理インターフェースを提供し、攻撃者がコマンドを実行してネットワーク内を横断移動できるようにする。このトラフィックは標準的なHTTP/HTTPSポートを経由するため、基本的なファイアウォールのほとんどを回避してしまう。本ガイドでは、これらのスクリプトの追跡方法、動作の分析、そして感染の適切な除去について解説する。
Webシェルが検出しにくい理由
Webシェルはアプリケーション層の中に堂々と潜んでいる。新しいポートを開いたり、リスナーを起動したりする必要がない。サーバーが.phpファイルを実行できるなら、シェルを動かせる。攻撃者は発見を避けるためにいくつかのトリックを使う:
- 難読化:
base64_encodeやstr_rot13を使って「system」や「exec」といった文字列を隠蔽する。 - タイムストンピング:
touchコマンドを使って、シェルの更新日時を2018年の正規ファイルと一致させる。 - 偽装:
wp-includes.phpやthumb_823.phpという名前のシェルが、5,000枚もの画像が入ったアップロードフォルダに紛れ込んでいることがある。
インストール:ツールキットの準備
手動検査は不可欠だが、自動スキャナーは分かりやすい脅威を素早く発見してくれる。ここでは、Maldetとも呼ばれるLinux Malware Detect(LMD)をネイティブCLIツールとあわせて使用する。
Linux Malware Detect(LMD)のインストール
LMDは共有ホスティングやWeb環境で見つかるシェルの種類に特化してチューニングされている。標準的なUbuntuまたはDebianシステムへのセットアップ手順は以下の通りだ:
cd /tmp
wget http://www.rfxn.com/downloads/maldetect-current.tar.gz
tar -xvf maldetect-current.tar.gz
cd maldetect-*
sudo ./install.sh
インストールが完了したら、すぐに最新のシグネチャを取得しよう。新しいシェルの亜種は毎日出現しており、古いシグネチャでは役に立たない。
sudo maldet -u
ネイティブLinuxユーティリティ
高度なソフトウェアが常に必要なわけではない。私は調査の90%をgrep、find、awkに頼っている。正確なファイルメタデータで異常を発見するため、coreutilsが最新であることを確認しておこう。
設定:ハントの準備
シェルを見つけるには、悪意のあるコードの「においを嗅ぎ取る」必要がある。パターンマッチングと時系列分析を組み合わせて調査する。
1. 悪意のあるパターンの検索
ほとんどのシェルは、悪事を行うために特定のPHP関数に依存している。Webルート(通常は/var/www/html)に対して再帰的な検索を実行し、これらの関数にフラグを立てよう。このコマンドはPerlの正規表現を使って一般的な実行用の文字列を探す:
grep -RPn "(passthru|shell_exec|system|base64_decode|eval|assert|fopen|gzuncompress)" /var/www/html/
ノイズが多く出ることは覚悟しておこう。LaravelやWordPressのようなモダンなフレームワークも、正当な目的でbase64やfopenを使用する。WordPressサイトの堅牢化を事前に施しておけば、こうした誤検知の量を大幅に減らすことができる。注意すべきは、これらの関数が長い1行の意味不明なテキストに含まれているファイルだ。
2. 最近更新されたファイルの検索
今朝から不審な動作が始まった場合は、過去24時間以内に更新されたファイルを確認しよう。攻撃者は触れたすべてのファイルのタイムスタンプを書き換えることをしばしば忘れる。
find /var/www/html -type f -mtime -1 -ls
/wp-content/uploads/ディレクトリ内に.phpファイルを見つけた場合、ほぼ確実に悪意のあるものだ。正規のアップロードフォルダにはメディアのみが含まれるべきであり、実行可能なコードは含まれない。
3. Maldetの自動化
/usr/local/maldetect/conf.maldetを編集して防御を自動化しよう。セキュリティとシステムパフォーマンスのバランスを取るため、以下の設定を推奨する:
# アラートを受信するには1に設定
email_alert="1"
email_addr="[email protected]"
# 検出されたファイルを自動的に検疫に移動
quarantine_hits="1"
# ファイルへのマルウェア注入の除去を試みる
quarantine_clean="1"
検証とモニタリング:侵害の分析
不審なファイルを見つけることは戦いの半分に過ぎない。攻撃者が侵入中に何をしたかを把握する必要がある。
ステップ1:隔離
まだファイルを削除してはいけない。フォレンジック調査で必要になるかもしれない。代わりに、安全な場所に移動して実行権限を剥奪しよう。
mkdir /root/quarantine
mv /var/www/html/path/to/suspect.php /root/quarantine/
chmod 000 /root/quarantine/suspect.php
ステップ2:シェルのデコード
vimまたはnanoでファイルを開こう。eval(base64_decode('...'))が見えたら、攻撃者がコードを隠蔽している証拠だ。PHPのコマンドラインを使って安全にデコードし、実際のロジックを確認できる:
# できればサンドボックス環境で実行すること
php -r "echo base64_decode('ENCODED_STRING_HERE');" > decoded_output.txt
ステップ3:アクティブな接続の確認
Webシェルはしばしばコマンド&コントロール(C2)サーバーに接続する。ssを使って、Webサーバーのプロセスが不審なIPアドレスと通信していないか確認しよう:
ss -antp | grep -E "(httpd|apache|nginx|php-fpm)"
ポート4444または8080への不明なIPへのアウトバウンド接続は、重大な警告サインだ。通常、リバースシェルが現在アクティブであることを示している。
ステップ4:ログの相関分析
シェルが作成された正確な時刻を特定しよう。その後、その時刻のaccess.logからPOSTリクエストを検索する。侵入口を探しているのだ:
grep "shell.php" /var/log/apache2/access.log
典型的なログエントリはこのようになっているはずだ:1.2.3.4 - - [10/Oct/2023:14:00:01] "POST /plugin/upload.php HTTP/1.1" 200。これにより、どのプラグインが脆弱かが正確に分かる。そのプラグインにパッチを当てなければ、攻撃者は数分以内に戻ってくる。
ステップ5:Auditdによるリアルタイム監視
将来の攻撃を防ぐには、Auditdを使ってWebディレクトリを監視しよう。これにより、すべてのファイル変更がリアルタイムでログに記録される。
sudo auditctl -w /var/www/html -p wa -k web_modification
ファイルが書き込まれたり変更されたりするたびに、/var/log/audit/audit.logに記録される。これにより、将来のインシデントに対して否定できない証拠の痕跡が残る。
まとめチェックリスト
maldetをcronで毎日実行するよう設定する。- Webルートの危険なPHP関数を毎週監査する。
.htaccessまたはNginxの設定でアップロードディレクトリの実行を無効化する。- ファイルのタイムスタンプとWebサーバーのログを相関させて脆弱性を特定する。
- サイトをオンラインに戻す前に、必ず侵入口にパッチを当てる。
サーバー管理は根気のゲームだ。自動化ツールと手動のログ分析を組み合わせることで、Webシェルが本格的なデータ侵害に発展する前に捕捉できる。常に警戒を怠らず、「クリーン」なスキャン結果が安全を意味すると思い込まないようにしよう。

