Update API 사용

개요

Update API를 사용하면 클라이언트 애플리케이션이 로컬 또는 인메모리 데이터베이스의 스토리지에 대한 Web Risk 목록의 해시된 버전을 다운로드할 수 있습니다. 그런 다음 로컬에서 URL을 확인할 수 있습니다. 로컬 데이터베이스에 일치하는 항목이 있으면 클라이언트는 Web Risk 서버에 요청을 보내 Web Risk 목록에 해당 URL이 포함되어 있는지 확인합니다.

로컬 데이터베이스 업데이트

최신 상태를 유지하려면 클라이언트가 로컬 데이터베이스의 Web Risk 목록을 주기적으로 업데이트해야 합니다. 대역폭을 절약하기 위해 클라이언트는 원시 URL이 아닌 URL의 해시 프리픽스를 다운로드합니다. 예를 들어 'www.badurl.com/'이 Web Risk 목록에 있는 경우 클라이언트는 URL 자체가 아닌 해당 URL의 SHA256 해시 프리픽스를 다운로드합니다. 대부분의 경우 해시 프리픽스는 4바이트입니다. 즉, 단일 목록 항목을 다운로드하는데 필요한 평균 대역폭 비용은 압축 전 4바이트입니다.

로컬 데이터베이스의 Web Risk 목록을 업데이트하려면 threatLists.computeDiff 메서드에 HTTP GET 요청을 보냅니다.

  • HTTP GET 요청에는 메모리 및 대역폭 제한을 고려하여 클라이언트 제약조건과 함께 업데이트할 목록의 이름이 포함됩니다.
  • HTTP GET 응답은 전체 업데이트 또는 부분 업데이트를 반환합니다. 또한 응답은 다음 컴퓨팅 비교 작업까지의 권장 대기 시간을 반환할 수 있습니다.

예: threatLists.computeDiff

HTTP GET 요청

다음 예시에서는 멀웨어 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 목록을 식별합니다. 이 예시에서는 멀웨어 Web Risk 목록의 비교를 요청합니다.

버전 토큰

versionToken 필드에는 Web Risk 목록의 현재 클라이언트 상태가 포함됩니다. 버전 토큰은 threatLists.computeDiff 응답newVersionToken 필드에 반환됩니다. 초기 업데이트의 경우 versionToken 필드를 비워둡니다.

크기 제한

maxDiffEntries 필드는 클라이언트가 관리할 수 있는 총 업데이트 수를 지정합니다(예: 2048). maxDatabaseEntries 필드는 로컬 데이터베이스가 관리할 수 있는 총 항목 수를 지정합니다(예: 4096). 클라이언트는 메모리 및 대역폭 제한을 보호하고 목록 증가로부터 보호하기 위해 크기 제약조건을 설정해야 합니다. 자세한 내용은 업데이트 제약조건을 참조하세요.

지원되는 압축

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)를 나타냅니다. 이 예시에서는 부분 비교가 반환되므로 응답에 추가와 삭제가 모두 포함됩니다. 여러 개의 추가 항목이 있을 수 있지만 하나의 삭제 모음만 있을 수 있습니다. 자세한 내용은 데이터베이스 비교를 참조하세요.

새 버전 토큰

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 목록에 있는지 확인하려면 hashes.search 메서드에 HTTP GET 요청을 보냅니다.

  • HTTP GET 요청에는 확인할 URL의 해시 프리픽스가 포함됩니다.
  • HTTP GET 응답은 일치하는 전체 길이 해시를 양성 및 음성 만료 시간과 함께 반환합니다.

예: hashes.search

HTTP GET 요청

다음 예시에서는 비교 및 확인을 위해 두 개의 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의 두 목록이 식별됩니다.

위협 해시 프리픽스

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은 안전한 것으로 간주됩니다.

만료 시간

expireTimenegativeExpireTime 필드는 각각 해시를 안전하지 않거나 안전하다고 간주해야 할 때까지를 나타냅니다. 자세한 내용은 캐싱을 참조하세요.