モダンなLinuxセキュリティ:Unified Kernel Image (UKI) によるブートプロセスの要塞化

Security tutorial - IT technology blog
Security tutorial - IT technology blog

Unified Kernel Imageへの移行:なぜブートセキュリティが重要なのか

従来のLinuxブートプロセスは、バトンタッチの回数が多すぎるリレーのようなものです。UEFI(ファームウェア)がGRUBなどのブートローダーに制御を渡し、そこからディスク上の個別のファイルであるカーネルと初期RAMディスク(initrd)がロードされます。

このモジュール性は柔軟性には優れていますが、攻撃者に対して隙を与えることにもなります。もし悪意のある者がルート権限を取得した場合、initrdを改ざんされたものに差し替えることが可能です。この不正なinitrdは、ログインプロンプトが表示される前にLUKSディスク暗号化パスワードを盗み出すかもしれません。

私がこの教訓を身をもって学んだのは、管理していたサーバーが1時間で4,000回以上のSSHログイン試行を受けた時でした。ネットワーク攻撃はブロックしましたが、ネットワークの要塞化は戦いの半分に過ぎないことに気づきました。基盤となるOSのブートプロセスが検証されていなければ、その上のすべてのセキュリティレイヤーは砂上の楼閣に過ぎません。この気づきが、Unified Kernel Image (UKI) の採用につながりました。

UKIは、単一の自己完結型EFI実行ファイルです。Linuxカーネル、initrd、カーネルコマンドライン、そして小さなUEFIスタブを1つのファイルに統合します。何十もの署名を管理する代わりに、1つのバイナリに署名するだけで済みます。UEFIファームウェアはこの単一の署名を検証し、システムのコアが意図した通りであることを保証します。

環境のセットアップ

これらのイメージを構築し署名するには、いくつかの専用ツールが必要です。Arch、Fedora、Debian (Sid/Trixie) を含む最近の主要なディストリビューションでは、これらは標準リポジトリで提供されています。今回は、イメージ作成のデファクトスタンダードとなっている <a href="https://itnotes.dev/ja/systemd%e3%82%b5%e3%83%bc%e3%83%93%e3%82%b9%e3%81%ae%e8%a6%81%e5%a1%9e%e5%8c%96%ef%bc%9a%e3%82%b5%e3%83%b3%e3%83%89%e3%83%9c%e3%83%83%e3%82%af%e3%82%b9%e5%8c%96%e3%81%ae%e5%ae%9f%e8%b7%b5%e3%82%ac/">systemd</a>-ukify を使用します。

Debianベースのシステムでは、apt を使用して依存関係をインストールします:

sudo apt update
sudo apt install systemd-boot binutils sbsigntools python3-pefile

Arch Linuxユーザーの場合:

sudo pacman -S systemd ukify sbsigntools

ここで最も重要なコンポーネントは sbsigntools パッケージです。これは、マザーボードのSecure Bootメカニズムがバイナリを信頼するために必要な暗号署名を付与するためのユーティリティを提供します。

ステップ1:独自のSecure Bootキーの生成

工場出荷時にインストールされているMicrosoftのキーだけに頼ることは、ハードウェアの信頼の起点(Root of Trust)をサードパーティに委ねることを意味します。完全に制御するためには、独自のMachine Owner Key (MOK) を生成する必要があります。このガイドでは、UKI의署名専用に2048ビットのRSAキーペアを作成します。

# キー専用のディレクトリを作成
mkdir -p ~/secure-boot-keys
cd ~/secure-boot-keys

# 秘密鍵と10年間有効な証明書を生成
openssl req -new -x509 -newkey rsa:2048 -nodes -days 3650 -subj "/CN=My Custom UKI Key/" -keyout uki.key -out uki.crt

# UEFI登録用に証明書をDER形式に変換
openssl x509 -in uki.crt -out uki.cer -outform DER

uki.key ファイルは命の次に大切に保管してください。このファイルを入手した人は誰でも、お使いのコンピュータが正当なものとして扱う悪意のあるカーネルに署名できてしまいます。

