ものがたり(旧)

atsushieno.hatenablog.com に続く

WebGLの(実質的に)仕様上の脆弱性について(日本語訳)

WebGLの(実質的に)仕様上の脆弱性が見つかったとされて、話題になっています。元はContext Information Security社のブログの記事なのですが、
http://www.contextis.co.uk/resources/blog/webgl/

日本語でもかいつまんで紹介されています。
http://japan.cnet.com/news/service/35002505/

とはいえ、これじゃ何だか意味が分かりませんし、原文はなかなか簡単には読めないと思うので、ちょっくら日本語訳してみました。全体的にやっつけながら、後半は特に寝ぼけながら訳しているので、何かおかしいところがありましたらコメント等で教えて下さいませ。翻訳許諾は明日辺りお願いしてみようと思います。(ダメって言われたら消す)→もらいました。調査の次のラウンドが終わったらまた結果を教えてくれるみたい。

追記: Khronos仕事早いですね。対応する動きを見せています。
http://www.itmedia.co.jp/enterprise/articles/1105/11/news026.html


WebGLの管理団体Khronos Groupはこの問題について、DoSなどの攻撃についてはOpenGL規格の拡張機能「GL_ARB_robustness」で対応済みだと説明した。この拡張機能は一部のGPUベンダーに採用されているが、他社にも採用が広がることを期待するとしている。WebブラウザではWebGLコンテンツを有効にする前にGL_ARB_robustness拡張の存在をチェックすることができ、近いうちにWebGLでもこれが実装モードになる見通しだとした。

 クロスドメイン問題については、「Cross Origin Resource Sharing」(CORS)を選択できるようにするなど、悪用を防ぐ仕組みについてWebGL作業部会で検討すると表明した。

      • -

要約

WebGLは、3Dグラフィックスをインターネット上の任意のページで表現できるようにする、ブラウザ向けの新しいWeb標準です。これは最近になって、Firefox 4とGoogle Chromeでデフォルトで有効とされており、Safariの最新のビルドでも有効に出来ます。Context社は、セキュリティ面に影響する新しいエリアの研究に関心をもっており、特にわたしたちのカスタマーに重大な影響を与える場合に備えて注意しています。わたしたちは以下の件を発見しました:

1. WebGLの仕様および実装で、いくつかの重大なセキュリティ問題が検出されたこと。
2. これらの問題によって、攻撃者が悪意のコードをWebブラウザ経由でGPUおよびグラフィックスドライバに攻撃を仕掛けられるようになるということ。これらWebGL経由でのGPUに対する攻撃によって、マシン全体が利用不能になり得ます。
3. さらに、WebGLには、ユーザーのデータ、プライバシー、セキュリティを危険に晒す問題があります。
4. これらの問題は、WebGLの仕様にかかる問題であり、そのプラットフォーム設計を修正するためには、多大なアーキテクチャの変更が必要になるでしょう。根本的に、WebGLでは現在、コンピューター上でもっとも保護されて(カーネルモードで)実行いるはずの、グラフィックスドライバおよびグラフィックスハードウェアに、インターネット上から全ての(チューリング完全な)プログラムを実行できるようになっています。
5. WebGLをデフォルトで有効にしているブラウザは、ユーザーをこれらの問題による危険に晒しています。


  • (1) ユーザーが、悪意のあるWebGLスクリプトのあるサイトを訪れる
  • (2) WebGLコンポーネントが、指定された3Dジオメトリとコードをグラフィックスカードにアップロードする
  • (3) そのジオメトリあるいはコードが、バグのある、あるいは未パッチのグラフィックスドライバの脆弱性問題を突く
  • (4) そのグラフィックスハードウェアが、システムをフリーズやクラッシュに繋がるような攻撃を受ける可能性がある

WebGL

Webの歴史を通して、Webコンテンツのインタラクティビティと表現力を高める試みがなされてきました。スクリプティングへの進出、広汎なプラグイン機能やActiveXからvideoやcanvasタグのようなHTML5機能まで、ブラウザはどんどん多くの複雑な機能をデフォルトで提供するようになってきました。

モダンブラウザの革新のそれぞれのステージにおいて、新しい機能によって重大な攻撃に晒されることがないか、それまでのセキュリティの教訓が、何度も評価され続けてきました。例えば、スクリプティングが導入されるまでは、悪意のあるページが他のサイトのコンテンツへのアクセスを得る簡単なメカニズムはありませんでした。同一の発信元というポリシーを実装する必要は無い、と言えたわけです。その過去になされたブラウザのセキュリティについての判断は、新しい革新については、特にクロスドメインのコンテンツアクセスには、当てはまらない場合があるわけです。

