Execution Timing

Execution Timing

October 1, 2020
Abuse Event Loop, Service Workers, Site Isolation, CSS Injections, Regex Injections, iframes
Category Attack
Defenses Fetch Metadata, SameSite Cookies, COOP, Framing Protections

ブラウザ上でのJavaScriptの実行時間を測定することで、攻撃者は特定のイベントがいつ発生したか、ある操作にどれくらいの時間がかかったかといった情報を得ることができます。

イベントループのタイミング #

JavaScriptの並行処理モデルは、single-threaded event loopに基づいており、これは一度に一つのタスクしか実行できないことを意味します。 例えば、ある時間のかかるタスクがイベントループをブロックした場合、UIスレッドが枯渇した結果として、ユーザーはページがフリーズしたように感じることがあります。 他のタスクはブロックされたタスクが終了するまで待たなければなりません。 各ブラウザは異なるプロセスモデルを実装しているので、ウェブサイトによっては、その関係によって異なるスレッド(およびイベントループ)で実行されることがあります。

このモデルを悪用して、クロスオリジンページから秘密を盗みだす手法があります。

  • イベントプールで次に実行されるまでの時間を測定することで、異なるオリジンのコードが実行されるまでの時間を推測する。攻撃者は固定されたプロパティを持つイベントをイベントループ12に送り続け、プールが空になると最終的にディスパッチされます。他のオリジンは同じプールにイベントをディスパッチし、ここで攻撃者はそのタスクの一つで遅延が発生したかどうかを検出することで、時間差を推測します。
  • 攻撃者が制御する文字列によって前記の機密情報が比較される場合、クロスオリジンページから機密情報を盗む。このリークは、1文字ずつの文字列比較2のイベントループで時間差を比較した結果です(前出の手法を使用)。process isolationを行わないブラウザでは、異なるオリジン間のクロスウィンドウ通信が同じスレッドで実行され、同じイベントループを共有します。

important

process isolationの仕組みがあるブラウザでは、後者の攻撃の可能性はすでにありません。このような仕組みは、現在Chromiumベースのブラウザでは Site Isolationのみで、Firefox にはProject Fission という名前で間もなく導入される予定です。

Busy Event Loop #

別の手法として、スレッドのイベントループをブロックし、イベントループが再び利用可能になるまでの時間を計測する方法があります。 この手法の主な利点の1つは、攻撃者のオリジンが他のオリジンの実行に影響を与えることができるため、Site Isolationを回避できることです。この攻撃は次のように動作します。

  1. 対象のウェブサイトをwindow.openで別ウィンドウに表示するか、iframe内に表示する。(Framing Protectionsが設定されていない場合)
  2. 長い計算が始まるのを待つ。
  3. Framing Protectionsに関係なく、同じサイトのページをiframe内に読み込む

攻撃者は、(手順3の)iframeonloadイベントをトリガーするのにかかった時間を計ることで、ターゲットのウェブサイトが実行された時間を検出できます。(Network Timing of step 3 should be minimal) 両方のナビゲーションは同じコンテキストで発生し、それらは同じサイトであるため、同じスレッドで実行され、同じイベントループを共有します。(それらは互いにブロックすることができます。)

// 新しいウィンドウを開いて、example.comのイベントループを
// ウィンドウがブロックする時間を測定する
window.open('https://example.org/expensive');

// TODO: タイムアウトなどでコストの掛かるウィンドウがロードされるのを待ちます。
var ifr = document.createElement('iframe');
ifr.src = "https://example.org";
document.body.appendChild(ifr);

// 初期時間の測定
var start = performance.now();

ifr.onload = () => {
    // iframeが読み込まれたら、時間差を計算する
    var time = performance.now() - start;
    console.log('It took %d ms to load the window', time);
}

サービスワーカー #

サービスワーカーは、ウェブアプリケーションにオフラインソリューションを提供するために使用できますが、攻撃者によってJavaScriptの実行タイミングを計測するために悪用される可能性があります3。サービスワーカーは、ブラウザとネットワークの間のプロキシとして機能し、アプリケーションがメインスレッド(document)によるあらゆるネットワークリクエストを傍受することを可能にします。

タイミングを測定するために、攻撃者は以下の手順を実行することができます。

  1. 攻撃者は自分のドメイン(attacker.com)の1つにサービスワーカーを登録する。
  2. メインドキュメントで、攻撃者はターゲットウェブサイトへのナビゲーション(window.open)を発行し、サービスワーカーにタイマーを起動するよう指示する。
  3. 新しいウィンドウのロードが始まると、手順2で取得した参照をサービスワーカーが処理するページに移動させます。
  4. 手順3で実行したリクエストがサービスワーカーに到着すると、サービスワーカーは204(No Content)レスポンスを返し、ナビゲーションを中止する。
  5. この時点で、サービスワーカーは、ステップ2で開始したタイマーの計測値を収集します。この測定値は、JavaScriptがどれくらいの時間ナビゲーションをブロックしたかに影響されます。

実際にはナビゲーションは発生しないので、ステップ3から5を繰り返して、連続したJavaScriptの実行タイミングについてより多くの測定値を得ることができます。

jQuery、CSSセレクタ、そしてShort-circuit Timing #

攻撃者は、CSS セレクタのもう一つの興味深い挙動である、式のshort-circuit(短絡評価)を悪用することができます。この式はURLハッシュで受け取られ、ページjQuery(location.hash)4を実行したときに評価されます。

セレクタ main[id='site-main'] がマッチせず評価に失敗すると、実行に時間のかかるセレクタの他の部分 (*:has(*:has(*:has(*))))) は無視されます (and 演算子と同じような感じですが、逆です) ので、タイミング攻撃が可能です。

$("*:has(*:has(*:has(*)) *:has(*:has(*:has(*))) *:has(*:has(*:has(*)))) main[id='site-main']")

tip

process isolation機構を持つブラウザでは、サービスワーカーを悪用して実行タイミング計測を取得したり、Busy Event Loop tricksなどでprocess isolationを回避できます。

ReDoS #

warning

この一連のXS-Leaksは、ターゲットページにRegexを注入することを必要とします。

正規表現サービス拒否(ReDoS)とは、ユーザー入力として正規表現を許可しているアプリケーションにおいて、サービス拒否を引き起こす手法です 2 5。悪意を持って細工された正規表現を指数関数的な時間で実行させることができます。これは、ページ上のデータによって異なる実行時間を持つ正規表現を注入することができる場合、XS-リークのベクトルとして使用することができます。これは、クライアントサイドまたはサーバーサイドで起こり得ます。

対策 #

Attack AlternativeSameSite Cookies (Lax)COOPFraming ProtectionsIsolation Policies
T. Event LoopNIP
Service Workers✔️✔️NIP
jQuery✔️NIP
ReDoS✔️NIP
Busy Event Loop✔️✔️NIP

参考文献 #


  1. Loophole: Timing Attacks on Shared Event Loops in Chrome, link ↩︎

  2. Matryoshka - Web Application Timing Attacks (or.. Timing Attacks against JavaScript Applications in Browsers), link ↩︎ ↩︎ ↩︎

  3. Security: XS-Search + XSS Auditor = Not Cool, link ↩︎

  4. A timing attack with CSS selectors and Javascript, link ↩︎

  5. A Rough Idea of Blind Regular Expression Injection Attack, link ↩︎