Sicurezza seria: in che modo i tYpO deliberati possono migliorare la sicurezza DNS

Sicurezza seria: in che modo i tYpO deliberati possono migliorare la sicurezza DNS

Nel corso degli anni, abbiamo scritto ed parlato su Naked Security più volte a proposito dello spinoso problema dei DNS dirottamento.

DNS, come probabilmente saprai, è l'abbreviazione di Domain Name System, e lo sentirai spesso descritto come l'"elenco telefonico" o il "dizionario geografico" di Internet.

Se non hai familiarità con la parola dizionario geografico, si riferisce all'indice sul retro di un atlante dove guardi, ad esempio, Monrovia, Liberia in un comodo elenco alfabetico e dice qualcosa del tipo 184 - C4. Questo ti dice di andare direttamente a pagina 184 e di seguire le linee della griglia a partire dalla lettera C nella parte superiore della mappa e di fronte al numero 4 a sinistra. Dove le linee si incontrano, troverai Monrovia.

Per la maggior parte degli utenti, la maggior parte delle ricerche DNS vengono eseguite contenenti un nome di server, chiedendo una risposta che includa quello che è noto come record A o record AAAA.

(I record A vengono utilizzati per i numeri Internet IPv32 a 4 bit, ad esempio 203.0.113.42; I record AAAA sono le risposte equivalenti per indirizzi IPv128 a 6 bit, come ad esempio 2001:db8:15a:d0c::42 – in questo articolo utilizzeremo solo i record A e i numeri IPv4, ma in entrambi i casi si applicano gli stessi problemi di sicurezza al processo di ricerca.)

Ecco un esempio in cui stiamo cercando il nome di dominio immaginario naksec.test tramite un server DNS creato appositamente per tracciare e informarti sul traffico DNS.

