コンテナとサーバーレスにおける永続化の課題

By

Category: Unit 42

Tags: , , , ,

This illustrates the concept of container security.

This post is also available in: English (英語)

要約

熟練した攻撃者であれば、永続化はハッキング活動にとっての重要な要素だと言うでしょう。永続化することで、手に入れたサーバーを継続的に自身の制御下に置くことができるからです。ですから攻撃者たちは、目的がリソース ハイジャックであれ、データ抽出であれ、プロキシであれ、自分たちの大事な脆弱性がパッチを適用されて保護されてしまったり、侵入経路を遮断されて使えなくなるリスクに常にさらされています。そして従来のコンピューティングがコンテナやサーバーレスのようなテクノロジへと変化したことで、永続性の確保は難しくなっています。それはこうしたテクノロジのもつ一時性と強力な分離メカニズムのおかげです。

なお、パロアルトネットワークスのPrisma Cloudをご利用中のお客様は、脆弱性を検出・緩和することができます。また、Prisma Cloudコンピューティングの大規模監査機能や実行時防御機能を活用することにより、マシン上で永続性を取得しようとする攻撃者を捕捉することができます。

コンテナとサーバーレスは攻撃者を制限する

コンテナやサーバーレスのセキュリティ監査では、その主眼が脆弱性緩和に向くことがよくあります。セキュリティ監査担当者は、実行中のコンテナやイメージ内のすべての既知の脆弱性をスキャンすることで、悪意のある攻撃者に利用されかねない不具合がそのなかに存在しないようにしているのです。ただし、非常に注意深く厳密にセキュリティレビューを行っても、たまたま運の良い攻撃者がこのさき見つけることになるゼロデイ脆弱性を検出することはできません。

そこにうまくいくセキュリティモデルに多層防御が含まれている理由があります。多層防御は、攻撃者たちが何とか最初の足がかりを得ても、ランタイム保護や権限制約、各種リソース(コンピューティング、メモリ、ネットワークなど)へのアクセス制限によって、彼らの行く手を阻んでいるのです。脆弱性悪用に成功しても何ができるのでしょう? どうやってデータを窃取し、どんなふうにサービスに影響を与えることができるでしょう?

この点、コンテナ化された環境やサーバーレスには従来型コンピューティングにはない特異なメリットがあります。コンテナは、機能や特権が制限されるように設計されています。それらは一時的で、使い捨てで、リソースは容易に制御可能です。くわえて、サーバーレス関数はスコープ面でも制限されています。呼び出し時にのみ実行されるし、たいていリソースに対する特権やアクセスが設計上制限されています。

永続化という課題

つまり、侵害済みのコンテナやサーバーレス関数の利用じたいがひと苦労なわけですが、これらインスタンスの永続性確保はそれ以上に大きな課題であることがわかるでしょう。

永続化の概念について簡単に考えてみましょう。エクスプロイトが成功すると、攻撃者は標的のマシンに対する一時的なアクセスを入手し、それを自らの利益のために使用する可能性があります。仮想通貨のマイナーを実行したり、データを抽出することが可能になります。しかしそれほど経たずに、侵入を可能にした脆弱性にパッチが適用されるかもしれません。マシンの制御とそのペイロードを保持するには、攻撃者はそのマシン内に橋頭堡を築く方法を見つなければなりません。永続化の実現方法は、構成の編集といった単純で受動的なものもあれば、バイナリやライブラリのインストール・変更といったさらに能動的なものもあります。攻撃者は、起動ごとや必要時に定期的にマシン上で自分のコードが実行されるようにすることで、初期の侵入経路が使えなくなってもマシンへのアクセスを確保している場合があります。このように後から攻撃者が戻ってこられるようにするコードや構成のことをバックドアと呼びます。このさいは、攻撃者自身のマシンを使う場合もあるし、多数の感染済みマシンに接続したコマンド&コントロール(C2)サーバー使って制御する場合もあります。

次にコンテナについて見てみましょう。経験的にはコンテナ寿命は短いものとして設計されていて、数時間から数日であることが多いでしょう。永続的な仮想マシン(VM)を置き換える目的でコンテナが無期限に使用されているまれなケースでも、コンテナイメージへの更新・変更があるごとに、それらは廃棄・再起動されます。Kubernetesをはじめとするコンテナオーケストレーターもこうした考えに依拠して、大規模かつ自動的にコンテナをスピンアップしています。

コンテナの永続化

つまりコンテナは一時的なものなので、永続性確保のために攻撃者が使用する従来の方法は、部分的な効力しか持ちません。cron jobのインストール、バイナリまたはその他の変更といった方法は、コンテナがシャットダウンされるまでしか持続しません。

創造的な攻撃者は、組み込まれたアーキテクチャ固有のアプリケーションを悪用することで、コンテナ内に潜伏する妙手を見つけ出すかもしれません。たとえばコンテナが永続ストレージ(Volumesbind mount)やデータベースからコードを実行するといったことを行うと、攻撃者はその機能を利用して、これらの外部デバイスにバックドアをインストールすることができます。過剰なコンテナ機能や、資格情報やAPIキーの公開といった構成の不備も、永続化の手段を探す攻撃者によって悪用される可能性が高くなります。

