サーバー運用者の危機対応

ログが消された・書き換えられたとき

ログの消去の通知を受けてから、実行の記録で消したプロセスをたどり、ジャーナルで消えた行を見つけ、記録を書き出し、転送で外に写しを残すまでを練習します。

  • レベル: 実践
  • 約35分
  • 2026-11-12

#まず、通知を読む

ログが消されたり書き換えられたりすると、ログ消去の監視 が気づいて通知を出します。この講座は、その通知を受け取ったあとの手順です。だれが消したかを調べ、消えた行がどこに残っているかを確かめ、証拠を固め、同じことが起きても今度は追えるように備えます。

SSH で入られ、ログインの記録を消された

攻撃者が盗んだ鍵で SSH に入り、/var/log/auth.log から自分のログインの行を消しました。あなたのところには「ログの消去の疑い」の通知が届いています。auth.log を開いても、ログインの記録はもうありません。ここから、何が起きたかをたどります。

練習は、使い捨ての環境で

この講座の演習は、ログを書き換えたり、設定を変えたりします。使い捨ての VM で試してください。消す対象は、自分で作った無害なログインの行です。先に写しを取り、最後に戻します。VM の時計は UTC です。日本時間は 9 時間足して読みます。

事象を一度だけ再現して、通知を読む

auth.log を書き換える操作です(変更を伴う操作です)。先に写しを取ります。admin は、自分のアカウント名に置き換えます。

sudo cp -p /var/log/auth.log /root/auth.log.bak
ssh-keygen -q -t ed25519 -N "" -f ~/.ssh/lab_key
cat ~/.ssh/lab_key.pub >> ~/.ssh/authorized_keys
ssh -o StrictHostKeyChecking=no -i ~/.ssh/lab_key admin@127.0.0.1 true
sleep 35
ssh -o StrictHostKeyChecking=no -i ~/.ssh/lab_key admin@127.0.0.1 \
  'sudo sed -i "/Accepted publickey/d" /var/log/auth.log'
sleep 35
sudo roamswitch notifications | grep -A8 'ログの消去' | head -9
出力の抜粋
  ログの消去の疑いを検知 (1 件)
    ホスト: ubuntu (IP: 192.168.64.20)
    次のログが、ログローテーションでは説明できない形で変わりました:
    /var/log/auth.log が別のファイル(inode が違う)に差し替えられました。sed -i などで書き直すと、こうなります
    攻撃者が痕跡を消した可能性があります。
    確認: `last` と `sudo journalctl -u ssh` で直近のログインを、`sudo roamswitch fim verify` で重要ファイルと SUID ファイルの変化を見てください。
    時刻: 2026-11-12 01:48:42
    変更したプロセスは特定できません(ファイルの状態を定期的に比べて見つけたため)

通知からわかることは 3 つです。

  • どのファイルが、どう変わったか。ここでは auth.log が、inode の違う別のファイルに差し替えられました。sed -i は、新しいファイルを作って元と差し替えるためです
  • ローテーションでは説明できない変化だと判定しています。正しいローテーションは除かれます
  • 最後の行のとおり、だれが消したかは、この通知では分かりません。ファイルの状態(大きさや inode)を 30 秒ごとに比べて見つけるためです

演習の準備で authorized_keys に鍵を足した時点でも、重要システムファイルの改ざん監視 の「クリティカルパス改ざん検知 (FIM)」が1件届きます。書いたプロセスと、SSH のログイン(見つからないときは、プロセスが属するサービス)が付くので、自分の操作だと確かめられます。

次の章で、その「だれが」を埋めます。

#だれが消したかを、実行の記録でたどる

通知は、変更したプロセスを特定できませんでした。そこを埋めるのが 改ざん検知つきの記録 です。デーモンは、実行されたプロセスを記録しています。消した相手がプロセスを動かした以上、その記録は残ります。

実行の記録から、auth.log を触ったプロセスを探す

記録を読むだけです。何も変更しません。events search は、引数を省くと直近の記録を、--text を付けるとその文字列を含む記録だけを返します。

