Update API の使用

概要

Update API を使用すると、クライアントアプリケーションで、Web Risk リストのハッシュバージョンをダウンロードして、ローカルデータベースまたはメモリ内データベースに保存できます。その後、URL をローカルで確認できます。ローカル データベースで一致が見つかった場合、クライアントは Web Risk サーバーにリクエストを送信して、その URL が Web Risk リストに含まれているかどうかを確認します。

ローカル データベースの更新

最新の状態を維持するため、クライアントはローカル データベースの Web Risk リストを定期的に更新する必要があります。帯域幅を節約するために、クライアントは未加工の URL ではなく URL のハッシュ プレフィックスをダウンロードします。たとえば、Web Risk に「www.badurl.com/」が含まれている場合、クライアントは URL そのものではなく、その URL の SHA256 ハッシュ プレフィックスをダウンロードします。ほとんどの場合、ハッシュ プレフィックスの長さは 4 バイトです。つまり、1 つのリストエントリをダウンロードするための平均帯域幅コストは圧縮前の 4 バイトです。

ローカル データベース内のWeb Risk リストを更新するには、HTTP GET リクエストを threatLists.computeDiff メソッドに送信します。

  • HTTP GET リクエストには、メモリと帯域幅の制限を考慮して、更新されるリストの名前とクライアントの制約が含まれます。
  • HTTP GET レスポンスは、完全な更新または部分的な更新を返します。 レスポンスは、次のコンピューティング差分演算を計算するまでの推奨待ち時間も返します。

例: threatLists.computeDiff

HTTP GET リクエスト

次の例では、MALware Web Risk リストの差分がリクエストされます。詳細については、threatLists.computeDiff クエリ パラメータとコード例に続く説明をご覧ください。

HTTP メソッドと URL:

GET https://webrisk.googleapis.com/v1/threatLists:computeDiff?threatType=MALWARE&versionToken=Gg4IBBADIgYQgBAiAQEoAQ%3D%3D&constraints.maxDiffEntries=2048&constraints.maxDatabaseEntries=4096&constraints.supportedCompressions=RAW&key=API_KEY

リクエストを送信するには、次のいずれかのオプションを選択します。

curl

次のコマンドを実行します。

curl -X GET \
"https://webrisk.googleapis.com/v1/threatLists:computeDiff?threatType=MALWARE&versionToken=Gg4IBBADIgYQgBAiAQEoAQ%3D%3D&constraints.maxDiffEntries=2048&constraints.maxDatabaseEntries=4096&constraints.supportedCompressions=RAW&key=API_KEY"

PowerShell

次のコマンドを実行します。

$headers = @{  }

