Usar a API Update

Vista geral

A API Update permite que as suas aplicações cliente transfiram versões com hash das listas do Web Risk para armazenamento numa base de dados local ou na memória. Em seguida, os URLs podem ser verificados localmente. Quando é encontrada uma correspondência na base de dados local, o cliente envia um pedido aos servidores do Web Risk para verificar se o URL está incluído nas listas do Web Risk.

Atualizar a base de dados local

Para se manterem atualizados, os clientes têm de atualizar periodicamente as listas do Web Risk na respetiva base de dados local. Para poupar largura de banda, os clientes transferem os prefixos de hash dos URLs em vez dos URLs não processados. Por exemplo, se "www.badurl.com/" estiver numa lista de risco na Web, os clientes transferem o prefixo de hash SHA256 desse URL em vez do próprio URL. Na maioria dos casos, os prefixos de hash têm 4 bytes de comprimento, o que significa que o custo médio da largura de banda de transferir uma única entrada da lista é de 4 bytes antes da compressão.

Para atualizar as listas do Web Risk na base de dados local, envie um pedido HTTP GET para o método threatLists.computeDiff:

  • O pedido GET HTTP inclui o nome da lista a atualizar, juntamente com restrições do cliente para ter em conta as limitações de memória e largura de banda.
  • A resposta HTTP GET devolve uma atualização completa ou uma atualização parcial. A resposta também pode devolver um tempo de espera recomendado até à próxima operação de cálculo de diferenças.

Exemplo: threatLists.computeDiff

Pedido HTTP GET

No exemplo seguinte, são pedidas as diferenças para a lista de risco na Web de SOFTWARE MALICIOSO. Para mais detalhes, consulte os threatLists.computeDiff parâmetros de consulta e as explicações que se seguem ao exemplo de código.

Método HTTP e 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

Para enviar o seu pedido, escolha uma destas opções:

curl

Execute o seguinte comando:

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

Execute o seguinte comando:

$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

Deve receber uma resposta JSON semelhante à seguinte:

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

Listas do Web Risk

O campo threatType identifica a lista de risco na Web. No exemplo, são pedidas as diferenças para a lista de risco na Web de SOFTWARE MALICIOSO.

Token de versão

O campo versionToken contém o estado atual do cliente da lista de riscos na Web. Os tokens de versão são devolvidos no campo newVersionToken da resposta threatLists.computeDiff. Para atualizações iniciais, deixe o campo versionToken vazio.

Restrições de tamanho

O campo maxDiffEntries especifica o número total de atualizações que o cliente pode gerir (no exemplo, 2048). O campo maxDatabaseEntries especifica o número total de entradas que a base de dados local pode gerir (no exemplo, 4096). Os clientes devem definir restrições de tamanho para proteger a memória e as limitações de largura de banda, bem como para se salvaguardarem contra o crescimento das listas. Para mais informações, consulte o artigo Restrições de atualização).

Compressões suportadas

O campo supportedCompressions lista os tipos de compressão suportados pelo cliente. No exemplo, o cliente suporta apenas dados não processados e não comprimidos. No entanto, o Web Risk suporta tipos de compressão adicionais. Para mais informações, consulte o artigo Compressão.

Resposta HTTP GET

Neste exemplo, a resposta devolve uma atualização parcial da lista de riscos Web com o tipo de compressão pedido.

Corpo da resposta

O corpo da resposta inclui as informações de diferenças (o tipo de resposta, as adições e as remoções a aplicar à base de dados local, o novo token de versão e uma soma de verificação).

No exemplo, a resposta também inclui um tempo de diferença seguinte recomendado. Para mais detalhes, consulte o threatLists.computeDiff corpo da resposta e as explicações que se seguem ao exemplo de código.

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

Diferenças da base de dados

O campo responseType indica uma atualização parcial (DIFF) ou total (RESET). No exemplo, são devolvidas diferenças parciais, pelo que a resposta inclui adições e remoções. Pode haver vários conjuntos de adições, mas apenas um conjunto de remoções. Para mais informações, consulte o artigo Diferenças entre bases de dados.

Token da nova versão