sudo roamswitch events search --text /var/log/auth.log
出力の抜粋
2026-11-12T01:48:19.226Z pid=1646 ppid=1645 root /usr/bin/sed -i /Accepted publickey/d /var/log/auth.log
2026-11-12T01:48:19.152Z pid=1645 ppid=1644 admin /usr/bin/sudo sed -i /Accepted publickey/d /var/log/auth.log
2026-11-12T01:48:19.152Z pid=1645 ppid=1644 [euid 1000→0] admin /usr/bin/sudo sed -i /Accepted publickey/d /var/log/auth.log
2026-11-12T01:48:19.151Z pid=1645 ppid=1644 admin /usr/bin/bash -c sudo sed -i "/Accepted publickey/d" /var/log/auth.log
2026-11-12T01:48:18.757Z pid=1581 ppid=1155 admin /usr/bin/ssh -o StrictHostKeyChecking=no -i /home/admin/.ssh/lab_key admin@127.0.0.1 sudo sed -i "/Accepted publickey/d" /var/log/auth.log

auth.log を触ったのは、root の sed -i でした。行を消したコマンドが、そのまま残っています。その親の PID 1645 は、admin の bash -c が sudo に替わったものです。[euid 1000→0] の行は、その sudo が root になった時点の記録です。いちばん下の行は、ssh で入ってコマンドを渡した側です。この sed の PID を、events tree に渡します。

sudo roamswitch events tree 1646
実行結果
1 /usr/lib/systemd/systemd
1269 /usr/sbin/sshd
1582 /usr/sbin/sshd
1644 /usr/sbin/sshd
1645 /usr/bin/sudo
            1646 /usr/bin/sed -i /Accepted publickey/d /var/log/auth.log

上から下へ、親から子への連鎖です。sshd が入り口で、そこから sudo、そして sed が auth.log を書き換えました。通知が埋められなかった「だれが」は、この連鎖で分かります。外から入られたときは、いちばん上の sshd が、どのセッションかを指します。

#消えた行が残っている場所を押さえる

ログを消しても、同じ出来事が別の場所に残っていることがあります。消された auth.log の行は、systemd のジャーナルと、通知の記録にもありました。

ジャーナルと時系列で、消えた行を見つける

読むだけです。何も変更しません。

sudo grep -c 'Accepted publickey' /var/log/auth.log
sudo journalctl -u ssh --no-pager | grep 'Accepted publickey' | tail -1
出力の抜粋
0
Nov 12 01:48:18 ubuntu sshd[1582]: Accepted publickey for admin from 127.0.0.1 port 45200 ssh2: ED25519 SHA256:kbT0Z1OwPpDVRhXwYwtf2NxztMQEiHlCyuEwF1glUOY

auth.log からは消えていますが、ジャーナルには同じログインが残っていました。sshd はジャーナルにも書くためです。sshd[1582] は、events tree に出た sshd の PID と同じです。どこから入ったかが、ここで分かります。続けて、インシデントのタイムライン で、消去そのものを時系列として見ます。

sudo roamswitch timeline | grep -B1 -A2 'log_replaced'
出力の抜粋
  2026-11-12T01:48:42.755625472+00:00  [FIM]  記録のみ
    ログの改ざん(log_replaced): /var/log/auth.log
    MITRE ATT&CK: T1685.006 (Disable or Modify Tools: Clear Linux or Mac System Logs)
    実施した対応: 記録して通知

時系列には、消去が手口(ATT&CK の T1685.006)として並びます。「記録のみ」「記録して通知」は、知らせただけで、プロセスの停止や隔離はしていない、という意味です。

auth.log が増えなくなったら、rsyslog を開き直す

sed -i は、ファイルを新しいものに差し替えます。rsyslog は、差し替え前のファイルを掴んだまま書き続けるため、新しい auth.log はしばらく増えません。sudo systemctl restart rsyslog で開き直すと、また書かれます。ジャーナルはこの影響を受けないので、調べるときはジャーナルを先に見ます。

#証拠を固める

実行の記録は、あとで消されたり書き換えられたりすると意味がなくなります。だから、早い段階で、改ざんを見破れる形で取り出します。

ハッシュチェーンを確かめ、記録を書き出す

読み出しと、ファイルへの書き出しです。監視対象のログは変えません。

sudo roamswitch events verify
実行結果
✓ ハッシュチェーンは正常です(1 セグメント)。改ざんは検知されていません(検知であり防止ではありません)。
  最新のチェックポイントより後の 34 件は、次のチェックポイントまで検証の対象外です。