ステップ2:ukifyによるUKIのビルド

ここからが本番です。カーネル(vmlinuz)、initramfs、およびブートパラメータを単一の .efi ファイルにまとめます。ukify の設定ファイルを使用することで、プロセスを再現可能にし、長いコマンド文字列でのタイポを防ぎます。

uki-config.conf という名前のファイルを作成します:

[UKI]
Linux=/boot/vmlinuz-linux
Initrd=/boot/initramfs-linux.img
Cmdline="root=UUID=550e8400-e29b-41d4-a716-446655440000 rw quiet bgrt_disable"
OSRelease=@/etc/os-release
Stub=/usr/lib/systemd/boot/efi/linuxx64.efi.stub

以下のコマンドを実行して、署名前のイメージをビルドします:

/usr/lib/systemd/ukify build --config=uki-config.conf --output=vmlinuz-unsigned.efi

ukify はビルドプロセス中に署名を行うこともできますが、ワークフローを明確にするために、次のステップで手動で署名する方法を説明します。

ステップ3:統合イメージへの署名

次に、暗号スタンプを適用します。このステップでは、EFIバイナリのPEヘッダーに署名を付加します。これにより、ファームウェアは次のステップで登録するキーと照らし合わせてバイナリを検証できるようになります。

sbsign --key uki.key --cert uki.crt --output /boot/EFI/Linux/systemd-linux.efi vmlinuz-unsigned.efi

出力先は /boot/EFI/Linux/ にすることをお勧めします。最近のバージョンの systemd-boot はこのディレクトリを自動的にスキャンします。.efi ファイルが見つかると、手動で設定を追加しなくても自動的にブートメニューに追加されます。

ステップ4:UEFIへのキーの登録

現時点では、マザーボードは uki.crt の存在を知りません。この橋渡しをするには2つの方法があります。

  1. MOK管理: ‘shim’ を使用している場合(UbuntuやFedoraのデフォルト)、mokutil --import uki.cer を使用します。これにより、次回の再起動時にブルー画面のインターフェースが表示され、キーの登録を確認できます。
  2. カスタムキー: UEFI設定で、デフォルトの工場出荷時キーを独自のものに置き換えることができます。これは「玄人向け」の手段であり、最高のセキュリティを提供しますが、メンテナンスに手間がかかります。

ほとんどの環境では、mokutil が最も現実的な選択肢です:

sudo mokutil --import ~/secure-boot-keys/uki.cer

一時的なパスワードを設定して再起動し、UEFI環境で “Enroll MOK” のプロンプトに従ってください。

検証と自動化

検証はパズルの最後のピースです。新しいUKIで再起動したら、セキュリティループが閉じていることを確認する必要があります。

Secure Bootステータスの確認

bootctl を実行して環境を確認します:

bootctl status

Secure Boot: enabled という表示を探してください。これがあれば、カーネルコードが1行でも実行される前に、ファームウェアがUKIの署名を正常に検証したことを意味します。

バイナリ署名の検証

ディスク上のファイルを再確認するには、sbverify を使用します:

sbverify --list /boot/EFI/Linux/systemd-linux.efi

このコマンドは証明書の詳細を表示します。ファイルが改ざんされている場合、検証は即座に失敗します。

ワークフローの効率化

アップデートのたびに手動でカーネルに署名するのは、システムを壊す原因になります network攻撃はブロックしましたが、ネットワークの要塞化は戦いの半分に過ぎないことに気づきました。Arch Linuxでは pacman フックを使用します。他のディストリビューションでは、/etc/kernel/install.d/ 内のスクリプトで ukifysbsign のプロセスを自動化できます。これにより、システムアップデートを実行するたびに、手動操作なしでセキュリティが維持されます。

UKIに移行することで、ブートローダーの設定という単一障害点を排除できます。カーネルとinitrdは、単一の不変なユニットになります。これは従来のアーキテクチャからの大きな飛躍であり、要塞化された Linuxワークステーションにとって不可欠なコンポーネントです。

Share: