PR 本記事には広告(Amazonアソシエイト・もしもアフィリエイト・A8.net等)が含まれます。掲載情報の正確性には努めていますが、商品の詳細は必ずリンク先で最新情報をご確認ください。
CTF・セキュリティ学習

【Linuxカーネル&コンテナエスケープ編】DirtyPipeからDocker socketまで|CTF思考フレームワーク #38

かも次郎とアンペンが「コンテナ脱出」を解説するマスコットイラスト
安全に生きたい編集部

こんにちは、アンペンです!

前回は、奪った認証情報を使って隣の端末へ進む横展開を扱いました。

今回は、Linuxカーネルやコンテナの『隔離の壁』を突破するカーネル脆弱性とコンテナエスケープを見ていきます。DirtyPipeからDocker socket悪用まで、隔離が崩れる経路と守り方を学びましょう。

コンテナって隔離されてるから安全なんじゃないの?

隔離はカーネル機能で実現してるから、カーネルの脆弱性や、コンテナの設定ミスがあると壁が薄くなるんだ。

『コンテナは隔離されているから安全』——よく聞く言葉ですが、今日はその“隔離”がどこまで本物か、を確かめる回です。結論から言うと、コンテナの壁は、状況しだいで意外と薄くなります。なぜなら、その壁を支えているのが“ホストと共有しているカーネル”だから。今日は借家と大家のマスターキーのたとえで、壁が崩れる経路と、それを厚く保つ運用を見ていきます。

まず結論

コンテナの隔離はLinuxカーネルが提供しています。だから、カーネル脆弱性(DirtyPipe等)・privileged コンテナ・docker.sock マウントなどの設定ミスがあると、コンテナの外(ホスト)に脱出されます。守りはパッチ・rootless・seccomp/AppArmor・最小権限コンテナの組み合わせです。

この記事で分かること

  • コンテナ隔離の仕組みと、なぜ壁が薄くなるか
  • カーネル脆弱性とコンテナ設定ミスの代表3経路
  • rootless・seccomp・AppArmor等の守り方
難易度:上級向け 所要時間:11分 体験:コンテナ設定を点検 おすすめ:#37の後

📖 はじめてのWebセキュリティ #38|Linuxカーネル&コンテナエスケープ編
『隔離されている』前提が崩れる経路を、運用観点で学びます。 シリーズ一覧を見る →

⚠️ 大事なお約束
カーネル脆弱性のPoCやコンテナエスケープの試験は、自分が管理する検証環境・CTFのみで行ってください。共有サーバや他社環境での実行は不正アクセスに該当します。

コンテナ隔離は『カーネルが頑張っている』

コンテナは、Linuxカーネルの機能(namespace・cgroups・capabilities)で『見えているリソースを限定する』仕組みです。仮想化技術ではなく、カーネルそのものを共有している点が、安全境界の弱点になり得ます。

カーネルに脆弱性があれば、コンテナ内のプロセスが特権を取り、ホストOSの世界に到達します。さらに、コンテナの設定ミスでも隔離は崩れます。

壁が崩れる道は、大きく2つに分かれます。一つは『土台のヒビ』——カーネル自体の脆弱性を突かれるケース。もう一つは、もっと多くて、もっと防ぎやすい『鍵の置き忘れ』——コンテナの設定ミスです。実は現場で起きるコンテナ脱出の多くは、後者。高度なカーネル攻撃ではなく、“うっかり強すぎる権限で動かしていた”という設定の問題なんです。だからこそ、設定の見直しがよく効きます。

ここで、コンテナと仮想マシン(VM)の違いを押さえておきましょう。VMは、ハードウェアごと丸ごと別に作る“独立した一軒家”です。一方コンテナは、一棟のマンション(=ホストのカーネル)を壁で仕切った“各部屋”。住人ごとに部屋は分かれていても、建物の土台(カーネル)は全員で共有しています。だから、土台そのものにヒビ(カーネル脆弱性)が入ると、部屋の壁だけ頑丈でも意味がなくなる。これがコンテナ隔離の“弱点”の正体です。

