This post is also available in: English (英語)
概要
2019年3月4日、私はKubernetesおよびOpenShiftのセキュリティチームにkubectlのセキュリティ脆弱性を報告しました。その後、この脆弱性にはCVE-2019-1002101が割り振られました。本稿では、その発見プロセス、脆弱性の詳細とその影響、および悪用方法について説明します。開示プロセスを調整してくださったRed HatのBrandon Phillips氏に感謝を申し上げます。本日、Kubernetesチームによって行われた発表については、こちらをご覧ください。
脆弱性の発見
Kubernetesコマンドを調べていたとき、ある注記が目に留まりました。
この注記は、コンテナとユーザーマシンの間でファイルをコピーできるkubectl cpコマンドについて取り上げています。コンテナとの間でファイルをコピーするために、Kubernetesはコンテナ内のtar
バイナリを呼び出して、要求されたファイルでtarアーカイブを作成または解凍します。これはcpコマンドの通常の動作ですが、私が驚いたのは、1年ほど前にcpコードの脆弱性が検出された後でも、まだ同じ設計が使用されていた点です。
読者の方々の中には、去年の3月にcpコマンドで検出されたディレクトリトラバーサルの脆弱性を思い出す方もおられるでしょう。この脆弱性にはCVE-2018-1002100が割り振られましたが、同じ記事で発表されたOpenShiftの同類の脆弱性の陰に隠れていました。
この脆弱性は、根本的には古典的なディレクトリトラバーサルです。../
(ドット ドット スラッシュ)を使用したディレクトリクライミングを含むパスが無害化されず、悪意のあるコンテナが、任意のファイルがコピーされたときに、ユーザーマシン上の任意のパスに書き込むことができるものです。
私が発見した脆弱性を掘り下げて調べる前に、kubectl cpアーキテクチャについて詳しく見ていきましょう。
コンテナからファイルをコピーするために、kubectlはコンテナ内にあるソースファイルでtarを作成し、ユーザーマシンで解凍します。ユーザーマシンからコンテナにファイルをコピーするために、kubectlはファイルでtarを作成し、コンテナ内で解凍します。
ユーザーマシンでtarアーカイブを作成および解凍する場合、kubectlはcmd/cp/cp.goのtar解析コードを利用します。ただし、コンテナでこれらの操作を行う場合、kubectlはコンテナ内でtar
バイナリを実行します。このため、cpコマンドが機能するには、この注記に書かれているように、tar
バイナリがコンテナ内に存在する必要があります。
コンテナ内のtar
バイナリに悪意がある場合、任意のコードを実行して、予期しない、悪意のある結果が生成される可能性があります。これは、以前の脆弱性と悪用される新たな脆弱性両方の必要条件です。
cp.goの関数
は、コンテナからファイルをコピーするプロセスを実装します。リモート実行(copyFromPod
)を使用してコンテナ内のtarを呼び出した後、関数&exec.DefaultRemoteExecutor
を使用してユーザーマシンでtarファイルを解凍します。この関数は、“archive/tar” Goパッケージを使用してtarを解析し、最後にtarファイルのヘッダーに基づいて、ファイルを宛先ディレクトリに書き込みます。untarAll
CVE-2018-1002100に対する対策以降、tar解凍関数は
関数を呼び出して、パストラバーサルを除去します。cp.go:clean
ただし、コードを読み取った後、この関数はtarヘッダーからシンボリックリンクを作成する作業と、リンクをたどる作業の両方を実行できることがわかりました。攻撃者は、ほぼすべてのパスへのシンボリックリンクを含むヘッダーと、ディレクトリ内のsymlinkと同じ名前を持つファイルへのシンボリックリンクを含む後続のヘッダーを持つ、悪意のあるtarを作成できます。cp untar関数によって抽出されたら、シンボリックリンクのパスに目的のファイルを作成したり変更したりできるようになります。
影響
以下の2つのシナリオでは、この脆弱性が危険になることがあります。
- ユーザーが知らずに、悪質なtarを使用して悪意のあるコンテナイメージをダウンロードする場合。攻撃者はこうしたイメージを、自身が制御できる一般的なイメージの任意のレジストリ(Docker Hubなど)に挿入したり、タイポスクワッティングを利用できます。
- 攻撃者が他の脆弱性を悪用して実行中のコンテナを侵害する場合。攻撃者がコンテナへの正規のアクセス権を持っている場合もあります。このような場合、攻撃者はイメージの元のtarを悪意のあるtarに差し替えます。
さらに巧妙な攻撃者は、攻撃がすぐに明らかにならないように、悪意のあるtarの出力に元々要求されていたファイルを含めるか、symlinkファイルをドットファイルにすることで、エクスプロイトを隠します。
これまでのところ、それ自体で危険なディレクトリトラバーサルについてのみ説明してきました。kubectlユーザーは一般に開発者、DevOpsスタッフ、または管理者であり、環境には機密性の高い設定ファイルや導入ファイルが含まれています。そのため、この脆弱性を標的としたエクスプロイトが、機密性の高い情報の漏洩および引き出しにつながる可能性があります。しかしながら、この脆弱性を利用してユーザーマシン上でコードを完全に実行することが、攻撃者にとってどのくらい簡単なことなのかが疑問点となります。
まず、kubectlがrootとして実行される場合、多くの設定ファイルまたはシステムファイルの1つを変更することで、リモートコード実行は非常に簡単になります。/etc/profileファイルやcronファイルなどのファイルも格好の標的ですが、ほぼすべてのスタートアップファイルも容易に標的となり、即時かつ永続的にコードを実行します。
現在のところ、kubectlは一般にユーザーとして実行されています。このことが、攻撃者がコード実行を確定的に行うのを難しくしています。結局のところ、攻撃者の創造性またはユーザーのファイルシステムについてどれだけ知っているかに要約されますが、このブログのために、多くの事例で使用できる簡単なアイデアをご紹介します。
以下で発見された概念実証においては、ディレクトリkubectlの実行元の.bashrc
ファイルに書き込むことで、コードを実行しました。パス/proc/self/cwdはこのディレクトリにリンクしています。kubectlがユーザーのホームディレクトリから実行される場合、bashロードスクリプトが私のペイロードに置き換えられ、次回bashシェルが生成されるときに、このペイロードが実行されます。
概念実証
次の解説画像は、このエクスプロイトの手順を示しています。
再設計の提案
この脆弱性は、
関数を修正し、シンボリックリンクの代わりに通常のファイルを書き込むことでクローズできます。元のアドバイザリーでは、この関数の別の非セキュリティOut-of-Boundsアクセスバグについても報告しています。メンテナーは、簡易なPRで問題を両方ともクローズできるでしょう。また、CVEは修正済とマークされるでしょう。untarAll
しかし、私の見解では、kubectl cpは、さらに言えばKubernetesコマンドは、tarを呼び出したり、コンテナ内のバイナリを実行したりすべきではありません。コンテナ内部からの出力がすべて、安全である、または信頼できると考えるべきではありません。侵害された場合、攻撃者が制御できる可能性があるためです。脆弱性がなくても、バイナリは熟練ユーザーでさえも混乱させるような、誤解を招きやすいテキスト(tarの場合はstderrを介して)をユーザーのターミナルに出力する可能性があります。または、ターミナルの脆弱性を悪用して、より多くのことを行おうとします。(1)
セキュリティではなく使いやすさを理由にしてではありますが、kubectl cpの要件からtarを除外しようという論争がすでに提起されています。
Twistlock(Prisma Cloud)による保護
Prisma Cloud(旧Twistlock)は、侵害を警告し、この脆弱性が悪用されるのを阻止することで、実行中のコンテナ内におけるtarバイナリの変更を警告したり、防ぐことできます。また、TwistlockではCISベンチマークを採用しており、すべてのイメージを読み込み専用ルート ファイル システムで実行させて、実行中のコンテナ内のtarやバイナリが乗っ取られるのを阻止することができます。
Twistlockを使用して、Trusted Imagesを定義することもできます。これは、2年前にTwistlock 1.7で導入された機能で、組織内で使用できるレジストリ、リポジトリ、イメージまたはベースレイヤーのセットを選択できます。
最後に、新しいKubernetes監査機能によって、cpコマンドの使用を可視化し、コンテナの侵害によってユーザーが影響を受けるイベントを容易に明らかにすることができます。
すべてのcpイベントを監視するには、次のルールを使用します。
1 |
jpath("stage") = "ResponseComplete" and jpath("objectRef.resource") = "pods" and jpath("objectRef.subresource") = "exec" and jpath("verb") = "create" and jpath("requestURI") contains "command=tar" |
このルールを提供してくださったMishaとOmriに感謝します。
まとめ
この脆弱性は、Kubernetesのユーザークライアントであるkubectl (およびKubernetesのkubectlに相当するOpenShiftのoc)にのみ影響を与えます。v1.9.0-alpha.2から1.14.0のすべてのkubectlバージョンには脆弱性があります(1.11.9、1.12.7、1.13.5には修正プログラムもあります)。
Twitterをフォローすると、当社のアドバイザリをご確認いただけます。また、投稿もいち早くご覧いただけます。
- エスケープ シーケンス ターミナルの脆弱性について詳しくは、AtlSecConでの講演のスライドをご覧ください