URL di hashing

Panoramica

Gli elenchi di Web Risk sono costituiti da hash SHA256 di lunghezza variabile. Per maggiori dettagli, consulta Contenuti dell'elenco. Per verificare un URL in base a un elenco di Web Risk, in locale o sul server, i client devono prima calcolare il prefisso hash dell'URL.

Per calcolare il prefisso dell'hash di un URL:

  1. Esegui la canonicalizzazione dell'URL come descritto in Canonicalizzazione.
  2. Crea le espressioni di suffisso/prefisso per l'URL come descritto in Espressioni di suffisso/prefisso.
  3. Calcola l'hash completo per ogni espressione di suffisso/prefisso come descritto in Calcoli di hash.
  4. Calcola il prefisso dell'hash per ogni hash completo, come descritto in Calcoli del prefisso dell'hash.

Tieni presente che questi passaggi rispecchiano la procedura utilizzata dal server Web Risk per gestire gli elenchi di Web Risk.

Canonicalizzazione

Per iniziare, assumiamo che il client abbia analizzato l'URL e lo abbia reso valido secondo RFC 2396. Se l'URL utilizza un nome di dominio internazionalizzato (IDN), il client deve convertire l'URL nella rappresentazione ASCII Punycode. L'URL deve includere un componente del percorso, ovvero deve avere una barra iniziale (http://google.com/).

Innanzitutto, rimuovi i caratteri tab (0x09), CR (0x0d) e LF (0x0a) dall'URL. Non rimuovere le sequenze di escape per questi caratteri, ad esempio %0a.

In secondo luogo, se l'URL termina con un frammento, rimuovilo. Ad esempio, abbrevia http://google.com/#frag in http://google.com/.

In terzo luogo, rimuovi ripetutamente gli escape percent dall'URL finché non sono più presenti.

Per eseguire la canonizzazione del nome host

Estrai il nome host dall'URL e poi:

  1. Rimuovi tutti i punti iniziali e finali.
  2. Sostituisci i punti consecutivi con un solo punto.
  3. Se il nome host può essere analizzato come indirizzo IP, normalizzalo in 4 valori decimali separati da punti. Il client deve gestire qualsiasi codifica dell'indirizzo IP legale, inclusi ottali, esadecimali e meno di quattro componenti.
  4. Scrivi tutta la stringa in minuscolo.

Per eseguire la canonicalizzazione del percorso

  1. Risolvi le sequenze /../ e /./ nel percorso sostituendo /./ con / e rimuovendo /../ insieme al componente del percorso precedente.
  2. Sostituisci le serie di barre consecutive con un singolo carattere barra.

Non applicare queste canonizzazioni dei percorsi ai parametri di ricerca.

Nell'URL, inserisci un codice di escape per tutti i caratteri <= ASCII 32, >= 127, # o %. Gli escape devono utilizzare caratteri esadecimali maiuscoli.

Di seguito sono riportati i test che consentono di convalidare un'implementazione della canonizzazione.

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

Espressioni con suffisso/prefisso

Dopo aver canonizzato l'URL, il passaggio successivo consiste nel creare le espressioni di suffisso/prefisso. Ogni espressione di suffisso/prefisso è composta da un suffisso dell'host (o dall'host completo) e da un prefisso del percorso (o dal percorso completo), come mostrato in questi esempi.

Espressione suffisso/prefisso Espressione regolare equivalente
a.b/mypath/ http\:\/\/.*\.a\.b\/mypath\/.*
c.d/full/path.html?myparam=a http\:\/\/.*.c\.d\/full\/path\.html?myparam=a

Il client formerà fino a 30 possibili combinazioni di suffisso host e prefisso percorso. Queste combinazioni utilizzano solo i componenti host e path dell'URL. Lo schema, il nome utente, la password e la porta vengono ignorati. Se l'URL include parametri di ricerca, almeno una combinazione includerà il percorso completo e parametri di ricerca.

Per l'host, il client proverà al massimo cinque stringhe diverse. Questi sono:

  • Il nome host esatto nell'URL.
  • Fino a quattro nomi host formati iniziando con gli ultimi cinque componenti erimuovendo successivamente il componente iniziale. Il dominio di primo livello può essere saltato. Questi nomi host aggiuntivi non devono essere selezionati se l'host è un indirizzo IP.

Per il percorso, il client proverà al massimo sei stringhe diverse. Questi sono:

  • Il percorso esatto dell'URL, inclusi parametri di ricerca.
  • Il percorso esatto dell'URL, senza parametri di ricerca.
  • I quattro percorsi formati iniziando dalla radice (/) e aggiungendo successivamente i componenti del percorso, inclusa una barra finale.

Gli esempi riportati di seguito illustrano il comportamento del controllo:

Per l'URL http://a.b.c/1/2.html?param=1, il client proverà queste possibili stringhe:

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/

Per l'URL http://a.b.c.d.e.f.g/1.html, il client proverà queste possibili stringhe:

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/

Per l'URL http://1.2.3.4/1/, il client proverà queste possibili stringhe:

1.2.3.4/1/
1.2.3.4/

Calcoli di hash

Dopo aver creato l'insieme di espressioni di suffisso/prefisso, il passaggio successivo consiste nel calcolare l'hash SHA256 completo per ogni espressione. Di seguito è riportato un test di unità in pseudo-C che puoi utilizzare per convalidare i calcoli di hash.

Esempi tratti da 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]);

Calcoli del prefisso hash

Infine, il client deve calcolare il prefisso dell'hash per ogni hash SHA256 di lunghezza intera. Per il rischio web, un prefisso hash è costituito dai 4-32 byte più significativi di un hash SHA256.

Esempi tratti da FIPS-180-2:

  • Esempio B1 da FIPS-180-2
    • L'input è "abc".
    • Il digest SHA256 è ba7816bf 8f01cfea 414140de 5dae2223 b00361a3 96177a9c b410ff61 f20015ad.
    • Il prefisso dell'hash a 32 bit è ba7816bf.
  • Esempio B2 da FIPS-180-2
    • L'input è abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq.
    • Il digest SHA256 è 248d6a61 d20638b8 e5c02693 0c3e6039 a33ce459 64ff2167 f6ecedd4 19db06c1.
    • Il prefisso dell'hash di 48 bit è 248d6a61 d206.