【テクニカル・上級編】 Dockerデーモンソケットの保護とTCP/Unixソケットのアクセス制御 – インフラ・ネットワーク & クラウドセキュリティ防御ガイド

Dockerソケットという「パンドラの箱」:権限管理の聖域と現実解

セキュリティの現場で長年、数多くのペネトレーションテストやインシデントレスポンスを担当してきて痛感するのは、「Dockerデーモンソケット(/var/run/docker.sock)を野晒しにしている環境は、玄関に鍵をかけず、かつ中身が丸見えの金庫を置いているようなものだ」という事実だ。

このソケットは、Docker APIの基盤であり、コンテナのライフサイクルを制御する神の権限(root権限)と直結している。これを不用意に露出させることは、OSのカーネルメモリへの直接的攻撃、あるいはホストからのコンテナ脱出(Container Escape)を許容する最大の入り口となる。

1. なぜ「Docker脱出」はこれほどまでに安易なのか

攻撃者の視点から見れば、コンテナ内のプロセスが docker.sock をマウントしている状況は、事実上の「ホストOSへのシェルアクセス」と同義だ。

プロセスがコンテナ内で実行されていても、docker run -v /var/run/docker.sock:/var/run/docker.sock ... といった設定があれば、コンテナ内からホスト上のDockerデーモンを操作できる。攻撃者は、以下のようなコマンドを叩くだけでホストのルート権限を奪取する。

# コンテナ内からホストのルートディレクトリをマウントしてシェルを奪取する例
docker run -it -v /:/host alpine chroot /host /bin/bash

この攻撃手法は、カーネルの脆弱性(CVE-2019-5736など)を利用して runc を上書きし、ホスト側のプロセスを乗っ取る手法へと進化している。メモリレベルでは、ランタイムのバイナリ実行中にファイルディスクリプタを操作し、ホスト側の実行ファイルを標的にする。これはもはや設定ミスというより、設計上の「物理的な近道」を許してしまっている状態だ。

2. Unixソケットの権限管理と「最小権限の原則」

まず、最も基本的な防御策は「誰がソケットに触れるか」を物理的に制限することだ。docker グループにユーザーを追加することは、実質的にそのユーザーを root にすることと同義である。

監査の際は、以下のコマンドで現在このソケットにアクセス権を持つユーザーを特定せよ。

# Dockerソケットの所有者と権限を確認
ls -l /var/run/docker.sock
# 出力例: srw-rw---- 1 root docker ...
# この場合、dockerグループに属する全ユーザーがホスト権限を持つ

もし、CI/CDパイプラインなどでDockerが必要な場合、ソケットを直接渡すのではなく、docker-socket-proxy のようなプロキシ層を挟むことが必須となる。これは特定のAPIメソッド(例えば GET のみ許可し、POST や DELETE を弾く)を制限するガードレイルとして機能する。

3. リモートAPIのTLS認証強制:プロトコルの要塞化

ネットワーク経由でDocker APIを公開する場合、平文のTCPポート(2375)を開放するなど言語道断だ。攻撃者はパケット解析により、コンテナの構成情報や環境変数(DBパスワードやAPI鍵を含む)を瞬時に窃取する。

必ず相互TLS(mTLS)を強制し、CA証明書を介した認証を実装する必要がある。daemon.json の設定は以下の通りだ。

{
  "tls": true,
  "tlscacert": "/etc/docker/ca.pem",
  "tlscert": "/etc/docker/server-cert.pem",
  "tlskey": "/etc/docker/server-key.pem",
  "tlsverify": true,
  "hosts": ["tcp://0.0.0.0:2376", "unix:///var/run/docker.sock"]
}

ここで重要なのは、証明書の有効期限管理と失効リスト(CRL)の配布だ。将来的な耐量子暗号(PQC)への移行を見据えるならば、現在はRSA 4096bit以上の鍵長、あるいはECDSA(P-384)を採用し、将来のアルゴリズム切り替えに備えたインフラの抽象化(PKI基盤の分離)を設計しておくべきだ。

4. アーキテクトが講じるべき「最後の一手」

単なる設定変更だけでは、現代の巧妙な攻撃(サイドチャネル攻撃やプロンプトインジェクションによるコンテナ操作)を防ぐには不十分だ。以下の多層防御を推奨する。

1. gVisor または Kata Containers の採用:
Dockerデーモンとホストカーネルの間にサンドボックス層を設ける。これにより、仮にソケットを悪用されても、システムコールがホストカーネルに直接到達するのを防ぐ。
2. Seccompプロファイルの厳格化:
デフォルトのプロファイルに依存せず、必要なシステムコールのみを許可するホワイトリスト形式のSeccompプロファイルをコンテナごとに適用せよ。
3. 生成AIによるガードレイル:
もしDocker APIを操作するAIエージェントを構築しているなら、API呼び出しの前にプロンプトの意図を検証するガードレイル(例:NeMo Guardrails 等)を配置し、exec や volume mount を含む危険な命令を動的にブロックする構造を構築すること。

結びに代えて

セキュリティとは、「完璧な防御」を目指すことではない。攻撃者がコストを支払うことを嫌がり、別のターゲットへ向かうような「高コストな防御壁」を積み上げることだ。

/var/run/docker.sock は、あなたの環境の心臓部だ。そこを保護することは、単なるOSのハーデニングを超え、組織全体の信頼性を担保するインフラエンジニアとしての矜持である。今すぐ本番環境のソケット権限を確認し、不要なプロセスの特権を剥奪せよ。それが、今日から始められる最優先のタスクであるはずだ。

コメント

タイトルとURLをコピーしました