Clocks

Clocks

October 1, 2020
Category Instrument

クロックには、明示的なものと暗黙的なものの2種類があります。 明示的なクロックは、開発者が直接タイミングを測定するために使用されるもので、その機構はブラウザによって明示的に提供されます。 一方で、暗黙的なクロックは、特定のWebの機能を利用して作り出される想定外のもので、それを利用することで相対的な時間経過を測定できるものです。

明示的なクロック #

performance.now API #

performance.now() APIは、開発者がより高精度に時間を計測することを可能にします。

info

XS-Leaksのいくつかのタイプを緩和するため、performance.now()の精度は、すべてのモダンブラウザでナノ秒からマイクロ秒の範囲に縮小されました。123


  1. Reduce resolution of performance.now (Webkit). link ↩︎

  2. Reduce precision of performance.now() to 20us (Gecko). link ↩︎

  3. Reduce resolution of performance.now to prevent timing attacks (Blink). link ↩︎

Date API #

[Date] APIは、タイミング測定に使用できる最も古いブラウザのAPIです。 これにより開発者は日付を取得したり、Date.now()を使ってUnixタイムスタンプを取得したりすることができます。 より新しいAPIが導入される前は、このAPIが攻撃に使われていました。1

暗黙的なクロック #

SharedArrayBufferとWeb Workers #

Web Workersの導入に伴い、スレッド間でデータを交換するための新しいメカニズムが作られました。2それらの機構の一つがSharedArrayBufferで、メインスレッドとワーカスレッドの間でメモリ共有を提供します。悪意のあるウェブサイトは、バッファ内の数値をインクリメントさせる無限ループを実効するワーカーをロードすることで、implicit クロックを作成することができます。この値は、メインスレッドからいつでもアクセスでき、何回インクリメントが行われたかを読み取ることができる。

info

Spectreの公開に伴い、SharedArrayBufferはブラウザから削除されました。 その後、2020年に再導入され、このAPIを利用する際はドキュメントがセキュアコンテキスト内にあることが要求されるようになりました。 セキュアコンテキストは、アクセスすることを明示的にオプトインしていないクロスオリジンコンテンツは参照できないので、これはSharedArrayBufferがいくつかのXS-Leakにおいてはクロックとして使用できないことを意味します。

モダンブラウザでSharedArrayBufferを使用するには、アプリケーションは以下のヘッダを設定することで、明示的にCOOPCOEPを有効にする必要があります。

Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
// WebWorker内部で実行する関数を定義する
function worker_function() {
  self.onmessage = function (event) {
    const sharedBuffer = event.data;
    const sharedArray = new Uint32Array(sharedBuffer);

	// uint32の数値を無限に増加増加させる
    while (true) Atomics.add(sharedArray, 0, 1);
  };
}

// Create the WebWorker from the JS function and invoke it
const worker = new Worker(
  URL.createObjectURL(
    new Blob([`(${worker_function})()`], {
      type: "text/javascript"
    }))
);

// WebWorkerとドキュメント間のShared bufferを作成する
const sharedBuffer = new SharedArrayBuffer(Uint32Array.BYTES_PER_ELEMENT);
const sharedArray = new Uint32Array(sharedBuffer);
worker.postMessage(sharedBuffer);

tip

メインスレッドでの相対時間を取得するには、Atomics APIを利用する。

Atomics.load(sharedArray, 0);

その他のクロック #

攻撃者が暗黙的なクロックを作り出すために悪用できるAPIは、相当数存在します。: Broadcast Channel APIMessage Channel APIrequestAnimationFramesetTimeout、CSSアニメーション、その他3 4.

参考文献 #


  1. Exposing Private Information by Timing Web Applications, link ↩︎

  2. Shared memory: Side-channel information leaks, link ↩︎

  3. Fantastic Timers and Where to Find Them: High-Resolution Microarchitectural Attacks in JavaScript, link ↩︎

  4. Trusted Browsers for Uncertain Times, link ↩︎