図解:通常の隔離 vs 脱出後

コンテナが正しく隔離されている状態と、エスケープでホストに到達してしまう状態を比較した図
カーネル脆弱性や設定ミスが壁を薄くする。

本来コンテナは『ホストの一区画』ですが、脱出が成立するとホスト全体に到達してしまいます。

借家の中に大家のマスターキーが置いてあり、他の部屋まで開けられてしまうたとえ図
借家の中にマスターキーがあると他の部屋まで開いてしまう。コンテナ内のdocker.sockと同じ構造。
🏘️ たとえるなら、借家と大家のマスターキー

借家は、本来は壁とドアで区切られています。でも、大家のマスターキー(=ホストの管理権限)が借家の中に置いてあったら、ちょっと探せば住人がそれを使って他の部屋にも入れます。コンテナの中にホスト操作の鍵(docker.sock等)を渡すのは、まさにこの状況です。

ここで覚える用語:privileged コンテナ
Dockerなどで --privileged オプションを付けて起動したコンテナ。capabilities がほぼ全部許可され、ホストデバイスへのアクセスも開かれます。便利な反面、エスケープの足場が大量に手に入る危険な構成です。原則として本番では使いません。

--privileged は、たとえるなら『借家の住人に、建物全体のマスターキーを最初から渡してしまう』ようなもの。たしかに何でもできて便利ですが、その住人(コンテナ)が乗っ取られた瞬間、建物まるごと攻撃者の手に落ちます。デバッグや特殊用途でつい付けたまま本番に……というのが事故の典型。「便利だから」で渡した強い権限は、そっくりそのまま“脱出の足場”になる、と覚えておきましょう。

隔離を崩す代表3経路

コンテナ脱出の代表的な道は3つ。『土台のヒビを突く(カーネル脆弱性)』『建物の管理キーを部屋に置く(docker.sockのマウント)』『最初から壁を取り払う(privilegedや各種host共有)』。とくに2つ目のdocker.sockは見落としがち。これをコンテナの中に渡すと、その中から“新しいコンテナをホスト上で自由に起動”できてしまい、実質ホスト乗っ取りと同じになります。

よくある脱出パターン

カーネル脆弱性・docker.sockマウント・privileged/hostPIDの3つの脱出経路を示したカード型インフォグラフィック
①カーネル脆弱性 ②docker.sock ③privileged。守りはパッチ+rootless+seccomp+最小権限。
  • カーネル脆弱性悪用:DirtyPipe(CVE-2022-0847)・DirtyCow(CVE-2016-5195)等で特権昇格
  • docker.sock マウント:コンテナに /var/run/docker.sock をマウントしていると、コンテナからホスト上で任意コンテナ起動が可能
  • privileged / hostPID / hostNetwork:過剰な権限・名前空間共有でホストプロセスやネットワークに到達

これらは『コードの脆弱性』ではなく『設定の問題』も多いため、運用レビュー・IaCの自動チェックで早期に潰すことが重要です。

ここがこの回のいちばんの救い、でもあります。多くのコンテナ脱出は“設定の問題”なので、コードを直す必要すらない。設定ファイルを正すだけで防げるんです。しかも今は、その設定を“人の目”でなく“機械”でチェックできます。コンテナの定義(Dockerfileやマニフェスト)を自動スキャンして、「privilegedが付いてる」「docker.sockをマウントしてる」と警告してくれるツール(IaCスキャン)がある。守りを“仕組み化”できる、数少ない領域なんです。

練習は、自分のコンテナ環境の“隔離レベル”を点検すること。--privileged を使っていないか、docker.sockを渡していないか、権限を絞れているか——攻撃ではなく設定の健康診断ですね。カーネルのPoC(実証コード)を共有サーバや他社環境で動かすのは厳禁。必ず自分の検証環境の中だけで確かめましょう。

