現場のエンジニア諸君、今日もサーバーのログと睨めっこしているか?
セキュリティの現場では、ルールを暗記するだけでは不十分だ。攻撃者は「設定の隙間」ではなく「設計の怠慢」を突いてくる。
今日は、Dockerを運用するエンジニアなら一度は耳にする、しかし多くの現場で放置されている「Dockerデーモンソケットの保護」について、現場の知見を叩き込む。
—
1. なぜ /var/run/docker.sock は「パンドラの箱」なのか
結論から言おう。Dockerソケットをコンテナにマウントさせることは、「ホストOSの管理者権限をコンテナ内のプロセスにプレゼントする」ことと同義だ。
攻撃者から見た景色(PoCの視点)
攻撃者は、Webアプリの脆弱性(RCEなど)を突いてコンテナ内に侵入した後、真っ先に /var/run/docker.sock が存在するかを確認する。もし存在すれば、以下のようなコマンドを叩くだけでホストを掌握する。
# コンテナ内からホストのルートディレクトリをマウントした特権コンテナを起動する
docker run -v /:/host --rm -it alpine chroot /host
これだけで攻撃者はホストOSの /etc/shadow を書き換え、SSH鍵を仕込み、バックドアを設置する。Dockerデーモンはroot権限で動作しているため、ソケットを握ることは「Dockerの神になる」ことと同じなのだ。
—
2. 実践的な要塞化:Dockerソケットを守る3つの鉄則
現場で戦うための具体的な防御戦略を授ける。
鉄則1:不要なソケット公開は即刻停止
デフォルトでは、DockerはUNIXソケットのみを使用する。これをネットワーク経由(TCP)で公開してはいけない。「APIを叩きたいから」といって 0.0.0.0:2375 を開くのは、玄関の鍵を開けて「ご自由にどうぞ」と言っているのと変わらない。
鉄則2:TLS認証を強制する
どうしてもリモートからAPIを叩く必要がある場合は、TLSによる相互認証(mTLS)が必須だ。自己署名証明書で構わないので、CAを構築し、クライアントとサーバーで証明書を検証させる。
鉄則3:Unixソケットのパーミッション制御
もしDockerソケットをコンテナにマウントせざるを得ない特異な構成(CI/CDのRunner等)であれば、グループ権限を厳密に管理しろ。
—
3. 実装サンプル:TLSを用いた安全なDocker API通信
リモートからAPIを操作する場合の、Pythonを用いたセキュアな接続例だ。生のHTTP通信ではなく、証明書を指定したセッションを構築する。
import docker
# クライアント側でのセキュアな接続実装例
# 事前に生成したCA証明書、クライアント証明書、秘密鍵を指定する
tls_config = docker.tls.TLSConfig(
client_cert=('/path/to/client-cert.pem', '/path/to/client-key.pem'),
ca_cert='/path/to/ca.pem',
verify=True # 証明書の検証を強制する
)
# Dockerデーモンへの接続(TCP経由)
client = docker.DockerClient(
base_url='tcp://your-docker-host:2376',
tls=tls_config
)
# コンテナ一覧を取得してみる
try:
for container in client.containers.list():
print(f"Container Name: {container.name}")
except Exception as e:
print(f"セキュアな接続に失敗しました: {e}")
—
4. 運用上の「盲点」:Dockerソケットの権限確認
エンジニアとして、今すぐ自分のサーバーで以下のコマンドを叩いてみてくれ。
ls -l /var/run/docker.sock
もし所有者が root:docker で、権限が srw-rw---- (660)であれば、docker グループに所属しているユーザーは誰でもホストを乗っ取れる。
現場でのTips:
もしCI/CDツールなどでDockerを利用する必要がある場合は、ソケットをマウントするのではなく、docker-in-docker (dind) を使うか、あるいはDocker APIをリバースプロキシ(Nginx)越しに特定の権限で制限する構成を検討しろ。
NginxでAPIをフィルタリングする例
# Docker APIへのアクセスを特定のメソッドのみに制限する設定例
location /containers/ {
# GET以外(POSTやDELETE)は拒否する設定を入れる
if ($request_method !~ ^(GET)$ ) {
return 403;
}
proxy_pass http://unix:/var/run/docker.sock;
}
—
最後の忠告
セキュリティとは「一度設定して終わり」のタスクではない。コンテナ技術は便利だが、その利便性は「ホストとの境界を曖昧にする」リスクと背中合わせだ。
- ソケットは極力マウントするな。
- マウントするなら権限を最小化しろ。
- リモートAPIはmTLSで武装しろ。
この3つを守るだけで、君のインフラは攻撃者にとって「割に合わないターゲット」に格上げされる。脆弱なシステムを放置して後悔する前に、今すぐ設定を見直してくれ。現場からは以上だ。健闘を祈る。
コメント