Menggunakan Update API

Ringkasan

Dengan Update API, aplikasi klien Anda dapat mendownload versi yang di-hash dari daftar Web Risk untuk disimpan di database lokal atau dalam memori. URL kemudian dapat diperiksa secara lokal. Ketika kecocokan ditemukan di database lokal, klien akan mengirimkan permintaan ke server Web Risk untuk memverifikasi apakah URL disertakan dalam daftar Web Risk atau tidak.

Memperbarui database lokal

Agar tetap mendapatkan informasi terbaru, klien diwajibkan untuk memperbarui daftar Web Risk secara berkala di database lokal mereka. Untuk menghemat bandwidth, klien mendownload awalan hash URL, bukan URL mentah. Misalnya, jika "www.badurl.com/" ada dalam daftar Web Risk, klien akan mendownload awalan hash SHA256 dari URL tersebut, bukan URL itu sendiri. Pada umumnya, awalan hash panjangnya 4 byte. Artinya, biaya bandwidth rata-rata untuk mendownload satu entri daftar adalah 4 byte sebelum kompresi.

Untuk memperbarui daftar Web Risk di database lokal, kirim permintaan HTTP GET ke metode threatLists.computeDiff:

  • Permintaan GET HTTP menyertakan nama daftar yang akan diperbarui beserta batasan klien untuk memperhitungkan batasan memori dan bandwidth.
  • Respons GET HTTP menampilkan update lengkap atau update sebagian. Respons bisa juga menampilkan waktu tunggu yang direkomendasikan hingga operasi perbedaan komputasi berikutnya.

Contoh: ancamanLists.computeDiff

Permintaan GET HTTP

Pada contoh berikut, perbedaan untuk daftar MALWARE Web Risk akan diminta. Untuk mengetahui detail selengkapnya, lihat parameter kueri threatLists.computeDiff dan penjelasan yang mengikuti contoh kode.

Metode HTTP dan 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

Untuk mengirim permintaan Anda, pilih salah satu opsi berikut:

curl

Jalankan perintah berikut:

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

Jalankan perintah berikut:

$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

Anda akan melihat respons JSON seperti berikut:

{
  "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

Daftar Web Risk

Kolom threatType menunjukkan daftar Web Risk. Dalam contoh, perbedaan untuk daftar MALWARE Web Risk diminta.

Token versi

Kolom versionToken menyimpan status klien saat ini dari daftar Web Risk. Token Versi ditampilkan di kolom newVersionToken pada respons threatLists.computeDiff. Untuk update awal, kosongkan kolom versionToken.

Batasan ukuran

Kolom maxDiffEntries menentukan jumlah total update yang dapat dikelola klien (dalam contoh, 2048). Kolom maxDatabaseEntries menentukan jumlah total entri yang dapat dikelola database lokal (misalnya, 4096). Klien harus menetapkan batasan ukuran untuk melindungi batasan memori dan bandwidth, serta agar tidak terjadi pertumbuhan daftar. Untuk mengetahui informasi selengkapnya, lihat Memperbarui Batasan).

Kompresi yang didukung

Kolom supportedCompressions mencantumkan jenis kompresi yang didukung klien. Dalam contoh, klien hanya mendukung data mentah dan tidak dikompresi. Namun, Web Risk mendukung jenis kompresi tambahan. Untuk mengetahui informasi selengkapnya, lihat Kompresi.

Respons HTTP GET

Dalam contoh ini, respons menampilkan update sebagian untuk daftar Web Risk menggunakan jenis kompresi yang diminta.

Isi respons

Isi respons mencakup informasi diff (jenis respons, penambahan, dan penghapusan yang akan diterapkan ke database lokal, token versi baru, dan checksum).

Dalam contoh, respons juga menyertakan waktu diff berikutnya yang direkomendasikan. Untuk mengetahui detail selengkapnya, lihat isi respons threatLists.computeDiff dan penjelasan yang mengikuti contoh kode.

{
  "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"
}

Perbedaan database

Kolom responseType akan menunjukkan update sebagian (DIFF) atau update lengkap (RESET). Dalam contoh, perbedaan parsial ditampilkan, sehingga respons menyertakan penambahan dan penghapusan. Mungkin ada beberapa kumpulan tambahan, tetapi hanya satu kumpulan penghapusan. Untuk informasi selengkapnya, lihat Database Diffs.

Token versi baru

