Our connectivity efforts focuses on expanding internet access and adoption around the world. これには、Terragraph などのテクノロジーに関する取り組み、地方でのアクセスを拡大するためのモバイル オペレーターとの協力、Telecom Infra Project の一員としての取り組み、Free Basics などのプログラムなどがあります。 Free Basicsの開発を進める中で、私たちは市民社会やその他のステークホルダーからのフィードバックや提言に耳を傾けてきました。 私たちは、これらの提言に対応し、接続をサポートする新しい製品に取り入れるために、特にDiscoverを開発しました。 本日、Facebook ConnectivityとBitel、Claro、Entel、Movistarのパートナーは、ペルーでDiscoverのトライアルを開始します。
潜在的なセキュリティ リスクから人々の安全を守りながらこのサービスを提供することは、技術的に難しい課題でした。 私たちは、リソース (スクリプト、メディア、スタイル シートなど) を含め、利用可能なすべてのドメインからの Web ページを安全に表示できるモデルを開発したいと考えました。 以下では、私たちが構築したモデル、その過程で行ったユニークなアーキテクチャーの選択、そしてリスクを軽減するために取った措置について説明します。
Where we started
Free Basics では、モバイル ウェブを使っている人たちに、サードパーティのアプリがサポートされていないフィーチャーフォンでも無料でサービスを提供する方法を見つけることが私たちのチャレンジとなりました。 携帯電話会社のパートナーはサービスを提供できますが、ネットワークやゲートウェイ機器の制約により、特定の宛先(通常はIPアドレスレンジやドメイン名のリスト)へのトラフィックしか無料にできません。 その新しいアプローチでは、まず Web ベースのプロキシ サービスを構築し、オペレータが freebasics.com という単一のドメインに対して無料でサービスを利用できるようにする必要がありました。 そこから、私たちはユーザーに代わって Web ページを取得し、ユーザーのデバイスに配信することになります。 最近のブラウザでも、ウェブベースのプロキシ・アーキテクチャにはいくつかの懸念があります。 ウェブ上では、クライアントはCORS(cross-origin resource sharing)やCSP(Content Security Policy)などのセキュリティHTTPヘッダーを評価し、サイトから直接クッキーを利用することができる。 しかし、プロキシサーバー構成では、クライアントはプロキシと対話し、プロキシはサイトに対するクライアントとして機能する。 サードパーティの Web サイトを単一のネームスペースでプロキシすることは、Cookie の保存方法、コンテンツの読み取りや編集にスクリプトがどの程度アクセスできるか、CORS と CSP の評価方法に関するいくつかの前提に違反することになります。
これらの懸念に対処するため、私たちは当初、Free Basics でアクセスできるサイトやスクリプトを実行できないなど、いくつかの簡単な制限を課していました。 後者は、モバイル サイトを含む多くの Web サイトが、コンテンツのレンダリングなど重要な機能を JavaScript に依存し始めたため、時間の経過とともにより大きな問題となっています。
初期のアーキテクチャ
ドメイン設計
多くのモバイル オペレータのゲートウェイが限定的であることを考慮し、以下を含む別のアーキテクチャを検討しました。 free.example.com
)を割り当て、オペレータがそれを当社のIPスペースに解決して、ユーザーに無料で提供できるようにする協力的なソリューションです。
このソリューションには長所があります:
- クライアントとサーバー間でエンドツーエンドの直接通信が可能です。
- ブラウザは、サーバー名表示 (SNI) を通して特定のドメインを要求する必要があり、プロキシはどこに接続すればよいかを知ることができます。 しかし、SNI のサポートは普遍的ではないため、このソリューションはあまり実行可能ではありませんでした。
- 加入者が誤って
free.example.com
サブドメインではなくexample.com
に直接アクセスした場合、料金が発生します。
- IPv4-in-IPv6 Encapsulation では、単一の無料データ IPv6 サブネット内に IPv4 空間全体をカプセル化することができます。 カスタマイズされた DNS リゾルバは、IPv4 を再帰的に解決し、カプセル化された IPv6 の回答で応答します。
このソリューションには長所もありました:
- ウェブサイトの所有者からの協力を必要としませんでした。
そして短所:
- ブラウザは
www.example.com.freebasics.com
ドメインを表示しますが、www.example.com
証明書はエラーになります。 - この方法で IPv6 をサポートしているキャリア ゲートウェイはごくわずかです。 最終的に、私たちのプロキシが
freebasics.com
の下の単一の起点折りたたみドメイン ネームスペース内で実行される起点折りたたみアーキテクチャが最良であると判断しました。 そうすれば、オペレータはこの宛先へのトラフィックをより簡単に許可し、設定をシンプルに保つことができます。 各サード パーティ製オリジンはサブドメインにエンコードされているため、名前解決により、トラフィックは常に空いている IP に誘導されることが保証されます。 この同じロジックにより、HTTP のみのサイトでも、クライアントとプロキシ間の Free Basics 上で HTTPS により安全に配信されるようになります。 この URL リライトスキームにより、インターネット上のすべてのサブドメインに対して個別の証明書を必要とするのではなく、単一の名前空間と TLS 証明書を使用することができるようになりました。すべてのインターネット上のオリジンは
0.freebasics.com
の下の兄弟になりますが、これはある種のセキュリティ上の考慮事項を生じさせます。 すべてのオリジンに対して異なる Cookie を発行する必要があるため、Public Suffix List にドメインを追加する利点を活用できず、結局ブラウザの Cookie 制限を超えてしまいます。Cookies
サイトからの Cookie を直接利用できる Web クライアントとは異なり、プロキシ サービスは異なる設定を必要とします。 Free Basics は、いくつかの理由により、ユーザーの Cookie をサーバー側に保存します。
- Down-level モバイル ブラウザの Cookie サポートには制限があることがよくあります。 プロキシドメインで1サイトにつき1つでもCookieを発行すると、わずか数十個のCookie設定に制限される可能性があります。 Free Basics が
0.freebasics.com
配下の各サイトにクライアントサイド Cookie を設定すると、古いブラウザではすぐにローカル Cookie ストレージの限界に達し、最新のブラウザでもドメインごとの限界に達してしまいます。 - 私たちが実装しなければならないドメインの名前空間の制約により、兄弟 Cookie や階層的 Cookie も使用できなくなりました。 たとえば、
.example.com
の任意のサブドメインに設定されたクッキーは、通常、他の任意のサブドメインで読み取ることができます。 言い換えれば、a.example.com
が.example.com
にクッキーをセットすれば、b.example.com
はそれを読むことができるはずです。 Free Basicsの場合、a-example-com.0.freebasics.com
はexample.com.0.freebasics.com
にクッキーを設定することになり、これは規格上許されません。
プロキシ・サービスがこのサーバー側の Cookie ジャーにアクセスできるようにするために、Free Basics はクライアント側の Cookie を 2 つ利用しています:
-
datr
Cookie、サイトの完全性の目的で使用するブラウザ ID。 -
ick
(Internet Cookie Key)は、サーバー側のCookie Jarを暗号化するために使用される暗号鍵を含んでいます。
サーバサイドクッキージャーにクッキーを保存する際、ユーザーのプライバシーとセキュリティを保護するために、次のことを確認します。
- サーバサイドクッキーは、クライアントのみに保存される
ick
で暗号化されています。 - クライアントが
ick
を提供すると、サーバーはそれを一度も記録することなく、各リクエストで忘れます。 - 私たちはクライアントサイドクッキーを
Secure
とHttpOnly
としてマークしています。 - クライアントのキーを使用してクッキーのインデックスをハッシュ化し、キーが存在しないときにクッキーをユーザーまで追跡できないようにします。
スクリプトの実行を許可すると、サーバー側クッキーの固定化のリスクがあります。 これを防ぐため、Free BasicsではJavaScriptの利用を禁止しています。 さらに、どのようなウェブサイトも Free Basics の一部となり得ますが、コンテンツに関係なく、悪用される可能性がないか、各サイトを個別に審査します。
Improving what we had built
あらゆるウェブサイトに対応し、より安全にスクリプトを実行できるモデルを支えるために、ユーザーのクッキーを読んだり固定化することができるスクリプトなどの脅威を防止できるアーキテクチャを大幅に考え直す必要がありました。 JavaScriptは解析が非常に難しく、意図しないコードが実行されるのを防ぐのが難しいのです。
例として、攻撃者がコードを注入する方法をいくつか挙げますが、これをフィルタリングできるようにする必要があります。 私たちは、第三者のコンテンツを表示する内側のフレームが改ざんされていないことを証明するために、信頼できる外側のフレームを使用しています。 次のセクションでは、セッションフィクセーションやフィッシング、クリックジャックなどの攻撃を軽減する方法を詳しく説明します。 3312>
Discover のアーキテクチャの改善
この時点でのドメインへの参照は、私たちの新しいドメイン、同様に起源が崩壊した
discoverapp.com
に変更されます。サード パーティ サイトからの JavaScript を許可するにあたり、スクリプトがリンクを変更および書き換え、DOM の任意の部分にアクセスし、最悪の場合はクライアント側の Cookie を固定できるため、私たちが準備すべき特定のベクターを可能にすることを認めざるをえませんでした。
- サインアップ時に、新しい安全なランダム
ick
を生成します。 -
ick
はHttpOnly
Cookie としてブラウザに送信されます。 - 次に、
ick
とdatr
の両方のダイジェストからickt
という値を HMAC して(両方の固定化を避けるため)、ickt
のコピーをクライアント上のlocalStorage
に、攻撃者が書き込みできない場所に保存します。 使用する場所はhttps://www.0.discoverapp.com
で、これは決してサードパーティのコンテンツを提供しない。 - 私たちは、リクエストで見られる
ick
Cookie から派生したickt
を、すべてのサードパーティプロキシのレスポンスの HTML 内に埋め込みます。 - ページがロードされると、
window.postMessage()
を使用して、埋め込まれたickt
と信頼できるickt
を比較し、一致しない場合はdatr
およびick
Cookie を削除してセッションを無効にします。 - このプロセスが完了するまで、ユーザーがページと対話できないようにします。
さらなる保護として、同じ場所で複数の Cookie を検出した場合、新しい
datr
Cookie を設定し、タイムスタンプを埋め込んで、常に最新のものを使用することができます。 これを行うには、セキュアなオリジンのページ内の<iframe>
内にサード パーティ サイトを埋め込み、サード パーティ サイトに JavaScript の一部を注入します。内部フレーム
内部フレーム内では、提供するすべてのプロキシされたページにスクリプトを注入します。 また、リクエストに含まれる
ick
から計算されたickt
値も一緒に注入されます。 内部フレームの動作は次のとおりです。- 外部フレームで確認します。
-
postMessage
ページに埋め込まれたickt
でトップへ戻ります。 - スクリプトの待機時間が長すぎるか、予期しない送信元から応答を取得した場合、外部フレームが存在しないか、内部フレームが期待するものとは異なる可能性があるため、フレームをサード パーティ コンテンツのないエラー画面 (「Oops」ページ) に移動させます。
-
-
parent
:-
postMessage
toparent
. - 待つ。
-
source===parent
と.0.discoverapp.com
以下の origin で応答を取得すると、スクリプトを実行します。 - 待ち時間が長くなるか、予想外の origin から応答を取得すると、Oops ページを表示するように移動します。
-
内部フレームに関するいくつかの注意事項:
- 回避されたとしても、潜在的な攻撃者はコード実行を達成できるオリジンのみを固定することができ、クッキーの固定ベクトルを冗長にすることができます。
- 私たちは、良性のオリジンが inner-outer メッセージング プロトコルを意図的に回避することはないと仮定します。
Outer frame
The outer frame is there to attest that the inner frame is consistent:
- We make sure that outer frame is always the top frame with JavaScript and
X-Frame-Options: DENY
. postMessage
を待ちます。- 外側のフレームがメッセージを受信した場合:
- それは内側のフレームの起源からですか?
- はい、それは正しい
ickt
値を報告していますか?- はい、承認メッセージを送信します。
- いいえ、セッションを削除してすべてのクッキーを削除して安全な起源に移動しています。
外枠が数秒間メッセージを受信しないか、サブフレームが最上位の内枠でない場合、安全な枠のアドレスバーから場所を削除します。
ページのインタラクション
内部フレームが検証を完了する前に、固定されたクッキーの下でパスワードを入力するかもしれないレース状態を避けるために、内部フレームの検証シーケンスが完了する前に、人々がページと相互作用するのを防ぐことが重要です。
これを防ぐために、サーバーはすべてのページの
<html>
要素にstyle="display:none"
を追加しています。 内部フレームは、外部フレームの確認を取得するとこれを削除します。JavaScriptコードはまだ実行することができ、リソースはまだフェッチされます。 しかし、人がページに何も入力していない限り、潜在的な攻撃者がサイトを訪問するだけでできなかったことを、ブラウザは何もしません – サイトがすでにクロス サイト リクエスト フォージェリ (CSRF) に対して脆弱でない限り。
- Down-level モバイル ブラウザの Cookie サポートには制限があることがよくあります。 プロキシドメインで1サイトにつき1つでもCookieを発行すると、わずか数十個のCookie設定に制限される可能性があります。 Free Basics が
- Clickjacking due to framing.
- Phishing impersonating the Discover domain.
この時点まで、我々が実装した保護は同期的固定を説明してきましたが、それらはまた非同期に発生する可能性もありました。 これを防ぐために、私たちは古典的なCSRFの防止方法を使用します。 POST には、ページが読み込まれたときに表示される datr
を含むクエリ パラメータを含めるよう要求します。 次に、クエリパラメータをリクエストに含まれる datr
クッキーと比較します。 3312>
datr
の漏洩を避けるため、暗号化されたバージョンの datr
を内部フレームに埋め込み、このクエリパラメータがすべての <form>
および XHR
オブジェクトに追加されるようにします。 ページは datr
トークンを自分では導き出せないので、追加された datr
はその時点で見られるものです。
匿名リクエストに対しては、同様に datr
クエリーパラメーターを持つことが要求されます。 匿名性は、第三者サイトに漏らさないので保たれます。ick
Cookie がないので、Cookie の壺を使うことができないのです。 ただし、この場合、datr
Cookie に対する検証はできないので、固定セッションの下で匿名の POST を行うことができます。 しかし、匿名でick
を欠いているので、機密情報は漏れません。
Clickjacking
サイトがX-Frame-Options: DENY
を送信すると、インナーフレームで読み込まれなくなるのです。 このヘッダーは、ウェブサイトがクリックジャッキングなどの特定の種類の攻撃にさらされるのを防ぐために使用されます。 HTTPレスポンスからこのヘッダーを削除しますが、インナーフレームにはpostMessage
を使用してparent
がtop
ウィンドウフレームであることを確認するよう依頼します。
フィッシング
私たちが安全なフレームで提供する「アドレスバー」は、一番上のインナーフレームのオリジンをユーザーに公開するために使用されます。 しかし、Discoverになりすましたフィッシングサイトにコピーされる可能性があります。 <iframe sandbox>
を使用してトップナビゲーションを防止することで、悪意のあるリンクがDiscoverから離れるのを防ぎます。 3312>
Client-side Cookies
document.cookie
により、JavaScript は HttpOnly
とマークされていない Cookie を読み取り、変更することができます。 これを安全にサポートすることは、サーバー上でクッキーを維持するシステムでは困難です。
クッキーにアクセスする。 リクエストが受け取られたとき、プロキシはそのオリジンから見えるすべてのクッキーを列挙します。 そして、JSON ペイロードをレスポンス ページに添付します。 クライアントサイドのコードは document.cookie
をシミュレートするために注入され、あたかも本当のクライアントサイドクッキーであるかのように、これらのクッキーを他のスクリプトから見えるようにします。 ブラウザのCORS機能を信頼することは、この場合、十分ではありません。example.com
にクッキーを設定しようとするa.example.com
は、ブラウザによってブロックされるでしょう。
それでも、サーバーがクライアントによって設定された新しい Cookie を受け取るとき、ターゲットドメインが許可されているかどうかを安全に実施できません。
クライアントに、特定のドメインに Cookie を設定する資格があることを強制するために、JSON ペイロードに加えて、要求元のオリジンが Cookie の設定を許可されている各 origin の暗号トークンのリストが送信されます。 これらのトークンは ick
値で塩漬けされているので、ユーザー間で転送することはできません。
document.cookie
のクライアント側シムは、プロキシに送信される実際のクッキーテキストにトークンを解決して埋め込む処理をします。 プロキシは、書き込み元が Cookie のターゲット ドメインに書き込むためのトークンを実際に持っていることを確認し、それをサーバー側の Cookie 壺に格納し、次にページが要求されたときに再びクライアントに送信します。 それぞれ異なるニーズがあります。
- Portal origin は
datr
. - Secure origin は
ickt
. - Rewrite origin は
datr
およびick
を必要とします。
With localStorage protocol
以下は、ほとんどのモダンなモバイル ブラウザのブートストラップ プロセスの表現です。
重要なことは、反射を避けるために、安全なオリジンのブートストラップのエンドポイントは常に新しい ick
と ickt
を発行し、ick
は決してユーザーの入力に依存していないという点です。 ick
と datr
の両方に domain=.discoverapp.com
を設定しているため、これらはすべてのオリジン タイプで利用可能であり、ickt
は安全なオリジンでしか利用できないことに注意してください。
Without localStorage protocol
オペラ ミニなど特定のブラウザ (Discover が事業を展開する多くの国で人気がある) は localStorage
をサポートしていないので、ick
と ickt
を保存することはできません。 つまり、別のプロトコルを使用する必要があります。
私たちは、パブリック サフィックス リストに従って、同じホスト サフィックスを共有しないように、リライト ソースとセキュア オリジンを分離することを決定しました。 私たちは ickt
の安全なコピーを保存するために www.0.discoverapp.com
を使用し (クッキーとして)、すべてのサードパーティのオリジンを 0.i.org
の下に移動させました。 行儀の良いブラウザでは、安全なオリジンにクッキーを設定すると、すべての書き換え可能なオリジンにアクセスできなくなります。
オリジンが別々になったので、起動プロセスは 2 段階のプロセスになりました。 以前は、localStorage
を ickt
にプロビジョニングするのと同じリクエストで ick
を設定することができました。
私たちは、最初に ickt
Cookie で安全な起源をブートストラップし、プロキシだけが知っているキーで、ユーザーに ick
の暗号化バージョンを与えることによって、これを解決します。 ick
暗号文には、書き換え元の特定の ick
を解読して Cookie を設定するために使用できる nonce が付属していますが、一度しか使用できません。
どちらの場合でも、攻撃者は同時に特定のick
値を知って、ユーザーに強制することはできません。 このプロセスはまた、オリジン間のdatr
同期も行います。
このアーキテクチャは、内部および外部の実質的なセキュリティ テストを経ています。 このアーキテクチャは、内部および外部でかなりのセキュリティ テストが実施されました。私たちは、実際に見られるような種類の Web アプリケーション攻撃に対して十分に堅牢で、モバイル オペレータが持続可能な接続を安全に提供できる設計を開発したと考えています。 ペルーでのDiscoverの発売に続き、タイ、フィリピン、イラクなど、製品機能のベータテストを実施している他の多くの国でも、パートナー通信事業者とDiscoverの追加トライアルを展開する予定です。 また、パートナー オペレーターが参加を希望する追加のトライアルについても検討します。
この作業への Berk Demir 氏の協力に感謝します。
より包括的な表現にするため、この投稿を編集し、「ホワイトリスト」を「許可リスト」と置き換えました。