監視ダッシュボードにCPU使用率98%と表示されているのに、アプリケーションはアイドル状態でトラフィックは完全に正常に見える。その組み合わせ——CPU高止まり、説明ゼロ——は、サーバー上の何かがあなたのリソースを無断で消費していることを意味します。
私のクライアントがこれを痛い目で学びました。XMRigマイナーが3週間もひそかにVPSでMoneroをマイニングし続け、クラウド料金が異常に高くなって初めてアラートが発動しました。私が呼ばれた時点では、週末全体を感染のトレース、永続化メカニズムの除去、セキュリティ強化の再構築に費やしました。私自身のサーバーも数年前の午前2時にSSHブルートフォース攻撃を受けました——それ以来、新しいサーバーでまず最初に設定するのはセキュリティです。
現実の問題:サイレントCPUハイジャック
クリプトマイナーはマルウェアの世界で奇妙なニッチを占めています。データを破壊せず、身代金も要求せず、見えないように努力します。ビジネスモデルは純粋な計算リソース窃盗:あなたのCPUサイクル、あなたの電気代、彼らのMoneroウォレット。検出されない時間が長いほど攻撃者の利益になり——あなたには原因不明の請求が発生します。
症状は徐々に現れます:
- 原因不明のCPUスパイク(全コアで70〜100%になることが多い)
- トラフィックが正常なのにサーバーの応答時間が悪化
- 予想より高いクラウドコンピューティングの請求
- 未知のIPへの異常なアウトバウンドネットワーク接続
- 自分で作成していない新しいcronジョブまたはsystemdサービス
ほとんどの管理者が気づいた時点では、マイナーは数日または数週間稼働しています。
根本原因分析:どうやって侵入したのか?
プロセスに触れる前に、侵入口を特定してください。その入口を閉じずにマイナーを除去しても、数時間以内に戻ってきます。クリプトマイナーは同じ侵入口を繰り返し悪用します——パターンを知っていれば、フォレンジックの追跡がずっと簡単になります。
SSHブルートフォース / クレデンシャルスタッフィング
パスワード認証でSSHを公開しているのが第1の侵入経路です。デプロイされたばかりのVPSは最初の1時間で1,000回以上のログイン試行を受けることがあります。自動ボットが24時間365日、/8レンジ全体をスキャンします。rootとsudoアカウントの弱いまたは使い回しのパスワードはすぐに解読されます——ターゲットにされたシステムでは5分以内のこともあります。一度侵入すると、攻撃者はすぐにマイニングペイロードをダウンロードして実行します。
Webアプリケーションの脆弱性悪用
パッチが当たっていないWordPress、PHPアプリ、または既知のRCE脆弱性を持つフレームワークは、攻撃者に直接コマンド実行を許してしまいます。2021年12月に公開されたLog4Shell(CVE-2021-44228)は、公開から48時間以内にクリプトマイナーの配信手段となりました。PHPデシリアライゼーションの欠陥やSSTI脆弱性も同じパターンに従います。マイナーはWebシェルや直接コマンドインジェクションを通じてインストールされます——悪用から数秒以内のことが多いです。
公開されたDockerおよびKubernetes API
TLS認証なしのポート2375は、ホストへの実質的に認証なしのrootアクセスです。攻撃者はDocker APIに直接接続し、ホストファイルシステムにアクセスできる特権コンテナを起動して、ペイロードをインストールするために脱出します。設定ミスのKubernetesダッシュボードも別の経路で同じ結果をもたらします。
侵害されたパッケージとCI/CDパイプライン
悪意のあるnpmまたはPyPIパッケージ——そして侵害されたビルドパイプライン——は、デプロイメントにマイニングコードをひそかに注入します。これらは最も検出が難しいものです。配信メカニズムが完全に正当なものに見えるため、標準的な境界防御はフラグを立てません。
検出:何かに触れる前に感染の全容をマッピングする
全体像を把握する前にプロセスをkillすると、ほぼ必ず逆効果になります。マイナーはまだ見つけていない永続化メカニズムから自分自身を再植え付けします。以下が実際に機能する系統的なアプローチです。
ステップ1:不審なプロセスの特定
# CPU使用量が多いプロセスを確認する
top -b -n 1 | head -20
# フルコマンドパスを含む詳細表示
ps aux --sort=-%cpu | head -20
# 削除されたバイナリから実行されているプロセスを確認する(古典的な隠蔽手法)
ls -la /proc/*/exe 2>/dev/null | grep deleted
マイナーはしばしばシステムプロセスを偽装します:kworker、kthreadd、sshd、またはランダムな文字列に見えるもの。削除されたバイナリのチェックに特に注意してください——/proc/<PID>/exeが(deleted)パスを指している場合、ほぼ必ず悪意のあるものです。攻撃者はバイナリを実行してからすぐにディスクから削除し、実行中のプロセスだけを残します。
ステップ2:アウトバウンドネットワーク接続のトレース
# 担当プロセスとともにすべての接続を一覧表示する
ss -tulpn
# XMRigは通常ポート3333、4444、5555、14444のマイニングプールに接続する
ss -tnp | grep -E ':3333|:4444|:5555|:14444'
# 不審な接続のIPを逆引きする
for ip in $(ss -tn | grep ESTAB | awk '{print $5}' | cut -d: -f1 | sort -u); do
host "$ip" 2>/dev/null | head -1
done
ステップ3:すべての永続化メカニズムの監査
永続化こそがマイナーの巧みさが現れる部分です。プロセスをkillしても別の場所から再起動されるよう、複数の場所に自分自身を仕込みます。
# ユーザーごとのものを含む、すべてのcrontabを確認する
crontab -l 2>/dev/null
cat /etc/crontab
ls -la /etc/cron.d/ /etc/cron.daily/ /etc/cron.hourly/
for user in $(cut -d: -f1 /etc/passwd); do
crontab -u "$user" -l 2>/dev/null && echo "--- $user ---"
done
# 見慣れない名前のsystemdサービスを確認する
systemctl list-units --type=service --state=running
ls -la /etc/systemd/system/
# シェル起動ファイルに注入されたダウンローダーを確認する
find /root /home -name '.bashrc' -o -name '.profile' -o -name '.bash_profile' \
| xargs grep -l 'curl\|wget\|chmod' 2>/dev/null
ステップ4:マイナーファイルの特定
# マイナーが好む書き込み可能な場所を検索する
ls -la /tmp/ /dev/shm/ /var/tmp/
find /tmp /dev/shm /var/tmp -type f -newer /etc/passwd 2>/dev/null
# XMRig設定ファイルを検索する
find / -name 'config.json' -newer /etc/passwd 2>/dev/null \
| xargs grep -l 'pool\|wallet' 2>/dev/null
# WebルートのPHP Webシェルを確認する
find /var/www -name '*.php' -newer /etc/passwd 2>/dev/null \
| xargs grep -l 'base64_decode\|eval\|system(' 2>/dev/null
解決策の比較:侵害されたサーバーの3つの対処法
感染の全容をマッピングしたら、本当の岐路に立たされます。各オプションは異なるリスクプロファイルを持っています——間違った選択をすると、1日を無駄にするか、攻撃者への抜け穴を残すことになります。
オプションA:ライブクリーンアップ(高速、リスク高め)
プロセスをkill、ファイルを削除、永続化をその場でパージします。感染が単純でそのすべての要素を把握できている場合に有効です。本当のリスク:永続化メカニズムを1つ見逃すと、何事もなかったかのように翌朝戻ってきます。
オプションB:サーバーの完全な再構築(徹底的、時間がかかる)
新しいサーバーをプロビジョニングし、確実にクリーンなバックアップから復元するか、アプリケーションスタックをゼロから再デプロイします。クリーンな状態を保証できる唯一の方法です。サーバーに機密データが含まれているか、攻撃ベクトルが完全に明確でない場合は、これが正しい判断です——議論の余地なし。
オプションC:スナップショットロールバック
クラウドプロバイダー(AWS、GCP、DigitalOcean)では、感染前のスナップショットにロールバックします。高速でクリーンです——ただし、スナップショットが有効になっていること、そして感染が開始した正確な時刻を知る必要があります。そのタイムスタンプが明確なことはほとんどありません。
私の推奨:攻撃ベクトルが不明な本番サーバーには再構築(オプションB)。マイナーがどのように侵入したかを正確に追跡できるdevまたはstaging環境ではライブクリーンアップで問題ありません——ただし次に進む前に徹底的に検証してください。
最良のアプローチ:構造化されたクリーンアップとセキュリティ強化
フェーズ1:封じ込め——マイナーを即座に遮断する
# 一般的なマイニングプールポートへのアウトバウンド接続をブロックする
iptables -A OUTPUT -p tcp --dport 3333 -j DROP
iptables -A OUTPUT -p tcp --dport 4444 -j DROP
iptables -A OUTPUT -p tcp --dport 5555 -j DROP
iptables -A OUTPUT -p tcp --dport 14444 -j DROP
# 既知のマイニングプールドメインをDNSレベルでブロックする
cat >> /etc/hosts << 'EOF'
0.0.0.0 pool.minexmr.com
0.0.0.0 xmr.pool.minergate.com
0.0.0.0 xmrpool.eu
0.0.0.0 monerohash.com
EOF
フェーズ2:根絶——すべての要素を除去する
# マイナープロセスをkillする
kill -9 <PID>
# systemdベースの永続化を除去する
systemctl stop <malicious-service>
systemctl disable <malicious-service>
rm /etc/systemd/system/<malicious-service>.service
systemctl daemon-reload
# マイナーがよく配置される場所をクリーンアップする
rm -rf /tmp/xmrig /dev/shm/.x /var/tmp/.update*
# 悪意のあるcrontabエントリを削除する(不審な行を編集して削除する)
crontab -e
フェーズ3:クリーンな状態の確認
# CPUが正常に戻ったことを確認する
top -b -n 3 | grep '%Cpu'
# 不審なアウトバウンド接続が残っていないことを確認する
watch -n 2 'ss -tnp | grep -v "127.0.0\|::1"'
# ルートキットチェックを実行する
apt install -y chkrootkit rkhunter
chkrootkit
rkhunter --check --sk
フェーズ4:再感染への対策強化
# SSHパスワード認証を無効化する
# この正規表現はコメントアウトされた行とそうでないPasswordAuthentication行の両方を処理する
sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
systemctl restart sshd
# すべてのSSH認証済み鍵をローテーションする——認識できないものは取り消す
cat ~/.ssh/authorized_keys # 慎重に確認すること
# SSHのためにfail2banをインストールして設定する
apt install -y fail2ban
cat > /etc/fail2ban/jail.local << 'EOF'
[sshd]
enabled = true
maxretry = 3
bantime = 3600
findtime = 600
EOF
systemctl enable --now fail2ban
# 自動セキュリティアップデートを有効化する
apt install -y unattended-upgrades
dpkg-reconfigure --priority=low unattended-upgrades
# 誰でも書き込めるディレクトリからの実行を制限する
# remountは一時的——再起動後も有効にするには/etc/fstabにエントリを追加する
mount -o remount,noexec /tmp
mount -o remount,noexec /dev/shm
# 永続化のために/etc/fstabに追加する:
# tmpfs /tmp tmpfs defaults,noexec,nosuid,nodev 0 0
# tmpfs /dev/shm tmpfs defaults,noexec,nosuid,nodev 0 0
フェーズ5:CPU異常アラートの設定
# CPUが80%を超えたらアラートを発する——vmstatはディストリビューション間で信頼性の高い出力を提供する
cat > /usr/local/bin/cpu-monitor.sh << 'EOF'
#!/bin/bash
THRESHOLD=80
# vmstatの列15はidle%;100から引いてtotal busy%を計算する
CPU=$(vmstat 1 2 | tail -1 | awk '{print 100 - $15}' | cut -d'.' -f1)
if [ "$CPU" -gt "$THRESHOLD" ]; then
echo "CPU高負荷アラート: $(hostname) でのCPU使用率 ${CPU}% ($(date))" \
| mail -s "CPUアラート" [email protected]
fi
EOF
chmod +x /usr/local/bin/cpu-monitor.sh
echo "*/5 * * * * root /usr/local/bin/cpu-monitor.sh" > /etc/cron.d/cpu-monitor
# /tmpからの実行を検出するためにauditdを設定する
apt install -y auditd
auditctl -w /tmp -p x -k tmp-execution
auditctl -w /etc/cron.d/ -p wa -k crontab-changes
# 監査ログを確認する
ausearch -k tmp-execution
ausearch -k crontab-changes
私が対処したすべての再感染ケースで繰り返されるパターンがあります:管理者がマイナーを除去したが、元の侵入口を特定しなかった。まず穴を塞いでください。攻撃者がどのように侵入したかを特定できない場合、唯一の道は完全な再構築です——古いサーバーは完全に侵害されたものとして扱い、復旧させないでください。
検出速度こそが、軽微なインシデントと深刻なものを分けるものです。最初の1時間で発見されたマイナーはほぼコストゼロです。3週間も検出されなかったマイニングは、実際の金銭的損失、潜在的なデータ漏洩、そして——確かに——非常に長い週末を意味します。

