Ubuntuで学ぶcapsh活用術:Linuxケーパビリティの確認と権限分離

はじめに

Linux環境においてプロセスが保持する特権を細分化して管理する「ケーパビリティ(Capabilities)」の検証には、専用ラッパーである capsh(Capability Shell Wrapper)が欠かせません。本稿ではUbuntuをベースに、capsh ツールのセットアップ手順からシェルプロセスの権限調査、16進数ビットマスクのデコード、不要な権限の破棄(Drop)、そして非特権ユーザー環境下での最小権限付与といった実務に直結するテクニックを実践形式で解説します。

libcap2-binパッケージの導入と現在のプロセス権限確認 (–print)

Linuxのケーパビリティ操作に必要なバイナリ群を取り揃えた libcap2-bin パッケージを、パッケージマネージャー経由でインストールします。

apt-get update -qq && apt-get install -y libcap2-binの実行

capsh --print を実行すると、現行シェルに割り当てられている各ケーパビリティセット(Effective、Permitted、Boundingなど)や、実行コンテキストにおけるUID、GID、Securebits等の詳細パラメータが網羅的に出力されます。
ターミナル上の結果を精査することで、現在動作しているシェルがシステムに対してどこまでの操作特権を保持しているかを俯瞰できます。
⚙️ [主要オプション]

--print : 現在のプロセスに割り当てられているケーパビリティセットやユーザー/グループID、各種セキュリティビットを一覧表示します。
--drop : バウンディングセット(Bounding set)から特定の権限を恒久的に除外します。
--caps : プロセスに適用するケーパビリティセットを明示的に指定します。
--user : 指定したユーザー・グループのコンテキストに切り替えてコマンドを実行します。
--inh : 継承可能(Inheritable)なケーパビリティセットを構成します。
--addamb : アンビエント(Ambient)セットに特権を追加し、実行ファイルへの特権継承を有効化します。
--secbits : プロセスのセキュアビット(Securebits)フラグを制御し、権限昇格や変更ポリシーを制限します。
--chroot : ルートディレクトリの変更(chroot)を行い、隔離されたファイルシステム空間を立ち上げます。

capsh –printの実行結果

カーネル側の機能サポート検証とビットマスク値のデコード (–supports, –decode)

稼働中のLinuxカーネルが対象のケーパビリティを実装しているかどうかは、--supports オプションで素早く判定可能です。例えば capsh --supports=cap_net_raw を実行すると、カーネルが cap_net_raw に対応していれば標準出力へのテキストを伴わず終了ステータス 0(正常終了)が返されます。

capsh –supports=cap_net_rawの実行結果

システム管理全般に及ぶ強力な権限である cap_sys_admin についても、capsh --supports=cap_sys_admin を用いて有効性を確かめられます。
エラーなく終了することを利用すれば、自動化スクリプトやCIパイプラインにおいて対象ノードの機能サポート状況を事前にアサートする仕組みとして重宝します。

capsh –supports=cap_sys_adminの実行結果

/proc/[PID]/status などのシステムファイルに出力されるケーパビリティ値は、16進数のビットマスクとして表現されています。capsh --decode=0x000001ffffffffff コマンドを通すことで、この機械的なビット列を可読性の高い個々のケーパビリティ名へと変換できます。
デコード出力を確認すれば、cap_chown や cap_sys_admin、cap_bpf など、どの特権ビットが有効化されているのかが一目瞭然となります。

capsh –decode=0x000001ffffffffffの実行結果

バウンディングセットからの権限剥奪とプロセス隔離 (–drop)

プロセスの特権上限を規定するバウンディングセット(Bounding set)から特定機能を削ぎ落とすには --drop を指定します。capsh --drop=cap_chown,cap_setuid --print を実行すると、指定した cap_chown と cap_setuid が恒久的に排除され、Bounding set および Current IAB の一覧から両権限が確実にドロップされた状態を確認できます。

capsh –drop=cap_chown,cap_setuid –printの実行結果

権限を制限したシェルを起動し、その子プロセス側でも制限が維持されているかを確かめるには -- を挟んでコマンドを渡します。capsh --drop=cap_chown -- -c "capsh --print | grep 'Bounding set'" では、cap_chown が除外された環境下で新しいプロセスを立ち上げており、子プロセスのバウンディングセットにもその剥奪状態が安全に引き継がれている様子が読み取れます。

capsh –drop=cap_chown – -c “capsh –print | grep ‘Bounding set’“の実行結果

非特権アカウントへの遷移と個別ケーパビリティの付与 (–user, –caps)

capsh --user=nobody --print は、プロセスの実行コンテキストを低特権アカウントである nobody へと切り替えた上で資格情報を検証するコマンドです。
実行結果からUIDおよびGIDが nobody(65534)へと変化していること、ならびに特別な設定を行わない標準的なユーザー遷移において各種ケーパビリティがどのように制限されるかを把握できます。

capsh –user=nobody –printの実行結果

特権を持たない一般ユーザーに対しても、特定のネットワークポート待機など限定的な権限のみをピンポイントで委譲したいケースがあります。capsh --user=nobody --caps="cap_net_bind_service+ep cap_setpcap-ep" --print を実行すると、nobody 権限へと降格させつつも、特権ポートのバインドに必要な cap_net_bind_service だけを Effective(実行時有効)および Permitted(許可)セットに与えることが可能です。Current 欄に cap_net_bind_service=ep が反映されていることからも、root権限を一切与えずに必要最小限の機能だけを安全に持たせられる仕組みが確認できます。

capsh –user=nobody –caps=“cap_net_bind_service+ep cap_setpcap-ep” –printの実行結果

今回はUbuntu環境を題材に、capsh ユーティリティを用いてLinuxケーパビリティの状態を可視化し、不要な特権を遮断・カスタマイズする実践的なアプローチを紹介しました。
常時root権限に頼る運用から脱却し、デーモンやアプリケーションごとに必要最小限の特権のみを配分することで、より堅牢でセキュアなLinuxインフラを構築してみてください。