CTFでやってみよう:コンテナ設定を点検

やってみよう / 自分の環境・CTFのみ

自分のコンテナ環境で、設定上の隔離レベルを確認しよう

目的は実際の脱出ではなく、『隔離がどれくらい薄くなっていないか』を可視化することです。

  1. 本番で --privilegedhostPID / hostNetwork を使っていないか確認
  2. コンテナへの docker.sock マウントの有無を確認(必要ならread-only等の代替検討)
  3. capabilities が最小化されているか(--cap-drop=ALL ベース)を確認
  4. seccomp/AppArmor/SELinux プロファイルが有効か確認
  5. ホストOS・コンテナランタイムが最新パッチか、Trivy等で脆弱性スキャンする
共有環境・他社環境のホスト上でカーネルPoCを実行することは絶対にやめてください。確認は自分の検証環境だけです。

守りの柱の一つ『rootless(非root実行)』について、会話で補足します。

コンテナの中のrootって、ホストのrootとは別物でしょ?気にしなくていいんじゃない?

鋭い疑問。基本は別物なんだけど、“万一壁が破られたとき”が問題なんだ。コンテナ内でrootとして動いていると、脱出した瞬間にホストでも強い権限を持ちやすい。逆に、コンテナを最初から“ただの一般ユーザ”で動かしておけば(rootless)、たとえ壁を抜けても、その先でできることがぐっと限られる。これも“破られた後の被害を小さくする”という、前回までと同じ考え方。コンテナの中でも、わざわざrootでいる必要はないんだよ。

守る側なら、「パッチ+rootless+seccomp+最小権限」

コンテナエスケープの守りは、「カーネルとランタイムのパッチ最新化」「rootless / 非root実行」「seccomp/AppArmor で syscall を絞る」「最小権限コンテナ」の4本柱で組みます。

守るための基本チェック
  • ホストOS・コンテナランタイム・カーネルを最新パッチに保つ
  • コンテナは原則非rootユーザで動かす(USER設定・rootless Docker/Podman活用)
  • --privileged / hostPID / hostNetwork / hostPath を本番で使わない
  • capabilities を --cap-drop=ALL から必要分だけ追加する
  • seccomp・AppArmor・SELinux プロファイルを必須化
  • イメージは信頼レジストリから、署名(Cosign等)で改ざん検出

『コンテナだから安心』じゃなくて、『コンテナを安全に保つ運用』が必要なんだね。

そう。隔離はカーネルと運用が両輪。設定ミス1つで壁が薄くなることを意識しよう。

ここまでをひと言で言うと、コンテナの守りは『隔離は“運用で”保つ』。コンテナは置いただけで安全な箱ではなく、土台(カーネル)にパッチを当て続け、権限を最小に絞り、設定を機械でチェックして、はじめて壁が厚いまま保たれます。“コンテナ=安全”ではなく“コンテナ=正しく運用すれば安全”——この一語の違いが大事です。

まとめ:『隔離は運用で保つ』

今回のポイント
  • コンテナ隔離はカーネル機能で実現されている
  • カーネル脆弱性・docker.sock・privilegedが代表脱出経路
  • 守りはパッチ+rootless+seccomp+最小権限
  • 設定の自動チェック(IaC scan)を運用に組み込む

今日の持ち帰りは『便利な強権限は、脱出の足場になる』です。privilegedも、docker.sockも、付ければ確かに便利。でもその便利さは、攻撃者にとっての“出口”でもあります。本番では強い権限を渡さない、土台は最新に保つ、設定は自動でチェックする。“壁の厚さは、運用で決まる”——これがコンテナ防御の核心です。

次回は、攻撃者が侵入後に居座るための永続化(Persistence)を扱います。cron・systemd・scheduled task・WMIで居座る手口と検知を見ていきましょう。

次に読みたい記事

参考資料

記事URLをコピーしました