データの盗取は重大な問題ですが、ブラウザとホストオペレーティング環境のintegrityも、新技術の導入において忘れられてはならない問題です。時には、利益がより大きな呪いをもたらす場合があります。例えば、バイナリブラウザプラグインサポートを考えてみましょう(例: ActiveXあるいはNetscape Plugin Application Programming Interface = NPAPI)。これらをサポートすることで、サードパーティは、ブラウザの機能を拡張しwebページで呼び出し可能なインターフェースを提供することが、とても簡単になります。これはそして、ブラウザ上での攻撃の機会がより多くのコードに向けられることになります(それらの一部はほぼ明らかにまずい書き方になっているでしょう)。そうなると、ブラウザベンダーは、問題のあるコードが自身のコードですらないかもしれないので、安全なプラットフォームを提供するのが難しくなり、IEのKillbitやFirefoxプラグインチェッカーのように、ブロックしたりユーザーに必須のアップデートを通知したりするような、やっつけ(band-aids)対策を施すことになります。結局のところ、唯一の安全な方法は、そのような幅広いネイティブコンテンツをそもそも持たせない、というものですが、現在のところの一般的なコンセンサスとしては、これらのもたらす利益はセキュリティリスクを上回る、というところです。

これが、今回の投稿の主題であるWebGLに繋がってきます。もしWebGLなんて聞いたことがないとしても、近いうちに耳にすることになるでしょう。WebGLの目的は、OpenGLから派生した3DのAPIを、ブラウザで任意のWebページからJavaScriptを通じてアクセスできるようにする、というものです。最近リリースされたMozilla Firefox 4ブラウザ、GoogleChromeブラウザのバージョン9以降、そしてSafari (WebKit) 5以降では、これをデフォルトで有効にしています。

このこと自体は異論を呼ぶようなことではありませんが、この実装のされ方と、現在のPCおよびグラフィックス プロセッサのアーキテクチャのあり方によって、このアプローチのセキュリティに問題が生じてきます。Context社では、WebGLの仕様に由来する、可能性のあるセキュリティ上の懸念に関する初期調査を行い、果たしてWebGLが現在サポートされているプラットフォームで利用可能とされるべきものか、その利益がリスクを上回るものであるか、という疑問に至りました。

3Dグラフィックス パイプラインの簡単な概要

まず以下の、3Dグラフィックスが大半のモダンなPCスタイルのアーキテクチャでどのように実装されているかを示す、非常に簡略化された図から話を始めましょう。

図1 - グラフィックス パイプラインの簡単な図

最も低いレベルには、グラフィックス プロセッサ (GPU) ハードウェア自身があり、これは必ずしも特定のAPIを実装しているわけではありません(ほぼ確実に、ここは製造者が開発しているプロプラエタリなインターフェースです)が、少なくともプログラミングAPIレベルで期待されている機能はサポートしているはずです。モダンな3Dハードウェアはほぼ全て、各自のプログラマブル ユニット(通常シェーダーと呼ばれます)を持っており、それらはユーザーモードのプロセスによって個別にプログラムできます。このシェーダーのコードのネイティブ フォーマットは、一般的にはハードウェアベンダーに特化していますが、クロスプラットフォームのコードを開発できるよう、共通の言語が存在しています。

ハードウェアの上にあるのは、通常はオペレーティングシステムカーネルモードで動作する、ドライバです。ドライバの仕事は、低レベルのハードウェア機能を扱い、標準化されたインターフェース(例: WDDM)を、オペレーティングシステムGPUにアクセス出来る他のコンポーネントを通じて、提供する、というものです。

次はスケジューリングです。これは様々な場所、たとえばOSのカーネルドライバ自身で、あるいは完全なユーザーモードで、実装されうるものです。スケジューラーの責務は、GPUへのアクセスを、同じマシン上で動作している各プログラムに共有・分配するというものです。伝統的な環境では、どの時点でもひとつのアプリケーション(たとえばウィンドウマネージャ)のみが、GPUへの直接のアクセスを必要としたため、スケジューラーは不要だったでしょう。3Dのシナリオにおいて、シェーダーとテクスチャおよびジオメトリをアップロードするメモリへの直接アクセスに関する要件とは、それらが適切に管理される必要がある、ということです。

