URLs de hash

Visão geral

As listas da Web Risk consistem em hashes SHA256 de comprimento variável. Para mais detalhes, consulte Listar conteúdo. Para verificar um URL em uma lista da Web Risk, localmente ou no servidor, primeiro os clientes precisam calcular o prefixo de hash desse URL.

Para calcular o prefixo de hash de um URL, siga estas etapas:

  1. Canonizar o URL conforme descrito em canonicidade;
  2. Crie as expressões de sufixo/prefixo para o URL, conforme descrito em Expressões de sufixo/prefixo.
  3. Calcule o hash completo para cada expressão de sufixo/prefixo, conforme descrito em Cálculos de hash.
  4. Calcule o prefixo de hash para cada hash completo, conforme descrito em Cálculos de prefixo de hash.

Observe que essas etapas refletem o processo que o servidor da Web Risk usa para manter as listas da Web Risk.

Canonicidade

Para começar, presumimos que o cliente analisou o URL e o tornou válido de acordo com a RFC 2396. Se o URL usar um nome de domínio internacionalizado (IDN, na sigla em inglês), o cliente deverá converter o URL para a representação ASCII de punycode. O URL precisa incluir um componente de caminho; Ou seja, ele precisa ter uma barra inicial (http://google.com/).

Primeiro, remova os caracteres tab (0x09), CR (0x0d) e LF (0x0a) do URL. Não remova sequências de escape para esses caracteres, como %0a.

Segundo, se o URL terminar em um fragmento, remova o fragmento. Por exemplo, reduza http://google.com/#frag para http://google.com/.

Em terceiro lugar, remova repetidamente o escape de porcentagem do URL até que ele não tenha mais escape de porcentagem.

Para canonizar o nome do host

Extraia o nome do host do URL e:

  1. Remova todos os pontos iniciais e finais.
  2. Substitua os pontos consecutivos por um único ponto.
  3. Se o nome do host puder ser analisado como um endereço IP, normalize-o para quatro valores decimais separados por ponto. O cliente deve lidar com qualquer codificação de endereço IP legal, incluindo octil, hex e menos de quatro componentes.
  4. Minúsculas a string inteira.

Para canonizar o caminho

  1. Resolva as sequências /../ e /./ no caminho substituindo /./ por / e removendo /../ junto com o componente de caminho anterior.
  2. Substitua execuções de barras consecutivas por uma única barra.

Não aplique essas canonizações de caminho aos parâmetros de consulta.

No URL, use a função de escape de porcentagem para todos os caracteres que são {= ASCII 32, = = 127, # ou %. Os escape devem usar caracteres hexadecimais em maiúsculas.

Veja abaixo os testes para validar uma implementação de canonização.

Canonicalize("http://host/%25%32%35") = "http://host/%25";
Canonicalize("http://host/%25%32%35%25%32%35") = "http://host/%25%25";
Canonicalize("http://host/%2525252525252525") = "http://host/%25";
Canonicalize("http://host/asdf%25%32%35asd") = "http://host/asdf%25asd";
Canonicalize("http://host/%%%25%32%35asd%%") = "http://host/%25%25%25asd%25%25";
Canonicalize("http://www.google.com/") = "http://www.google.com/";
Canonicalize("http://%31%36%38%2e%31%38%38%2e%39%39%2e%32%36/%2E%73%65%63%75%72%65/%77%77%77%2E%65%62%61%79%2E%63%6F%6D/") = "http://168.188.99.26/.secure/www.ebay.com/";
Canonicalize("http://195.127.0.11/uploads/%20%20%20%20/.verify/.eBaysecure=updateuserdataxplimnbqmn-xplmvalidateinfoswqpcmlx=hgplmcx/") = "http://195.127.0.11/uploads/%20%20%20%20/.verify/.eBaysecure=updateuserdataxplimnbqmn-xplmvalidateinfoswqpcmlx=hgplmcx/";
Canonicalize("http://host%23.com/%257Ea%2521b%2540c%2523d%2524e%25f%255E00%252611%252A22%252833%252944_55%252B") = "http://host%23.com/~a!b@c%23d$e%25f^00&11*22(33)44_55+";
Canonicalize("http://3279880203/blah") = "http://195.127.0.11/blah";
Canonicalize("http://www.google.com/blah/..") = "http://www.google.com/";
Canonicalize("www.google.com/") = "http://www.google.com/";
Canonicalize("www.google.com") = "http://www.google.com/";
Canonicalize("http://www.evil.com/blah#frag") = "http://www.evil.com/blah";
Canonicalize("http://www.GOOgle.com/") = "http://www.google.com/";
Canonicalize("http://www.google.com.../") = "http://www.google.com/";
Canonicalize("http://www.google.com/foo\tbar\rbaz\n2") ="http://www.google.com/foobarbaz2";
Canonicalize("http://www.google.com/q?") = "http://www.google.com/q?";
Canonicalize("http://www.google.com/q?r?") = "http://www.google.com/q?r?";
Canonicalize("http://www.google.com/q?r?s") = "http://www.google.com/q?r?s";
Canonicalize("http://evil.com/foo#bar#baz") = "http://evil.com/foo";
Canonicalize("http://evil.com/foo;") = "http://evil.com/foo;";
Canonicalize("http://evil.com/foo?bar;") = "http://evil.com/foo?bar;";
Canonicalize("http://\x01\x80.com/") = "http://%01%80.com/";
Canonicalize("http://notrailingslash.com") = "http://notrailingslash.com/";
Canonicalize("http://www.gotaport.com:1234/") = "http://www.gotaport.com/";
Canonicalize("  http://www.google.com/  ") = "http://www.google.com/";
Canonicalize("http:// leadingspace.com/") = "http://%20leadingspace.com/";
Canonicalize("http://%20leadingspace.com/") = "http://%20leadingspace.com/";
Canonicalize("%20leadingspace.com/") = "http://%20leadingspace.com/";
Canonicalize("https://www.securesite.com/") = "https://www.securesite.com/";
Canonicalize("http://host.com/ab%23cd") = "http://host.com/ab%23cd";
Canonicalize("http://host.com//twoslashes?more//slashes") = "http://host.com/twoslashes?more//slashes";

Expressões de sufixo/prefixo

Depois que o URL for canonizado, a próxima etapa será criar as expressões de sufixo/prefixo. Cada expressão de sufixo/prefixo consiste em um sufixo de host (ou host completo) e um prefixo de caminho (ou caminho completo), conforme mostrado nesses exemplos.

Expressão de sufixo/prefixo Expressão regular equivalente
a.b/mypath/ http\:\/\/.*\.a\.b\/mypath\/.*
c.d/full/path.html?myparam=a http\:\/\/.*.c\.d\/full\/path\.html?myparam=a

O cliente formará até 30 combinações possíveis de sufixo de host e prefixo de caminho. Essas combinações usam apenas os componentes de host e caminho do URL. O esquema, o nome de usuário, a senha e a porta são descartados. Se o URL incluir parâmetros de consulta, pelo menos uma combinação incluirá o caminho completo e os parâmetros de consulta.

Para o host, o cliente tentará no máximo cinco strings diferentes. Elas são:

  • O nome do host exato no URL.
  • Até quatro nomes de host formados começando pelos últimos cinco componentes e removendo o componente principal. O domínio de nível superior pode ser ignorado. Esses nomes de host adicionais não devem ser verificados se o host for um endereço IP.

Para o caminho, o cliente tentará no máximo seis strings diferentes. Elas são:

  • O caminho exato do URL, incluindo os parâmetros de consulta.
  • O caminho exato do URL, sem parâmetros de consulta.
  • Os quatro caminhos formados começando pela raiz (/) e anexando componentes de caminho, incluindo uma barra final.

Os exemplos a seguir ilustram o comportamento da verificação:

Para o URL http://a.b.c/1/2.html?param=1, o cliente tentará estas strings possíveis:

a.b.c/1/2.html?param=1
a.b.c/1/2.html
a.b.c/
a.b.c/1/
b.c/1/2.html?param=1
b.c/1/2.html
b.c/
b.c/1/

Para o URL http://a.b.c.d.e.f.g/1.html, o cliente tentará estas strings possíveis:

a.b.c.d.e.f.g/1.html
a.b.c.d.e.f.g/
(Note: skip b.c.d.e.f.g, since we'll take only the last five hostname components, and the full hostname)
c.d.e.f.g/1.html
c.d.e.f.g/
d.e.f.g/1.html
d.e.f.g/
e.f.g/1.html
e.f.g/
f.g/1.html
f.g/

Para o URL http://1.2.3.4/1/, o cliente tentará estas strings possíveis:

1.2.3.4/1/
1.2.3.4/

Cálculos de hash

Após a criação do conjunto de expressões de sufixo/prefixo, a próxima etapa é calcular o hash SHA256 completo para cada expressão. Veja abaixo um teste de unidade em pseudo-C que você pode usar para validar seus cálculos de hash.

Exemplos de FIPS-180-2:


// Example B1 from FIPS-180-2
string input1 = "abc";
string output1 = TruncatedSha256Prefix(input1, 32);
int expected1[] = { 0xba, 0x78, 0x16, 0xbf };
assert(output1.size() == 4);  // 4 bytes == 32 bits
for (int i = 0; i < output1.size(); i++) assert(output1[i] == expected1[i]);

// Example B2 from FIPS-180-2
string input2 = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
string output2 = TruncatedSha256Prefix(input2, 48);
int expected2[] = { 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06 };
assert(output2.size() == 6);
for (int i = 0; i < output2.size(); i++) assert(output2[i] == expected2[i]);

// Example B3 from FIPS-180-2
string input3(1000000, 'a');  // 'a' repeated a million times
string output3 = TruncatedSha256Prefix(input3, 96);
int expected3[] = { 0xcd, 0xc7, 0x6e, 0x5c, 0x99, 0x14, 0xfb, 0x92,
                    0x81, 0xa1, 0xc7, 0xe2 };
assert(output3.size() == 12);
for (int i = 0; i < output3.size(); i++) assert(output3[i] == expected3[i]);

Cálculos de prefixo de hash

Por fim, o cliente precisa calcular o prefixo de hash para cada hash SHA256 completo. Para a Web Risk, um prefixo de hash consiste nos 4 a 32 bytes mais significativos de um hash SHA256.

Exemplos de FIPS-180-2:

  • Exemplo B1 de FIPS-180-2
    • A entrada é "abc".
    • O resumo SHA256 é ba7816bf 8f01cfea 414140de 5dae2223 b00361a3 96177a9c b410ff61 f20015ad.
    • O prefixo de hash de 32 bits é ba7816bf.
  • Exemplo B2 do FIPS-180-2
    • A entrada é abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq.
    • O resumo SHA256 é 248d6a61 d20638b8 e5c02693 0c3e6039 a33ce459 64ff2167 f6ecedd4 19db06c1.
    • O prefixo de hash de 48 bits é 248d6a61 d206.