Privateブラウジングの検出

NY Timesは、ユーザー登録していないと見られる記事数に限りがあって、かつユーザー登録しても無料では見られる記事数に限りがある。で、スマホでNYTimesを見た時、ユーザー登録せずにprivate windowでみることでこの制限を迂回しようとしたらなんとprivate windowで見ていることを検知されてしまった。なんでこんなことがおきるのか調査したメモ。

注意

純粋な興味でやっているので悪用はうんたらかんたら

環境

この振る舞いを確認した環境は、PC版Firefox, PC・モバイル版Chrome。ただしPC版でGhosteryを有効にして外部スクリプトをいくらかブロックするとこの振る舞いも消えた。どうやらこれに引っかかってるっぽい。

方法

実は予想以上に奥が深い話だった。もともと、ここにあるように、localStorageとかFS関連とか、いくつかの機能がprivate windowsでは無効化されているようで、それを捉えればよかったんだけど、最新版のchromeでは知られている穴はふさがれていたらしい。まあ、当たり前ですよね。でも、実際NY Timesはいまだにchromeのprivate windowを補足できる。で、当然なんで?ってなるわけだけど、例えばこことかでも議論されている。で、、ここで紹介されている方法は二つ。

一つはFS APIで書き込みにかかる時間の違いを利用したtiming attack。private windowだとtmpfsなので速くかつブレが少ないらしい。でもそもそもFSに対する書き込みって、すぐにはsyncされないんじゃなかったっけ…?ちょっとここら辺の理解が甘いので、何とも言えないです。

もう一つは、storageのクオータの違いを見る方法。private windowだとこれは空きメモリの10%でかつ120MBを超えないらしい。一方非privateだとこれはmin(ディスク空き容量の10%, 2GB)の半分になるんだとか。だからnavigator.storage.estimate()でquotaを見て、まあ普通のデバイスの空き容量は2.4GB以上あるでしょ、と思ってこのquotaが120MB以下ならprivate windowと結論付ける。ただこれにも問題はあって、モバイルデバイスでかつかつの管理をしている人とかを誤検知したらまあマズい気がする。

ということで、正直現状どちらもNY Timesが採用するほどrobustな方法に思えない。要調査。ちなみにぼくの予想は後者の応用。どうもwww.nytimes.comでnavigator.storageがキナ臭い動きをしているので…。

追記

Tampermonkeyを使ってこんなスクリプトを放り込んでみた。

// ==UserScript==
// @name         NYTimes private bypass
// @match        https://www.nytimes.com/*
// @run-at       document-start
// ==/UserScript==

(function() {
    'use strict';
    navigator.storage.estimate = async () => {return {"quota":10000000000}};
})();

すると、やはりquotaを大きくするとprivate windowであることが検知されなくなった。一応、もう少しちゃんと見てみようということで、

// ==UserScript==
// @name         NYTimes private bypass
// @match        https://www.nytimes.com/*
// @run-at       document-start
// ==/UserScript==

(function() {
    'use strict';
    navigator.storage.estimate = async () => {return {get quota() {console.trace();}}};
})();

とかやっていぢめてあげると、

return !!(e && e.quota && e.quota <= 120 * i)

という行があることがわかり、i = Math.pow(2, 20)とのことで、やはり120MBを閾値として判断しているみたい(ちなみに、quotaを0にするとなぜかprivateと判定されずにあれ?となっていたのだけど、その謎も解けましたw)。しかし、こんなことに気が付くとはNYTimesの技術力なかなかすごいですね。無駄なSPA化で有名な某新聞社にも見習ってほしいものです。

あれ、でもそうするとモバイルデバイスとかどうなるんじゃろ?って思い、USBケーブルをつなぐのが面倒だったためjavascript:navigator.storage.estimate().then(e => alert(JSON.stringify(e)))とかスマホのアドレスバーにちゃかちゃか打ち込んで動作を確認してみたんだけど、結論から言うとそもそも上記サイトのquotaに関する振る舞いは確認できなかったです。PC版、モバイル版とも非private windowでは残りストレージと全然関係なさそうな量(ぼくの環境では70GB/32GB程度)を返す一方、private windowではどちらも100MB程度の値を返してきました。まあ、さすがに通常windowで残りストレージに関係する量を返してしまうとプライバシー的な問題がありそうということに誰かが気が付いたんでしょうか。でもそうするとpeivate windowの挙動が謎。あとそもそもそれじゃあquotaの意味なくねという説もあります。バグかな?ソース見てみる…?

Comments

comments powered by Disqus