CVE-2020-15257:新たな脆弱性、containerd-shim API を悪用 #aqua #コンテナ #セキュリティ #脆弱性 #containerd #CVE-2020-15257
この記事は1年以上前に投稿されました。情報が古い可能性がありますので、ご注意ください。
本ブログは「Aqua Security」社の技術ブログで2020年12月17日に公開された「 CVE-2020-15257: New Vulnerability Exploits containerd-shim API 」の日本語翻訳です。
CVE-2020-15257:新たな脆弱性、containerd-shim API を悪用
containerd に新たな脆弱性が発見されました(CVE-2020-15257)。これが悪用されると、コンテナを介してホストネットワークへの接続に成功した後、攻撃者はホスト上の root 権限を取得できます。この脆弱性は NCC Group 社の Jeff Dileo 氏によって開示されたものであり、Team Nautilus による調査結果とも一致しました。
Containerd は、Docker と Kubernetes の基礎となる業界標準のコンテナランタイムです。イメージの転送と保管、コンテナの実行と監視、ネットワークのアタッチメントなど、ホストシステムのコンテナライフサイクルを管理できます。Containerd-shim はコンテナを管理する containerd の子プロセスで、containerd-shim API を介してコンテナライフサイクルの各機能を containerd に公開します。
この API は、root ネットワークの名前空間からアクセス可能な抽象的な名前空間 UNIX ドメインソケットを介して公開されます。このためホストネットワークと UID 0 を持つコンテナは、この API へのアクセス・containerd-shim による特権コンテナの実行・特権取得の有効化・ホスト上での root 権限の確立など、悪意のあるアクションを実行できます。
ホストネットワーク名前空間でのコンテナの実行は、以下の方法で行います。
- Docker: docker run --net=host
- Kubernetes: .spec.hostNetwork: true
詳細に掘り下げる
抽象的な名前空間 UNIX ドメインソケットの使用が、この脆弱性につながる主な原因でした。通常の UNIX ドメインソケットはファイルパスにバインドされており、他のファイルと同様にパーミッションを持っています。しかし抽象的な UNIX ソケットは、ネットワークの名前空間にバインドされており、「パーミッションレス」となっています。これらはすべて「@」記号で始まる NULL バイトのファイルなので、netstat コマンドの実行で容易に見つけられます。
ファイルシステム上のパスに接続されたいくつかの UNIX ドメインソケットを見ることができますが、「@/containerd-shim/.sock@」の形式で抽象的な名前空間 UNIX ソケットが確認できます(このシステム上で実行されている各 docker コンテナにつき、1つずつ)。前述したように、これらのソケットはパーミッションレスです。これらのソケットにはアクセス制御が組み込まれていないことを意味するので、認証や認可はこれらのソケットをリッスンするプロセスで処理する必要があります。残念ながら、接続しているユーザが containerd-shim を実行しているユーザと同じであるか否かだけがチェックされます。
悪用の流れ
では、containerd-shim API と通信できることを考えると、この API は何を提供しているのでしょうか。containerd-shim API の protobuf(Protocol Buffers) を見るとわかります。
上記から様々なことが実行可能なことを示しており、とくに Create() と Start() が際立っています。これらの API は「docker create」と「docker run」と一致しており、ホストを乗っ取るには十分すぎるほどのものであることがわかります。API に特権コンテナの設定をするだけで、そこからホストを乗っ取ることができます。直接ソケットに通信することで、設定を完全に掌握し、任意の PID 名前空間にケーパビリティを追加したり、AppArmor/Seccomp などのセキュリティ設定を無効にできます。
解決方法
脆弱性があるかどうかを確認するには、以下のコマンドを使用して、脆弱性のある containerd-shim プロセスが実行されているか否かを判断します。
$ cat /proc/net/unix | grep 'containerd-shim' | grep '@'
自分の身を守るために、いくつかの方法をご紹介します。
- containerd を最新版にアップデートします。
この CVE は、containerd v1.4.3.3/v1.3.9 で、抽象的な名前空間ソケットからファイルベースの UNIX ソケットに切り替えることで修正されました。 - コンテナを root 以外、または UID=0 以外で実行すると、抽象的な名前空間ソケットへのアクセスがブロックされます。
Dockerでは、
docker run --net=host --user 11111 --security-opt no-new-privileges
ユーザ指定が containerd の UID と一致していないことを確認し、no-new-privileges を使用して sudo を利用できないようにします。
Kubernetesでは、.spec.containers.securityContext パスで以下を指定します。
runAsUser: 11111 allowPrivilegeEscalation: false
- AppArmor を使用する場合、AppArmor プロファイルにこの行を追加して、すべての抽象ソケットへのアクセスを拒否します。
deny unix addr=@**,
Dockerでは、
docker run --net=host --security-opt apparmor=
Kubernetesでは、
https://kubernetes.io/docs/tutorials/clusters/apparmor/
問題を修正した後に重要なのは、ホストネットワーク名前空間でコンテナを実行することは、一般的に安全でないと認識することです。しかし、それらを使用する必要がある場合は、上記の制限を適用するようにしてください。
まとめ
CVE-2020-15257 は、制限されたコンテナにたった 1 つ余分な特権を与えただけで、完全に特権を取得しホストを乗っ取ることができることを示す新たな良い例です。攻撃者が containerd-shim API ソケットへの接続に成功した場合、ホストを直接侵害する可能性があります。
今後も新たな脆弱性が続々と発生するため、境界線の確保だけでなく、クラウドインフラ内部の制限、監視、セキュリティの確保も重要になります。
参考ABSTRACT SHIMMER (CVE-2020-15257): Host Networking is root-Equivalent, Again |