記録は、ハッシュでつないであります。2行目は、最新のチェックポイントより後の記録の件数で、その記録があるときだけ出ます。途中が消されたり書き換えられたりすると、このチェーンが切れて分かります。続けて、auth.log に関わる記録を JSON Lines で書き出し、証拠として手元に残します。

sudo roamswitch events export --text auth.log > /tmp/exec-auth.jsonl
wc -l /tmp/exec-auth.jsonl
実行結果
22 /tmp/exec-auth.jsonl

1 行が 1 件の記録です。--text auth.log は、コマンドラインに auth.log を含む記録を選ぶので、export を動かした自分のコマンドも入ります。別の安全な場所に写して、調査の証拠にします。

チェーンが正常だから、何も起きていないと考える

ハッシュチェーンの「正常」は、記録そのものが後から改ざんされていない、という意味です(検知であり防止ではありません)。記録の中身には、この章で見たとおり、ログを消した操作が残っています。チェーンの確認と、記録の中身の確認は、別の作業です。両方を行います。

#転送して、次に備える

ここまでの記録は、このマシンの中にあります。root を取った相手は、それも消せます。根本の備えは、検知をマシンの外へ送っておくことです。イベントの転送(SIEM・syslog・Webhook) は、既定ではオフです。オンにすると、検知を syslog やファイル、Webhook へ送ります。

転送をオンにして、外に写しが残ることを確かめる

設定を変える操作です(変更を伴う操作です)。ここでは、同じマシンの中に転送先の受け取り側を立てて、届き方を確かめます。本番では、別のマシンの syslog や SIEM に向けます。

sudo mkdir -p /var/log/roamswitch
sudo roamswitch server config set forward_file_path /var/log/roamswitch/forward.jsonl
sudo roamswitch server config set forward_enabled true
sudo roamswitch server restart
sleep 5
sudo roamswitch forward status
sudo roamswitch forward test
出力の抜粋
イベント転送 (SIEM/syslog/webhook) — オプトイン、既定はオフ
  有効: はい
  稼働中: 送信要求=0 破棄(最古)=0 再送キュー=0 件 / 0 bytes
  - file: 成功=0 失敗=0 直近エラー=-
  成功 file

転送は、オンにしたあとの検知だけを送ります。最初の演習の検知は、まだ転送先にありません。最初の演習と同じ sed -i を、もう一度実行して確かめます。

同じファイルの2回目の消去は、すぐには通知されません。前の通知から 5 分のあいだの消去は保留され、5 分たったところで1件にまとめて通知されます。保留は、あいだの server restart をはさんでも残ります。そのため、転送先に行が入るまで待ちます。

ssh -o StrictHostKeyChecking=no -i ~/.ssh/lab_key admin@127.0.0.1 \
  'sudo sed -i "/Accepted publickey/d" /var/log/auth.log'
until sudo grep -q 'log_replaced' /var/log/roamswitch/forward.jsonl; do sleep 10; done
sudo grep 'log_replaced' /var/log/roamswitch/forward.jsonl | tail -1
出力の抜粋
{"host":"ubuntu","event_id":"18e72957ba8bc1a1-2219","ts":"2026-11-12T01:53:53.305Z","source":"timeline.fim","severity":"critical","rule":"T1685.006","action":"notified","pid":null,"proc":null,"summary":"Log tampering (log_replaced): /var/log/auth.log"}

1回目の通知(01:48:42)から約 5 分後の 01:53:53 に、2回目の消去が検知されて、転送先に1件が残りました。同じときの通知には「(前の通知のあと、同じファイルでさらに 1 回起きました。最後の変化を示しています)」が付きます。timeline.fim の行の要約は、画面の言語にかかわらず英語です。転送先には、通知そのもの("source":"notification")も、サーバーの言語の文で1行入ります。転送先が別のマシンなら、こちらのログを消しても、その写しは消せません。ジャーナルから出来事の数を数える セキュリティログの監査 も、ふだんの監視に足します。auth.log を書き換えても、ジャーナルは別に残るためです。

sudo roamswitch audit-logs 1 | head -14
出力の抜粋
=====================================================
  📜 セキュリティログ監査 (過去1時間)
