はじめに
注: このドキュメントは現在開発中です。近日中に機能改善が予定されています。
Google セーフ ブラウジング v5 は、Google セーフ ブラウジング v4 の進化版です。v5 での主な変更点は、データの更新速度と IP プライバシーです。さらに、API サーフェスは柔軟性と効率性を高め、肥大化を減らすために改善されました。さらに、Google セーフ ブラウジング v5 は、v4 から簡単に移行できるように設計されています。
現在、Google は v4 と v5 の両方を提供しており、どちらも本番環境対応とみなされます。v4 または v5 を使用できます。バージョン 4 のサポート終了日は未定ですが、その場合、Google は最短で 1 年前に通知を行います。このページでは、v5 について説明し、v4 から v5 への移行ガイドを示します。完全な v4 のドキュメントは引き続き利用可能です。
データの更新頻度
Google セーフ ブラウジング v5(具体的には v4 Update API)から大幅に改善された点の一つは、データの更新速度とカバレッジです。この保護はクライアントが維持するローカル データベースに大きく依存するため、ローカル データベースの更新の遅延とサイズが保護を見逃す主な原因となります。v4 の場合、クライアントが最新バージョンの脅威リストを取得するまでに 20 ~ 50 分かかります。残念なことに、フィッシング攻撃は急速に拡散しています。2021 年現在、攻撃を仕掛けるサイトの 60% が 10 分未満で稼働しています。Google の分析によると、フィッシング対策が行われていないユーザーの約 25 ~ 30% は、このようなデータの未更新が原因です。また、デバイスによっては、Google セーフ ブラウジングの脅威リスト全体を管理できないため、リストの規模は拡大し続けています。
v5 では、リアルタイム保護と呼ばれる運用モードが導入されています。これにより、前述のデータ未更新の問題を回避できます。v4 では、クライアントはローカル データベースをダウンロードして維持し、ローカルにダウンロードした脅威リストに対してチェックを行い、部分的な接頭辞と一致する場合にハッシュ全体をダウンロードするように要求されます。v5 でも、クライアントは引き続き脅威リストのローカル データベースをダウンロードして維持する必要がありますが、クライアントには無害なサイトのリスト(グローバル キャッシュ)をダウンロードし、このグローバル キャッシュのローカル チェックとローカルの脅威リスト チェックの両方を実施する必要があります。最後に、脅威リストで接頭辞が一致していない場合、またはグローバル キャッシュに一致しない場合、完全なハッシュをダウンロードするように要求します。(クライアントが必要とするローカル処理の詳細については、下記の該当する手順をご覧ください)。これは、「デフォルトで許可」から「デフォルトでチェック」に移行したことを意味します。これは、ウェブ上での脅威の拡散が加速するなかで、保護を強化することにつながります。つまり、このプロトコルは準リアルタイムの保護を提供することを目的としたプロトコルです。Google は、最新の Google セーフ ブラウジング データをクライアントに提供しています。
IP プライバシー
Google セーフ ブラウジング(v4 または v5)は、リクエストの処理中にユーザー ID に関連付けられた何も処理しません。送信された Cookie は無視されます。リクエストの発信元 IP アドレスは Google に認識されますが、Google が IP アドレスを使用するのは重要なネットワーキング ニーズ(レスポンスの送信など)と DoS 対策の目的に限られます。
v5 と同時に、Safe Browsing Oblivious HTTP Gateway API というコンパニオン API を導入します。これは Oblivious HTTP を使用して、エンドユーザーのGoogle の IP アドレスを取得します。これは、ユーザー リクエストの暗号化されたバージョンを、共謀していない第三者に処理して Google に転送するという仕組みです。つまり、サードパーティは IP アドレスにのみアクセスでき、Google はリクエストのコンテンツにのみアクセスできます。サードパーティは Oblivious HTTP Relay(Fastly が提供するこのサービスなど)を、Google は Oblivious HTTP Gateway を運用しています。これはオプションのコンパニオン API です。Google セーフ ブラウジングと併用すると、エンドユーザーのIP アドレスは Google に送信されなくなります。
適切な使用
使用の許可
Safe Browsing API は非営利目的でのみ使用できます(つまり、「販売や収益化を目的としたものではありません」)。営利目的のソリューションが必要な場合は、Web Risk をご覧ください。
料金
Google Safe Browsing API はすべて無料です。
割り当て
デベロッパーには、Safe Browsing API を有効にするとデフォルトの使用量の割り当てが割り当てられます。現在の割り当てと使用量は、Google Developer Console で確認できます。現在割り当てられている割り当てを超えることが予想される場合は、Play Console の割り当てインターフェースから追加の割り当てをリクエストできます。Google はこれらのリクエストを審査し、サービスの可用性がすべてのユーザーのニーズを満たせるようにするため、割り当ての増加をお申込みいただく際は、ご連絡させていただきます。
適切な URL
Google セーフ ブラウジングは、ブラウザのアドレスバーに表示される URL で動作するように設計されています。サブリソース(HTML ファイルによって参照される JavaScript や画像、JavaScript によって開始された WebSocket URL など)のチェックに使用することは想定されていません。このようなサブリソースの URL については、Google セーフ ブラウジングのチェックを行わないでください。
URL へのアクセスによってリダイレクト(HTTP 301 など)が発生した場合は、リダイレクト先の URL を Google セーフ ブラウジングに照らしてチェックすることをおすすめします。クライアントサイドの URL 操作(History.pushState
など)では、新しい URL が Google セーフ ブラウジングのチェックを受けることはありません。
ユーザーへの警告
Google セーフ ブラウジングを使用して、特定のウェブページからのリスクについてユーザーに警告する場合は、次のガイドラインが適用されます。
このガイドラインは、ページが安全でないウェブリソースであることが 100% の確実性でわかっていないことを明確化し、警告から発生し得るリスクを特定するにすぎないことを明確にすることで、お客様と Google の双方を誤解から守ることを目的としています。
- ユーザーに表示される警告で、問題のページが安全でないウェブリソースであるとユーザーに誤解を与えないようにする必要があります。特定されたページ、またはユーザーがもたらす可能性のあるリスクについて言及する場合は、「疑わしい、潜在的、可能性のある、可能性が高い」、「可能性は高い」などの用語を使用して警告を表示する必要があります。
- この警告は、ユーザーがさまざまな脅威に関する Google の定義を確認して詳細を把握できるようにする必要があります。次のリンクをおすすめします。
<ph type="x-smartling-placeholder">
- </ph>
- ソーシャル エンジニアリング: https://developers.google.com/search/docs/monitor-debug/security/social-engineering
- マルウェアと望ましくないソフトウェア: https://developers.google.com/search/docs/monitor-debug/security/malware
- 有害な可能性があるアプリ(Android のみ): https://developers.google.com/android/play-protect/potentially-harmful-applications
- セーフ ブラウジング サービスによってリスクが高いと識別されたページに関する警告を表示する場合は、「Google によるアドバイザリ」という行を追加して、Google に帰属を表示する必要があります。セーフ ブラウジング アドバイザリへのリンクも記載しています。他のソースに基づく警告も商品に表示される場合は、Google 以外のデータから得られる警告に Google の帰属情報を含めないでください。
プロダクトのドキュメントで、Google セーフ ブラウジングによる保護が完全なものではないことをユーザーに知らせる必要があります。偽陽性(危険なサイトとして危険と警告されているサイト)と偽陰性(危険のフラグが付けられていない安全なサイト)の両方の可能性があることをお客様に伝える必要があります。次の表現を使用することをおすすめします。
Google は、安全でないウェブリソースについて、最も正確で最新の情報を提供するよう努めています。ただし、Google は、サイトの情報が包括的でエラーがないことを保証するものではありません。危険なサイトもあれば、安全なサイトが誤って特定される場合もあります。
運用モード
Google セーフ ブラウジング v5 では、クライアントは 3 つの動作モードから選択できます。
リアルタイム モード
クライアントが Google セーフ ブラウジング v5 をリアルタイム モードで使用することを選択した場合、クライアントは、(i)ホスト サフィックス/パス プレフィックス URL 式の SHA256 ハッシュとしてフォーマットされた、良性の可能性があるサイトのグローバル キャッシュ、(ii)ホスト サフィックス/パス プレフィックス URL 式の SHA256 ハッシュ形式としてフォーマットされた脅威リストのセットをローカル データベースに保持します。大まかに言うと、クライアントが特定の URL をチェックしようとするたびに、グローバル キャッシュを使用してローカル チェックが実行されます。このチェックに合格すると、ローカルの脅威リストのチェックが実行されます。それ以外の場合、クライアントは以下に詳述するように、リアルタイム ハッシュ チェックを続行します。
クライアントは、ローカル データベースのほかにローカル キャッシュを保持します。このようなローカル キャッシュは永続ストレージには必要なく、メモリ不足の場合にクリアされます。
この手順の詳細な仕様については、以下をご覧ください。
ローカルリスト モード
クライアントがこのモードで Google セーフ ブラウジング v5 を使用することを選択した場合、クライアントの動作は v5 の改善された API サーフェスを使用する点を除き、v4 Update API と同様です。クライアントは、ホスト・サフィックス/パス・プレフィックスの URL 式の SHA256 ハッシュ・プレフィックスとしてフォーマットされた、一連の脅威リストをローカル・データベースに保持します。クライアントが特定の URL をチェックしようとするたびに、ローカルの脅威リストを使用してチェックが実行されます。一致する場合にのみ、クライアントはサーバーに接続してチェックを続行します。
前述したように、クライアントは永続ストレージにある必要のないローカル キャッシュも保持します。
ストレージなしのリアルタイム モード
クライアントが Google セーフ ブラウジング v5 をストレージのないリアルタイム モードで使用することを選択した場合、クライアントは永続的なローカル データベースを維持する必要がありません。ただし、クライアントにはローカル キャッシュを維持することが求められます。このようなローカル キャッシュは永続ストレージには必要なく、メモリ不足の場合にクリアされます。
クライアントが特定の URL をチェックしようとするたびに、クライアントは常にサーバーに接続してチェックを実行します。このモードは、v4 Lookup API のクライアントが実装するモードと類似しています。
リアルタイム モードと比較すると、このモードではより多くのネットワーク帯域幅を使用できますが、永続的なローカル状態を維持するのにクライアントが不便な場合は、このモードのほうが適している可能性があります。
URL の確認
このセクションでは、クライアントが URL をチェックする仕組みについて詳しく説明します。
URL の正規化
URL を確認する前に、クライアントは URL の正規化を行うことが求められます。
まずは、クライアントが URL を解析し、RFC 2396 に基づいて有効にしたとします。URL で国際化ドメイン名(IDN)が使用されている場合、クライアントは URL を ASCII の Punycode 表現に変換する必要があります。URL にはパス コンポーネントを含める必要があります。つまり、ドメインの後に少なくとも 1 つのスラッシュが必要です(http://google.com
ではなく http://google.com/
)。
まず、URL からタブ文字(0x09)、CR(0x0d)、LF(0x0a)文字を削除します。これらの文字のエスケープ シーケンス(%0a
など)は削除しないでください。
次に、URL がフラグメントで終わっている場合は、そのフラグメントを削除します。たとえば、http://google.com/#frag
を http://google.com/
に短縮します。
3 番目に、パーセント エスケープがなくなるまで、URL のエスケープ処理をパーセントで繰り返します。(これにより、URL が無効になることがあります)。
ホスト名を正規化するには:
URL からホスト名を抽出し、次の操作を行います。
- 先頭と末尾のドットをすべて削除する。
- 連続するドットを 1 つのドットに置き換える。
- ホスト名を IPv4 アドレスとして解析できる場合は、4 つのドット区切りの 10 進数値に正規化します。クライアントは、8 進数、16 進数、4 個未満の要素など、正式な IP アドレス エンコードをすべて処理する必要があります。
- ホスト名を角かっこで囲まれた IPv6 アドレスとして解析できる場合は、コンポーネント内の不要な先頭のゼロを削除し、ダブルコロン構文を使用してゼロのコンポーネントを折りたたんで正規化します。たとえば、
[2001:0db8:0000::1]
は[2001:db8::1]
に変換する必要があります。ホスト名が次の 2 つの特別な IPv6 アドレスタイプのいずれかである場合は、IPv4 に変換します。 <ph type="x-smartling-placeholder">- </ph>
- IPv4 にマッピングされた IPv6 アドレス(例:
[::ffff:1.2.3.4]
)。1.2.3.4
に変換する必要があります。 - 既知のプレフィックス 64:ff9b::/96 を使用した NAT64 アドレス(
[64:ff9b::1.2.3.4]
など)。1.2.3.4
に変換する必要があります。
- IPv4 にマッピングされた IPv6 アドレス(例:
- 文字列全体を小文字にする。
パスを正規化するには:
/./
を/
に置き換え、前のパス コンポーネントとともに/../
を削除することで、パス内のシーケンス/../
と/./
を解決します。- 連続するスラッシュの実行は単一のスラッシュ文字に置き換えます。
これらのパスの正規化をクエリ パラメータに適用しないでください。
URL 内で、ASCII 32 以下、127 以上、#
または %
のすべての文字をパーセントでエスケープします。エスケープには大文字の 16 進数を使用する必要があります。
ホスト サフィックスのパス接頭辞の式
URL が正規化されたら、次のステップとしてサフィックス/プレフィックスの式を作成します。接尾辞/接頭辞の式は、それぞれホスト接尾辞(またはフルホスト)とパス接頭辞(またはフルパス)で構成されます。
クライアントは、可能なホスト サフィックスとパス プレフィックスの組み合わせを最大 30 種類作成できます。これらの組み合わせでは、URL のホストとパスのコンポーネントのみが使用されます。スキーム、ユーザー名、パスワード、ポートは破棄されます。URL にクエリ パラメータが含まれている場合は、少なくとも 1 つの組み合わせにフルパスとクエリ パラメータが含まれます。
ホストの場合、クライアントは最大で 5 つの異なる文字列を試行します。それらは次のとおりです。
- ホスト名が IPv4 でも IPv6 でもリテラルでない場合、eTLD+1 ドメインから始まり、先頭に連続してコンポーネントを追加することで、最大 4 つのホスト名が生成されます。eTLD+1 の決定は、公開サフィックス リストに基づいて行う必要があります。たとえば、
a.b.example.com
と指定すると、eTLD+1 ドメインはexample.com
になり、ホストには 1 つの追加のホスト コンポーネントb.example.com
が付加されます。 - URL の正確なホスト名。上記の例では、
a.b.example.com
がチェックされます。
パスの場合、クライアントは最大で 6 つの異なる文字列を試行します。次のとおりです。
- クエリ パラメータを含む URL の正確なパス。
- クエリ パラメータなしの URL の正確なパス。
- ルート(/)から始まり、末尾のスラッシュを含むパス コンポーネントが連続して追加される 4 つのパス。
次の例では、チェックの動作を示します。
URL http://a.b.com/1/2.html?param=1
の場合、クライアントは次の文字列の候補を試行します。
a.b.com/1/2.html?param=1
a.b.com/1/2.html
a.b.com/
a.b.com/1/
b.com/1/2.html?param=1
b.com/1/2.html
b.com/
b.com/1/
URL http://a.b.c.d.e.f.com/1.html
の場合、クライアントは次の文字列の候補を試行します。
a.b.c.d.e.f.com/1.html
a.b.c.d.e.f.com/
c.d.e.f.com/1.html
c.d.e.f.com/
d.e.f.com/1.html
d.e.f.com/
e.f.com/1.html
e.f.com/
f.com/1.html
f.com/
(注: b.c.d.e.f.com
はスキップします。最後の 5 つのホスト名コンポーネントと完全なホスト名のみが取得されるため)。
URL http://1.2.3.4/1/
の場合、クライアントは次の文字列の候補を試行します。
1.2.3.4/1/
1.2.3.4/
URL http://example.co.uk/1
の場合、クライアントは次の文字列の候補を試行します。
example.co.uk/1
example.co.uk/
ハッシュ化
Google セーフ ブラウジングは、ハッシュ関数として SHA256 のみを使用します。このハッシュ関数は、上記の式に適用する必要があります。
完全な 32 バイトのハッシュは、状況に応じて 4 バイト、8 バイト、または 16 バイトに切り捨てられます。
現在、hashes.search メソッドを使用する場合、リクエスト内のハッシュは 4 バイトに切り詰められる必要があります。このリクエストで追加のバイトを送信すると、ユーザーのプライバシーが侵害されます。
hashList.get メソッドまたは hashLists.batchGet メソッドを使用してローカル データベースのリストをダウンロードする場合、サーバーから送信されたハッシュの長さは、リストの性質と、
desired_hash_length
パラメータで通知されるクライアントのハッシュ長の設定によって決まります。
リアルタイムでの URL チェックの手順
この手順は、クライアントがリアルタイム運用モードを選択した場合に使用されます。
このプロシージャは、単一の URL u
を受け取り、SAFE
、UNSAFE
、または UNSURE
を返します。SAFE
が返された場合、その URL は Google セーフ ブラウジングによって安全であると判断されます。UNSAFE
が返された場合、その URL は Google セーフ ブラウジングによって安全でない可能性があるとみなされ、エンドユーザーに警告を表示する、受信したメッセージを迷惑メールフォルダに移動する、続行前にユーザーによる追加の確認を求めるなどの適切な措置を講じる必要があります。UNSURE
が返された場合は、後で次のローカルチェック手順を使用する必要があります。
expressions
を、URLu
によって生成されるサフィックス/プレフィックス式のリストとします。expressionHashes
をリストとします。要素はexpressions
の各式の SHA256 ハッシュです。expressionHashes
のhash
ごとに: <ph type="x-smartling-placeholder">- </ph>
hash
がグローバル キャッシュで見つかる場合は、UNSURE
を返します。
expressionHashPrefixes
をリストとします。要素はexpressionHashes
の各ハッシュの最初の 4 バイトです。expressionHashPrefixes
のexpressionHashPrefix
ごとに: <ph type="x-smartling-placeholder">- </ph>
- ローカル キャッシュで
expressionHashPrefix
を検索します。 - キャッシュ エントリが見つかった場合:
<ph type="x-smartling-placeholder">
- </ph>
- 現在の時刻が有効期限よりも後かどうかを判断する。
- 大きい方の場合:
<ph type="x-smartling-placeholder">
- </ph>
- 見つかったキャッシュ エントリをローカル キャッシュから削除します。
- ループ再生を続ける。
- サイズが小さい場合は、以下のようにします。
<ph type="x-smartling-placeholder">
- </ph>
- この特定の
expressionHashPrefix
をexpressionHashPrefixes
から削除します。 expressionHashes
内の対応するフルハッシュがキャッシュ エントリにあるかどうかを確認します。- 見つかった場合は、
UNSAFE
を返します。 - 見つからなかった場合は、ループを続行します。
- この特定の
- キャッシュされたエントリが見つからない場合は、このループを続行します。
- ローカル キャッシュで
- RPC SearchHashes または REST メソッド hashes.search を使用して、Google セーフ ブラウジング v5 サーバーに
expressionHashPrefixes
を送信します。エラー(ネットワーク エラー、HTTP エラーなど)が発生した場合は、UNSURE
を返します。それ以外の場合は、レスポンスを SB サーバーから受信したresponse
とします。これは、脅威の性質(ソーシャル エンジニアリング、マルウェアなど)を識別する補助情報とともにフルハッシュのリストと、キャッシュの有効期限expiration
です。 response
のfullHash
ごとに: <ph type="x-smartling-placeholder">- </ph>
fullHash
をexpiration
とともにローカル キャッシュに挿入します。
response
のfullHash
ごとに: <ph type="x-smartling-placeholder">- </ph>
expressionHashes
でfullHash
が見つかった結果をisFound
とします。isFound
が False の場合は、ループを続行します。isFound
が True の場合は、UNSAFE
を返します。
SAFE
を返します。
このプロトコルではクライアントが expressionHashPrefixes
をサーバーに送信するタイミングを指定しますが、送信する具体的な方法は意図的には指定していません。たとえば、クライアントが 1 つのリクエストですべての expressionHashPrefixes
を送信することも、expressionHashPrefixes
の接頭辞をそれぞれ別のリクエストでサーバーに送信することもできます(並行処理が望ましい)。また、1 回のリクエストで送信されるハッシュ接頭辞の数が 30 を超えない限り、クライアントが expressionHashPrefixes
のハッシュ接頭辞とともに、無関係な、またはランダムに生成されたハッシュ接頭辞を送信することもできます。
LocalThreat リストの URL チェック手順
この手順は、クライアントがローカルリスト操作モードを選択した場合に使用されます。また、上記の RealTimeCheck プロシージャがクライアントが UNSURE
の値を返す場合にも使用されます。
このプロシージャは、単一の URL u
を受け取り、SAFE
または UNSAFE
を返します。
expressions
を、URLu
によって生成されるサフィックス/プレフィックス式のリストとします。expressionHashes
をリストとします。要素はexpressions
の各式の SHA256 ハッシュです。expressionHashPrefixes
をリストとします。要素はexpressionHashes
の各ハッシュの最初の 4 バイトです。expressionHashPrefixes
のexpressionHashPrefix
ごとに: <ph type="x-smartling-placeholder">- </ph>
- ローカル キャッシュで
expressionHashPrefix
を検索します。 - キャッシュ エントリが見つかった場合:
<ph type="x-smartling-placeholder">
- </ph>
- 現在の時刻が有効期限よりも後かどうかを判断する。
- 大きい方の場合:
<ph type="x-smartling-placeholder">
- </ph>
- 見つかったキャッシュ エントリをローカル キャッシュから削除します。
- ループ再生を続ける。
- サイズが小さい場合は、以下のようにします。
<ph type="x-smartling-placeholder">
- </ph>
- この特定の
expressionHashPrefix
をexpressionHashPrefixes
から削除します。 expressionHashes
内の対応するフルハッシュがキャッシュ エントリにあるかどうかを確認します。- 見つかった場合は、
UNSAFE
を返します。 - 見つからなかった場合は、ループを続行します。
- この特定の
- キャッシュされたエントリが見つからない場合は、このループを続行します。
- ローカル キャッシュで
expressionHashPrefixes
のexpressionHashPrefix
ごとに: <ph type="x-smartling-placeholder">- </ph>
- ローカルの脅威リスト データベースで
expressionHashPrefix
を検索します。 - ローカルの脅威リスト データベースで
expressionHashPrefix
が見つからない場合は、expressionHashPrefixes
から削除します。
- ローカルの脅威リスト データベースで
- RPC SearchHashes または REST メソッド hashes.search を使用して、Google セーフ ブラウジング v5 サーバーに
expressionHashPrefixes
を送信します。エラー(ネットワーク エラー、HTTP エラーなど)が発生した場合は、SAFE
を返します。それ以外の場合は、レスポンスを SB サーバーから受信したresponse
とします。これは、脅威の性質(ソーシャル エンジニアリング、マルウェアなど)を識別する補助情報とともにフルハッシュのリストと、キャッシュの有効期限expiration
です。 response
のfullHash
ごとに: <ph type="x-smartling-placeholder">- </ph>
fullHash
をexpiration
とともにローカル キャッシュに挿入します。
response
のfullHash
ごとに: <ph type="x-smartling-placeholder">- </ph>
expressionHashes
でfullHash
が見つかった結果をisFound
とします。isFound
が False の場合は、ループを続行します。isFound
が True の場合は、UNSAFE
を返します。
SAFE
を返します。
ローカル データベースを使用しないリアルタイム URL チェック手順
この手順は、クライアントがストレージなしのリアルタイム オペレーション モードを選択した場合に使用されます。
このプロシージャは、単一の URL u
を受け取り、SAFE
または UNSAFE
を返します。
expressions
を、URLu
によって生成されるサフィックス/プレフィックス式のリストとします。expressionHashes
をリストとします。要素はexpressions
の各式の SHA256 ハッシュです。expressionHashPrefixes
をリストとします。要素はexpressionHashes
の各ハッシュの最初の 4 バイトです。expressionHashPrefixes
のexpressionHashPrefix
ごとに: <ph type="x-smartling-placeholder">- </ph>
- ローカル キャッシュで
expressionHashPrefix
を検索します。 - キャッシュ エントリが見つかった場合:
<ph type="x-smartling-placeholder">
- </ph>
- 現在の時刻が有効期限よりも後かどうかを判断する。
- 大きい方の場合:
<ph type="x-smartling-placeholder">
- </ph>
- 見つかったキャッシュ エントリをローカル キャッシュから削除します。
- ループ再生を続ける。
- サイズが小さい場合は、以下のようにします。
<ph type="x-smartling-placeholder">
- </ph>
- この特定の
expressionHashPrefix
をexpressionHashPrefixes
から削除します。 expressionHashes
内の対応するフルハッシュがキャッシュ エントリにあるかどうかを確認します。- 見つかった場合は、
UNSAFE
を返します。 - 見つからなかった場合は、ループを続行します。
- この特定の
- キャッシュされたエントリが見つからない場合は、このループを続行します。
- ローカル キャッシュで
- RPC SearchHashes または REST メソッド hashes.search を使用して、Google セーフ ブラウジング v5 サーバーに
expressionHashPrefixes
を送信します。エラー(ネットワーク エラー、HTTP エラーなど)が発生した場合は、SAFE
を返します。それ以外の場合は、レスポンスを SB サーバーから受信したresponse
とします。これは、脅威の性質(ソーシャル エンジニアリング、マルウェアなど)を識別する補助情報とともにフルハッシュのリストと、キャッシュの有効期限expiration
です。 response
のfullHash
ごとに: <ph type="x-smartling-placeholder">- </ph>
fullHash
をexpiration
とともにローカル キャッシュに挿入します。
response
のfullHash
ごとに: <ph type="x-smartling-placeholder">- </ph>
expressionHashes
でfullHash
が見つかった結果をisFound
とします。isFound
が False の場合は、ループを続行します。isFound
が True の場合は、UNSAFE
を返します。
SAFE
を返します。
リアルタイム URL チェック手順と同様に、この手順ではハッシュ プレフィックスをサーバーに送信する具体的な方法は指定しません。たとえば、クライアントが 1 つのリクエストですべての expressionHashPrefixes
を送信することも、expressionHashPrefixes
の接頭辞をそれぞれ別のリクエストでサーバーに送信することもできます(並行処理が望ましい)。また、1 回のリクエストで送信されるハッシュ接頭辞の数が 30 を超えない限り、クライアントが expressionHashPrefixes
のハッシュ接頭辞とともに、無関係な、またはランダムに生成されたハッシュ接頭辞を送信することもできます。
ローカル データベースのメンテナンス
Google セーフ ブラウジング v5 では、クライアントがローカル データベースを保持することを想定しています(クライアントが「ストレージなしリアルタイム モード」を選択している場合を除きます)。このローカル データベースの形式とストレージはクライアントによって異なります。このローカル データベースの内容は、概念的には、さまざまなリストをファイルとして含むフォルダと考えることができ、これらのファイルの内容は SHA256 ハッシュまたはハッシュ プレフィックスです。
データベースの更新
クライアントは定期的に hashList.get メソッドまたは hashLists.batchGet メソッドを呼び出して、データベースを更新します。一般的なクライアントでは複数のリストを一度に更新する必要があるため、hashLists.batchGet メソッドを使用することをおすすめします。
リストは個別の名前で識別されます。名前は、数文字の短い ASCII 文字列です。
V4 とは異なり、リストは脅威の種類、プラットフォーム タイプ、脅威エントリ タイプのタプルによって識別されますが、v5 のリストは単に名前によって識別されます。これにより、複数の v5 リストが同じ脅威タイプを共有する場合でも、柔軟に対応できます。プラットフォーム タイプと脅威エントリ タイプは v5 で削除されます。
リストの名前を一度指定すると、その名前が変更されることはありません。また、一度表示されたリストが削除されることはありません(リストが有用でなくなった場合、そのリストは空になりますが、そのまま残ります)。そのため、これらの名前を Google セーフ ブラウジングのクライアント コードにハードコードすることをおすすめします。
hashList.get メソッドと hashLists.batchGet メソッドはどちらも増分更新をサポートしています。増分アップデートを使用すると、帯域幅が節約され、パフォーマンスが向上します。増分アップデートは、クライアントのリストのバージョンとリストの最新バージョンの間の差分を送信することによって機能します。(クライアントが新たに導入され、利用可能なバージョンがない場合は、フル アップデートが利用可能です)。増分アップデートには削除インデックスと追加コンテンツが含まれています。クライアントはまず、指定されたインデックスにあるエントリをローカル データベースから削除してから、追加を適用します。
最後に、破損を防ぐため、クライアントはサーバーから提供されるチェックサムと照らし合わせて、格納されているデータを確認する必要があります。チェックサムが一致しない場合、クライアントはフル アップデートを実行する必要があります。
リスト内容のデコード
ハッシュとハッシュプレフィックスのデコード
すべてのリストは、サイズを小さくするために特別なエンコードを使用して配信されます。このエンコードは、Google セーフ ブラウジング リストに、統計的にランダムな整数と区別できないハッシュまたはハッシュ接頭辞のセットが概念的に含まれていることを認識することで機能します。これらの整数を並べ替えて隣接する差分を取る場合、隣接する差分は「小さい」と予想されます。なるほど。Golomb-Rice エンコードでは、この小ささを利用します。
ホスト サフィックスのパス プレフィックス式 a.example.com/
、b.example.com/
、y.example.com/
の 3 つの式を、4 バイトのハッシュ プレフィックスを使用して送信するとします。さらに、Rice パラメータ(k)は 30 に選択されたとします。サーバーはまず、これらの文字列の完全なハッシュを計算します。
291bc5421f1cd54d99afcc55d166e2b9fe42447025895bf09dd41b2110a687dc a.example.com/
1d32c5084a360e58f1b87109637a6810acad97a861a7769e8f1841410d2a960c b.example.com/
f7a502e56e8b01c6dc242b35122683c9d25d07fb1f532d9853eb0ef3ff334f03 y.example.com/
サーバーは、上記のそれぞれに 4 バイトのハッシュ接頭辞を形成します。これは、32 バイトのフルハッシュの最初の 4 バイトであり、ビッグエンディアンの 32 ビット整数として解釈されます。ビッグ エンディアンとは、完全なハッシュの最初のバイトが 32 ビット整数の最上位バイトになることを意味します。このステップにより、整数 0x291bc542、0x1d32c508、0xf7a502e5 が得られます。
サーバーはこれら 3 つのハッシュ接頭辞を辞書順に並べ替える必要があり(ビッグエンディアンの数値ソートに相当)、その結果は 0x1d32c508、0x291bc542、0xf7a502e5 になります。最初のハッシュ接頭辞は、変更されることなく first_value
フィールドに保存されます。
サーバーは、隣接する 2 つの差分、それぞれ 0xbe9003a と 0xce893da3 を計算します。k が 30 であるとすると、サーバーはこの 2 つの数値を商部分と余り部分(それぞれ 2 ビットと 30 ビット長)に分割します。1 つ目の商は 0 で、余りは 0xbe9003a です。2 番目の数字では、商は 3 になります。これは、上位 2 つのビットが 2 進数で 11 で、余りが 0xe893da3 だからです。指定された商 q
について、正確に 1 + q
ビットを使用して (1 << q) - 1
にエンコードされます。余りは k ビットを使用して直接エンコードされます。最初の数値の商部分は 0 としてエンコードされ、残りの部分は 2 進数で 001011111010010000000000111010 となります。2 番目の数字の商部分は 0111 としてエンコードされ、余りは 001110100010010011110110100011 になります。
これらの数値がバイト文字列に生成される場合、リトル エンディアンが使用されます。概念的には、長いビット文字列が最下位ビットから始まることを想像しやすくなります。つまり、最初の数値の商部分を取得し、最初の数値の余りを先頭に付加します。次に、2 番目の数値の商部分を先頭に、余りを先頭に追加します。その結果、次のように多数の結果が出力されるはずです(わかりやすくするために改行とコメントが追加されています)。
001110100010010011110110100011 # Second number, remainder part
0111 # Second number, quotient part
001011111010010000000000111010 # First number, remainder part
0 # First number, quotient part
これを 1 行で記述すると、次のようになります。
00111010001001001111011010001101110010111110100100000000001110100
明らかに、この数値は 1 バイトで利用可能な 8 ビットをはるかに超えています。その後、リトル エンディアンでエンコードされ、その数値の最下位 8 ビットが取得され、最初のバイトである 01110100 が出力されます。わかりやすくするため、上記のビット文字列を最下位ビットから 8 個のグループにグループ化できます。
0 01110100 01001001 11101101 00011011 10010111 11010010 00000000 01110100
リトル エンディアンでエンコードして、右側から各バイトをバイト文字列に格納します。
01110100
00000000
11010010
10010111
00011011
11101101
01001001
01110100
00000000
概念的には、新しい部分を左側の大きな数に追加する(つまり、上位ビットを追加する)が、右側(最下位ビット)からエンコードを行うため、エンコードとデコードを段階的に行うことができます。
最終的に、
additions_four_bytes {
first_value: 489866504
rice_parameter: 30
entries_count: 2
encoded_data: "t\000\322\227\033\355It\000"
}
クライアントは単純に上記の手順を逆に行い、ハッシュ接頭辞をデコードします。v4 とは異なり、ハッシュ接頭辞の整数はビッグ エンディアンとして解釈されるため、最後にバイトスワップを行う必要はありません。
削除インデックスのデコード
削除インデックスは、32 ビット整数を使用して、上記とまったく同じ手法を用いてエンコードされます。削除インデックスのエンコードとデコードは、v4 と v5 で変更されていません。
使用可能なリスト
v5alpha1 での使用が推奨されるリストは次のとおりです。
リスト名 | 対応する v4 ThreatType 列挙型 |
説明 |
---|---|---|
gc |
なし | このリストはグローバル キャッシュのリストです。これは、リアルタイム オペレーション モードでのみ使用される特別なリストです。 |
se |
SOCIAL_ENGINEERING |
このリストには、SOCIAL_ENGINEERING 脅威タイプの脅威が含まれています。 |
mw |
MALWARE |
このリストには、デスクトップ・プラットフォームを対象とするマルウェアの脅威の種類が掲載されています。 |
uws |
UNWANTED_SOFTWARE |
このリストには、デスクトップ プラットフォーム向けの UNWANTED_SOFTWARE 脅威タイプに関する脅威が含まれています。 |
uwsa |
UNWANTED_SOFTWARE |
このリストには、Android プラットフォームに対する UNWANTED_SOFTWARE 脅威タイプに関する脅威が含まれています。 |
pha |
POTENTIALLY_HARMFUL_APPLICATION |
このリストには、Android プラットフォームに対する POTENTIALLY_HARMFUL_APPLICATION 脅威タイプによる脅威が含まれています。 |
他のリストは後日追加可能になり、その時点で上記の表を拡張します。
クライアントがキャッシュ プロキシ サーバーを動作させ、上記のリストの一部またはすべてを取得してから、クライアントがプロキシ サーバーに接続することが許可されます。これを実装する場合は、キャッシュ期間を 5 分など短くすることをおすすめします。将来的には、このキャッシュ期間は標準の Cache-Control
HTTP ヘッダーを使用して通知される可能性があります。
更新の頻度
クライアントは、サーバーの minimum_wait_duration
フィールドで返された値を確認し、その値を使用してデータベースの次回の更新をスケジュールする必要があります。この値は 0 の可能性があり(フィールド minimum_wait_duration
が完全に欠落している場合)、クライアントはすぐに別の更新を実行するべきです。
リクエストの例
このセクションでは、HTTP API を直接使用して Google セーフ ブラウジングにアクセスする例をいくつか紹介します。通常は、生成された言語バインディングを使用することをおすすめします。これは、エンコードとデコードを便利な方法で自動的に処理するためです。バインディングについては、ドキュメントをご覧ください。
hashes.search メソッドを使用した HTTP リクエストの例を次に示します。
GET https://safebrowsing.googleapis.com/v5/hashes:search?key=INSERT_YOUR_API_KEY_HERE&hashPrefixes=WwuJdQ
レスポンスの本文はプロトコル バッファ形式のペイロードで、デコードできます。
hashLists.batchGet メソッドを使用した HTTP リクエストの例を次に示します。
GET https://safebrowsing.googleapis.com/v5alpha1/hashLists:batchGet?key=INSERT_YOUR_API_KEY_HERE&names=se&names=mw
レスポンスの本文もプロトコル バッファ形式のペイロードで、デコードできます。
移行ガイド
現在 v4 Update API を使用している場合は、ローカル データベースをリセットまたは消去することなく、v4 から v5 にシームレスに移行できます。このセクションでは、その方法について説明します。
リストの更新の変換
v4 では、threatListUpdates.fetch メソッドを使用してリストをダウンロードします。v5 では、hashLists.batchGet メソッドに切り替えます。
リクエストを次のように変更してください。
- v4
ClientInfo
オブジェクトを完全に削除します。専用のフィールドを使用してクライアントの ID を指定する代わりに、よく知られた User-Agent ヘッダーを使用するだけで済みます。このヘッダーにはクライアント ID を指定する決まった形式はありませんが、元のクライアント ID とクライアント バージョンをスペースまたはスラッシュで区切って指定することをおすすめします。 - 各 v4
ListUpdateRequest
オブジェクトについて: <ph type="x-smartling-placeholder">- </ph>
- 上記の表で対応する v5 のリスト名を検索し、その名前を v5 のリクエストに指定します。
threat_entry_type
やplatform_type
などの不要なフィールドを削除します。- v4 の
state
フィールドは、v5 のversions
フィールドと直接互換性があります。v4 ではstate
フィールドを使用してサーバーに送信されるのと同じバイト文字列を、v5 でもversions
フィールドを使用して簡単に送信できます。 - v4 の制約については、v5 では
SizeConstraints
という簡素化されたバージョンが使用されます。region
などの追加フィールドは削除する必要があります。
レスポンスを次のように変更する必要があります。
- v4 の enum
ResponseType
は、単にpartial_update
という名前のブール値フィールドに置き換えられます。 minimum_wait_duration
フィールドを 0 にすることも、省略することもできるようになりました。含まれている場合、クライアントはすぐに別のリクエストを行うよう要求されます。これは、クライアントがSizeConstraints
で、最大更新サイズに対して、最大データベース サイズよりも小さい制約を指定した場合にのみ発生します。- 32 ビット整数用の Rice デコード アルゴリズムを調整する必要があります。違いは、エンコードされたデータが別のエンディアンでエンコードされることです。v4 と v5 の両方で、32 ビットのハッシュ接頭辞は辞書順に並べ替えられます。しかし、v4 では、これらの接頭辞は並べ替え時にリトル エンディアンとして扱われ、v5 では並べ替え時にビッグ エンディアンとして扱われます。つまり、辞書順の並べ替えはビッグ エンディアンを使用する数値の並べ替えと同一であるため、クライアントは並べ替えを行う必要はありません。Chromium の v4 実装におけるこの種の例については、こちらをご覧ください。このような並べ替えは削除できます。
- 他のハッシュ長に対しては、Rice デコード アルゴリズムを実装する必要があります。
ハッシュ検索の変換
v4 では、fullHashes.find メソッドを使用してフルハッシュを取得します。V5 の同等のメソッドは hashes.search メソッドです。
リクエストを次のように変更してください。
- 長さがちょうど 4 バイトのハッシュ接頭辞のみを送信するようにコードを構造化します。
- v4 の
ClientInfo
オブジェクトを完全に削除します。専用のフィールドを使用してクライアントの ID を指定する代わりに、よく知られた User-Agent ヘッダーを使用するだけで済みます。このヘッダーにはクライアント ID を指定する決まった形式はありませんが、元のクライアント ID とクライアント バージョンをスペースまたはスラッシュで区切って指定することをおすすめします。 client_states
フィールドを削除します。不要になりました。threat_types
などのフィールドを含める必要がなくなりました。
レスポンスを次のように変更する必要があります。
minimum_wait_duration
フィールドが削除されました。クライアントはいつでも新しいリクエストを発行できます。- v4 の
ThreatMatch
オブジェクトは、FullHash
オブジェクトに簡略化されました。 - キャッシュは、単一のキャッシュ期間に簡素化されました。キャッシュの操作については、上記の手順をご覧ください。