2020年3月3日火曜日

投機的なWebの修復

先日Mozaic.fmでCross Origin Info Leaksについて話しました。

  1. ep63 Cross Origin Info Leaks
  2. 雑談編(こちらはプラバシーや新しいEdgeなどセキュリティとは関係ない雑談です)
ここではMozaicで話した事をまとめてみたいと思います。


スペクターとはなんだったのか

スペクターはCPUの脆弱性で、別のOSプロセスの情報をサイドチャネル攻撃を使って読み取れる脆弱性の総称です。

各OSプロセスはそれぞれアドレス空間が割り当てられ、別プロセスの情報は原則読み取ることは出来ません。勿論、WindowsのMedium Integrity Level(IL)のプロセスなどは、ユーザ権限がある為、権限が同等もしくは低いプロセスをデバッグできるので、別プロセスの情報を読むことが出来ます(権限が高いプロセスはデバッグ出来ないのでEoPではない)。しかしこれはMedium IL以上のプロセスが出来ることであり、権限の低いプロセスではこのようなことは出来ません。
その為、プロセス間で通信する際にはInter-Process Communication(IPC)が必要となります。

しかしスペクターを使うことで、例えばウェブページをレンダリングするレンダラプロセス(Chromeの場合、Untrusted IL)からブラウザプロセス(Medium IL)に割り当てられたメモリを読むことが出来てしまいます。更に、それがJavaScriptからも出来ていました。

何が直ったのか

スペクターにはいくつかの種類があり、正確に全てがどう直ったのかは分かりません。

  1. OSにより修正が違うものがある
  2. CPUから提供されたマイクロコードのパッチにはどう直したかの説明がない
実際にGoogle ProjectZeroが直ったはずのRIDLを使ってレンダラプロセスを掌握した攻撃者はChromeのサンドボックスを迂回出来ることを証明しています。

ただ、OSが保証する範囲は各プロセス隔離である為、スペクターのパッチが完璧にされているとしても、同一プロセス内のメモリを読むサイドチャネルは可能です。

何故ブラウザの問題は残っているのか

ブラウザはクロスオリジンのiframeなどを従来親フレームと同一プロセス内にレンダリングしていました。これが問題の原点で、スペクターを使うとJavaScriptから同一プロセス内のメモリを読めるということは、例えば攻撃者のサイトからGoogle.comのコンテンツが読めると言うことになります。

しかし、JavaScriptから同一プロセス内のメモリを読めると言うのは直接何かを読めるわけではなく、細工されたJavaScriptを実行し、CPUが計算処理をした後の返り値の速さを元にして情報を読み取ります。その為、攻撃にはCPUの処理速度の違いがわかるほど精密なタイマーが必要となります。

ブラウザはどの様な対策をとったのか

上記の通り、攻撃には精密なタイマーが必要な為全てのブラウザが以下の緩和策を取りました。

  1. performance.nowの精度を下げた
  2. SharedArrayBufferを無効にした
更にChromeのデスクトップ版ではSite Isolationが有効になり、各サイトごとにプロセスが割り当てられ隔離されるようになりました。その為、Chromeのデスクトップ版ではSharedArrayBufferが有効になっています。

ブラウザの対策は十分だったのか

ChromeのJavaScriptエンジンのV8チームのブログによると、全ブラウザがとった緩和策には大きく分けて2つの弱点があるそうです。
  1. サイドチャネルが発生するCPUの処理を何度も実行させ、CPUの処理を増やすことにより、精度が落ちたperformance.nowでも処理速度の違いが分かるようになる
  2. Webの技術を使ってperformance.now以外にも精度の高いタイマーが作れるという論文が公開されている
このことから、Chromeは緩和策が完璧な対策にはならないと考え、Site Isolationへの舵をきりました。

Site Isolationとは

各サイトを個別のプロセスにレンダリングするセキュリティ機能です。
元々は攻撃者にJavaScriptエンジンなどのメモリ破壊バグを突かれ、プロセスが掌握されてしまったとしても、他サイトの情報を盗まれない様にする為開発が進められていました。

しかし、サイトごとにプロセスを分けるという設計なので、スペクターの対策にもなることが分かり、開発の速度が一気に上がりました。Chrome 67でスペクター対策として有効にされ、Chrome 77でプロセスが攻撃者に掌握されてもUXSSなどが出来ない様になりました。

しかし、Site IsolationはあくまでOSレイヤーでのプロセスの隔離で成り立っている機能であり、OS以上のレイヤーでセキュリティ境界が崩れた場合は役に立ちません。つまり新しいもしくは古いスペクターの種類のパッチがCPUまたはOSで完全に出来ていない場合、Site Isolationまたはブラウザでの対策は出来ません。

