これは TECHSCORE Advent Calendar 2019 の 23 日目の記事です。
こんにちは。松本です。
社内向けに作成した ITP(Intelligent Tracking Prevention) に関するドキュメントを再編集し、ブログ記事として以下に公開します。対象は、ITP 1.0 から ITP 2.3 に加え、2019/12/10 に発表された Preventing Tracking Prevention Tracking までとなります。
WebKit のソースコードに目を通すところまでは出来ていないので、あくまでも WebKit ブログから読み解ける内容が中心となります。
前提知識(用語など)
まず、ITP に関連して頻出する用語をピックアップして解説します。
WebKit
WebKit(ウェブキット)は、HTML や CSS などで記述されたドキュメントを解釈し、ユーザインタフェース上で視覚的に表現するための、ブラウザエンジン(レンダリングエンジン)と呼ばれるソフトウェアコンポーネントのひとつ。Apple が中心となって OSS として開発し、Safari や PlayStation 4 インターネットブラウザーなどで使用されています。
ITP は Safari の機能だと認識されることも多いようですが、実際は WebKit の機能です。また、iOS デバイス上で App Store を介し配信されるアプリが使用するブラウザエンジンは WebKit で、iOS 版の Google Chrome も WebKit を使用しています(iOS 版以外は Blink を使用)。
しかし、執筆次点では、ITP 機能を利用しているのは Safari のみのようです(一次情報が見つからないのですが)。
document.cookie が扱うクッキー
document.cookie を介して JavaScript で扱えるクッキーは、1st-party ドメインのクッキーです。
RFC 6265 の 5.3. Storage Model にあるように、Set-Cookie にて HttpOnly 属性が付けられたクッキーは、document.cookie で上書きすることはできません(ブラウザの種類やバージョンにより挙動が異なる)。
Session Cookie と Persistent Cookie
呼び名を意識することがあまり無いかもしれませんが、Set-Cookie や document.cookie に Expires 属性を付けないクッキーが Session Cookie で、付けたものが Persistent Cookie です。前者はブラウザを閉じると消えますが、後者はブラウザを閉じても指定した有効期限内は残ります。
eTLD+1
effective top-level domain(.co.jp や .com など)に、ドメインラベルをもうひとつ追加した example.co.jp や example.com といったドメイン(top privately-controlled domain)を指します。www.example.co.jp や www.example.com は eTLD+1 ではありません(これらは eTLD+2)。
リンクデコレーション
リンク先 URL のクエリ文字列などに追加のパラメータなどを仕込むことで、リンク元からリンク先に任意の情報を受け渡す仕組みです。
この仕組みを使うことで、リンク元からリンク先にページ訪問者の識別子を渡すことが可能になり、リンク先側でその識別子を 1st-party クッキーに保存しておけば、3rd-party クッキーを介さないクロスサイトトラッキングを実現できます。
リファラ URL が、リンクデコレーションとして利用されることもあります。
ITP では、次の条件を満たす場合に、リンクデコレーションによるクロスサイトトラッキングであると判定します。
- リンク元ページが、ITP によりクロスサイトトラッカーとして識別されたドメイン(eTLD+1)である
- リンク先ページの URL にクエリ文字列、あるいはフラグメントが含まれている
1st-party バウンストラッキング
HTTP リダイレクトを用いて行われるクロスサイトトラッキングです。この手法では、ユーザーを別のページにナビゲートする際、間にトラッカーサイトを挟みます。
例えば、サイト from-domain からサイト to-domain に移動する場合を考えます。通常は、from-domain から to-domain に直接リンクさせます。
1 |
from-domain --[Link]--> to-domain |
1st-party バウンストラッキングでは、ユーザーが from-domain 上のリンクをクリックするとまず tracker-domain に移動し、そこから to-domain にリダイレクトさせます。この時、1st-party バウンストラッカーである tracker-domain は、ユーザーに関する情報を、自ドメインの 1st-party コンテキストでクッキーとして記録できます。
1 |
from-domain --[Link]--> tracker-domain --[Redirect]--> to-domain |
パーティションキャッシュ(Partitioned Cache)
3rd-party コンテキストでロードされたリソースに関する WebKit のキャッシュ機能です。
A partitioned cache means cache entries for third-party resources are double-keyed to their origin and the first-party eTLD+1. This prohibits cross-site trackers from using the cache to track users. Even so, our research has shown that trackers, in order to keep their practices alive under ITP, have resorted to partitioned cache abuse.
上の説明文は ITP のブログ記事からの引用です。パーティションキャッシュでは、3rd-party コンテキストでロードされたリソースのキャッシュを、そのリソースの Origin と 1st-party の eTLD+1 の組み合わせごとに隔離して保存します。
例えば、https://www.techscore.com 配下にある /3rd-page.html というリソースを、次の四つのページ配下にて 3rd-party コンテキストとして読み込んだとします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
(1) https://example.com/1st-page-1.html | +- https://www.techscore.com/3rd-page.html (2) https://example.com/1st-page-2.html | +- https://www.techscore.com/3rd-page.html (3) https://sub.example.com/1st-page-3.html | +- https://www.techscore.com/3rd-page.html (4) https://example.org/1st-page-4.html | +- https://www.techscore.com/3rd-page.html |
結果として、https://www.techscore.com/3rd-page.html は、(1) (2) (3) で共通のキャッシュと、(4) のキャッシュの、二つが保存されます。(1) (2) (3) はいずれの 1st-party ドメインも eTLD+1 が example.com で、(4) のみ eTLD+1 が example.org であるからです(.com ではなく .org)。
このパーティションキャッシュは、クロスサイトトラッカードメインであるかどうかに関係なく、全ての 3rd-party コンテキスト内のリソースキャッシュに適用されます。
各バージョンの仕様
以降の解説においては、ユーザーが対象ドメインに対し、1st-party コンテキストで最後にアクセスした日時を UIT(User Interaction Timestamp)と呼ぶこととし、そこを起点としたタイムラインを記載しています。
ITP 2.0 の記事で次のように書かれており、(少なくとも ITP 2.0 以降は)ブラウザを使っていない期間を経過日数としてはカウントしないようです。
The user doesn’t use Safari which means that these three days do not count towards the 30 days before website data purge.
なお、ITP によって規制を受けるクッキーは、基本的にクロスサイトトラッカードメインの Persistent Cookie ですが、2019/12 に発表された Preventing Tracking Prevention Tracking からは、クロスサイトトラッカードメインだけにとどまらない規制がかかるようになりました。
以下、ところどころで ITP 特有の技術用語が出てきますが、それらは記事の後半に説明を掲載していますので、そちらをご参考ください。
ITP 1 系
- UIT を起点とするタイムライン
- UIT から 24 時間以内: クロスサイトトラッカードメインは、3rd-party コンテキストでのクッキーの読み書きが可能。
- UIT から 24 時間経過: クロスサイトトラッカードメインは、3rd-party コンテキストでのクッキーの読み書きが不可能に。
- UIT から 30 日以降: クロスサイトトラッカードメインに関するクッキーを含めたすべてのデータが削除される。
ITP 1.0(2017/6)
- タイムライン上 2 で作成されたクッキーは、パーティション化して保存。
- タイムライン上 3 の削除処理は 1 時間に 1 回のサイクルで実行。3rd-party コンテキストで新たに追加されたデータも同サイクルで削除され続ける。
【参考】
ITP 1.1(2018/3) での変更点
- タイムライン上 2 で作成されたクッキーは、パーティション化された上で、Session Cookie として存在。
- タイムライン上 3 で実際に削除されるまでの間、同ドメインに対する新たなクッキー作成はブロック。
- Storage Access API が導入された。クロスサイトトラッカードメインは、API を介して自身の 1st-party クッキーにアクセス可能に(同時に UIT も更新される)。
【参考】
ITP 2 系
- UIT を起点とするタイムライン
- UIT 時点: クロスサイトトラッカードメインは、3rd-party コンテキストでのクッキーの読み書きが不可能に。
- UIT から 30 日以降: クロスサイトトラッカードメインに関するクッキーを含めたすべてのデータが削除される。
ITP 2.0(2018/6) での変更点
- タイムライン上 1 で作成されたクッキーは、パーティション化された上で、Session Cookie として存在。
- Storage Access API へのアクセスに、ユーザーの承諾が必要に。承諾されていないドメインからのアクセス時にプロンプトが表示される。ここでの承諾は、タイムライン上 2 の削除処理とともに無効化される。
- 1st-party バウンストラッカーも、クロスサイトトラッカーとして扱われるように。
- クロスサイトトラッカーに対する 3rd-party リクエスト時の Referer ヘッダーを Origin にダウングレード。
- ポップアップを利用したフェデレーションログインによる 3rd-party クッキーへの依存を、一時的措置として動作可能に。
【参考】
ITP 2.1(2019/2) での変更点
- タイムライン上 1 でクッキーの作成自体が不可能に。パーティションクッキー機能は廃止に。
- document.cookie を介して作成されたクッキーは有効期限が最大 7 日間に。
- クロスサイトトラッカードメインのパーティションキャッシュの有効期限が 7 日間に。
- DNT のサポートが廃止に。
- ITP 2.0 で一時的に動作可能としたフェデレーションログインシナリオへの一時的措置を廃止に。
【参考】
ITP 2.2(2019/4) での変更点
- リンクデコレーションと判定されたリンク先ページ上で documento.cookie を介して作成されたクッキーの有効期限が最大 24 時間に。
【参考】
ITP 2.3(2019/9) での変更点
- リンクデコレーションによるリンク先ページ上での、スクリプト書き込み可能な Cookie 以外のデータ(LocalStorage など)は、最終アクセスから 7 日後に削除されることに。
- リファラを使ったリンクデコレーションも規制対象になり、document.referrer で読み取れる URL が eTLD+1 にダウングレード。
- Storage Access API へのアクセスをユーザーが明示的に拒否する場合のみユーザーのアクションが必要になるよう変更。二度、拒否すると、以降はプロンプトは表示されなくなり、アクセスが拒否されたままとなる。
- ITP がオフの場合の document.hasStorageAccess() では true が返るように。
- macOS 上 の Safari 13 に ITP デバッグモードが装備された。
【参考】
Preventing Tracking Prevention Tracking(2019/12) での変更点
- 全てのクロスサイトリクエストの Referer ヘッダーを、Origin にダウングレード。
- ドメインの分類に関係なく、1st-party コンテキスト上でユーザ操作が一度もないドメインは、3rd-party コンテキストでのクッキーへのアクセスがブロックされるように。また、この状態での document.hasStorageAccess() では false が返るように。
【参考】
ITP 特有の技術に関する補足
機械学習によるドメインの分類
ITP では、アクセスしたドメイン(eTLD+1)がクロスサイトトラッキング機能を有するかどうかを、機械学習モデルを使って分類し、デバイス上に記録します。ここでクロスサイトトラッカーとして分類されたドメインが、ITP によって各種制限を受けることになります。
- ITP 1.0 - 導入。
- ITP 2.0 - 1st-party バウンストラッキングを行うドメインも、クロスサイトトラッカーとして扱われるように。
パーティションクッキー(Partitioned Cookies)
ITP 機能の一部として用意された特別なクッキー。クロスサイトトラッカーのクッキーを、パーティションキャッシュと同様に、1st-party の eTLD+1 ごとに隔離保存します。3rd-party コンテキストからのアクセスはできません。
- ITP 1.0 - パーティションクッキーを導入。
- ITP 1.1 - パーティションクッキーはすべて Session Cookie として扱われるように。
- ITP 2.1 - パーティションクッキーを廃止。
Storage Access API
3rd-party の埋め込み(iframe)が、自身が 1st-party コンテキストで作成したクッキーにアクセスする仕組み。iframe タグの sandbox 属性に allow-storage-access-by-user-activation を指定することで利用可能。
Storage Access API は、二つのメソッド document.hasStorageAccess(), document.requestStorageAccess() を持っています。
document.hasStorageAccess() は、ドキュメントがその 1st-party クッキーにアクセス可能であるかを boolean 値で示す Promise を返します。
document.requestStorageAccess() は、アクセスが許可された場合と拒否された場合で処理を切り分ける Promise を返します。
- ITP 1.1 - Storage Access API を導入。
- ITP 2.0 - Storage Access API へのアクセスに、ユーザーの承諾が必要に。承諾されていないドメインからのアクセス時にプロンプトが表示される。
- ITP 2.3 - Storage Access API へのアクセスをユーザーが明示的に拒否する場合のみ、ユーザーのアクションが必要に。二度、拒否すると、以降はプロンプトは表示されなくなり、アクセスが拒否されたままとなる。また、ITP がオフの場合の document.hasStorageAccess() の戻り値が、true に変わった。
- Preventing Tracking Prevention Tracking(2019/12) - ドメインの分類に関係なく、1st-party コンテキスト上でユーザ操作が一度もないドメインは、document.hasStorageAccess() が false を返すように。
【参考】
最後に
みなさん、良いクリスマスを!