O campo newVersionToken contém o token da nova versão da lista de riscos na Web recentemente atualizada. Os clientes têm de guardar o novo estado do cliente para pedidos de atualização subsequentes (o campo versionToken no pedido threatLists.computeDiff).

Somas de verificação

A soma de verificação permite que os clientes verifiquem se a base de dados local não sofreu nenhuma corrupção. Se a soma de verificação não corresponder, o cliente tem de limpar a base de dados e reemitir uma atualização com um campo versionToken vazio. No entanto, os clientes nesta situação têm de seguir os intervalos de tempo para atualizações. Para mais informações, consulte o artigo Frequência de pedidos.

O campo recommendedNextDiff indica uma data/hora até à qual o cliente deve aguardar antes de enviar outro pedido de atualização. Tenha em atenção que o período de espera recomendado pode ou não estar incluído na resposta. Para mais detalhes, consulte Frequência de pedidos.

A verificar os URLs

Para verificar se um URL está numa lista do Web Risk, o cliente tem de calcular primeiro o hash e o prefixo de hash do URL. Para ver detalhes, consulte o artigo URLs e hash. Em seguida, o cliente consulta a base de dados local para determinar se existe uma correspondência. Se o prefixo hash não estiver presente na base de dados local, o URL é considerado seguro (ou seja, não está nas listas de risco na Web).

Se o prefixo de hash estiver presente na base de dados local (uma colisão de prefixos de hash), o cliente tem de enviar o prefixo de hash para os servidores do Web Risk para validação. Os servidores devolvem todos os hashes SHA 256 de comprimento total que contêm o prefixo de hash fornecido. Se um desses hashes de comprimento total corresponder ao hash de comprimento total do URL em questão, o URL é considerado não seguro. Se nenhum dos hashes de comprimento total corresponder ao hash de comprimento total do URL em questão, esse URL é considerado seguro.

Em nenhum momento, a Google fica a conhecer os URLs que está a examinar. A Google aprende os prefixos hash dos URLs, mas os prefixos hash não fornecem muitas informações sobre os URLs reais.

Para verificar se um URL está numa lista de risco na Web, envie um pedido HTTP GET para o método hashes.search:

  • O pedido GET HTTP inclui o prefixo hash do URL a verificar.
  • A resposta HTTP GET devolve os hashes de comprimento total correspondentes juntamente com os prazos de validade positivos e negativos.

Exemplo: hashes.search

Pedido HTTP GET

No exemplo seguinte, os nomes de duas listas de risco na Web e um prefixo de hash são enviados para comparação e validação. Para mais detalhes, consulte os hashes.search parâmetros de consulta e as explicações que se seguem ao exemplo de código.

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

Listas do Web Risk

O campo threatTypes identifica as listas de risco na Web. No exemplo, são identificadas duas listas: MALWARE e SOCIAL_ENGINEERING.

Prefixos hash de ameaças

O campo hashPrefix contém o prefixo hash do URL que quer verificar. Este campo tem de conter o prefixo de hash exato presente na base de dados local. Por exemplo, se o prefixo da hash local tiver 4 bytes, o campo hashPrefix tem de ter 4 bytes. Se o prefixo hash local tiver sido aumentado para 7 bytes, o campo hashPrefix tem de ter 7 bytes.

Resposta HTTP GET

No exemplo seguinte, a resposta devolve as ameaças correspondentes, contendo as listas do Web Risk com as quais estabeleceram correspondência, juntamente com as horas de expiração.

Corpo da resposta

O corpo da resposta inclui as informações de correspondência (os nomes das listas, os hashes de comprimento total e as durações da cache). Para mais detalhes, consulte o hashes.search corpo da resposta e as explicações que se seguem ao exemplo de código.

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

Correspondências

O campo threats devolve hashes completos correspondentes para o prefixo de hash. Os URLs correspondentes a estes hashes são considerados não seguros. Se não for encontrada nenhuma correspondência para um prefixo de hash, não é devolvido nada. O URL correspondente a esse prefixo de hash é considerado seguro.

Hora de validade

Os campos expireTime e negativeExpireTime indicam até quando os hashes devem ser considerados, respetivamente, inseguros ou seguros. Para mais detalhes, consulte a secção Colocação em cache.