=====================================================

  • sudo 認証失敗の行:         0 行
  • SSH 失敗の行:              0 行
  • ファイアウォール遮断の行:  0 行
  • AppArmor/LSM 拒否の行:     0 行
  • マルウェア検知の行:        0 行
  • USB 接続の行:              0 行
    数はログの行の数で、試行の回数ではありません。1 回の失敗が 2 行以上になることがあります(存在しないユーザーへの SSH ログインは「Invalid user」と「Failed password」の 2 行)。SSH の行は、パスワードの失敗、存在しないユーザー、同じ接続元からの繰り返しの切断です。成功したログインは数えません。

  ⚠ ログは直近 500 行だけを調べました。それより前の分は含みません。

数は、ログの行の数です。成功したログインは数えないので、この演習のログインは 0 のままです。

最後に、演習で変えたものを戻します。写しを書き戻すと、auth.log が小さくなるため、それもログの消去の疑いとして通知されます(Falco が動いていれば、Clear Log Activities も出ます)。前の通知から 5 分のうちなら、5 分たってから「さらに 1 回」として届きます。自分の操作だと分かる通知です。

sudo cp /root/auth.log.bak /var/log/auth.log
sudo sed -i '/lab_key/d' ~/.ssh/authorized_keys
rm -f ~/.ssh/lab_key ~/.ssh/lab_key.pub
sudo roamswitch server config set forward_enabled false
sudo roamswitch server restart
転送先を、ファイルにするか、別のマシンにするか

forward_file_path は、同じマシンの中のファイルに書きます。届き方の確認や、手元での集約には向きます。ただし、このマシンで root を取った相手は、そのファイルも消せます。痕跡消しへの備えとしては、forward_syslog_url で別のマシンの syslog か SIEM に送るほうが強いです。相手の手が届かない場所に、検知の写しが残るためです。両方を同時に使うこともできます。

#見えない部分

確かめたこと・確かめていないこと

使い捨ての Ubuntu 24.04 の VM で確かめた範囲では、次のようになります。

  • 消去の通知には、消したプロセスが出ません。ファイルの状態を 30 秒ごとに比べて見つけるためです。だれがを埋めるのは、実行の記録です。この VM では、sshd から sudo、sed までの連鎖が残っていました
  • 実行の記録は、消えるのが速いプロセスを取りこぼすことがあります。events status の「取りこぼし」の件数で分かります
  • ハッシュチェーンの確認は、記録が後から改ざんされていないかだけを見ます。最新のチェックポイントより後の数件は、次のチェックポイントまで対象外です
  • 転送は、既定ではオフです。オンにして送信先を決めるまで、外には何も出ません。送信先が正しく届くかは、forward test で確かめます。失敗した送信先があると終了コード 2、送信先が1つもないと 1 で終わるので、定期の確認にも使えます
  • 知らせるだけで、止めません。この講座の検知のあと、プロセスやネットワークの隔離は起きませんでした。消去への対応は、人が行います
確認問題

「ログの消去の疑い」の通知に「変更したプロセスは特定できません」と出ました。だれが消したかを調べる最初の一手はどれですか

解説を見る

消去の通知は、ファイルの状態の比較で見つけるため、プロセスが出ません。実行の記録には、そのファイルを触ったコマンドが残っています。PID を events tree に渡すと、sshd からの連鎖が見えます。元に戻すのは、証拠を取ってからです。

確認問題

攻撃者が /var/log/auth.log を空にしました。ログインの記録を取り戻せる見込みが高いのはどれですか

解説を見る

sshd はジャーナルにも書くので、auth.log を消してもジャーナルには残ります。転送をオンにしてあれば、検知の写しが別の場所にあります。転送先が別のマシンなら、こちらのログを消しても、その写しは消せません。

#次に学ぶこと

扱う機能

対応する攻撃手法 (ATT&CK): T1685.006

確認した内容

2026-11-12に確認しました。対象は Linux 1.17.39 です。使い捨ての Ubuntu 24.04 の VM(公開版 1.17.39)で、自分のログインの行を sed -i で消す演習から、転送、片付けまでを、日本語と英語で別の新しい VM で実行しました。

コマンドの出力は、製品の版や環境によって変わります。違いが出たら、まず製品の版を確かめてください。