上記のスタックの最後の部分はインターフェースライブラリです。その主な経路は、ユーザーのプロセスがグラフィックスライブラリにアクセスする、というものです。これは抽象化の最後のレベルであり、どんなハードウェア固有の機能も排除されています。共通のインターフェースライブラリとしては、Direct3D(これにはカーネル機能も幾分か含まれています)や、クロスプラットフォームOpenGLです。これらは3Dジオメトリを生成し表示するためのAPIや、シェーダープログラムをよりGPU向けの表現に変換し、あるいはテクスチャ情報をビデオカードメモリ上に確保しアップロードするためのコンパイラを、提供します。

WebGLの問題

以上の簡単な説明に基づいて、現在のWebGLの仕様のあり方、設計、実装について、何が問題なのかを説明できるようになりました。伝統的なブラウザコンテンツは、通常、ハードウェアに対する直接的なアクセスは、いかなるかたちでも行いません。もしあなたがビットマップを描画したら、それはビットマップを描画する責務を負ったブラウザ中のコードによって処理されるでしょう。これはさらに、描画を自ら行うOSのコンポーネントに責務を委譲することになるでしょう。ポピュラーなブラウザの全てにおける2Dグラフィックスアクセラレーションの導入によって、この境界は消失しつつありますが、それでもなおGPUの機能がWebページに直接晒されているわけではありません。最も違いの際立つ点としては、それらのコンテンツは簡単に検証することができ、コンテンツによって測定可能なレンダリング時間をもち、一般的にプログラマブルな機能(少なくともグラフィックハードウェアに送られるようなもの)はほとんど含まない、といったことが挙げられます。

一方、WebGLは、その機能要件から必然的に、グラフィックス ハードウェアへのアクセスを提供します。シェーダーのコードは、GPUのネイティブ言語で書かれるわけではありませんが、コンパイルされ、グラフィックス ハードウェア上にアップロードされて実行されます。中規模以上に複雑なジオメトリのレンダリング時間は、実際にその内容をレンダリングしてみないと正確な値を生成するのは困難であるため、生データからは事前に予測することが困難であるという、古典的な鶏と卵の問題です。また、データによっては検証が困難であり、WebGLの実装の管理外では、セキュリティ上の制限を強制するのも難しいでしょう。

これは、現在のハードウェアおよびグラフィックス パイプライン実装が、プリエンプティブであったりセキュリティ境界を維持するようには設計されていない、という事実さえなければ、それほど問題ではなかったかもしれません。いったんスケジューラーによってGPU上のディスプレイリストの配置が決まると、少なくともシステム全体で明らかに生じ得るビジュアルの崩壊や不安定なしで、これを止めるのは困難です。コンテンツを念入りに造成すれば、ユーザーインターフェースを描画するOSの能力に重大な影響を与える、あるいはそれ以上にまずいことを起こすことも可能でしょう。コンテンツの全てを検証しセキュリティ境界を維持するという困難に無理に立ち向かえば、システムおよびユーザーデータのintegrityに、悪影響が出る可能性があります。

現在に至るまで、グラフィックス ハードウェアの製造者は、その製品での信頼できない用途について、心配する必要がありませんでした。確かに、integrityとサービス拒否(DoS)の問題は、ネイティブプログラムでもあり得ましたが、開発者は一般的には、自分たちのプログラムが問題を引き起こさない方向に関心を向けるものです。悪意ある行為者は、他者を説得して悪いコードをインストールさせる必要があるでしょうが、そこでグラフィックス ハードウェアが狙われるというのは、あまりユーザーが心配すべきところではないでしょう。グラフィックスドライバは通常、セキュリティに焦点を当てて書かれているわけではなく、パフォーマンスが最重要であるものです。セキュリティには人月と工数が大幅にかかるものであり、製造者が現状のWebGLをサポートするために製品にコストをかけるインセンティブは、極めて小さいでしょう。

仮にセキュリティ問題が特定できたとしても、膨大なGPU製造者がどのようにパッチを提供するかは、自明ではありません。ATINVIDIAのみでSecurity Focusを検索しても、公開された脆弱性がいくつか見つかるのみです(2008年まで遡ってもです)。関連するセキュリティ公示をGoogleで検索しても、特に情報が上がってきません。ドライバおよびハードウェアインタラクションの複雑性を思えば、そのソフトウェアの中に、直ちに解決すべき脆弱性問題のあるバグが無かったとは考えにくいです。

