gVisor: 現実世界で GKE とサーバーレス ユーザーを保護
Google Cloud Japan Team
※この投稿は米国時間 2020 年 9 月 19 日に、Google Cloud blog に投稿されたものの抄訳です。
セキュリティは Google Cloud の最優先事項であり、インフラストラクチャやサービスの設計と業務プロセスを通じてお客様の保護に取り組んでいます。cgroups などコンテナの基本コンポーネントのいくつかは Google のエンジニアによって作成され、Google は社内システムでコンテナをいち早く取り入れていました。そしてこのテクノロジーのセキュリティを強化する手段が必要であることに気付きました。このことが gVisor の開発につながりました。gVisor は、オープンソースで公開され、複数の Google Cloud プロダクトに統合されているコンテナ セキュリティ サンドボックスです。先頃 Linux カーネルの脆弱性が明らかになったときにも、これらのプロダクトを利用しているユーザーは gVisor で保護されていたため、その影響を受けませんでした。
最新のコンテナ エスケープ
Palo Alto Networks の社員が 5.7 カーネル リリースの監査中に発見した Linux カーネルの脆弱性は、「コンテナ エスケープ」に利用できる可能性があるものでした。コンテナは同一のホストカーネルを共有しますが、これはコンテナがコンパクトで高い移植性を持つ原因となる特性の一つです。コンテナ エスケープとは、コンテナ化システムで発生する、ある種の脆弱性を指します。権限のないユーザーがホストシステムにアクセスできるようになり、攻撃者が侵入してデータの引き出しやクリプトマイニングなどの活動を行うことができるようになります。これは通常、権限昇格によって発生します(コンテナ セキュリティの基本については、コンテナ セキュリティがビジネスにとって重要な理由をご覧ください)。
この脆弱性(CVE-2020-14386)は Linux カーネルの CAP_NET_RAW 機能を使ってメモリの破損を引き起こし、攻撃者が本来取得してはならない root アクセスを取得できるようになります。Kubernetes で最もよく使用されるコンテナ形式である Docker では、CAP_NET_RAW 機能がデフォルトで有効になっています。つまり、サーバーレス アプリケーションのインフラストラクチャである Kubernetes デプロイメントは、デフォルト状態で最近見つかったこの脆弱性によるセキュリティ侵害を受ける可能性があります。セキュリティ チームからこれらのデフォルト機能の一部を無効にするように指示されている場合でも、CAP_NET_RAW は通常、ping や tcpdump などのネットワーキング ツールにより使用されるので、トラブルシューティングの目的で再び有効にされている可能性があります。
gVisor を使用した CVE-2020-14386 の緩和
Google Kubernetes Engine のセキュリティ情報に、これまでになかった「GKE Sandbox で実行中の Pod はこの脆弱性の影響を受けません」という一文が追加されていることにお気付きかもしれません。Cloud Run、Cloud Functions、App Engine スタンダード環境をご利用の場合は、この脆弱性から保護されており、サービスの中断が発生したりパッチ適用の指示が通知されたりすることはありません。これらすべてのプラットフォームでは gVisor を使用してワークロードが安全に「サンドボックス化」され、ユーザーがこの脆弱性から保護されています。
gVisor は、複数の個別の保護レイヤを導入するべきであり、また各レイヤは同種の危険性に対して脆弱ではないようにするべきであるというセキュリティの一般原則から着想を得ています。コンテナでは主な隔離レイヤとして名前空間と cgroups が使われています。gVisor では、ユーザー空間で Linux をエミュレートする Sentry(Go で作成されたカーネル)で syscall を処理することで 2 つ目のレイヤを実現しています。これにより、ホストカーネルに到達できる syscall の数が大幅に減少し、攻撃対象領域が縮小します。Sentry により実現する分離の他に、gVisor では固有の TCP/IP スタックである Netstack を使用して、保護をさらに強化しています。
この場合、最初に CAP_NET_RAW をデフォルトで無効にすることで脆弱性への対処がなされます。ただし CAP_NET_RAW が有効であっても、gVisor にとってこの脆弱性は存在しません。Linux の問題の C コードは gVisor ネットワーキング スタックでは使用されません。さらに重要な点として、このタイプの攻撃、つまり配列境界外の書き込みの悪用は、Sentry やそのネットワーキング スタックでは、Go を使用しているために発生する可能性がかなり低いことがあります。gVisor によってこの脆弱性が緩和される仕組みについての技術的な詳細についてはこちらをご覧ください。
セキュリティを最優先に
Linux は基本的に複雑かつ進化するシステムであるため、セキュリティは継続的な課題となります。1996 年、カリフォルニア大学バークレー校の教授であった私は Linux のセキュリティ強化のための syscall のインターセプトの研究を進めましたが、現在でもこれは重要な手法であり続けています。その後 Dune システムが仮想化ハードウェアを使って syscall をインターセプトする方法を公開し、これが「仮想マシン」ではなく「仮想プロセス」へと本質的につながっていきました。ただし、早期の研究と同様に、コールは標準の Linux カーネルに転送され、攻撃者が下層のカーネルにアクセスできる可能性がありました。
gVisor では対照的に、Linux syscall が Go で直接実装されます。gVisor でも基盤となるカーネルを使用していますが、gVisor が悪意を持って制御されるデータの直接パススルーとなることはありません。gVisor は安全(小規模)なバージョンの Linux といえます。Go は型安全かつメモリ安全であるため、バッファ オーバーフローや境界外配列書き込みなどの、従来の Linux の大きな問題は解消されています。実装も大幅に小型化されているため、セキュリティがさらに向上します。
ただし gVisor によるアプローチにはトレードオフが伴います。現在、より安全なこの方法を採用する場合にはいくつかの欠点があります。1 つ目の欠点は、gVisor はほとんどのアプリケーションを実際に実行できるものの、常に「本物の」Linux とはセマンティクスの違いがあることです。コンテナの台頭により、ディストリビューションの仕様への関心が薄れ、移植性の需要が増加していることは、このマイナス面をある程度打ち消しています。Linux は API 安定性の面で非常に優れているので、セマンティクスが安定しており明確に定義されています。
2 つ目の欠点は、syscall のインターセプトには、(データの量ではなくコールの数に基づく)I/O 集中型ワークロードのパフォーマンス オーバーヘッドが伴うことです。もちろんこの点は時間の経過とともに改善される見込みですが、一部のアプリケーションにとっては考慮すべき要因となります。多くのアプリケーションでは強力なセキュリティが優先されますが、これはすべてのアプリケーションに該当するわけではありません。
Linux とセキュリティ コミュニティの今後の取り組みによって、ユーザーがセキュリティのためにパフォーマンスを犠牲にせずに済む状況が実現することを願っています。これを実現するには、オープンソース コミュニティがカーネルの上流設計やその他のコア オープンソース プロジェクトでセキュリティを優先する必要があります。Open Source Security Foundation などの取り組みから、この点を協力して解決できると信じています。
クラウドネイティブ アプリケーションの保護
一方で、Google は安全で容易な手法の確立に取り組んでいます。Google Cloud では、GKE Sandbox を使用したGoogle Kubernetes Engine(GKE)クラスタで gVisor を使用できるようにし、Google のサーバーレス サービスである App Engine、Cloud Run、Cloud Functions を実行するインフラストラクチャに gVisor を組み込みました。GKE では数回のクリックで多層防御を追加でき、Cloud Run と App Engine では、ユーザーは何も操作をすることなく、追加されたこの多層防御を使用できます。
GKE Sandbox で実行している場合、Pod はこの脆弱性の影響を受けません。ただしセキュリティのベスト プラクティスとして、すべてのノードで実行されるシステム コンテナを保護するためにアップグレードを行うようにしてください。GKE Sandbox を使用していない場合は、最初にコントロール プレーンとノードを GKE のセキュリティ情報にリストされているバージョンの一つにアップグレードし、推奨事項に基づいて Policy Controller、Gatekeeper、PodSecurityPolicy で CAP_NET_RAW を削除します。
次に GKE Sandbox を有効にします。GKE Sandbox はマネージド サービスであり、ユーザーに代わって実行中のオープンソース gVisor 内部の処理を行います。アプリケーションの変更は不要であり、Pod への多層防御の追加は数回のクリックで完了できます。
アプリケーションがコンテナで実行されている場合でも、サーバーレスで実行されている場合でも、GKE または Google Cloud のサーバーレス ソリューションを使用すると、gVisor のもたらすセキュリティ上のメリットを活用できます。
-Google Cloud インフラストラクチャ担当バイス プレジデント兼フェロー Eric Brewer