Invoke-WebRequest `
-Method GET `
-Headers $headers `
-Uri "https://webrisk.googleapis.com/v1/threatLists:computeDiff?threatType=MALWARE&versionToken=Gg4IBBADIgYQgBAiAQEoAQ%3D%3D&constraints.maxDiffEntries=2048&constraints.maxDatabaseEntries=4096&constraints.supportedCompressions=RAW&key=API_KEY" | Select-Object -Expand Content

次のような JSON レスポンスが返されます。

{
  "recommendedNextDiff": "2020-01-08T19:41:45.436722194Z",
  "responseType": "RESET",
  "additions": {
    "rawHashes": [
      {
        "prefixSize": 4,
        "rawHashes": "AArQMQAMoUgAPn8lAE..."
      }
    ]
  },
  "newVersionToken": "ChAIARAGGAEiAzAwMSiAEDABEPDyBhoCGAlTcIVL",
  "checksum": {
    "sha256": "wy6jh0+MAg/V/+VdErFhZIpOW+L8ulrVwhlV61XkROI="
  }
}

Java


import com.google.cloud.webrisk.v1.WebRiskServiceClient;
import com.google.protobuf.ByteString;
import com.google.webrisk.v1.CompressionType;
import com.google.webrisk.v1.ComputeThreatListDiffRequest;
import com.google.webrisk.v1.ComputeThreatListDiffRequest.Constraints;
import com.google.webrisk.v1.ComputeThreatListDiffResponse;
import com.google.webrisk.v1.ThreatType;
import java.io.IOException;

public class ComputeThreatListDiff {

  public static void main(String[] args) throws IOException {
    // TODO(developer): Replace these variables before running the sample.
    // The threat list to update. Only a single ThreatType should be specified per request.
    ThreatType threatType = ThreatType.MALWARE;

    // The current version token of the client for the requested list. If the client does not have
    // a version token (this is the first time calling ComputeThreatListDiff), this may be
    // left empty and a full database snapshot will be returned.
    ByteString versionToken = ByteString.EMPTY;

    // The maximum size in number of entries. The diff will not contain more entries
    // than this value. This should be a power of 2 between 2**10 and 2**20.
    // If zero, no diff size limit is set.
    int maxDiffEntries = 1024;

    // Sets the maximum number of entries that the client is willing to have in the local database.
    // This should be a power of 2 between 2**10 and 2**20. If zero, no database size limit is set.
    int maxDatabaseEntries = 1024;

    // The compression type supported by the client.
    CompressionType compressionType = CompressionType.RAW;

    computeThreatDiffList(threatType, versionToken, maxDiffEntries, maxDatabaseEntries,
        compressionType);
  }

  // Gets the most recent threat list diffs. These diffs should be applied to a local database of
  // hashes to keep it up-to-date.
  // If the local database is empty or excessively out-of-date,
  // a complete snapshot of the database will be returned. This Method only updates a
  // single ThreatList at a time. To update multiple ThreatList databases, this method needs to be
  // called once for each list.
  public static void computeThreatDiffList(ThreatType threatType, ByteString versionToken,
      int maxDiffEntries, int maxDatabaseEntries, CompressionType compressionType)
      throws IOException {
    // Initialize client that will be used to send requests. This client only needs to be created
    // once, and can be reused for multiple requests. After completing all of your requests, call
    // the `webRiskServiceClient.close()` method on the client to safely
    // clean up any remaining background resources.
    try (WebRiskServiceClient webRiskServiceClient = WebRiskServiceClient.create()) {

      Constraints constraints = Constraints.newBuilder()
          .setMaxDiffEntries(maxDiffEntries)
          .setMaxDatabaseEntries(maxDatabaseEntries)
          .addSupportedCompressions(compressionType)
          .build();

      ComputeThreatListDiffResponse response = webRiskServiceClient.computeThreatListDiff(
          ComputeThreatListDiffRequest.newBuilder()
              .setThreatType(threatType)
              .setVersionToken(versionToken)
              .setConstraints(constraints)
              .build());

      // The returned response contains the following information:
      // https://cloud.google.com/web-risk/docs/reference/rpc/google.cloud.webrisk.v1#computethreatlistdiffresponse
      // Type of response: DIFF/ RESET/ RESPONSE_TYPE_UNSPECIFIED
      System.out.println(response.getResponseType());
      // List of entries to add and/or remove.
      // System.out.println(response.getAdditions());
      // System.out.println(response.getRemovals());

      // New version token to be used the next time when querying.
      System.out.println(response.getNewVersionToken());

      // Recommended next diff timestamp.
      System.out.println(response.getRecommendedNextDiff());

      System.out.println("Obtained threat list diff.");
    }
  }
}

Python

from google.cloud import webrisk_v1
from google.cloud.webrisk_v1 import ComputeThreatListDiffResponse

def compute_threatlist_diff(
    threat_type: webrisk_v1.ThreatType,
    version_token: bytes,
    max_diff_entries: int,
    max_database_entries: int,
    compression_type: webrisk_v1.CompressionType,
) -> ComputeThreatListDiffResponse:
    """Gets the most recent threat list diffs.

    These diffs should be applied to a local database of hashes to keep it up-to-date.
    If the local database is empty or excessively out-of-date,
    a complete snapshot of the database will be returned. This Method only updates a
    single ThreatList at a time. To update multiple ThreatList databases, this method needs to be
    called once for each list.

    Args:
        threat_type: The threat list to update. Only a single ThreatType should be specified per request.
            threat_type = webrisk_v1.ThreatType.MALWARE

        version_token: The current version token of the client for the requested list. If the
            client does not have a version token (this is the first time calling ComputeThreatListDiff),
            this may be left empty and a full database snapshot will be returned.

        max_diff_entries: The maximum size in number of entries. The diff will not contain more entries
            than this value. This should be a power of 2 between 2**10 and 2**20.
            If zero, no diff size limit is set.
            max_diff_entries = 1024

        max_database_entries: Sets the maximum number of entries that the client is willing to have in the local database.
            This should be a power of 2 between 2**10 and 2**20. If zero, no database size limit is set.
            max_database_entries = 1024

        compression_type: The compression type supported by the client.
            compression_type = webrisk_v1.CompressionType.RAW

    Returns:
        The response which contains the diff between local and remote threat lists. In addition to the threat list,
        the response also contains the version token and the recommended time for next diff.
    """

    webrisk_client = webrisk_v1.WebRiskServiceClient()

    constraints = webrisk_v1.ComputeThreatListDiffRequest.Constraints()
    constraints.max_diff_entries = max_diff_entries
    constraints.max_database_entries = max_database_entries
    constraints.supported_compressions = [compression_type]

    request = webrisk_v1.ComputeThreatListDiffRequest()
    request.threat_type = threat_type
    request.version_token = version_token
    request.constraints = constraints

    response = webrisk_client.compute_threat_list_diff(request)

    # The returned response contains the following information:
    # https://cloud.google.com/web-risk/docs/reference/rpc/google.cloud.webrisk.v1#computethreatlistdiffresponse
    # Type of response: DIFF/ RESET/ RESPONSE_TYPE_UNSPECIFIED
    print(response.response_type)
    # New version token to be used the next time when querying.
    print(response.new_version_token)
    # Recommended next diff timestamp.
    print(response.recommended_next_diff)

    return response

Web Risk リスト

threatType フィールドは、Web Risk リストを識別します。この例では、MALware Web Risk リストの差分がリクエストされます。

バージョン トークン

versionToken フィールドには、Web Risk リストの現在のクライアントの状態が保持されます。バージョン トークンは、TheatLists.computeDiff レスポンスnewVersionToken フィールドで返されます。最初の更新では、versionToken フィールドは空のままにします。

サイズ制限

maxDiffEntriesフィールドは、クライアントが管理できる更新の合計数を指定します(この例では 2,048)。maxDatabaseEntriesフィールドは、ローカルデータベースが管理できるエントリの合計数を指定します(この例では 4,096)。クライアントは、メモリと帯域幅の制限を保護し、リストの増加を防ぐために、サイズの制約を設定する必要があります。詳しくは、更新の制約をご覧ください。

サポートされている圧縮

supportedCompressions フィールドには、クライアントでサポートされる圧縮タイプが一覧表示されます。この例のクライアントでは、未加工の非圧縮データのみがサポートされています。ただし、Web Risk では、他の圧縮タイプもサポートされています。詳細については、圧縮をご覧ください。

HTTP GET レスポンス

この例では、レスポンスはリクエストされた圧縮タイプを使用してWeb Risk リストの部分更新を返します。

レスポンスの本文

レスポンスの本文には、差分情報(レスポンスタイプ、ローカルデータベースに適用される追加と削除、新しいバージョン トークン、チェックサム)が含まれます。

この例では、推奨される次の差分時間もレスポンスに含まれています。詳細については、threatLists.computeDiff レスポンスの本文とコード例に続く説明をご覧ください。

{
  "responseType" :   "DIFF",
  "recommendedNextDiff": "2019-12-31T23:59:59.000000000Z",
  "additions": {
    "compressionType": "RAW",
    "rawHashes": [{
      "prefixSize": 4,
      "rawHashes":  "rnGLoQ=="
    }]
  },
  "removals": {
    "rawIndices": {
      "indices": [0, 2, 4]
    }
  },
  "newVersionToken": "ChAIBRADGAEiAzAwMSiAEDABEAFGpqhd",
  "checksum": {
    "sha256": "YSgoRtsRlgHDqDA3LAhM1gegEpEzs1TjzU33vqsR8iM="
  },
  "recommendedNextDiff": "2019-07-17T15:01:23.045123456Z"
}

データベースの差分

responseType フィールドは、部分的(DIFF)または完全な更新(RESET)を示します。この例では、部分差分が返されるため、レスポンスには追加と削除の両方が含まれます複数の追加が返される可能性がありますが、削除は 1 つだけです。詳細については、データベースの差分をご覧ください。

新しいバージョン トークン

newVersionToken フィールドには、新しく更新されたWeb Risk リストの新しいバージョン トークンが格納されます。クライアントは、後続の更新リクエスト(threatLists.computeDiff リクエストversionToken フィールド)のために新しいクライアント状態を保存する必要があります。

チェックサム

チェックサムを使用すると、クライアントはローカル データベースが破損していないことを確認できます。チェックサムが一致しない場合、クライアントはデータベースを消去し、空の versionToken フィールドを使用して更新を再発行する必要があります。ただし、この場合でも、クライアントは更新の間隔に従う必要があります。詳細については、リクエスト頻度をご覧ください。

recommendedNextDiff フィールドは、クライアントが別の更新リクエストを送信するまで待機する時点までのタイムスタンプを示します。推奨される待ち時間は、レスポンスに含まれる場合もあれば、含まれない場合もあります。詳細については、リクエスト頻度をご覧ください。

URL の確認

URL が Web Risk リストに含まれているかどうかを確認するには、クライアントはまず URL のハッシュとハッシュ プレフィックスを計算する必要があります。詳細については、URL とハッシュ化をご覧ください。次に、クライアントはローカル データベースにクエリを行い、一致するものがあるかどうかを判断します。ハッシュ プレフィックスがローカル データベースに存在しない場合、URL は安全と見なされます(つまり、Web Risk リストにはありません)。

ハッシュプレフィックスがローカルデータベースに存在する場合(ハッシュプレフィックスの競合)、クライアントは検証のためにハッシュプレフィックスを Web Risk サーバーに送信する必要があります。サーバーは、指定されたハッシュ プレフィックスを含むすべてのフルレングスの SHA 256 ハッシュを返します。これらのフルレングスのハッシュのいずれかが、問題の URL のフルレングスのハッシュと一致する場合、その URL は安全でないとみなされます。問題の URL のフルレングスのハッシュと一致するフルレングスのハッシュがない場合、その URL は安全と見なされます。

Google は、調査している URL をまったく認識しません。Google は URL のハッシュ プレフィックスを認識しますが、ハッシュ プレフィックスは実際の URL に関する情報を提供しません。

URL が Web Risk リストに含まれているかどうかを確認するには、HTTP GET リクエストを hashes.search メソッドに送信します。

  • HTTP GET リクエストには、確認する URL のハッシュ プレフィックスが含まれます。
  • HTTP GET レスポンスは、一致するフルレングスのハッシュをポジティブとネガティブの有効期限とともに返します。

例: hashes.search

HTTP GET リクエスト

次の例では、比較と確認のために 2 つの Web Risk リストの名前とハッシュ プレフィックスが送信されます。詳細については、hashes.search クエリ パラメータとコード例に続く説明をご覧ください。

curl \
  -H "Content-Type: application/json" \
  "https://webrisk.googleapis.com/v1/hashes:search?key=YOUR_API_KEY&threatTypes=MALWARE&threatTypes=SOCIAL_ENGINEERING&hashPrefix=WwuJdQ%3D%3D"

Java


import com.google.cloud.webrisk.v1.WebRiskServiceClient;
import com.google.protobuf.ByteString;
import com.google.webrisk.v1.SearchHashesRequest;
import com.google.webrisk.v1.SearchHashesResponse;
import com.google.webrisk.v1.SearchHashesResponse.ThreatHash;
import com.google.webrisk.v1.ThreatType;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Base64;
import java.util.List;

public class SearchHashes {

  public static void main(String[] args) throws IOException, NoSuchAlgorithmException {
    // TODO(developer): Replace these variables before running the sample.
    // A hash prefix, consisting of the most significant 4-32 bytes of a SHA256 hash.
    // For JSON requests, this field is base64-encoded. Note that if this parameter is provided
    // by a URI, it must be encoded using the web safe base64 variant (RFC 4648).
    String uri = "http://example.com";
    String encodedUri = Base64.getUrlEncoder().encodeToString(uri.getBytes(StandardCharsets.UTF_8));
    MessageDigest digest = MessageDigest.getInstance("SHA-256");
    byte[] encodedHashPrefix = digest.digest(encodedUri.getBytes(StandardCharsets.UTF_8));

    // The ThreatLists to search in. Multiple ThreatLists may be specified.
    // For the list on threat types, see: https://cloud.google.com/web-risk/docs/reference/rpc/google.cloud.webrisk.v1#threattype
    List<ThreatType> threatTypes = Arrays.asList(ThreatType.MALWARE, ThreatType.SOCIAL_ENGINEERING);

    searchHash(ByteString.copyFrom(encodedHashPrefix), threatTypes);
  }

  // Gets the full hashes that match the requested hash prefix.
  // This is used after a hash prefix is looked up in a threatList and there is a match.
  // The client side threatList only holds partial hashes so the client must query this method
  // to determine if there is a full hash match of a threat.
  public static void searchHash(ByteString encodedHashPrefix, List<ThreatType> threatTypes)
      throws IOException {
    // Initialize client that will be used to send requests. This client only needs to be created
    // once, and can be reused for multiple requests. After completing all of your requests, call
    // the `webRiskServiceClient.close()` method on the client to safely
    // clean up any remaining background resources.
    try (WebRiskServiceClient webRiskServiceClient = WebRiskServiceClient.create()) {

      // Set the hashPrefix and the threat types to search in.
      SearchHashesResponse response = webRiskServiceClient.searchHashes(
          SearchHashesRequest.newBuilder()
              .setHashPrefix(encodedHashPrefix)
              .addAllThreatTypes(threatTypes)
              .build());

      // Get all the hashes that match the prefix. Cache the returned hashes until the time
      // specified in threatHash.getExpireTime()
      // For more information on response type, see: https://cloud.google.com/web-risk/docs/reference/rpc/google.cloud.webrisk.v1#threathash
      for (ThreatHash threatHash : response.getThreatsList()) {
        System.out.println(threatHash.getHash());
      }
      System.out.println("Completed searching threat hashes.");
    }
  }
}

Python

from google.cloud import webrisk_v1

def search_hashes(hash_prefix: bytes, threat_type: webrisk_v1.ThreatType) -> list:
    """Gets the full hashes that match the requested hash prefix.

    This is used after a hash prefix is looked up in a threatList and there is a match.
    The client side threatList only holds partial hashes so the client must query this method
    to determine if there is a full hash match of a threat.

    Args:
        hash_prefix: A hash prefix, consisting of the most significant 4-32 bytes of a SHA256 hash.
            For JSON requests, this field is base64-encoded. Note that if this parameter is provided
            by a URI, it must be encoded using the web safe base64 variant (RFC 4648).
            Example:
                uri = "http://example.com"
                sha256 = sha256()
                sha256.update(base64.urlsafe_b64encode(bytes(uri, "utf-8")))
                hex_string = sha256.digest()

        threat_type: The ThreatLists to search in. Multiple ThreatLists may be specified.
            For the list on threat types, see:
            https://cloud.google.com/web-risk/docs/reference/rpc/google.cloud.webrisk.v1#threattype
            threat_type = [webrisk_v1.ThreatType.MALWARE, webrisk_v1.ThreatType.SOCIAL_ENGINEERING]

    Returns:
        A hash list that contain all hashes that matches the given hash prefix.
    """
    webrisk_client = webrisk_v1.WebRiskServiceClient()

    # Set the hashPrefix and the threat types to search in.
    request = webrisk_v1.SearchHashesRequest()
    request.hash_prefix = hash_prefix
    request.threat_types = [threat_type]

    response = webrisk_client.search_hashes(request)

    # Get all the hashes that match the prefix. Cache the returned hashes until the time
    # specified in threat_hash.expire_time
    # For more information on response type, see:
    # https://cloud.google.com/web-risk/docs/reference/rpc/google.cloud.webrisk.v1#threathash
    hash_list = []
    for threat_hash in response.threats:
        hash_list.append(threat_hash.hash)
    return hash_list

Web Risk リスト

threatTypes フィールドは、Web Risk リストを示します。この例では、MALWARESOCIAL_ENGINEERING の 2 つのリストが識別されます。

脅威のハッシュ プレフィックス

hashPrefix フィールドには、確認する URL のハッシュ プレフィックスが含まれます。このフィールドには、ローカル データベースに存在する正確なハッシュ プレフィックスを含める必要があります。たとえば、ローカル ハッシュ プレフィックスが 4 バイトの場合、hashPrefix フィールドは 4 バイトにする必要があります。ローカル ハッシュ プレフィックスが 7 バイトに延長されている場合、hashPrefix フィールドは 7 バイトにする必要があります。

HTTP GET レスポンス

次の例では、レスポンスは一致した Web Risk リストを含む一致する脅威と有効期限を返します。

レスポンスの本文

レスポンスの本文には、一致情報(リスト名、フルレングスのハッシュ、キャッシュ期間)が含まれます。詳細については、hashes.search レスポンスの本文とコード例に続く説明をご覧ください。

{
  "threats": [{
      "threatTypes": ["MALWARE"],
      "hash": "WwuJdQx48jP-4lxr4y2Sj82AWoxUVcIRDSk1PC9Rf-4="
      "expireTime": "2019-07-17T15:01:23.045123456Z"
    }, {
      "threatTypes": ["MALWARE", "SOCIAL_ENGINEERING"],
      "hash": "WwuJdQxaCSH453-uytERC456gf45rFExcE23F7-hnfD="
      "expireTime": "2019-07-17T15:01:23.045123456Z"
    },
  }],
  "negativeExpireTime": "2019-07-17T15:01:23.045123456Z"
}

一致する

threats フィールドには、ハッシュ プレフィックスに一致するフルレングスのハッシュが返されます。これらのハッシュに対応する URL は安全でないとみなされます。ハッシュ プレフィックスに一致するものが見つからない場合は、何も返されません。そのハッシュ プレフィックスに対応する URL は安全と見なされます。

有効期限

expireTime フィールドと negativeExpireTime フィールドは、ハッシュが安全でないか安全かを判断する必要があるタイミングをそれぞれ示します。詳しくは、キャッシュ保存をご覧ください。