午前2時、Telegramが鳴り響いた。クライアントから「サイトがGoogleに危険なサイトとしてマークされました」とメッセージが届いた。サーバーにSSHでログインし、ls -la /var/www/htmlを実行すると—昨日から見覚えのない.phpファイルが大量に出現していた。Webシェルだ。誰かがアップロードして、サーバーをボットネットのノードとして使っていたのだ。
その後、すべてのWebサーバーにLMD + ClamAVを導入した。今回はその手順を共有する—5分でできる初期セットアップから完全な自動設定まで。
クイックスタート — 5分で始める
サーバーがマルウェアに感染していると疑われ、すぐにスキャンが必要な場合はこの順序で実行する:
# 1. まずClamAVをインストール(データベースが大きいためダウンロードに時間がかかる)
sudo apt update && sudo apt install -y clamav clamav-daemon
# 2. ウイルスデータベースを更新(重要!)
sudo systemctl stop clamav-freshclam
sudo freshclam
sudo systemctl start clamav-freshclam
# 3. LMDをダウンロードしてインストール
cd /tmp
wget https://www.rfxn.com/downloads/maldetect-current.tar.gz
tar -zxvf maldetect-current.tar.gz
cd maldetect-*/
sudo ./install.sh
# 4. Webディレクトリを今すぐスキャン
sudo maldet -a /var/www/html
以上だ。LMDがスキャンして結果を画面に出力する。hits: X(X > 0)という行が表示された場合は、以下の対処方法を読み進めてほしい。
LMDとClamAVの違いを理解する
どちらか一方だけインストールすれば十分と思う人が多いが、実際には両者は互いを補完し合う関係にある。
ClamAVは数百万のシグネチャを持つアンチウイルスエンジンで、ウイルス、トロイの木馬、一般的なマルウェアの検出が得意だ。ただし、WebサーバーでもっともよくあるマルウェアであるWebシェルの検出には最適化されていない。
Linux Malware Detect(LMD)は共有ホスティングやWebサーバー向けに特化して構築されている。LMDのシグネチャはホスティング環境への実際の攻撃事例から収集されており—Webシェル、PHPバックドア、難読化コードなど—ClamAVが見落としがちなものを検出できる。
組み合わせて使うと:LMDはスキャンエンジンとしてClamAVを利用し(より高速)、同時に独自のシグネチャも使用する。2層の検出、1回のスキャン。
LMDを正しく設定する
メインの設定ファイルは/usr/local/maldetect/conf.maldetにある。デフォルトから変更すべき重要なオプションだけを説明する:
sudo nano /usr/local/maldetect/conf.maldet
# メールアラートを有効化(実際のメールアドレスに変更)
email_alert="1"
email_addr="[email protected]"
# 自動隔離を有効化 — 感染ファイルは削除せず隔離される
quar_hits="1"
quar_clean="1" # 隔離前にクリーンアップを試みる
quar_susp="0" # 「疑わしい」ファイルを自動で隔離しない(誤検知が多い)
# ClamAVをエンジンとして使用(大幅に高速化)
clamav_scan="1"
# inotifyによるリアルタイムスキャン(カーネルのサポートが必要)
inotify_base="/var/www"
inotify_users="www-data"
# CPUを使いすぎないようにスキャンを制限
scan_max_filesize="2048" # 2MB以上のファイルはスキップ
scan_tmpdir_paths="/tmp /var/tmp /dev/shm" # tmpディレクトリは常にスキャン
変更後、サービスを再起動する:
sudo systemctl restart maldet
毎日の自動スキャンを設定する
LMDのインストール後、/etc/cron.daily/maldetにcronジョブが自動作成されるが、デフォルトでは/tmpと/var/tmpしかスキャンしない。Webディレクトリを追加しよう:
sudo nano /etc/cron.daily/maldet
maldetを含む行を見つけ、Webのパスを追加する:
#!/bin/bash
/usr/local/maldetect/maldet -b -r /var/www/ 2>&1 | logger -t maldet
-bフラグはバックグラウンド実行、-rは再帰スキャンを意味する。結果はsyslogに記録される。
毎日ではなく毎週レポートをメールで受け取りたい場合(受信ボックスへのスパムを防ぐため)、専用のcronを作成する:
sudo crontab -e
# 毎週日曜日の午前3時に深いスキャンを実行
0 3 * * 0 /usr/local/maldetect/maldet -a /var/www/ && /usr/local/maldetect/maldet --report REPORT_DATE
マルウェア検出時の対処方法
スキャン後にhitsが見つかった場合、知っておくべきコマンドを紹介する:
# 最新のレポートを表示
maldet --report
# 特定のレポートの詳細を表示(YYYYMMDD-HHMMSS)
maldet --report 20240618-030000
# 隔離されたファイルの一覧を表示
ls -la /usr/local/maldetect/quarantine/
# 誤検知の場合はファイルを復元
maldet -s /usr/local/maldetect/quarantine/FILENAME
# クリーン(ファイルを保持したままマルウェアコードの削除を試みる)
maldet -c /path/to/file.php
実際には、保持が必要なファイル(インジェクトされたWordPressプラグインなど)には-cを使い、明らかなWebシェルは隔離後に直接削除している。
応用:inotifyによるリアルタイムスキャン
cronの実行を待つ代わりに、LMDはファイルシステムをリアルタイムで監視し、新しいファイルが作成・変更されたらすぐにスキャンできる:
# カーネルがinotifyをサポートしているか確認
ls /proc/sys/fs/inotify/
# max_queued_events、max_user_instances、max_user_watchesが表示されればOK
# 必要に応じてinotifyの制限を増やす(ファイル数が多いWebサーバー向け)
echo "fs.inotify.max_user_watches=524288" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
# リアルタイムモニターを開始
sudo maldet -m /var/www/
# モニターが動作中か確認
sudo maldet --monitor-status
注意:リアルタイムモニターは監視するファイル数によって約50〜100MBのRAMを消費する。小規模なVPS(1GB RAM)の場合、Webルート全体ではなくアップロードディレクトリのみ監視することを検討しよう。
ClamAVデーモンと組み合わせて高速スキャンを実現する
デフォルトではClamAVはスキャンのたびにすべてのシグネチャをRAMにロードするため遅い。clamscanの代わりに常駐デーモンを使ったclamdscanを利用しよう:
# clamav-daemonを有効化
sudo systemctl enable clamav-daemon
sudo systemctl start clamav-daemon
# デーモンが動作中か確認
sudo systemctl status clamav-daemon
# デーモンを使ってスキャンテスト(clamscanより大幅に高速)
clamdscan /var/www/html/suspicious-file.php
LMDの設定ファイル(conf.maldet)でclamav_scan="1"を設定すると、デーモンが利用可能な場合にLMDが自動的にclamdscanを使用する。
本番環境からの実践的なTips
最初から強力なパスワードを設定する。WebシェルのほとんどはFTP/SSHへのブルートフォース攻撃やWordPressパスワードの推測によって侵入される。サーバー上のすべてのアカウントに32文字のパスワードを生成するためにtoolcraft.app/ja/tools/security/password-generatorのパスワードジェネレーターを使っている—ツールは完全にブラウザ上で動作し、サーバーに何も送信しないため傍受の心配がない。
バックアップを復元する前にスキャンする。サーバーがハックされてバックアップから復元する場合は、まずLMDでバックアップをスキャンしよう—マルウェアが検出される前からバックアップに潜んでいることがある。
誤検知をホワイトリストに追加する。LMDは正規のファイル(Adminerや一部のWordPressプラグインなど)にフラグを立てることがある。スキャンを無効化するのではなく、ホワイトリストに追加しよう:
# ファイルハッシュでホワイトリスト登録
maldet -w /var/www/html/adminer.php
# ホワイトリストの一覧を表示
cat /usr/local/maldetect/ignore/hex
cat /usr/local/maldetect/ignore/paths
シグネチャの自動更新を維持する。LMDは実行時に自動でシグネチャを更新するが、ClamAVにはfreshclamが必要だ。freshclamが動作しているか確認しよう:
sudo systemctl status clamav-freshclam
# 動作していない場合:
sudo systemctl enable --now clamav-freshclam
ログを集中管理する。複数のサーバーを管理している場合は、LMDのログを一か所に集約しよう。cronでloggerを使ってsyslogに送り、rsyslogで中央のログサーバーに転送している。インシデント発生時に各サーバーにSSHするのではなく、一か所で検索できる。
セットアップ後の動作確認
# EICARテストファイルを作成(マルウェアテスト用文字列、無害)
echo 'X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*' > /tmp/eicar-test.php
# スキャンを実行
maldet -a /tmp/eicar-test.php
# 出力にhits: 1が表示されればLMD + ClamAVは正常に動作している
# テストファイルを削除
rm /tmp/eicar-test.php
セットアップが完了すると、積極的な防御層が手に入る。LMDは万能ではない—ゼロデイのWebシェルや高度に難読化されたコードは検出をすり抜けることがある—しかし共有ホスティングやWordPressへの一般的な攻撃の95%は、深刻な被害が出る前に遮断または検出される。

