Hashing de URL

Descripción general

Las listas de Web Risk constan de hash SHA256 de longitud variable. Para obtener más detalles, consulta Contenido de listas. Para verificar una URL con una lista de Web Risk, ya sea de forma local o en el servidor, los clientes deben calcular primero el prefijo de hash de esa URL.

Para calcular el prefijo de hash de una URL, sigue estos pasos:

  1. Canonicaliza la URL como se describe en canonicalización.
  2. Crea las expresiones de sufijo o prefijo para la URL como se describe en Expresiones de sufijo o prefijo.
  3. Calcula el hash de longitud total para cada expresión de sufijo/prefijo como se describe en Procesamientos de hash.
  4. Calcula el prefijo hash para cada hash de longitud total, como se describe en Cálculos de prefijos hash.

Ten en cuenta que estos pasos reflejan el proceso que utiliza el servidor de Web Risk para mantener las listas de Web Risk.

canonicalización

Para comenzar, suponemos que el cliente analizó la URL y la hizo válida según el estándar RFC 2396. Si la URL usa un nombre de dominio internacionalizado (IDN), el cliente debe convertir la URL a la representación ASCII de Punycode. La URL debe incluir un componente de ruta de acceso, es decir, debe tener una barra inicial (http://google.com/).

Primero, quita los caracteres de tabulación (0x09), CR (0x0d) y LF (0x0a) de la URL. No quites las secuencias de escape para estos caracteres, como %0a.

En segundo lugar, si la URL termina en un fragmento, quítalo. Por ejemplo, acorta http://google.com/#frag a http://google.com/.

En tercer lugar, quita los escapes del porcentaje de la URL hasta que no tenga más caracteres en los escapes.

Canonicaliza el nombre de host

Extrae el nombre de host de la URL y luego haz lo siguiente:

  1. Quita todos los puntos iniciales y finales.
  2. Reemplaza los puntos consecutivos por un solo punto.
  3. Si el nombre de host se puede analizar como una dirección IP, normalízalo con 4 valores decimales separados por puntos. El cliente debe manejar cualquier codificación de dirección IP legal, incluida la octal, la hexadecimal y menos de cuatro componentes.
  4. Pon en minúscula toda la string.

Canonicaliza la ruta de acceso

  1. Para resolver las secuencias /../ y /./ en la ruta de acceso, reemplaza /./ por / y quita /../ junto con el componente de la ruta de acceso anterior.
  2. Reemplaza las ejecuciones de barras consecutivas por un solo carácter de barra.

No apliques estas canonicalizaciones de ruta a los parámetros de búsqueda.

En la URL, usa el carácter de escape de porcentaje para todos los caracteres que son <= ASCII 32, > = 127, # o %. Se deben usar caracteres hexadecimales en mayúsculas en los escapes.

A continuación, se presentan pruebas que ayudan a validar una implementación de canonicalización.

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

Suffix/prefix expressions

Después de canonicalizar la URL, el siguiente paso es crear las expresiones de sufijo o prefijo. Cada expresión de sufijo o prefijo consta de un sufijo de host (o de host completo) y un prefijo de ruta de acceso (o de una ruta de acceso completa), como se muestra en estos ejemplos.

Expresión de sufijo o prefijo Expresión regular equivalente
a.b/mypath/ http\:\/\/.*\.a\.b\/mypath\/.*
c.d/full/path.html?myparam=a http\:\/\/.*.c\.d\/full\/path\.html?myparam=a

El cliente formará hasta 30 combinaciones posibles de sufijo de host y prefijo de ruta de acceso diferentes. Estas combinaciones solo usan los componentes de host y ruta de acceso de la URL. Se descartan el esquema, el nombre de usuario, la contraseña y el puerto. Si la URL incluye parámetros de consulta, al menos una combinación incluirá la ruta completa y los parámetros de búsqueda.

Para el host, el cliente intentará como máximo con cinco strings diferentes. Son:

  • El nombre de host exacto que aparece en la URL
  • Hasta cuatro nombres de host formados a partir de los últimos cinco componentes y quitando sucesivamente el principal. El dominio de nivel superior se puede omitir. Estos nombres de host adicionales no se deben verificar si el host es una dirección IP.

Para la ruta, el cliente intentará como máximo con seis strings diferentes. Son:

  • La ruta exacta de la URL, incluidos los parámetros de búsqueda.
  • La ruta exacta de la URL, sin parámetros de búsqueda.
  • Las cuatro rutas formadas a partir de la raíz (/) y sustituyendo componentes de ruta de acceso, incluida una barra final.

En los siguientes ejemplos, se muestra el comportamiento de las verificaciones:

Para la URL http://a.b.c/1/2.html?param=1, el cliente intentará ejecutar las siguientes posibles strings:

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 la URL http://a.b.c.d.e.f.g/1.html, el cliente probará estas posibles strings:

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 la URL http://1.2.3.4/1/, el cliente probará estas posibles strings:

1.2.3.4/1/
1.2.3.4/

Cálculos de hash

Después de crear el conjunto de expresiones de sufijo o prefijo, el siguiente paso es calcular el hash SHA256 de longitud completa para cada expresión. A continuación, se muestra una prueba de unidades en la seudo-C que puedes usar para validar tus cálculos de hash.

Ejemplos 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 prefijo hash

Por último, el cliente debe calcular el prefijo hash para cada hash SHA256 de longitud total. Para el Web Risk, un prefijo hash consta de los 4 a 32 bytes más importantes de un hash SHA256.

Ejemplos de FIPS-180-2:

  • Ejemplo B1 de FIPS-180-2
    • La entrada es "abc".
    • El resumen de SHA256 es ba7816bf 8f01cfea 414140de 5dae2223 b00361a3 96177a9c b410ff61 f20015ad.
    • El prefijo hash de 32 bits es ba7816bf.
  • Ejemplo B2 de FIPS-180-2
    • La entrada es abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq.
    • El resumen de SHA256 es 248d6a61 d20638b8 e5c02693 0c3e6039 a33ce459 64ff2167 f6ecedd4 19db06c1.
    • El prefijo hash de 48 bits es 248d6a61 d206.