放置された「パッチ未適用サーバー」は、攻撃者のATMである
現場でインシデント対応をしていると、溜息が出るほど多いのが「OSのアップデートを忘れていた」というケースだ。攻撃者は、我々がGitHubでコードを書いている間に、昨日公開されたCVE(共通脆弱性識別子)のPoC(概念実証コード)を使い、パッチ未適用の脆弱性を突いてくる。
特に怖いのは、パッケージリポジトリの改ざんや中間者攻撃(MITM)だ。もし君が運用しているサーバーが、リポジトリの署名検証をスキップするように設定されていたら、攻撃者は偽のパッケージを送り込み、root権限でバックドアを仕込むことができる。
今日は、Linuxサーバーを「放置していても安全」な状態に保つための、泥臭くも確実なハーデニング術を伝授する。
—
1. 自動アップデートの「本当の」防衛ライン:unattended-upgrades
「とりあえず自動更新を入れておけばいい」と考えるのは甘い。OSの再起動タイミングや、重要な設定ファイルの競合でサービスが落ちるリスクを制御しつつ、セキュリティパッチだけを確実に当てる。これがプロの仕事だ。
Debian/Ubuntu系であれば、unattended-upgradesを導入するのが定石だ。
設定ファイルの実装サンプル
/etc/apt/apt.conf.d/50unattended-upgrades を以下のように設定してほしい。重要なのは「セキュリティパッチ以外は自動更新しない」というフィルタリングと、リポジトリの検証だ。
// 許可するソースをセキュリティ系に限定する
Unattended-Upgrade::Allowed-Origins {
"${distro_id}:${distro_codename}-security";
// 注意: プロダクション環境では、マイナーアップデートすら自動で適用せず
// 検証環境で回してから本番に反映するのが理想だが、
// セキュリティパッチだけは即座に適用するポリシーを推奨する
};
// パッケージの署名を検証し、署名がない/不正なパッケージはインストールを拒否する
// デフォルトでtrueだが、明示的に記述して堅牢性を確保する
APT::Get::AllowUnauthenticated "false";
// 脆弱性対応後の再起動を自動化する(深夜帯に設定すること)
Unattended-Upgrade::Automatic-Reboot "true";
Unattended-Upgrade::Automatic-Reboot-Time "03:00";
—
2. なぜ「リポジトリの署名検証」を強制すべきなのか?
攻撃者が狙うのは、パッケージのミラーサイトだ。もしリポジトリが侵害された場合、偽のパッケージが配布される。署名検証が有効であれば、パッケージのハッシュ値とGPG鍵の照合が行われ、改ざんされたパッケージはインストール時にエラーで弾かれる。
これを強制するには、/etc/apt/apt.conf.d/99verify-peer のようなファイルを作成し、以下の設定を記述する。
// パッケージの署名がない、または鍵が一致しない場合にインストールを停止する
APT::Get::AllowUnauthenticated "false";
APT::Get::AllowDowngrades "false";
これだけで、万が一のサプライチェーン攻撃に対する強力な防波堤になる。
—
3. インフラ運用における「隠れたリスク」の排除
パッケージ管理の堅牢化と並行して、サーバー自体を「攻撃しにくい箱」にする必要がある。不要なサービスを停止するのは基本中の基本だが、さらに一歩進んで、「実行権限の最小化」を行うべきだ。
例えば、Webサーバー(Nginx等)がOSの重要ファイルを読み書きできないよう、Systemdの機能を使ってプロセスを制限する。
Nginxの堅牢化設定(systemdサービスファイル)
/etc/systemd/system/nginx.service.d/override.conf を作成し、以下のように権限を削ぎ落とす。
[Service]
# プロセスがシステムの設定ファイルを書き換えることを禁止
ProtectSystem=full
# プロセスがホームディレクトリにアクセスすることを禁止
ProtectHome=true
# 実行ファイル以外の領域を読み取り専用に
ProtectControlGroups=true
# 新しいプロセスが特権を持つことを禁止
NoNewPrivileges=true
—
現場のシニアからのアドバイス
いいか、セキュリティは「設定して終わり」ではない。自動更新が本当に動いているか、cronのログ(/var/log/unattended-upgrades/unattended-upgrades.log)を定期的に監視する仕組みを構築すること。
また、apt-get upgrade を実行する際に、必ずリポジトリのGPG鍵が正しく更新されているかも確認してくれ。古い鍵のまま運用を続けると、ある日突然、全てのアップデートが「署名エラー」で止まり、脆弱性が放置されるという最悪の事態を招く。
「自動化は、監視とセットで初めて機能する」。
この鉄則を忘れないでほしい。君が書くコードがどれほど素晴らしくても、その土台が腐っていれば、すべては無に帰す。インフラを守ることは、プロダクトを守ることと同義だ。自信を持って、堅牢なシステムを組み上げよう。
コメント