
Flatpakおよび類似プロジェクトで使用される低レベルの非特権サンドボックスツール
systemd-nspawn、docker などの多くのコンテナランタイムツールは、システム管理者やオーケストレーションツール(例: Kubernetes)がコンテナを実行するためのインフラストラクチャを提供することに焦点を当てています。
これらのツールは、特権のないユーザーに渡すのには適していません。なぜなら、そのようなアクセスをホスト上の完全に特権化されたrootシェルに変えるのは簡単だからです。
Linuxカーネルには、特権のないユーザーがコンテナ機能を使用できるようにする ユーザー名前空間 と呼ばれる機能があります。Bubblewrapはこれらを使用してサンドボックスを構築し、あらゆるユーザーがこのツールを使用できるようにします。
歴史的に、bubblewrapは特権のないユーザー名前空間がサポートされていないシステム向けにsetuidモードもサポートしていました。ただし、これは削除されました。
元のbubblewrapコードはユーザー名前空間より前に存在していました。これは xdg-app helper からコードを引き継いでおり、さらに遠い祖先は linux-user-chroot に由来します。
このツールのメンテナは、このツールが、そのディストリビューションにインストールされている典型的なソフトウェアと組み合わせて使用された場合でも、権限昇格を許可しないと考えています。ただし、ログインしたユーザーがサービス拒否攻撃を実行する能力を高める可能性はあります。
特に、bubblewrapは PR_SET_NO_NEW_PRIVS を使用してsetuidバイナリを無効にします。これは、chrootなどの環境から抜け出すための 伝統的な方法 です。
bubblewrapはサンドボックス環境を構築するためのツールです。 bubblewrapは、特定のセキュリティポリシーを持つ完全で既成のサンドボックスではありません。
bubblewrapのユースケースの中には、サンドボックスと実システムの間にセキュリティ境界を設けたいものがあります。また、サンドボックス内のプロセスのためにファイルシステムのレイアウトを変更する機能を望むが、セキュリティ境界を目的としないユースケースもあります。 その結果、サンドボックス化されたプロセスとホストシステムの間の保護レベルは、bubblewrapに渡される引数によって完全に決定されます。
bubblewrapのコマンドライン引数を構築するプログラム(多くの場合、Flatpak、libgnome-desktop、sandwine、またはアドホックなスクリプトなどのより大きなフレームワーク)は、独自のセキュリティモデルを定義し、そのセキュリティモデルを実装するための適切なbubblewrapコマンドライン引数を選択する責任があります。
特に注意が必要なサンドボックスセキュリティのいくつかの側面は、以下の 制限事項 セクションで説明されています。
このプログラムは、非root操作を実行するすべてのコンテナツールで共有できます。例:
また、Kubernetes/OpenShiftクラスターでこれを利用できるようにしたいと考えています。特権のないユーザーがコンテナ機能を使用できるようにすることは、インタラクティブなデバッグシナリオなどを大幅に容易にします。
bubblewrapはほとんどのLinuxディストリビューションのパッケージリポジトリで利用でき、そこからインストールできます。
ソースからbubblewrapをビルドする必要がある場合は、mesonを使用して行うことができます:
meson _builddir
meson compile -C _builddir
meson test -C _builddir
meson install -C _builddir
bubblewrapは、ルートがホストからは見えないtmpfs上にある、完全に空の新しいマウント名前空間を作成することで機能し、最後のプロセスが終了すると自動的にクリーンアップされます。その後、コマンドラインオプションを使用して、ルートファイルシステム、プロセス環境、および名前空間内で実行するコマンドを構築できます。
ソースコードにはより大きな デモスクリプト がありますが、ここではホストの /usr を再利用して新しいシェルを実行するトリミング版を示します。
bwrap \
--ro-bind /usr /usr \
--symlink usr/lib64 /lib64 \
--proc /proc \
--dev /dev \
--unshare-pid \
--new-session \
bash
これは不完全な例ですが、説明の目的には役立ちます。多くの場合、ホストのファイルシステムツリーを使用してコンテナを作成するのではなく、chrootをターゲットにしたいと思うでしょう。その場合、tmpfs内にシンボリックリンク lib64 -> usr/lib64 を作成するのではなく、ターゲットのrootfs内にすでに作成しているかもしれません。
bubblewrapの目標は、ホームディレクトリなどのオペレーティングシステムやユーザーデータの一部へのアクセスが制限されたサンドボックス内でアプリケーションを実行することです。
bubblewrapは常に新しいマウント名前空間を作成し、ユーザーはサンドボックス内でファイルシステムのどの部分を表示するかを正確に指定できます。指定したそのようなディレクトリはすべてデフォルトで nodev でマウントされ、読み取り専用にすることができます。
さらに、次のカーネル機能を使用できます:
ユーザー名前空間 (CLONE_NEWUSER): これにより、サンドボックスから現在のuidとgid以外のすべてが隠されます。サンドボックス内のuid/gidの値を変更することもできます。
IPC名前空間 (CLONE_NEWIPC): サンドボックスは、SysV共有メモリやセマフォなど、さまざまな形式のIPCすべての独自のコピーを取得します。
PID名前空間 (CLONE_NEWPID): サンドボックスはサンドボックス外のプロセスを一切見ることができません。さらに、bubblewrapはコンテナ内で簡単なpid1を実行し、サンドボックス内の子プロセスの回収という要件を処理します。これにより、現在 Docker pid 1問題 として知られているものを回避します。
ネットワーク名前空間 (CLONE_NEWNET): サンドボックスはネットワークを見ることができません。代わりに、ループバックデバイスのみを備えた独自のネットワーク名前空間を持ちます。
UTS名前空間 (CLONE_NEWUTS): サンドボックスは独自のホスト名を持ちます。
Seccompフィルター: サンドボックス内で実行できるsyscallを制限するseccompフィルターを渡すことができます。詳細については、Seccomp を参照してください。
上記の サンドボックスセキュリティ セクションで述べたように、サンドボックス化されたプロセスとホストシステムの間の保護レベルは、bubblewrapに渡される引数によって完全に決定されます。特別な注意が必要ないくつかの側面をここに示します。
seccompフィルターを使用して TIOCSTI コマンドをフィルタリングしていない場合、サンドボックス外でのコマンド実行から保護するために引数 --new-session が必要です
(CVE-2017-5226 を参照)。
サンドボックスにマウントされたものはすべて、権限昇格に使用される可能性があります。 たとえば、D-Busソケットをサンドボックスにバインドすると、systemdを介してコマンドを実行するために使用できます。xdg-dbus-proxy を使用してD-Bus通信をフィルタリングできます。
一部のアプリケーションは独自のサンドボックス化メカニズムを展開しており、これらはbubblewrapのサンドボックス化によって課される制約によって制限される可能性があります。 たとえば、seccompを介して子プロセスがファイルシステムにアクセスできないように構成する一部のWebブラウザーがあります。syscallを制限してseccomp syscallを許可しない場合、ブラウザーはこれらの制限を適用できません。同様に、これらのルールがサンドボックス内で利用できないファイルにコンパイルされている場合、ブラウザーはこのファイルからこれらのルールをロードできず、これらの制限を適用できません。
Firejail は、bubblewrapが分割される前のFlatpakに似ており、setuidツールとデスクトップ固有のサンドボックス化機能の多くを組み合わせています。たとえば、FirejailはPulseaudioを認識しますが、bubblewrapは認識しません。
bubblewrapの作者は、小さなsetuidプログラムを監査する方がはるかに簡単であり、Pulseaudioフィルタリングなどの機能を、現在Flatpakで行われているように、非特権プロセスとして維持する方が良いと考えています。
また、@cgwaltersは、ユーザーがパスを操作する無数の方法と、システム管理者がシステムを構成する無数の方法を考えると、ファイルパスのホワイトリスト化 を試みるのは悪い考えだと考えています。bubblewrapのアプローチは、CAP_SYS_ADMIN などのいくつかの特定のLinuxケーパビリティのみを保持し、ファイルシステムには常に呼び出し元のuidとしてアクセスすることです。これにより、TOCTTOU攻撃 などが完全に封じられます。
Sandstorm.io はサンドボックスをセットアップするために特権のないユーザー名前空間を必要としますが、setuidモードで動作するように簡単に適応させることもできます。@cgwaltersは彼らのコードはかなり良いと考えていますが、bubblewrapに統一することも依然として理にかなっているかもしれません。ただし、(Sandstormの)@kentonvは、これは原則的には理にかなっているが、現時点では切り替えコストが実用的な利益を上回ると感じています。この決定は将来再評価される可能性がありますが、現在積極的に追求されてはいません。
runC は現在、runCのインストール、作成、およびコンテナの管理の際に setuid やその他の特権を必要とせずに( setuid ではなく特権のないユーザー名前空間を使用して)、ルートレスコンテナ のサポートに取り組んでいます。ただし、runCの標準的な使用方法は、rootによって呼び出されることを意図したツールであるという点で systemd nspawn に似ています。
bubblewrapの作者は、runcとsystemd-nspawnはsetuidにされるように設計されておらず、そのようなモードのサポートにはほど遠いと考えています。ただし、ルートレスコンテナを使用すると、runCはbubblewrapがサポートする特定のユースケースを満たすことができます(標準化された完全なOCIランタイムであるという追加の利点があります)。
binctr はrunCの単なるラッパーであるため、その設計上のトレードオフをすべて引き継いでいます。
bubblewrapという名前は、このツールがアプリケーションの親として実行され(ある意味でアプリケーションをラップし)、その周囲に保護層(サンドボックス)を作成することを伝えるために選ばれました。

(Bubblewrapの猫: dancing_stupidity)