Menggunakan Update API

Ringkasan

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

Memperbarui database lokal

Agar tetap terbaru, klien diwajibkan untuk memperbarui daftar Risiko Web 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 URL tersebut, bukan URL itu sendiri. Dalam sebagian besar kasus, awalan hash memiliki panjang 4 byte, yang berarti biaya bandwidth rata-rata untuk mendownload satu entri daftar adalah 4 byte sebelum kompresi.

Untuk memperbarui daftar Risiko Web di database lokal, kirim permintaan GET HTTP 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 penuh atau update sebagian. Respons dapat juga menampilkan waktu tunggu yang direkomendasikan hingga operasi hitung perbedaan berikutnya.

Contoh: threatLists.computeDiff

Permintaan GET HTTP

Dalam contoh berikut, perbedaan untuk daftar Web Risk MALWARE 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 mengidentifikasi daftar Web Risk. Dalam contoh, perbedaan untuk daftar Web Risk MALWARE diminta.

Token versi

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

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 (dalam contoh, 4096). Klien harus menetapkan batasan ukuran untuk melindungi memori dan batasan bandwidth serta untuk mencegah pertumbuhan daftar. Untuk mengetahui informasi selengkapnya, lihat Batasan Update).

Kompresi yang didukung

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

Respons HTTP GET

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

Isi respons

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

Dalam contoh, respons juga menyertakan waktu perbedaan 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 pembaruan sebagian (DIFF) atau penuh (RESET). Dalam contoh, perbedaan sebagian ditampilkan, sehingga respons menyertakan penambahan dan penghapusan. Mungkin ada beberapa kumpulan penambahan, tetapi hanya satu kumpulan penghapusan. Untuk mengetahui informasi selengkapnya, lihat Database Diffs.

Token versi baru

Kolom newVersionToken menyimpan token versi baru untuk daftar Risiko Web yang baru saja 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 kosong. Namun, klien dalam situasi ini masih harus mengikuti interval waktu untuk update. Untuk mengetahui informasi selengkapnya, lihat Frekuensi Permintaan.

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

Memeriksa URL

Untuk memeriksa apakah URL ada dalam daftar Web Risk, klien harus terlebih dahulu menghitung hash dan awalan hash URL. Untuk mengetahui detailnya, lihat URL dan Hashing. Klien kemudian mengkueri database lokal untuk menentukan apakah ada kecocokan. Jika awalan hash tidak ada di database lokal, URL tersebut dianggap aman (yaitu, tidak ada dalam daftar Web Risk).

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

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

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

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

Contoh: hashes.search

Permintaan GET HTTP

Dalam contoh berikut, nama dua daftar Risiko Web dan awalan hash 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 awalan hash lokal memiliki panjang 4 byte, maka kolom hashPrefix harus memiliki panjang 4 byte. Jika awalan hash lokal diperpanjang menjadi 7 byte, kolom hashPrefix harus berukuran 7 byte.

Respons HTTP GET

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

Isi respons

Isi respons mencakup informasi kecocokan (nama daftar dan hash panjang penuh 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 panjang penuh yang cocok untuk awalan hash. URL yang sesuai dengan hash ini dianggap tidak aman. Jika tidak ada kecocokan yang ditemukan untuk awalan hash, tidak ada yang ditampilkan; URL yang sesuai dengan awalan hash tersebut dianggap aman.

Masa berlaku

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