もちろん、典型的なOEM製品の制限によって、特にラップトップ環境などでは、パッチ配布でも状況が改善されない可能性もあります。そのような場合は通常、GPU製造者が提供するリファレンスドライバをラップトップにインストールすることが妨げられ、セキュリティアップデートを適用することがより困難です。

WebGLの開発において、これをサポートするブラウザベンダーは全て、特定のドライバが不安定だったり完全にクラッシュしたりする問題に遭遇してきたようです。これを防ぐための回避策としては、ドライバのブラックリストがあるようです(Chromeの場合、Windows XPではWebGLを全く実行しないようです)(https://wiki.mozilla.org/Blocklisting/Blocked_Graphics_Driversを参照)。これは長期的に通用するアプローチではないでしょう。

サービス拒否 (DoS)

サービス拒否(DoS)の危険は、WebGLが直面する最も知られたセキュリティ問題のひとつです。これは、既に現在の仕様の文書にすら明記されているから、というだけではありません(https://www.khronos.org/registry/webgl/specs/1.0/#4.4を参照)。基本的には、WebGL APIからグラフィックス ハードウェアへのほぼ直接のアクセスによって、ハードウェアに多大なレンダリング時間を消費させるようなシェーダープログラムあるいは複雑な3Dジオメトリの集合を作成できてしまいます。影響のあるコンポーネントがブラウザのプロセスのみである場合には、クライアントのサービス拒否(DoS)攻撃に対処するのは簡単です(その方法は既に数多く存在します)が、この場合は、この攻撃ではユーザーのコンピューターへのアクセスを完全に遮断することができ、より深刻な事態に陥らせることもあり得ます。

ある条件下において、Context社ではオペレーティングシステムのクラッシュ(即ちBSOD, ブルースクリーン)を観測しました。それらのクラッシュは、ドライバのコードが潜在的脆弱性を突かれる状況を引き起こすかたちで暴走した (faulted) 無害なものでした(脆弱性という観点で)。これを引き起こした、実際にエクスプロイトになり得るコードの脆弱性について、これ以上の情報は現時点では開示しません。

Windows 7およびVistaでは、この点では多少良い状況にあります。もしGPUが約2秒以上ロックアップした場合、OSはこれをリセットします。これによって、リセットされるまでの間に3Dグラフィックスを使用していたアプリケーションは全て停止させられます。しかし、これらのOSでは、カーネルがバグチェックを強制する(BSOD)前に、これが短時間のうちに何回発生するかを最大値で制限する仕組みを持っています(http://msdn.microsoft.com/en-us/windows/hardware/gg487368.aspxを参照)。

もちろん、既に知られている通り、これを緩和するための努力は為されており、たとえばANGLEプロジェクト(http://code.google.com/p/angleproject/)には簡単なインラインループの使用を排除するシェーダーの検証機能が含まれており、これはFirefox 4とChromeで使用されています。この検証機能では、特にループを含まないがなお実行に多大な時間のかかる巨大なジオメトリとシェーダーを生成する場合など、サービス拒否(DoS)に繋がる全てのケースをブロックすることは出来ません。

ここまでで、proof of conceptをひとつくらい提示するというのも合理的そうです。しかし、KhronosですらWebGL SDKの中でひとつ作成しているので、Context社ではひとつも作成する必要がありませんでした。https://cvs.khronos.org/svn/repos/registry/trunk/public/webgl/sdk/tests/extra/lots-of-polys-example.htmlを見て下さい。このページは、OSXデスクトップを完全にロックし、XPマシンをほぼ確実にクラッシュさせ、Windows 7上でGPUをリセットさせるものと見なすことが出来ます。

クロスドメイン画像盗取

文書オブジェクトモデル(DOM)仕様およびJavaScriptのブラウザ処理における、もっとも根本的なセキュリティ境界のひとつが、ドメイン境界です。これは、たとえば www.evil.com で公開されているコンテンツが www.mybanking.com にある認証済みあるいは信頼されたリソースにアクセスするのを妨げるためのものです。コンテンツが境界を越えてアクセスされるのを認めるかどうかは、アクセスされるリソースの種類によります。これは時々「埋め込み権限」あるいは「読み取り権限」と言われるものです。たとえば、あなたのドメインの外にある画像を埋め込むことは、完全に認められています。これは、その下回りのAPIでは、(画像の大きさやロードの成否を除いて)実際のコンテンツを読み取るメカニズムが存在しないためです。一方で、XMLHttpRequestオブジェクトがあなたのドメイン外からコンテンツを取得すること(そしてその生データへのアクセスを獲得すること)は、一般には認められていません。

HTML5で標準化された'Canvas'要素が導入されるまでは、クロスドメインで画像の生データを盗取する方法はあまり存在しませんでした。この状況を闘うために、'origin-clean'フラグが導入されました。このフラグは内部的にtrueに設定され、もしクロスドメインの画像あるいはコンテンツがcanvas上に使用されるとfalseになります(http://www.w3.org/TR/html5/the-canvas-element.html#security-with-canvas-elementsを参照)。いったん'origin-clean'フラグがfalseになると、画像コンテンツを抽出する'toDataURL'のようなAPIの呼び出しは不可能になります。

WebGLAPIはこの'Canvas'要素の上にあり、やはりこのフラグのコンセプトを拡張して、クロスドメインのテクスチャの利用について指針が設計されています(https://www.khronos.org/registry/webgl/specs/1.0/#4.2を参照)。ひとつの問題を除くと、説明は以上です。既にサービス拒否(DoS)の部分で議論した通り、シェーダーのコードおよびジオメトリ描画を長時間にわたって引き起こすことができます。シェーダーが直接アクセス出来るリソースのひとつに、テクスチャのピクセルデータがあります。これはシェーダーのコードに到達すると、そのオリジンの概念を失うものです。従って、仮にわたしたちが直接読むことが出来ないとしても、ピクセル値を抽出するタイミング攻撃を開発することが可能です。これは、1つのピクセルの色や輝度を対象に、どれだけ長時間シェーダーを実行するかを変えて、JavaScript上でその描画プロセスがどれだけ時間をとるかを測定することで、実現できます。これはセキュリティの分野では、主として暗号システムを破るためのものとしてではありますが、標準的な攻撃手法です。WebGLとの関係では、これが問題になり得ることは、既に公開のメーリングリストで指摘されてきたことです(http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2011-March/030882.htmlを参照)。

もちろん、攻撃者はこの用途のために画像全体のピクセルデータを展開する必要はありません。たとえば、クロスドメイン画像を他の既知の画像と比較するために、単純なtrue/falseを返すために使用できます。例として、固定URL上のプロフィール画像を返すwebサイトにおいて、ブラウザに保存されたセッションクッキーによってコンテンツが決定されるとします。攻撃者はこのクロスドメイン画像を既知のプロフィール画像のリストと突き合わせて、いつ特定の人物が悪意のサイトを使用したか知ることが出来るかもしれません。

このように、わたしたちのWebGLの調査の一環として、この攻撃が実際的であることをデモンストレーションするために、proof-of-conceptのコードが開発されました(小さいものですが)。このproof of conceptにアクセスするにはこちらからどうぞ。これはWindos XP、Windows 7、Mac OSXにおいて、Firefox 4とChrome 11でテストされました。Firefoxが最も確実に動作します。Context社ではページからキャプチャしたデータを保持せず、全てはクライアント上で行われます。WebGLを処理出来ないマシンあるいはブラウザを使っている方向けに、短いビデオもあります。

図2 - 画像キャプチャの段階を示す流れ図

これについては、わたしたちは、WebGLの仕様において、クロスドメイン画像アクセスのあり方(nature)を変更することによってしか修正し得ないと考えます。それはクロスドメイン画像を全てブロックするか、CORS (http://www.w3.org/TR/cors/) のようなものを使用して、特定の画像コンテンツのみが特定のドメインにアクセス出来るように許可することで、解決できます。

結論

以上の限られた調査から、Context社は、WebGLはまだ一般向けに準備が整ったものであるとは言うことが出来ず、ユーザーおよび企業のITマネージャーには、WebブラウザWebGLを無効にすることを推奨します。

高性能な3DコンテンツがWeb上で利用可能になることについては、一定の需要があるでしょうが、WebGLは、十分に安全にサポートするために必要なインフラクラクチャを、十分考慮していないかたちで規定されています。セキュリティ問題を緩和する方法の開発として、検証レイヤーの導入とドライバ ブラックリストは有効であると分かっています。しかしながら、これはWebGLを安全にする責務を、ハードウェア製造者に押しつけています。おそらく最適解は、これらを考慮に入れた上で、3Dグラフィックスの仕様をゼロから作り上げることでしょう。