本文の内容は、2022年3月17日にStefano Chiericiが投稿したブログ(https://sysdig.com/blog/cve-2022-0811-cri-o/)を元に日本語に翻訳・再構成した内容となっております。
Crowdstrike社により、CRI-OコンテナエンジンにCVSS 8.8 (高) の新しい脆弱性CVE-2022-0811(別名cr8escape)が発見されました。この脆弱性により、任意のコードを実行される可能性があります。
影響を受けるコンテナエンジンは以下の通りです:
- CRI-O version 1.19+
これらの脆弱なコンテナエンジンに依存するコンテナ化されたインフラは、KubernetesやOpenShift(バージョン4.6~4.10)も含め、同様に影響を受けます。
脆弱性を悪用することで、敵対者はこれらのセーフガードを回避し、任意のカーネルパラメータを設定してホストを侵害し、サーバーをリモートコントロールしたり、コンテナを汚染する可能性があります。
この記事では、CVE-2022-0811の仕組み、Kubernetesのどの部分が影響を受けるのか、そしてどのように軽減するのかを理解します。
予備知識
CVE-2022-0811そのものについて話し始める前に、CRI-Oについて、そしてなぜこれが重要なポイントなのかを簡単に説明する必要があります。CRI-Oは2019年4月からのCNCFオープンソースプロジェクトで、OpenShift Container PlatformなどのKubernetes実装のコンテナエンジンとしてDockerサービスを代替できる、コミュニティ主導のコンテナエンジンのことを指します。
Kubernetes内のCRI-Oのアーキテクチャー
CRI-Oコンテナエンジンは、Open Container Initiative(OCI)互換のランタイムを実行するためのステーブルなプラットフォームを提供し、runcなどのOCI互換ランタイムを巻き込んでコンテナやポッドを起動させます。
CRI-Oの目標は、OpenShift Container PlatformとKubernetesのためのKubernetes Container Runtime Interface(CRI)を実装し、Dockerサービスに取って代わるリファレンスコンテナエンジンとなることです。
CVE-2022-0811の問題
CVE-2022-0811は、バージョンv1.19+からCRI-Oに影響を及ぼします。現在インストールされているバージョンを確認するためには、以下の方法があります。
run crio --version
CRI-Oは、Podのカーネルオプションを設定するために、pinnsユーティリティを使用します。バージョン1.19では、pinnsのサポートが追加され、ここに脆弱性が発見されました。この変更により、pinns には、適切な検証を行わずに任意のカーネルパラメータを設定できる欠陥があり、任意のコードの実行が可能となり、ホストの侵害につながる可能性があります。
具体的には、バージョン 1.19 の関数 getSysctlForPinns に関連する以下のコード片に脆弱性があります。この関数の内部では、カーネルパラメータに対する検証の欠落があり、これを悪用される可能性があります。
func getSysctlForPinns(sysctls map[string]string) string { // this assumes there's no sysctl with a `+` in it const pinnsSysctlDelim = "+" g := new(bytes.Buffer) for key, value := range sysctls { fmt.Fprintf(g, "'%s=%s'%s", key, value, pinnsSysctlDelim) } return strings.TrimSuffix(g.String(), pinnsSysctlDelim) }
バージョン1.19から既にパッチがリリースされており、脆弱性を阻止するために導入されたバリデーションを確認することができます。
CVE-2022-0847を有効にするコード
CVE-2022-0811の影響について
CVSSによると、CVE-2022-0811の深刻度は8.8です。この脆弱性は、攻撃の複雑性が低く、攻撃を実行するために特権が必要です。攻撃されたホストが完全に危険にさらされる可能性があるため、機密性、完全性、可用性に非常に高い影響を及ぼします。
CRI-OはKubernetesでサポートされているため、上記のエンジンを使用しているKubernetesクラスターも本脆弱性の影響を受けることを意味しています。
CVE-2022-0811の緩和策
このCVEの影響を受けている場合、CRI-Oで修正パッチがリリースされていますので、すぐにパッチを適用してください。すぐにパッチを適用できない場合は、悪用の試みを検出し、攻撃を防ぐことができます。本脆弱性の影響を受けるシステムおよびコンテナランタイムエンジンを既にアップグレードしている場合でも、悪用の試みを阻止し、侵害後の活動を検知するために、これらのメカニズムが必要です。
CVE-2022-0811は悪用されやすいため、ポッドレベルで行動し、特定の設定を持つポッドが環境にデプロイされるのを確実に防ぎ、悪用の可能性を検出することが可能です。
Falcoとポッドセキュリティが、この脆弱性に対してどのように役立つかを見てみましょう。
FalcoによるCVE-2022-0811の緩和
この脆弱性の悪用に成功すると、pinnsのバイナリは攻撃者が提供したカーネル設定を適用するよう騙されます。kernel.core_pattern
のような、ユーザが制御するスクリプトを指定できる設定は、このような状況で非常に有効です。core_pattern
には通常、アプリケーションが将来生成するコアダンプに名前を付けるための文字列が含まれています。パラメータの前に”|”が付いている場合、コアの出力を処理するプログラムにリダイレクトします。しかし、その仕事をするために待機しているプログラムは、実際には悪意のある細工されたスクリプトとなり、プログラムがクラッシュしてコアダンプを落とすたびに、攻撃者はプログラムやスクリプトを実行することができます。コアダンプを発生させるのは簡単なので、これを利用して攻撃者のペイロードを実行することができます。
この攻撃は、以下のFalcoルールによって実行時に検出することができます:
- rule: CVE-2022-0811 (CRI-O container escape) desc: Detects execution of pinns binary with container escape sysctl parameters (kernel.core_pattern) condition: spawned_process and proc.name = pinns and proc.cmdline contains "+" and proc.cmdline contains "=" and proc.cmdline contains "kernel.core_pattern" output: Possible CVE-2022-0811 exploit attempt using pinns %proc.cmdline priority: CRITICAL tags: [syscall,MITRE_T1068]
コンテナからエスケープするために適用可能な他のsysctlsが存在する可能性があることに注意してください(Kubernetesの公式ドキュメントによると、「安全な」sysctlsのリストはわずか5つです)。
ポッドセキュリティ
ポッドは最も細かい単位であることはご存知の通りです。しかし、Kubernetesポッドのセキュリティは非常に大きなトピックであり、ビルド、デプロイ、ランタイムといったDevOpsフロー全体の中で行うことが可能です。ビルド段階でKubernetesポッドのセキュリティを確保するために、コンテナイメージを強固にし、ポッド(またはポッドテンプレート)のセキュリティ属性を構成して攻撃対象領域を減らす方法について説明します。AppArmorやSELinuxラベルなど、ワークロードのセキュリティ属性の一部は実行段階で効果を発揮しますが、ワークロードのセキュリティ制御はすでに定義されています。
Kubernetesポッドのセキュリティを確保し、それらの設定を私たちの環境で実施するために、さまざまなツールを使用することができます。PodSecurityPolicyが最も有名かもしれませんが、Kubernetes v1.21の時点で非推奨となっており、v1.25では削除される予定です。
OPAを使ったCVE-2022-0811の緩和策
PodSecurityPolicyの代わりに、カスタマイズされたKubernetesアドミッションコントローラーで動作するOPAを使用することができます。OPAを使えば、必要なポリシーを定義し、CVE-2022-0811を使用するPodが環境にデプロイされるのを防ぐことができます。Kubernetes内のOPAのアーキテクチャー
このシナリオでは、以下のようなPodをデプロイすることで、脆弱性CVE-2022-0811を悪用することができます:
apiVersion: v1 kind: Pod metadata: name: sysctl-set spec: securityContext: sysctls: - name: kernel.shm_rmid_forced value: "1+kernel.core_pattern=|/var/lib/containers/storage/overlay/3ef1281bce79865599f673b476957be73f994d17c15109d2b6a426711cf753e6/diff/malicious.sh #" containers: - name: alpine image: alpine:latest
重要なのは、この脆弱性を利用するための設定です。OPA を使用すると、securityContent sysctl セクションで “
+
” や “=
”などの特殊文字を使用するすべてのポッドをブロックすることができます。package kubernetes.admission valueSysctls(sysctls) { contains(sysctls.value, "+") contains(sysctls.value, "=") } deny[message] { assign(workload, input.request.object); assign(setSysctls, input.request.object.spec.securityContext.sysctls[_]); valueSysctls(setSysctls); assign(message, sprintf("Workflow or pod not compliant with the security policy.", [workload.metadata.name])) }
以下は、提案されたポリシーが適用され、悪意のあるポッドをデプロイしようとしたときのOPAのエラーメッセージです。
Error from server (Workflow or pod not compliant with the security policy.%!(EXTRA string=sysctl-set)): error when creating "test-sysctl.yaml": admission webhook "validating-webhook.openpolicyagent.org" denied the request: Workflow or pod not compliant with the security policy.%!(EXTRA string=sysctl-set)
まとめ
CRI-Oに影響を与えるこの新しいHIGH Severity CVE-2022-0811は、任意のカーネルパラメータを設定することでホストやKubernetesクラスターなどの上記インフラを危険にさらすことができることがわかりました。幸いなことに、CRI-Oのバージョンをアップグレードすることで、この攻撃や類似の攻撃を回避することができます。さらに、適切なPodsのセキュリティ制限を適用することで、インフラストラクチャーに起こりうる攻撃を防ぐことができるかもしれません。