雑談ですが、そもそも何故ブラウザにUXSSが発生してしまうのかというと、レンダラプロセス内に実装されているSame-Origin Policyを迂回出来るバグがあり、そこが迂回出来てしまうと別サイトも同じプロセス内にレンダリングされていた為、容易に別サイトにアクセス出来ていました。Site Isolationはレンダラプロセス内のSame-Origin Policyにバグがあったとしても、そもそもそのプロセスに別サイトのデータがなきゃアクセス出来ないよね?という面白い設計で、僕なら絶対考えつかないなーと思いました。

Cross-Origin Read Blocking(CORB)とは

重要度が高いクロスオリジンなリソースが別サイトのレンダラプロセスに展開されることを防ぐセキュリティ機能です。
実はSite Isolationだけでスペクターの対策が出来るわけではありません。 例えば、攻撃者サイトがGoogle.comを画像として埋め込んだ場合(<img src="https://www.google.com">)、ブラウザは画像を表示する為に攻撃者サイトのレンダラブロセスにGoogle.comのコンテンツを展開してしまいます。この時点でスペクターを使うことによりGoogle.comのコンテンツが読めてしまいます。

この攻撃を防ぐ為、CORBはHTML、XML、JSON、PDF、ZIPなどのMIMEタイプが設定されたリソースを別サイトのプロセスに読み込まれることを防ぎます。CORBにより重要なリソースはデフォルトで保護されます。

Cross-Origin Resource Policy(CORP)とは

オプトインで任意のリソースを同一オリジンか同一サイトのみに埋め込みを許可することが出来るセキュリティ機能です。
残念ながら上記CORBはブラックリストベースの保護機能であり、例えば攻撃者サイトが他サイトの画像を埋め込むことを防ぐことは出来ません(Webが壊れる為)。

しかし、オプトインのCORPヘッダーを指定することで、任意のリソースの埋め込みを制限出来る為、例えば総理大臣の給与明細の画像が別サイトからスペクターを使って盗まれるということが起きなくなります。

COEPの登場により、CORPを使って逆にこのリソースは別サイトから埋め込まれてもいいという明示的な指定にも使われることになりそうです。

Cross-Origin Embedder Policy(COEP)とは

ウェブページとそのページをトップフレームとする全てのフレーム内に埋め込まれるリソースが明示的に埋め込まれていることを保証するセキュリティ機能です。

Site Isolationが有効になっていないブラウザでSharedArrayBufferなどが使えないのはWebの為に健全なことではありません。その為、SharedArrayBufferが使いたいウェブページのプロセスを隔離し、そのプロセス内に埋め込まれるリソースが全て明示的に埋め込まれていれば攻撃のしようがないよね、というのがCOEPです。

COEPヘッダーを指定したウェブページはそのページとそのページをトップフレームとする全てのフレーム内に埋め込まれるリソースが明示的にCORSかCORPを指定して許可していなければなりません。明示的に指定がないリソースはブロックされてしまいます。

Cross-Origin Opener Policy(COOP)とは

別のタブにあるWindowまたはOpenerの参照を無くすセキュリティ機能です。

COEPのみだとまだSharedArrayBufferなどは有効に出来ません。それはウェブページにある全てのリソースが明示的に埋め込まれていても、そのページへの参照をもつページが別のタブに開かれている場合、双方が同一プロセス内にレンダリングされるからです。

この状況を防ぐ為、例えばCOOPヘッダーをsame-originに指定するとそのページの参照がクロスオリジンなタブからは取れなくなります。これによりブラウザがCOEPヘッダーとCOOP same-originヘッダーの両方が指定されているページのプロセスを隔離することにより、そのページ上ではSharedArrayBufferなどが有効に出来る想定です。

COOPはそれ以外にも今まで常に可能だったクロスオリジンなタブのフレーム数のリークなどを防ぐ用途としても使えます。

Securer Contextとは

Secure Contextを拡張し、現在のSecure ContextをSecure Context Transportとして、COEPヘッダーとCOOP same-originヘッダーの両方が指定されているページをSecure Context Isolationとし、Strict CSP(とTrusted Types?)が指定されているページをSecure Context Injectionとしようという提案です。

つまり、現在のSecure Contextがないと使えないWeb APIがある様に、Secure Context IsolationがないとSharedArrayBufferなどを使えなくし、更にSecure Context InjectionがないとWebUSBなど強力なAPIを使えない様にしていこうという提案です。

個人的には、Webに必要なのかと言われる様な強力なAPIなどにPermission以外にも必要な制限をかけるというのはとても良いことだと思います。



ポッドキャストで説明した全ての機能は説明出来なかったので、時間がある方は是非ポッドキャストを聞いてみて下さい!