しかし、セキュリティが定石どおりに構成されている場合、攻撃者は標準のコンテナでどうすれば永続性を確保できるのでしょうか。コンテナ環境の境界をエスケープするには、攻撃者はその中心部で脆弱性を悪用する必要があります。つまり、オペレーティングシステム(OS)カーネル、コンテナランタイム、オーケストレータのいずれかをエクスプロイトしなければなりません。

成熟し潤沢な資金を持つ攻撃者ならゼロデイ脆弱性を見つけることでそれらを達成できるかもしれませんが、そうしたゼロデイ脆弱性が必ずしも必要というわけではありません。相手が古いソフトウェアを実行していれば、コンテナをエスケープできるようにする既知の過去の脆弱性を使用してもうまくいくでしょう。Linuxカーネルやカーネルモジュールには既知の脆弱性が多数あるので、それらをつかえばカーネルスコープでコードを実行したりコンテナ制限をエスケープできるようになります。

DockerやrunCなどコンテナ実装に脆弱性がある場合も、コンテナ境界のエスケープによるコンテナホスト上の永続性確保が可能になってしまいます。最近の有名な例としてCVE-2019-5736がありますが、この脆弱性を使えば、execコマンド実行時にコンテナがエスケープ可能になってしまいます。過去に見つかったその他の脆弱性には、いったんコンテナに侵入すれば、ユーザーが介入しなくても完全にエスケープできてしまうものもあります。その一例としてあげられるのが最近公開されたWindowsコンテナエスケープです。

コンテナ永続化のための潜在的な攻撃領域には、コンテナランライムの脆弱性または構成の不備、カーネルの脆弱性、公開されたストレージ、公開されたクラウドAPIおよびオーケストレーターの脆弱性または構成の不備が含まれます。
図1: コンテナ永続化を目指した潜在的攻撃対象領域(簡略化しています)

サーバーレスの永続化

サーバーレス関数についていえば、コンテナとの類似点こそあるものの、サーバーレス関数によって露出してしまう侵害要因たりうる攻撃ベクトル数はコンテナよりも少なくなります。サーバーレス関数は、サーバーレスプラットフォームが提供するコントロールされた環境内で実行されますし、各関数のスコープもその入力の解析とアクションの遂行とに限定されています。ネットワーキングからストレージに至るまでのその他すべてのものは、クラウドプロバイダが処理しています。悪用できる構成の不備やクラウドプロバイダ自体の脆弱性のない状況でサーバーレス関数を攻撃したければ、攻撃者は関数コードの欠陥か、そのコードが使用するパッケージに存在する脆弱性のどちらかを見つけねばなりません。

たとえばPythonハンドラを実行しYAMLデータを解析する関数の場合、YAML解析パッケージやその依存ライブラリに不具合があれば、そこが脆弱になる可能性があります。攻撃者がエクスプロイトをトリガーするデータで関数を呼び出せば関数の実行環境のコントロールを奪えるかもしれません。

ですが攻撃が成功しても露出する環境はかなり限定的です。攻撃者の得る特権や制約は脆弱性の性質やサーバーレスプラットフォームのアーキテクチャに左右されます。そしてサーバーレス関数全般について言えることは、その寿命が短いということです。

サーバーレス関数は数秒間実行されて目的を果たせば消えますし、再度呼び出されれば新しいインスタンスが起動します。サーバーレス関数の実行ランタイム環境そのものも一時的で、Amazon Web Services (AWS) Lambdaランタイムの場合約15分間でタイムアウトします。

AWS Lambdaの永続化に関する最近の記事でUnit 42リサーチャーのYuval Avrahamiは攻撃者が関数の呼び出しと次の呼び出しとの間にサーバーレス環境内にとどまり続けうることを示しています。攻撃者は、ハンドラの結果を制御することに成功し、複数の実行からデータを漏えいさせる場合があります。

ただし本物の永続性を確保したければ、攻撃者は侵害したインスタンスがAWSフレームワークにテイクダウンされないようにする必要があります。これは関数に継続的に要求を送信することで実現できます。このプロセスは「関数を暖気運転しておく(keep the function warm)」というように表現されることもあります。

関数を一定のパターンで定期的に呼び出すと、侵害した関数が検出される可能性は高まります。そのため、熟練した攻撃者は背後の意図をごまかす方法を何か考え出す必要があります。とはいえこういったシナリオもまったくないとはいえません。

結論

コンテナやサーバーレス関数で悪意のある攻撃者は永続化がしにくくなりますが、それぞれ特異な制約があります。これらの環境で攻撃を成功させるには、一時的実行に甘んじるか、コンテナや関数のサンドボックスをブレイクアウトして本物の永続性を確保する必要があります。同じ制約は従来のVMにも当てはまりますが、VMの場合はコンテナやサーバーレス関数とちがい、一時的用途で設計されることは多くありません。

防御の観点からは、コンテナやサーバーレスは継続的なセキュリティにとり有用と言えます。侵害されたコンテナやサーバーレス関数は容易に検出・廃棄できますし、同時にパッチ適用済みの新しいコードをすみやかにプッシュして機能を維持することもできます。

なお、パロアルトネットワークスのPrisma Cloudをご利用中のお客様は、脆弱性を検出・緩和することができます。また、Prisma Cloudコンピューティングの大規模監査機能や実行時防御機能を活用することにより、マシン上で永続性を取得しようとする攻撃者を捕捉することができます。