Abbiamo utilizzato lo strumento Linux della vecchia scuola dig, abbreviazione di groper di domini Internet, per generare una semplice richiesta DNS (dig l'impostazione predefinita è la ricerca dei record A) per il server che desideriamo:

$ dig +noedns @127.42.42.254 naksec.test ;; SEZIONE DOMANDE:
;naksec.test. IN UN ;; SEZIONE RISPOSTA:
TEST.NAKSEC. 5 IN A 203.0.113.42;; Tempo di interrogazione: 1 ms
;; SERVER: 127.42.42.254#53(127.42.42.254) (UDP)
;; QUANDO: lunedì 23 gennaio 14:38:42 GMT 2023
;; DIMENSIONE MSG ricevuto: 56

Ecco come il nostro server DNS ha gestito la richiesta, mostrando un dump esadecimale della richiesta in arrivo e la risposta riuscita in risposta:

---> Richiesta da 127.0.0.1:57708 a 127.42.42.254:53
---> 00000000 62 4e 01 20 00 01 00 00 00 00 00 00 06 6e 61 6b |bN. .........nak| 00000010 73 65 63 04 74 65 73 74 00 00 01 00 01 |sec.test..... | Ricerca DNS: record A per naksec.test ==> A=203.0.113.42 <--- Risposta da 127.42.42.254:53 a 127.0.0.1:57708
<--- 00000000 62 4e 84 b0 00 01 00 01 00 00 00 00 06 6e 61 6b |bN...........nak| 00000010 73 65 63 04 74 65 73 74 00 00 01 00 01 06 4e 41 |sec.test......NA| 00000020 4b 53 45 43 04 54 45 53 54 00 00 01 00 01 00 00 |KSEC.TEST.......| 00000030 00 05 00 04 cb 00 71 2a |......q* |

Tieni presente che, per motivi di prestazioni, la maggior parte delle richieste DNS utilizza UDP, il file protocollo datagramma utente, che funziona sulla base dell'invio e della speranza: invii un pacchetto UDP al server con cui vuoi parlare e poi attendi per vedere se arriva una risposta.

Ciò rende UDP molto più semplice e veloce del suo grande cugino TCP, il protocollo di controllo della trasmissione, che, come suggerisce il nome, si prende cura automaticamente di molti dettagli che UDP non fa.

In particolare, TCP si occupa di rilevare la perdita dei dati e di richiederli nuovamente; garantire che tutti i blocchi di dati arrivino nel giusto ordine; e fornire un'unica connessione di rete che, una volta configurata, può essere utilizzata per inviare e ricevere contemporaneamente.

UDP non ha il concetto di “connessione”, quindi le richieste e le risposte viaggiano essenzialmente in modo indipendente:

  • Una richiesta DNS arriva al server DNS in un proprio pacchetto UDP.
  • Il server DNS conserva un record di quale computer ha inviato quel particolare pacchetto.
  • Il server inizia a trovare una risposta da rispedire, o decidere che non ce n'è uno.
  • Il server invia una risposta al mittente originale, utilizzando un secondo pacchetto UDP.

Dal livello del sistema operativo o della rete, i due pacchetti UDP di cui sopra sono trasmissioni indipendenti e autonome: non sono legati insieme come parte della stessa connessione digitale.

Spetta al server ricordare a quale client inviare ciascuna risposta; e spetta al cliente capire quali risposte si riferiscono a quali richieste originariamente inviate.

Come puoi essere sicuro?

A questo punto, soprattutto considerando la dimensione ridotta della richiesta DNS e della risposta di cui sopra, probabilmente ti starai chiedendo: "Come può il client essere sicuro che corrisponda alla risposta giusta e non a una che è stata confusa durante il transito o indirizzata in modo errato?" per errore, per caso o per progetto?"

Sfortunatamente, molte, se non la maggior parte, delle richieste DNS (specialmente quelle da server a server, quando il primo server a cui chiedi non conosce la risposta e ha bisogno di trovarne uno che la conosca per formulare la sua risposta) non sono crittografate, o altrimenti etichettati con qualsiasi tipo di codice di autenticazione crittografica.

Di default, infatti, le richieste DNS includono un unico “tag identificativo”, a cui nella documentazione relativa al formato dei dati DNS viene fatto riferimento semplicemente come ID.

Sorprendentemente, nonostante abbia ricevuto numerosi aggiornamenti e suggerimenti di miglioramenti nel corso degli anni, la RFC ufficiale su Internet (richiesta di commenti) documento che funge da specifica DNS è ancora RFC 1035 (attualmente siamo in RFC a metà degli anni 9000), risalenti al novembre 1987, poco più di 35 anni fa!

Allora, sia la larghezza di banda che la potenza di elaborazione erano scarse: le velocità tipiche della CPU erano circa 10 MHz; i computer desktop avevano circa 1 MByte di RAM; le velocità di accesso a Internet, per le organizzazioni che potevano collegarsi online, erano spesso 56 kbit/sec o 64 kbit/sec, condivise tra tutti; e 1200 bit/sec era la scelta conveniente per la connettività personale tramite i modem dialup dell'epoca.

Ecco perché le intestazioni di richiesta e risposta DNS erano – e sono tuttora – compresse in soli 12 byte, di cui il tag ID occupa i primi due, come il simpatico tag RFC 1035 Arte ASCII chiarisce:

 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+ --+--+--+--+--+--+--+ | ID | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | QR| Codice operativo |AA|TC|RD|RA| Z| CODICE R | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | QDCOUNT | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ANCO | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | NCONTO | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ARCOUNT | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

Puoi vedere l'ID in azione nei dump esadecimali mostrati sopra, dove sia i pacchetti di richiesta che quelli di risposta iniziano con gli stessi due caratteri bN, che corrispondono all'identificatore a 16 bit 62 4e in esadecimale.

In parole povere, quei 16 bit sono tanti quanto fornisce il protocollo DNS ufficiale come “autenticazione” o “rilevamento degli errori”.

Interferenza per supposizioni

Come puoi immaginare, data la semplicità end-to-end del normale traffico DNS, chiunque abbia un cosiddetto middlebox or proxy di scansione chi può intercettare, esaminare e modificare il traffico di rete può interferire banalmente con il traffico DNS.

Ciò include l'invio di risposte che ti forniscono deliberatamente informazioni imprecise, ad esempio il tuo team IT che ti reindirizza lontano da server che sa essere pieni di malware.

Potrebbe anche includere il rispetto da parte del tuo ISP della legislazione del tuo paese che richiede che alcuni server vengano segnalati come inesistenti, anche se sono attivi e funzionanti, perché si trovano in una lista bloccata di contenuti illegali come materiale pedopornografico.

Ma, a prima vista, questo tipo ultradebole di tagging dell’ID DNS sembra renderlo banale anche per gli aggressori che non hanno alcuna visibilità del traffico di rete per inviare false risposte DNS ai tuoi utenti o ai tuoi server...

…con una probabilità di successo pericolosamente alta.

Dopotutto, se gli aggressori sanno che a qualcuno nella tua rete piace visitare regolarmente naksec.test, quel server potrebbe sembrare un posto interessante in cui impiantare notizie false, aggiornamenti poco affidabili o codice JavaScript non autorizzato.

E se gli aggressori non riescono ad hackerare il file naksec.test server stesso, cosa succederebbe se inviassero regolarmente e frequentemente pacchetti UDP al tuo server DNS, utilizzando un tag ID inventato, che affermasse di rispondere alla domanda: "Che cos'è il record A per?" naksec.test"?

In questo modo, potrebbero essere in grado di dirottare la richiesta DNS, fornire una risposta falsa e quindi indirizzare erroneamente la tua prossima visita al sito Web, essenzialmente dirottando il sito stesso senza mai dover attaccare il naksec.test server affatto.

È necessaria un po' di fortuna

Avrebbero bisogno di essere un po’ fortunati, ovviamente, anche se potrebbero provare più e più volte per aumentare le loro possibilità complessive, dato che hanno bisogno di riuscirci solo una volta, mentre è necessario ottenere ogni volta una risposta DNS veritiera.

Per avere successo, dovrebbero inviare la loro risposta DNS non autorizzata:

  • Durante un periodo in cui il tuo server non conosceva già la risposta alla domanda. Le risposte DNS includono un numero a 32 bit chiamato TTL, abbreviazione di tempo di vivere, che indica per quanto tempo l'altra estremità può continuare a riutilizzare la risposta. Se tu o qualcun altro sulla tua rete lo avete richiesto naksec.test di recente, il tuo server DNS potrebbe avere la risposta nella sua cache. Non sarebbero necessarie ulteriori ricerche e non ci sarebbe alcuna richiesta di dirottamento da parte degli aggressori.
  • Tra il momento in cui hai inviato la tua richiesta e la risposta ufficiale è arrivata dall'esterno. Anche ai vecchi tempi, i tempi di ricerca DNS raramente duravano più di qualche secondo. Oggi è meglio misurarli in millisecondi.
  • Con il numero giusto nei primi 16 bit. Puoi montare 65536 (216) valori diversi in 16 bit, quindi gli aggressori dovrebbero essere un po' fortunati. Ma con le larghezze di banda di rete di oggi, l’invio di 65536 diverse risposte false contemporaneamente, coprendo così tutti i possibili numeri ID, richiede una piccola frazione di secondo.

Fortunatamente, oggi i server DNS decenti fanno un passo in più per rendere difficile il dirottamento per impostazione predefinita.

Almeno, questo è quello che fanno dal 2008 circa, quando defunto Dan Kaminsky ha sottolineato che molti server DNS allora non erano solo configurati per ascoltare le richieste in entrata su una porta UDP fissa (quasi sempre la porta 53, ufficialmente assegnata al DNS)...

…ma anche per ricevere risposte in entrata anche su una porta fissa, spesso anche sulla porta 53, se non altro per creare una piacevole simmetria nel traffico.

La ragione per l'utilizzo di una porta fissa in entrambe le direzioni era probabilmente originariamente la semplicità della programmazione. Ascoltando sempre le risposte sullo stesso numero di porta UDP, non è necessario tenere traccia di quali porte devono essere aperte per quali risposte. Ciò significa che il gestore delle richieste e i componenti del generatore di risposte del vostro software DNS possono funzionare in modo indipendente. L'ascoltatore della richiesta non ha bisogno di dire al mittente della risposta: "Questa particolare risposta deve tornare su una porta speciale, non su quella solita".

Utilizza i numeri di porta come ID aggiuntivo

Oggi quasi tutti i server DNS basati su UDP ascoltano, come sempre, sulla porta 53, ma tengono traccia della cosiddetta “porta sorgente” utilizzata dal richiedente DNS, che si aspetta venga scelta in modo casuale.

Le porte di origine UDP, che sono un po' come un "numero di interno" in un centralino telefonico da ufficio della vecchia scuola, sono destinate ad essere utilizzate per aiutare te e la rete a differenziare le richieste le une dalle altre.

Le porte del protocollo Internet (anche TCP le utilizza) possono essere eseguite da 1 a 65535, sebbene la maggior parte delle connessioni in uscita utilizzi solo le porte di origine 1024-65535, poiché i numeri di porta 1023 e inferiori sono generalmente riservati ai processi con privilegi di sistema.

L'idea è che il mittente di qualsiasi ricerca DNS non solo inserisca un ID a 16 bit veramente casuale all'inizio di ogni richiesta, ma scelga anche un numero di porta di origine UDP veramente casuale su cui ascolterà la risposta associata.

Ciò aggiunge un ulteriore livello di congetture che i truffatori devono aggiungere alla loro lista di "dirottamento fortunato" di cui sopra, vale a dire che devono inviare una risposta falsa che soddisfa tutte queste caselle:

  • Deve essere una domanda posta di recente, in genere negli ultimi secondi.
  • Deve essere una ricerca che non era nella cache del server locale, in genere significa che nessun altro lo ha chiesto negli ultimi minuti.
  • Deve avere il numero ID corretto a 16 bit all'inizio del pacchetto dati.
  • Deve essere inviato al porto di destinazione corretto al numero IP del server pertinente.

E un'altra cosa

In effetti, c’è ancora un altro trucco che i richiedenti DNS possono eseguire, senza modificare il protocollo DNS sottostante e quindi (nella maggior parte dei casi) senza rompere nulla.

Questo trucco, sorprendentemente, lo era prima proposta nel 2008, in un articolo gloriosamente intitolato Maggiore resistenza alla falsificazione DNS tramite codifica 0x20 bit: sicurezza tramite query LeET.

L'idea è stranamente semplice e si basa su due dettagli nel protocollo DNS:

  • Tutte le risposte DNS devono includere all'inizio la sezione della query originale. Le query, ovviamente, hanno una sezione di risposta vuota, ma le risposte devono riflettere la domanda originale, il che aiuta a garantire che richieste e risposte non vengano confuse accidentalmente.
  • Tutte le domande DNS non fanno distinzione tra maiuscole e minuscole. Sia che tu lo chieda naksec.test, o NAKSEC.TEST, o nAksEc.tESt, dovresti ottenere la stessa risposta.

Ora, non c'è niente nel protocollo che dice che DEVI usare la stessa ortografia nella parte della risposta in cui ripeti la query originale, perché al DNS non interessa maiuscole e minuscole.

Ma sebbene RFC 1035 richieda di eseguire confronti senza distinzione tra maiuscole e minuscole, suggerisce fortemente che tu in realtà non cambia il caso di tutti i nomi di testo che ricevi nelle richieste o che recuperi dai tuoi database per utilizzarli nelle risposte.

In altre parole, se ricevi una richiesta per nAKsEC.tESTe il tuo database lo ha archiviato come NAKSEC.TEST, i due nomi sono comunque considerati identici e corrisponderanno.

Ma quando formuli la tua risposta, RFC 1035 ti suggerisce non modificare il carattere dei dati inseriti nella risposta, anche se potresti pensare che sembrerebbe più ordinato e anche se corrisponderebbe comunque all'altra estremità, grazie al confronto senza distinzione tra maiuscole e minuscole richiesto dal DNS.

Quindi, se mescoli casualmente le lettere maiuscole e minuscole in una richiesta DNS prima di inviarla, la maggior parte dei server DNS rifletterà fedelmente quello strano mashup di lettere, anche se il loro database memorizza il nome del server in modo diverso, come vedi qui :

$ dig +noedns @127.42.42.254 nAkSEc.tEsT ;; SEZIONE DOMANDE:
;nAkSEc.test. IN UN ;; SEZIONE RISPOSTA:
TEST.NAKSEC. 5 IN A 203.0.113.42;; Tempo di interrogazione: 1 ms
;; SERVER: 127.42.42.254#53(127.42.42.254) (UDP)
;; QUANDO: lunedì 23 gennaio 14:40:34 GMT 2023
;; DIMENSIONE MSG ricevuto: 56

Il nostro server DNS memorizza il nome naksec.test tutto in maiuscolo, quindi la sezione della risposta include il nome nel modulo NAKSEC.TEST, insieme al suo numero IPv4 (il record A) di 203.0.113.42.

Ma nella parte "ecco i dati della query restituiti per il controllo incrociato" della risposta che il nostro server DNS invia, viene conservato il mashup di maiuscole e minuscole originariamente utilizzato nella ricerca DNS:

---> Richiesta da 127.0.0.1:55772 a 127.42.42.254:53
---> 00000000 c0 55 01 20 00 01 00 00 00 00 00 00 06 6e 41 6b |.U. .........nAk| 00000010 53 45 63 04 74 45 73 54 00 00 01 00 01 |SEc.tEsT..... | Ricerca DNS: record A per nAkSEc.tEsT ==> A=203.0.113.42 <--- Risposta da 127.42.42.254:53 a 127.0.0.1:55772
<--- 00000000 c0 55 84 b0 00 01 00 01 00 00 00 00 06 6e 41 6b |.U...........nAk| 00000010 53 45 63 04 74 45 73 54 00 00 01 00 01 06 4e 41 |SEc.tEsT......NA| 00000020 4b 53 45 43 04 54 45 53 54 00 00 01 00 01 00 00 |KSEC.TEST.......| 00000030 00 05 00 04 cb 00 71 2a |......q* |
Sicurezza seria: come i tipi deliberati potrebbero migliorare la sicurezza DNS PlatoBlockchain Data Intelligence. Ricerca verticale. Ai.
Sopra. Richiesta DNS in Wireshark.
Sezione domande con mostrato un CASO MISTO.
Sicurezza seria: come i tipi deliberati potrebbero migliorare la sicurezza DNS PlatoBlockchain Data Intelligence. Ricerca verticale. Ai.
Sopra. Risposta DNS in Wireshark.
Nota come i dati della query vengono copiati esattamente dalla richiesta, anche se il database del server ha fornito un nome ALL-UPPER.

Etichettatura di sicurezza aggiuntiva, gratuita

Bingo!

C'è qualche altro "tagging di identificazione" che una ricerca DNS può aggiungere!

Insieme a circa 15 bit di porta di origine scelta casualmente e 16 bit di dati del numero ID scelti casualmente, il richiedente può scegliere tra maiuscole e minuscole per ciascun carattere alfabetico nel nome di dominio.

E altre ancora… naksec.test contiene 10 lettere, ciascuna delle quali può essere scritta in maiuscolo o minuscolo, per ulteriori 10 bit di "tagging" casuale.

Con questo dettaglio in più da indovinare, gli aggressori dovrebbero essere fortunati con il loro tempismo, il numero di porta UDP, il valore del tag ID e le maiuscole del nome di dominio, per iniettare una falsa "risposta di hijack" che il server richiedente accetterebbe.

A proposito, il nome Codifica 0x20 quello sopra è un po' uno scherzo: 0x20 in testa decimale è 00100000 in binario e il bit solitario in quel byte è ciò che differenzia le lettere maiuscole e minuscole nel sistema di codifica ASCII.

Le lettere A a I, ad esempio, escono da 0x41 a 0x49, mentre a a i escono come da 0x61 a 0x69.

 Grafico di codifica ASCII come testo ASCII
+------+------+------+------+------+------+------+ ------+
|00 ^@ |10 ^P |20 |30 0 |40 @ |50 P |60 ` |70 p |
|01 ^A |11 ^Q |21 ! |31 1 |41 A |51 Q |61 a |71 q |
|02 ^B |12 ^R |22 " |32 2 |42 B |52 R |62 b |72 r |
|03 ^C |13 ^S |23 # |33 3 |43 C |53 S |63 c |73 s |
|04 ^D |14 ^T |24 $ |34 4 |44 D |54 T |64 d |74 t |
|05 ^E |15 ^U |25 % |35 5 |45 E |55 U |65 e |75 u |
|06 ^F |16 ^V |26 & |36 6 |46 F |56 V |66 f |76 v |
|07 ^G |17 ^W |27 ' |37 7 |47 G |57 W |67 g |77 w |
|08 ^H |18 ^X |28 ( |38 8 |48 H |58 X |68 h |78 x |
|09 ^I |19 ^Y |29 ) |39 9 |49 I |59 Y |69 i |79 y |
|0A ^J |1A ^Z |2A * |3A : |4A J |5A Z |6A j |7A z |
|0B ^K |1B ^[ |2B + |3B ; |4B K |5B [ |6B k |7B { |
|0C ^L |1C ^ |2C , |3C  |4E N |5E ^ |6E n |7E ~ |
|0F ^O |1F ^_ |2F / |3F ? |4F O |5F _ |6F o |7F |
+------+------+------+------+------+------+------+ ------+

In altre parole, se aggiungi 0x41+0x20 per ottenere 0x61, giri A ai miglioramenti a; se sottrai 0x69-0x20 per ottenere 0x49, giri i ai miglioramenti I.

Perché ora?

A questo punto ti starai chiedendo: "Perché adesso, se l'idea è apparsa 15 anni fa, e sarebbe comunque utile?"

Il nostro improvviso interesse, guarda caso, deriva da a e-mail pubblica recente dai tecnici di Google, ammettendo che le loro sperimentazioni del 2022 con questo trucchetto di sicurezza vecchia scuola sono state implementate nella vita reale:

Come annunciato in precedenza, Google Public DNS sta abilitando la randomizzazione dei nomi delle query DNS inviate a server dei nomi autorevoli. Lo abbiamo implementato con successo in alcune regioni del Nord America, Europa e Asia proteggendo la maggior parte (90%) delle query DNS nelle regioni non coperte da DNS su TLS.

Curiosamente, Google suggerisce che il problema principale che ha avuto con questo tweak semplice e apparentemente incontrovertibile è che mentre la maggior parte dei server DNS sono costantemente case-insensitive (quindi questo trucco può essere utilizzato con loro) o costantemente no (quindi sono bloccati), come ci si potrebbe aspettare...

…alcuni server mainstream occasionalmente entrano in modalità “case-sensitive” per brevi periodi, il che suona come il tipo di incoerenza che speri che i principali fornitori di servizi evitino.

Aiuta davvero?

La risposta alla domanda, "Ne vale la pena?" non è ancora chiaro.

Se hai un bel nome di servizio lungo, tipo nakedsecurity.sophos.com (22 caratteri alfabetici), quindi c’è molto potere di segnalazione extra, perché 222 diverse maiuscole significano 4 milioni di combinazioni che i truffatori possono provare, moltiplicate per i 65536 diversi numeri ID, moltiplicate per circa 32000-64000 diverse porte di origine da indovinare...

…ma se hai pagato una piccola fortuna per un nome di dominio brevissimo, come quello di Twitter t.co, i tuoi aggressori avranno solo un lavoro 2x2x2=8 volte più difficile di prima.

Tuttavia, penso che possiamo dire "Chapeau" a Google per averlo provato.

Come amano dire gli osservatori della sicurezza informatica, gli attacchi diventano sempre più veloci, quindi tutto ciò che può prendere un protocollo esistente e aggiungervi ulteriore tempo di cracking, quasi “gratuitamente”, è un modo utile per contrattaccare.


Timestamp:

Di più da Sicurezza nuda