「SSHへの総当たり攻撃はufwとfail2banで弾いているから大丈夫」——そう思っていても、実は一度でもログインを許してしまった後の点検が抜けているケースは多いです。特にUbuntu 24.04やDebian 12ではrsyslogが標準で無効化され/var/log/auth.log自体が存在しない環境が増えており、journalctl -u sshを見ても失敗試行ばかりが並び、ログイン成功後に何をされたかまでは追えていない、という状態に陥りがちです。本記事では、journalctlのsshログとsudoログ、そしてauthorized_keysの更新日時を突き合わせて、ログイン成功後の権限昇格・鍵追加の痕跡を初心者でも点検できる手順をまとめます。

「総当たりは弾いた」だけでは片付かない理由

IPAの「2024年度 中小企業における情報セキュリティ対策に関する実態調査報告書」では、不正アクセスの手口として「脆弱性」が48.0%と最も多く、その約半数がパッチ未適用に起因すると報告されています。一方で2026年8月20日には、中国語話者のサイバー犯罪グループ「UAT-10147」がAI駆動型ツールを使い、世界中の脆弱なLinux/Windows Webサーバーへの攻撃を自動化しているという報告も出ています。ブルートフォース(総当たり)対策だけしていても、既知の脆弱性や設定不備を突かれて一度ログインを許してしまえば、その後の権限昇格や鍵の追加までは別問題として点検する必要があります。

2024年に発覚したxz utilsのサプライチェーン攻撃も、発見のきっかけは「SSHログインがいつもより0.5秒ほど遅い」というエンジニアの違和感でした。派手な兆候がなくても、ログとファイルの更新日時という地味な証拠を突き合わせる習慣が、二次被害の早期発見につながります。

journalctl -u sshだけでは「成功後」が見えにくい環境がある

まずauth.logがあるかどうかを確認する

Ubuntu 24.04やDebian 12はデフォルトでrsyslogが入っていない、または無効化されていることがあります。何を見ているコマンドかというと、認証ログをファイルに書き出す仕組み(rsyslog)が動いているかどうかの確認です。

ls -la /var/log/auth.log 2>/dev/null && echo "auth.logあり" || echo "auth.logなし"
systemctl is-active rsyslog

出力例:

auth.logなし
inactive

auth.logなしかつinactiveであれば、このサーバーの認証履歴はsystemdのジャーナル(journalctl)だけが頼りだと自覚してください。ここで昔の記憶のままtail -f /var/log/auth.logを打っても何も出ず、「ログが消えた」と勘違いする人が多いポイントです。

journalctlで成功・失敗の行だけを抜き出す

何を見ているかというと、sshd(Ubuntu/Debianではサービス名はssh。RHEL系はsshd)がジャーナルに残した行のうち、認証成功(Accepted)と認証失敗(Failed password)の行だけです。

sudo journalctl -u ssh --since "7 days ago" | grep -E "Accepted (password|publickey)|Failed password" | tail -n 40

出力例:

Aug 20 03:14:02 myserver sshd[12345]: Failed password for invalid user admin from 203.0.113.5 port 51234 ssh2
Aug 20 03:14:05 myserver sshd[12345]: Failed password for root from 203.0.113.5 port 51244 ssh2
Aug 20 03:14:09 myserver sshd[12345]: Failed password for invalid user test from 203.0.113.5 port 51260 ssh2

ここでAcceptedの行が1件も出てこないと「成功ログインはなかった」と結論づけたくなりますが、それは早計です。journalは容量に応じて古いログから自動的に削除(vacuum)されます。総当たりボットが1日に数千〜数万件のFailedを叩き込むと、journalの保持枠がそれだけで埋まり、数日〜数週間前にあった正規の成功ログインの記録がとっくに押し出されている可能性があります。

journalの残量と失敗件数の規模を見ておく

何を見ているかというと、journalがディスク上でどれだけ肥大化しているか、直近30日でどれだけ失敗試行が記録されているかです。

journalctl --disk-usage
sudo journalctl -u ssh --since "30 days ago" | grep -c "Failed password"

出力例:

Archived and active journals take up 96.0M in the file system.
58213

失敗件数が数万件規模になっている場合、journalのローテーションで古いログが失われている可能性が高いと判断し、次章のauthorized_keysとsudoログという「ローテーションされにくい別系統の証拠」で裏取りする必要があります。

authorized_keysの更新日時とsudoログを突き合わせる

authorized_keysが最近更新されていないか洗い出す

何を見ているかというと、SSHの公開鍵を登録するファイル(authorized_keys)のうち、直近で更新されたものです。攻撃者が侵入後に自分の鍵を追加すると、ここが更新されます。

sudo find / -xdev -name authorized_keys -newermt "30 days ago" -exec ls -l {} \;

出力例:

-rw------- 1 www-data www-data 411 Aug 19 02:03 /var/www/.ssh/authorized_keys
-rw------- 1 ubuntu   ubuntu   118 Aug 01 09:12 /home/ubuntu/.ssh/authorized_keys

判断ポイントは2つです。1つ目は「自分が最近鍵を追加した記憶があるか」。2つ目は「そもそもwww-datamysqlのようなシステムユーザーの.sshディレクトリにauthorized_keysが存在すること自体が不自然」という点です。心当たりのないユーザーで最近の更新日時が付いていたら、次のsudoログ確認に進みます。中身も見ておきましょう。