Kolom newVersionToken menyimpan token versi baru untuk daftar Web Risk yang baru diperbarui. Klien harus menyimpan status klien baru untuk permintaan update berikutnya (kolom versionToken dalam permintaan threatLists.computeDiff.

Checksums

Checksum memungkinkan klien memverifikasi bahwa database lokal tidak mengalami kerusakan. Jika checksum tidak cocok, klien harus menghapus database dan menerbitkan ulang update dengan kolom versionToken yang kosong. Namun, klien dalam situasi ini tetap harus mengikuti interval waktu untuk pembaruan. Untuk mengetahui informasi selengkapnya, lihat Frekuensi Permintaan.

Kolom recommendedNextDiff menunjukkan stempel waktu hingga saat klien harus menunggu sebelum mengirim permintaan update lainnya. Perlu diperhatikan bahwa periode tunggu yang direkomendasikan mungkin disertakan atau tidak disertakan dalam respons. Untuk mengetahui detail selengkapnya, lihat Frekuensi Permintaan.

Memeriksa URL

Untuk memeriksa apakah URL ada dalam daftar Web Risk atau tidak, klien harus terlebih dahulu menghitung awalan hash dan hash URL. Untuk mengetahui detailnya, lihat URL dan Hashing. Klien kemudian membuat kueri {i>database<i} lokal untuk menentukan apakah ada kecocokan. Jika awalan hash tidak ada dalam database lokal, maka URL akan dianggap aman (artinya, tidak termasuk dalam daftar Web Risk).

Jika awalan hash ada di database lokal (tumbukan awalan hash), klien harus mengirim awalan hash tersebut ke server Web Risk untuk diverifikasi. Server akan menampilkan semua hash SHA 256 panjang lengkap yang berisi awalan hash yang diberikan. Jika salah satu hash lengkap tersebut cocok dengan hash lengkap dari URL yang dimaksud, URL akan dianggap tidak aman. Jika tidak ada hash lengkap yang cocok dengan hash lengkap dari URL yang dimaksud, maka URL tersebut dianggap aman.

Google tidak akan mempelajari URL yang Anda periksa. Google mempelajari awalan hash URL, tetapi awalan hash tersebut tidak memberikan banyak informasi tentang URL sebenarnya.

Untuk memeriksa apakah URL ada dalam daftar Web Risk, kirim permintaan HTTP GET ke metode hashes.search:

  • Permintaan GET HTTP menyertakan awalan hash URL yang akan diperiksa.
  • Respons GET HTTP menampilkan hash lengkap yang cocok beserta waktu habis masa berlaku positif dan negatif.

Contoh: hashes.search

Permintaan GET HTTP

Pada contoh berikut, nama dua daftar Web Risk dan awalan hash akan dikirim untuk perbandingan dan verifikasi. Untuk mengetahui detail selengkapnya, lihat parameter kueri hashes.search dan penjelasan yang mengikuti contoh kode.

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

Daftar Web Risk

Kolom threatTypes mengidentifikasi daftar Web Risk. Dalam contoh, dua daftar diidentifikasi: MALWARE dan SOCIAL_ENGINEERING.

Awalan hash ancaman

Kolom hashPrefix berisi awalan hash URL yang ingin Anda periksa. Kolom ini harus berisi awalan hash yang sama persis dengan yang ada di database lokal. Misalnya, jika panjang awalan hash lokal adalah 4 byte, maka kolom hashPrefix harus sepanjang 4 byte. Jika awalan hash lokal diperpanjang hingga 7 byte, panjang kolom hashPrefix harus 7 byte.

Respons HTTP GET

Pada contoh berikut, respons menampilkan ancaman yang cocok, yang berisi daftar Web Risk yang cocok, beserta waktu habis masa berlakunya.

Isi respons

Isi respons menyertakan informasi kecocokan (nama daftar dan hash lengkap serta durasi cache). Untuk mengetahui detail selengkapnya, lihat isi respons hashes.search dan penjelasan yang mengikuti contoh kode.

{
  "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"
}

Mencocokkan dengan

Kolom threats menampilkan hash lengkap yang cocok untuk awalan hash. URL yang sesuai dengan hash ini dianggap tidak aman. Jika tidak ditemukan kecocokan untuk awalan hash, tidak ada yang akan ditampilkan; URL yang sesuai dengan awalan hash tersebut dianggap aman.

Masa berlaku

Kolom expireTime dan negativeExpireTime menunjukkan sampai kapan hash harus dianggap tidak aman atau aman. Untuk mengetahui detail selengkapnya, lihat Menyimpan ke cache.