「Dirty Pipe」Linuxの脆弱性とコンテナ化アプリケーション(CVE-2022-0847)
2022年3月9日
0 分で読めます「Dirty Pipe」脆弱性とは?(CVE-2022-0847)
最近、Linuxカーネルの欠陥を詳述するCVE-2022-0847が登録されました。この欠陥を悪用すると、権限設定や所有者に関係なく、あらゆるプロセスがファイルを変更できてしまいます。この脆弱性は、セキュリティコミュニティによって「Dirty Pipe」と名付けられました。「Dirty COW」と呼ばれる、CVE-2016-5195で報告された権限昇格の脆弱性に似ていること、そしてカーネルのパイプライン実装に欠陥があることがその由来です。詳しく知りたい方は、Snyk Intel Vulnerability Databaseに記載されたこの脆弱性に関する複数の情報をご覧ください。
この記事では、コンテナ化されたワークロードが直面するリスクを解説し、コンテナイメージの内容や通常は読み取り専用のファイルが、UIDやファイルシステムの権限に関係なく、悪意ある攻撃者によってどのように変更されるのかを詳しく見ていきます。
まず、Dirty Pipeからシステムを守るために、今すぐできることを説明します。
要約:Linuxホストをアップグレードする
この脆弱性に対する既知の修正方法は、Linuxホストを次のいずれかのカーネルバージョンにアップグレードすることだけです。
5.16.11
5.15.25
5.10.102
悪意ある攻撃者が環境にアクセスした場合、システムを保護できる他の緩和策はありません。
Dirty Pipeがコンテナイメージに与える影響
コンテナイメージの基礎知識

コンテナイメージは基本的に、複数のレイヤーを重ねて構成されています。コンテナを起動すると、ランタイムエンジン(Docker、containerD、cri-Oなど)がこれらのレイヤーを統合し、その結果をプロセスのファイルシステムとして表示します。レイヤーは常に読み取り専用で、変更は各コンテナインスタンス専用に作成される読み書きレイヤーで行われます。このレイヤーにはコピーオンライト(COW)方式が使われます。読み書きレイヤーは一時的なもので、コンテナがシステムから削除されると破棄されます。また、コンテナを読み取り専用モードで起動すれば、読み書きレイヤーを省略してコンテナを不変にできます。
コンテナのプロセスを非特権ユーザーとして実行し、ルートファイルシステムを読み取り専用にすることは、一般的に推奨されています。こうした対策により、攻撃者がアプリケーションの脆弱性を利用して攻撃範囲を広げることが難しくなります。コンテナのファイルシステムに独自のコードやスクリプトを持ち込むのが大幅に困難になるためです。その他のベストプラクティスについては、コンテナセキュリティガイドをご覧ください。
コンテナ内でDirty Pipeを悪用する
Dirty Pipe脆弱性の仕組みの詳細はこの記事の範囲外です。詳しくは発見時のブログ記事をご覧ください。ここでは概要を説明します。比較的簡単な手順で、権限や所有者の設定によって変更が制限されている場合でも、ほぼすべてのファイルの内容を変更できます。たとえば、上記の記事にある概念実証コードwrite_anythingを使って、次のDockerfileでイメージをビルドします。

次に読み取り専用モードで実行し、実行ファイルwrite_anythingを使って/etc/passwdを変更します。

このファイルは読み取り専用で、rootが所有し、ルートファイルシステムも読み取り専用なので、本来なら変更できないはずです。
次に、このコンテナを停止して削除し、新しいコンテナを起動して、そちらの/etc/passwdを確認します。

読み取り専用であるホスト上の実際のイメージレイヤーの内容が、前のコンテナプロセスによって変更されたため、ファイルの変更は残っています。このホストでは、イメージを削除または置き換えるまで変更が保持されます。
不正な操作を実行する前の低レベルイメージレイヤー

不正な操作を実行した後の低レベルイメージレイヤー

実際、同じホスト上で複数のコンテナを実行している場合、このような変更は、同じベースイメージレイヤーを共有するすべてのコンテナで直ちに確認される可能性があります(ただし、各コンテナの読み書きレイヤーですでに同じファイルを変更している場合は除きます)。
3つのコンテナで/etc/passwdファイルをwatchしている間に、4つ目のコンテナでwrite_anywhereの不正な操作を実行します。

Dirty Pipeに狙われるホストマウントボリューム

ご存じのとおり、ホストボリューム(バインドマウント)をコンテナにマウントするのは、決して推奨されません。通常、単純な設定ミスによって、コンテナにホスト上のファイルを意図せず変更するアクセス権を与えてしまう可能性があるためです。Dirty Pipeにより、この問題のリスクはさらに高まります。ボリュームに:roフラグを設定して読み取り専用でマウントしていても、ホストマウントボリュームがこのエクスプロイトの危険にさらされます。

Dirty Pipeによる権限昇格
広く出回っているエクスプロイトの概念実証の一例では、この欠陥を利用して、既存のSUID対応バイナリを変更し、本来の保護機能を回避して権限を昇格させます。これはコンテナに固有の問題ではありませんが、コンテナ内でも悪用される可能性があります。たとえば、攻撃者がアプリケーションのリモートコード実行(RCE)脆弱性を悪用し、このPOCコードを注入してコンテナ内でroot権限を取得するケースが考えられます。これにより、このような動作を制限するコンテナやKubernetesの設定が実質的に回避されます。
緩和策はありますか?
前述のとおり、この脆弱性からシステムを保護する既知の方法は、ホストシステムをアップグレードすることだけです。コンテナエンジンやKubernetesによる緩和策では、このようなカーネルレベルのエクスプロイトを十分に防ぐには抽象化レベルが高すぎます。
ベースイメージを更新すればよいのでは?
残念ながら、それでは解決しません。欠陥があるのはベースイメージのファイルシステムではなく、実行中のすべてのコンテナで共有されるホスティングサーバーのカーネルです。異なるベースイメージのコンテナでuname -aを実行すると、どのコンテナでもホストのカーネルバージョンが表示されることから確認できます。

KubernetesのSecurityContextはどうでしょうか?
readonlyRootFilesystem:true、runAsNonRoot:true、runAsUser:、AllowPrivilegeEscalation:falseなどのKubernetes SecurityContext設定は、どのユーザーでもこの脆弱性を悪用して設定を回避できるため、いずれも効果がありません。
だからといって、これらの設定を使うべきではないということではありません。それどころか、多層防御を実践するうえで優れた例であり、他の多くの攻撃からクラスターを守るのに役立ちます。
Kubernetesセキュリティチートシートでは、SecurityContextの設定と、Kubernetesアプリケーションのデプロイを強化するためにそれらを使うべき理由を解説しています。また、Snykの無料IaCスキャンツールでKubernetesマニフェストをスキャンし、このような設定ミスを見つけて修正することもできます。今すぐ使い始めるには、以下のリンクをクリックしてください。
まとめ
まだであれば、すぐにホストを更新してください。上記の内容に興味を持たれた方は、詳しく知るために以下のリンクをご覧ください。
CM4Allブログ:Dirty Pipe脆弱性の発見に関する記事
Snykブログ:イメージのビルド、レイヤー、コンテナ脆弱性スキャンを詳しく解説
Snykチートシート:知っておくべきKubernetes Security Contextの設定10選
ArsTechnica:Linux、ここ数年で最も深刻な脆弱性に見舞われる
ソースコードの段階からインフラを保護
Snykはワークフロー内のIaCセキュリティとコンプライアンスを自動化し、構成ドリフトや不足しているリソースを検出します。