cat /home/ubuntu/.ssh/authorized_keys

見るべきは鍵の行末についているコメント(user@hostのような部分)です。自分の鍵に覚えのないコメント、あるいはコメントが空の行、鍵の数が想定より増えている場合は要注意です。

sudoの実行履歴で「誰が書き込んだか」を確認する

何を見ているかというと、sudo(管理者権限でのコマンド実行)の記録です。auth.logがあればそこに、無ければjournalctl -u sudoに残ります。

sudo journalctl -u sudo --since "30 days ago" | tail -n 50
# auth.logがある環境では
sudo grep sudo /var/log/auth.log

出力例:

Aug 19 02:03:11 myserver sudo: ubuntu : TTY=pts/0 ; PWD=/home/ubuntu ; USER=root ; COMMAND=/usr/bin/tee -a /var/www/.ssh/authorized_keys

authorized_keysの更新時刻(先ほどの例ではAug 19 02:03)とほぼ同時刻に、teecat >>viecho >>のようなファイル書き込み系コマンドがsudoで実行されていないかを見ます。自分が実行した覚えのないコマンドがこの時間帯に出てきたら、侵入されて鍵を追加された可能性が高いと判断してください。

更新時刻の前後だけを切り出して裏取りする

ファイルの更新時刻を起点に、その前後5分間だけログをまとめて見る方法です。何を見ているかというと、authorized_keys更新の直前直後にどんなSSHログイン・sudo実行が起きていたかの一覧です。

AUTHKEYS_TIME=$(stat -c %y /home/ubuntu/.ssh/authorized_keys | cut -d. -f1)
sudo journalctl --since "$(date -d "$AUTHKEYS_TIME -5 minutes" '+%Y-%m-%d %H:%M:%S')" \
                 --until "$(date -d "$AUTHKEYS_TIME +5 minutes" '+%Y-%m-%d %H:%M:%S')"

この時間帯にログインしたIPアドレスと、実行されたsudoコマンドが同じ画面に並びます。心当たりのあるIPからの、心当たりのある作業であれば問題ありません。見覚えのないIPからのログイン直後に鍵が書き換わっていれば、二次被害があったとみて対処に進みます。

異常が見つかったときにやること

以下はいずれもシステムに変更を加える操作です。作業前に該当ファイルをコピーしてバックアップを取ってから進めてください。

  • 不審な鍵の削除:authorized_keysから該当行を削除する前にcp authorized_keys authorized_keys.bak_20260822のようにバックアップを取る(sudo要・自分で元に戻せる)
  • パスワード・鍵の再発行:影響範囲が分からない場合は関係する全アカウントのパスワード変更とSSH鍵の再発行を行う(sudo要)
  • 該当IPの遮断sudo ufw deny from 203.0.113.5で一時的に遮断する(sudo ufw delete deny from 203.0.113.5で元に戻せる)
  • ログの保全:対処前にsudo journalctl -u ssh --since "30 days ago" > ~/ssh_log_backup_20260822.txtのようにログをコピーしておく(証拠保全・設定変更なし)
  • 自動起動の設定(systemdサービス・cron)にも仕込みがないか、あわせてsystemctl・cronで不審な自動起動を点検2026年8月の手順で確認する

なお2026年7月にはLinuxカーネル2.6〜7.1系に影響する重大な脆弱性(CVE-2026-46331)のPoCが公開され、一般ユーザー権限からroot権限を奪われる恐れがあると報告されています。JPCERT/CCは修正版カーネルへの更新を最も有効な対策としつつ、信頼できる利用者だけにログイン権限を付与するといった権限管理の徹底も推奨しています。authorized_keysの点検は、まさにこの「誰がログインできる状態になっているか」を洗い出す作業そのものです。

journalのログ保持期間を延ばしておく

journalが揮発設定(再起動で消える、または短期間でローテーション)のままだと、次に同じ調査をするときにまた証拠が残っていない事態になりかねません。ジャーナルをディスクに永続保存する設定です(sudo要・設定変更あり)。

sudo mkdir -p /var/log/journal
sudo systemd-tempfiles --create --prefix /var/log/journal
sudo systemctl restart systemd-journald

元に戻す場合はsudo rm -rf /var/log/journalで永続保存ディレクトリを削除し、systemctl restart systemd-journaldすれば揮発モードに戻ります。あわせて/etc/systemd/journald.confSystemMaxUse=500MMaxRetentionSec=1monthのようにコメントアウトを外して保持容量・期間を明示しておくと、総当たり攻撃のログで古い証拠が押し出される事態を減らせます(変更後は同じくsystemctl restart systemd-journaldが必要。行頭の#を戻せば元の設定に戻ります)。ログイン成功後の点検だけでなく、システム全体の設定強度もあわせて見る場合はsystemd-analyze security点検2026年8月版も参考にしてください。

まとめ

ブルートフォース対策で失敗試行を弾けていても、それはログイン成功後に何もされていないことの証明にはなりません。Ubuntu 24.04やDebian 12のようにauth.logが存在しない環境では、journalctl -u sshの失敗ログだけを見て安心せず、journalの保持量を確認したうえで、ローテーションの影響を受けにくいauthorized_keysの更新日時とsudoログを突き合わせることが重要です。異常が見つかったら鍵の削除・パスワード再発行・ログ保全までを一連の作業として行い、journalの永続化設定で次回の調査に備えておきましょう。