コンテナを root として実行することは、本番環境における最も一般的で最も危険な設定ミスの一つです。それは静かに全てのワークロードの攻撃面を拡大し、インシデントが問題を浮き彫りにするまで、ほとんどのチームはそのことに気づきません。
「Root として実行」が実際に意味するもの
デフォルトでは、多くのコンテナイメージ(特に最小限のものやレガシーなもの)が、コンテナ内部でメインプロセスを UID 0 として実行します。コンテナは他のコンテナおよびホスト自体とホストカーネルを共有しているため、コンテナ内の root は完全に分離された仮想マシン上の root と同じではありませんが、それでも本来あるべき以上に強力です。攻撃者が root 所有のコンテナ内でコード実行を達成すると、以下を継承します:
- コンテナにマウントされたあらゆるファイルへの完全な読み取り/書き込みアクセス(意図されたパーミッションに関係なく)
- パッケージのインストール、バイナリの変更、アプリケーション状態の改ざんができる能力
- カーネルまたはランタイムの脆弱性が悪用可能な場合、コンテナ脱出へのより簡単な経路
- マウントされた Docker ソケットやホストファイルシステムパスのような設定ミスのあるボリュームと組み合わせたときの、より大きなレバレッジ
カーネルエクスプロイトがなくても、コンテナ内の root アクセスは、あらゆるアプリケーションレベルの脆弱性(SSRF、デシリアライゼーションバグ、任意ファイル書き込みなど)の爆発範囲を劇的に増加させます。
オーケストレーション環境でこれがさらに重要な理由
Kubernetes クラスタで、root コンテナと過度な Linux ケーパビリティまたは許容的なセキュリティコンテキストの組み合わせにより、攻撃者は以下が可能になります:
- ホストに影響を与える方法で
/procまたは/sysを変更する hostPID、hostNetwork、またはhostIPCが有効な場合、権限をエスカレートする- マウントされたサービスアカウントトークンを悪用してクラスタ全体にラテラルムーブメントする
privileged: trueが設定されているか、SYS_ADMINのような危険なケーパビリティが付与されている場合、ノードにエスケープする
root ユーザー自体が常に脆弱性であるわけではなく、コンテナ内の侵害をクラスタ全体の侵害に変える原因は、root に加えて過度に寛容なカーネルケーパビリティ、ホストマウント、またはネームスペース共有の組み合わせです。
実用的なハードニング手順
1. イメージに非 Root ユーザーを設定する
デフォルトに依存するのではなく、Dockerfile で明示的に非 root ユーザーを定義します:
FROM node:20-slim
RUN useradd --uid 10001 --shell /usr/sbin/nologin appuser
USER appuser
2. オーケストレーター レベルで強制する
イメージを信頼するだけではなく、実行時にポリシーを強制します。Kubernetes では、securityContext を使用します:
securityContext:
runAsNonRoot: true
runAsUser: 10001
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"]
runAsNonRoot: true により、イメージが UID 0 として実行しようとした場合、ポッドはアドミッション時に失敗し、ベストエフォート慣例ではなくハード保証が得られます。
3. 不要なケーパビリティを削除する
ほとんどのアプリケーションは、コンテナに付与されるデフォルト Linux ケーパビリティを必要としません。すべてを削除し、厳密に必要なもののみを追加します(低いポート へのバインディングなどのレアケースでは NET_BIND_SERVICE が必要な場合があります)。
4. 特権モードとホスト ネームスペース共有を避ける
privileged: true、hostNetwork: true、および hostPID: true は、非常に特定のインフラストラクチャ ワークロード(特定の CNI またはモニタリングエージェントなど)のために予約すべきであり、一般的なアプリケーション コンテナには決して使用しません。
5. ポリシーツールでスキャンと強制を行う
アドミッションコントローラーまたはポリシーエンジン(例:Kyverno、OPA/Gatekeneeper)を使用して、手動コードレビューに依存するのではなく、これらのルールに違反するデプロイメントを自動的に拒否します。これを CI のイメージスキャニングと組み合わせて、root ユーザーイメージがクラスタに到達する前に検出します。
完璧ではなく、層状の防御
非 root として実行しても、リスクは完全には排除されません。カーネルレベルのコンテナエスケープはコンテナ内ユーザーとは独立して存在しますが、低いハードルの権限エスカレーションおよびラテラルムーブメント技法の膨大なクラスを削除します。読み取り専用ファイルシステム、削除されたケーパビリティ、制限的なネットワークポリシーと組み合わせると、防御深層戦略におけるコンテナセキュリティの最も安価で最も効果的な層の一つを形成します。
クラウドネイティブ ワークロードのハードニングについてさらに深く知りたいですか?Korra Studio の Cloud security および DevOps パイプラインハードニングに関連するセグメントを探索して、防御深層戦略の残りの部分を構築してください。