Alvorlig sikkerhet: Hvordan overlagte skrivemåter kan forbedre DNS-sikkerheten

Alvorlig sikkerhet: Hvordan overlagte skrivemåter kan forbedre DNS-sikkerheten

Gjennom årene har vi skrevet og talt på Naked Security mange ganger om det vanskelige problemet med DNS kapring.

DNS, som du sikkert vet, er en forkortelse for domenenavn system, og du vil ofte høre det beskrevet som internetts "telefonkatalog" eller "gazetteer".

Hvis du ikke er kjent med ordet gazeteer, det refererer til indeksen på baksiden av et atlas der du ser opp, for eksempel, Monrovia, Liberia i en praktisk alfabetisk liste, og det står noe sånt som 184 - C4. Dette forteller deg å svinge rett til side 184, og følge rutenettet ned fra bokstaven C øverst på kartet, og på tvers av tallet 4 til venstre. Der linjene møtes, finner du Monrovia.

For de fleste brukere går de fleste DNS-oppslag ut som inneholder et servernavn, og ber om et svar for å komme tilbake som inkluderer det som kalles A-record eller AAAA-record.

(A-poster brukes for 32-biters IPv4 internettnumre, som f.eks 203.0.113.42; AAAA-poster er tilsvarende svar for 128-biters IPv6-adresser, som f.eks. 2001:db8:15a:d0c::42 – i denne artikkelen bruker vi bare A-poster og IPv4-numre, men de samme sikkerhetsproblemene gjelder for oppslagsprosessen i begge tilfeller.)

Her er et eksempel der vi ser opp det imaginære domenenavnet naksec.test via en DNS-server som er spesielt laget for å spore og lære deg om DNS-trafikk.

Vi har brukt det gamle Linux-verktøyet dig, kort for domene internett groper, for å generere en enkel DNS-forespørsel (dig standard til å slå opp A-poster) for serveren vi ønsker:

$ dig +noedns @127.42.42.254 naksec.test ;; SPØRSMÅLSDELEN:
;naksec.test. I EN ;; SVARDELEN:
NAKSEC.TEST. 5 IN A 203.0.113.42 ;; Spørretid: 1 msek
;; SERVER: 127.42.42.254#53(127.42.42.254) (UDP)
;; NÅR: Man 23. januar 14:38:42 GMT 2023
;; MSG STØRRELSE rcvd: 56

Her er hvordan DNS-serveren vår håndterte forespørselen, og viste en hex-dump av den innkommende forespørselen, og det vellykkede svaret som gikk tilbake:

---> Forespørsel fra 127.0.0.1:57708 til 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 |sek.test..... | DNS-oppslag: A-record for naksec.test ==> A=203.0.113.42 <--- Svar fra 127.42.42.254:53 til 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 |sek.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* |

Merk at av ytelsesgrunner bruker de fleste DNS-forespørsler UDP, den brukerdatagramprotokoll, som fungerer på en send-og-håp-basis: du fyrer av en UDP-pakke på serveren du vil snakke med, og venter så for å se om et svar kommer tilbake.

Dette gjør UDP mye enklere og raskere enn sin store fetter TCP, den protokoll for overføringskontroll, som, som navnet antyder, automatisk tar seg av mange detaljer som UDP ikke gjør.

Spesielt tar TCP seg av å oppdage data som går tapt og spørre om det igjen; sikre at alle biter av data kommer i riktig rekkefølge; og gir en enkelt nettverkstilkobling som, når den er satt opp, kan brukes til å sende og motta samtidig.

UDP har ikke konseptet med en "tilkobling", slik at forespørsler og svar i hovedsak reiser uavhengig:

  • En DNS-forespørsel kommer til DNS-serveren i en egen UDP-pakke.
  • DNS-serveren fører en oversikt av hvilken datamaskin som sendte den aktuelle pakken.
  • Serveren begynner å finne et svar å sende tilbake, eller bestemme at det ikke er en.
  • Serveren sender et svar til den opprinnelige avsenderen ved å bruke en andre UDP-pakke.

Fra nivået til operativsystemet eller nettverket er de to UDP-pakkene ovenfor uavhengige, frittstående overføringer – de er ikke bundet sammen som en del av den samme digitale forbindelsen.

Det er opp til serveren å huske hvilken klient de skal sende hvert svar til; og det er opp til klienten å finne ut hvilke svar som gjelder hvilke forespørsler den opprinnelig sendte ut.

Hvordan kan du være sikker?

På dette tidspunktet, spesielt når du ser på den lille størrelsen på DNS-forespørselen og svaret ovenfor, lurer du sannsynligvis på: "Hvordan kan klienten være sikker på at det samsvarer med det riktige svaret, og ikke et som har blitt forvansket under transport, eller rettet feil ved en feil, enten ved et uhell eller design?»

Dessverre er mange, om ikke de fleste, DNS-forespørsler (spesielt de fra server til server, når den første serveren du spør ikke vet svaret og må finne en som gjør det for å formulere svaret) ikke kryptert, eller ellers merket med en hvilken som helst form for kryptografisk autentiseringskode.

Faktisk inkluderer DNS-forespørsler som standard en enkelt "identifikasjonstagg", som i dokumentasjonen for DNS-dataformat ganske enkelt refereres til som ID.

Utrolig nok, til tross for å ha mottatt en rekke oppdateringer og foreslått forbedringer gjennom årene, har den offisielle internett-RFC (forespørsel om kommentarer) dokument som fungerer som DNS-spesifikasjonen fortsatt er RFC 1035 (vi er for tiden i RFC-er på midten av 9000-tallet), helt tilbake til november 1987, for litt over 35 år siden!

Den gang var både båndbredde og prosessorkraft mangelvare: typiske CPU-hastigheter var omtrent 10MHz; stasjonære datamaskiner hadde omtrent 1MByte RAM; Internett-tilgangshastigheter, for organisasjoner som i det hele tatt kunne komme på nett, var ofte 56 kbits/sek eller 64 kbits/sek, delt mellom alle; og 1200bits/sek var det rimelige valget for personlig tilkobling via dagens oppringte modemer.

Det er grunnen til at DNS-forespørsels- og svarhoder ble – og fortsatt er – klemt inn i søte 12 byte, hvorav ID-taggen tar opp de to første, siden RFC 1035 er søt ASCII kunst gjør det klart:

 1 1 1 1 1 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +--+--+--+--+--+--+--+--+--+ --+--+--+--+--+--+--+ | ID | +--+--+---+--+--+--+--+---+--+--+--+--+--+--+--+--+ | QR| Opkode |AA|TC|RD|RA| Z | RCODE | +--+--+---+--+--+--+--+---+--+--+--+--+--+--+--+--+ | QDCOUNT | +--+--+---+--+--+--+--+---+--+--+--+--+--+--+--+--+ | ANCOUNT | +--+--+---+--+--+--+--+---+--+--+--+--+--+--+--+--+ | NSCOUNT | +--+--+---+--+--+--+--+---+--+--+--+--+--+--+--+--+ | ARCOUNT | +--+--+--+--+--+--+---+--+--+--+--+--+--+--+--+--+

Du kan se ID-en i aksjon i hex-dumpene vist ovenfor, der både forespørselen og svarpakkene starter med de samme to tegnene bN, som tilsvarer 16-bits identifikatoren 62 4e i hex.

Svært løst sett er disse 16 bitene like mye som den offisielle DNS-protokollen gir i form av "autentisering" eller "feildeteksjon".

Innblanding ved gjetting

Som du kan forestille deg, gitt ende-til-ende-enkelheten til vanlig DNS-trafikk, vil alle med en s.k. mellomboks or skanner proxy som kan avskjære, undersøke og modifisere nettverkstrafikken din kan trivielt blande seg inn i DNS-trafikken din.

Dette inkluderer å sende tilbake svar som bevisst gir deg unøyaktig informasjon, for eksempel at IT-teamet ditt omdirigerer deg bort fra servere som det vet er fulle av skadelig programvare.

Det kan også inkludere at Internett-leverandøren din overholder lovgivningen i landet ditt som krever at enkelte servere rapporteres som ikke-eksisterende, selv om de er i live og fungerer bra, fordi de er på en blokkeringsliste over ulovlig innhold som materiale om overgrep mot barn.

Men ved første øyekast ser denne ultrasvake typen DNS ID-tagging også ut til å gjøre det trivielt selv for angripere som ikke har noen synlighet av nettverkstrafikken i det hele tatt å avfyre ​​falske DNS-svar mot brukerne eller serverne dine...

…med en farlig høy sjanse for å lykkes.

Tross alt, hvis angripere vet at noen på nettverket ditt regelmessig liker å besøke naksec.test, kan den serveren virke som et saftig sted å implantere falske nyheter, skumle oppdateringer eller useriøs JavaScript-kode.

Og hvis angriperne ikke er i stand til å hacke seg inn i naksec.test serveren selv, hva om de regelmessig og ofte skyter UDP-pakker på DNS-serveren din, ved å bruke en sammensatt ID-tag, som hevdet å svare på spørsmålet "Hva er A-rekorden for naksec.test"?

På den måten kan de være i stand til å kapre DNS-forespørselen, gi et falskt svar, og derfor feildirigere ditt neste besøk på nettstedet – i hovedsak kapre selve nettstedet uten å måtte angripe naksec.test server i det hele tatt.

Litt flaks kreves

De må selvfølgelig være litt heldige, selv om de kan prøve om og om igjen for å øke sine samlede sjanser, gitt at de bare trenger å lykkes én gang, mens du trenger å få et sannferdig DNS-svar hver gang.

For å lykkes, må de sende falske DNS-svar:

  • I en periode som din egen server ikke allerede visste svaret på spørsmålet. DNS-svar inkluderer et 32-bits nummer kalt TTL, en forkortelse for tid til å leve, som sier hvor lenge den andre enden kan fortsette å gjenbruke svaret. Hvis du eller noen andre på nettverket ditt ba om naksec.test nylig kan det hende at DNS-serveren din har svaret i hurtigbufferen. Ingen ytterligere oppslag ville være nødvendig, og det ville ikke være noen utgående forespørsel fra angriperne om å kapre.
  • Mellom tidspunktet du sendte forespørselen og det offisielle svaret kom tilbake utenfra. Selv i gamle dager gikk DNS-oppslagstidene sjelden inn i mer enn noen få sekunder. I dag måles de best i millisekunder.
  • Med riktig tall i de første 16 bitene. Du får plass til 65536 (216) forskjellige verdier i 16 biter, så angriperne må være litt heldige. Men ved dagens nettverksbåndbredder tar det en liten brøkdel av et sekund å sende 65536 forskjellige falske svar samtidig, og dermed dekke alle mulige ID-numre.

Heldigvis tar anstendige DNS-servere et ekstra skritt for å gjøre kapring vanskelig som standard.

Det er i hvert fall det de har gjort siden ca. 2008, da avdøde Dan Kaminsky påpekte at mange DNS-servere den gang ikke bare var konfigurert til å lytte etter innkommende forespørsler på en fast UDP-port (nesten alltid port 53, offisielt tildelt DNS) ...

…men også for å motta inngående svar på en fast port også, ofte også port 53, om så bare for å skape en behagelig symmetri i trafikken.

Grunnen til å bruke en fast port i begge retninger var trolig opprinnelig for enkel programmering. Ved å alltid lytte etter svar på samme UDP-portnummer, trenger du ikke å holde styr på hvilke porter som skal åpnes for hvilke svar. Dette betyr at forespørselsbehandleren og svargeneratorkomponentene til DNS-programvaren din kan fungere uavhengig. Forespørselslytteren trenger ikke å fortelle svaravsenderen: "Dette svaret må gå tilbake på en spesiell port, ikke den vanlige."

Bruk portnummer som ekstra ID

I disse dager lytter nesten alle UDP-baserte DNS-servere på port 53, som alltid, men de holder styr på den såkalte "kildeporten" som brukes av DNS-anmoderen, som den forventer skal velges tilfeldig.

UDP-kildeporter, som er litt som et "tilleggsnummer" i en gammeldags kontortelefonsentral, er ment å brukes til å hjelpe deg og nettverket med å skille forespørsler fra hverandre.

Internett-protokollporter (TCP bruker dem også) kan kjøre fra 1 til 65535, selv om de fleste utgående tilkoblinger bare bruker kildeportene 1024-65535, fordi portnummer 1023 og under vanligvis er reservert for prosesser med systemrettigheter.

Tanken er at avsenderen av ethvert DNS-oppslag ikke bare skal sette inn en virkelig tilfeldig 16-bits ID ved starten av hver forespørsel, men også velge et virkelig tilfeldig UDP-kildeportnummer som den vil lytte etter det tilknyttede svaret.

Dette legger til et ekstra nivå av gjetting som skurkene må legge til "hijack luck"-listen ovenfor, nemlig at de må sende et falskt svar som krysser av for alle disse boksene:

  • Må være et spørsmål som nylig ble stilt, vanligvis i løpet av de siste sekundene.
  • Må være et oppslag som ikke var i den lokale serverens cache, betyr vanligvis at ingen andre har spurt om det i løpet av de siste minuttene.
  • Må ha riktig 16-bits ID-nummer i starten av datapakken.
  • Må sendes til riktig destinasjonsport på den aktuelle serverens IP-nummer.

Og en annen ting

Faktisk er det enda et triks som DNS-anmodere kan gjøre, uten å endre den underliggende DNS-protokollen, og dermed (for det meste) uten å bryte noe.

Dette trikset var overraskende nok først foreslått tilbake i 2008, i en artikkel med strålende tittel Økt DNS-forfalskningsmotstand gjennom 0x20-biters koding: SIKKERHET VIA LeET QueRies.

Ideen er merkelig enkel, og er avhengig av to detaljer i DNS-protokollen:

  • Alle DNS-svar må inkludere den originale spørringsdelen ved starten. Spørsmål har åpenbart en tom svarseksjon, men svar kreves for å gjenspeile det opprinnelige spørsmålet, noe som bidrar til å sikre at forespørsler og svar ikke ved et uhell blandes sammen.
  • Alle DNS-spørsmål skiller mellom store og små bokstaver. Enten du ber om naksec.testeller NAKSEC.TESTeller nAksEc.tESt, bør du få det samme svaret.

Nå er det ingenting i protokollen som sier at du MÅ bruke samme stavemåte i den delen av svaret der du gjentar den opprinnelige spørringen, fordi DNS ikke bryr seg om sak.

Men selv om RFC 1035 krever at du gjør sammenligninger som ikke skiller mellom store og små bokstaver, foreslår det sterkt at du faktisk ikke endre saken av eventuelle tekstnavn som du mottar i forespørsler eller henter fra dine egne databaser for bruk i svar.

Med andre ord, hvis du mottar en forespørsel om nAKsEC.tEST, og databasen din har den lagret som NAKSEC.TEST, da anses disse to navnene likevel som identiske og vil samsvare.

Men når du formulerer svaret ditt, foreslår RFC 1035 at du ikke endre store og små bokstaver i dataene du legger inn i svaret ditt, selv om du kanskje tror det ville se penere ut, og selv om det fortsatt ville matche i den andre enden, takket være den kasus-ufølsomme sammenligningen som kreves av DNS.

Så hvis du tilfeldig blander bokstavene i en DNS-forespørsel før du sender den, vil de fleste DNS-servere trofast gjenspeile den rare samlingen av bokstaver, selv om deres egen database lagrer navnet på serveren annerledes, som du ser her :

$ dig +noedns @127.42.42.254 nAkSEc.tEsT ;; SPØRSMÅLSDELEN:
;nAkSEc.TEsT. I EN ;; SVARDELEN:
NAKSEC.TEST. 5 IN A 203.0.113.42 ;; Spørretid: 1 msek
;; SERVER: 127.42.42.254#53(127.42.42.254) (UDP)
;; NÅR: Man 23. januar 14:40:34 GMT 2023
;; MSG STØRRELSE rcvd: 56

Vår DNS-server lagrer navnet naksec.test alle med store bokstaver, og derfor inkluderer svardelen av svaret navnet i skjemaet NAKSEC.TEST, sammen med IPv4-nummeret (A-posten) til 203.0.113.42.

Men i delen "her er spørringsdataene returnert til deg for krysssjekking" av svaret som DNS-serveren vår sender tilbake, beholdes den opprinnelige bokstavstørrelsen som ble brukt i DNS-oppslaget:

---> Forespørsel fra 127.0.0.1:55772 til 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..... | DNS-oppslag: A-post for nAkSEc.tEsT ==> A=203.0.113.42 <--- Svar fra 127.42.42.254:53 til 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* |
Alvorlig sikkerhet: Hvordan overlagte skrivemåter kan forbedre DNS-sikkerheten PlatoBlockchain Data Intelligence. Vertikalt søk. Ai.
Ovenfor. DNS-forespørsel i Wireshark.
Spørsmålsdel med blandet sak vist.
Alvorlig sikkerhet: Hvordan overlagte skrivemåter kan forbedre DNS-sikkerheten PlatoBlockchain Data Intelligence. Vertikalt søk. Ai.
Ovenfor. DNS-svar i Wireshark.
Legg merke til hvordan spørringsdata kopieres nøyaktig fra forespørselen, selv om serverens database oppga et ALL-UPPER-navn.

Ekstra sikkerhetsmerking, gratis

Bingo!

Det er litt mer "identifikasjonsmerking" som et DNS-oppslag kan legge til!

Sammen med 15-eller-så biters verdi av tilfeldig valgt kildeport, og 16 biter med tilfeldig valgt ID-nummerdata, får forespørselen velge store versus små bokstaver for hvert alfabetisk tegn i domenenavnet.

Og naksec.test inneholder 10 bokstaver, som hver kan skrives med store eller små bokstaver, for ytterligere 10 bits tilfeldig "tagging".

Med denne ekstra detaljen å gjette, må angriperne være heldige med timingen, UDP-portnummeret, ID-tag-verdien og bruken av store bokstaver i domenenavnet, for å injisere et falskt "kapringssvar" fra serveren som ber om ville godta.

Forresten, navnet 0x20-koding ovenfor er litt av en spøk: 0x20 i headesimal er 00100000 i binær, og den enslige biten i den byten er det som skiller store og små bokstaver i ASCII-kodingssystemet.

Brevene A til I, for eksempel, kommer ut som 0x41 til 0x49, mens a til i kommer ut som 0x61 til 0x69.

 ASCII-kodingsdiagram som ASCII-tekst
+------+------+------+------+------+------+------+ ------+
|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 B |67 g |77 w |
|08 ^H |18 ^X |28 ( |38 8 |48 H |58 X |68 t |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 |
+------+------+------+------+------+------+------+ ------+

Med andre ord, hvis du legger til 0x41+0x20 for å få 0x61, snur du A inn a; hvis du trekker fra 0x69-0x20 for å få 0x49, snur du i inn I.

Hvorfor nå?

Du lurer kanskje nå, "Hvorfor nå, hvis ideen dukket opp for 15 år siden, og ville den faktisk gjøre noe godt likevel?"

Vår plutselige interesse, som det skjer, kommer fra en nylig offentlig e-post fra Google-teknikere, og innrømmer at deres eksperimenter i 2022 med dette gamle sikkerhetstrikset har blitt brukt i det virkelige liv:

Som vi tidligere kunngjorde, er Google Public DNS i ferd med å muliggjøre saksrandomisering av DNS-søkenavn sendt til autoritative navneservere. Vi har implementert den med suksess i noen regioner i Nord-Amerika, Europa og Asia, og beskytter flertallet (90 %) av DNS-søkene i de regionene som ikke dekkes av DNS over TLS.

Spennende nok foreslår Google at hovedproblemene den har hatt med denne enkle og tilsynelatende ukontroversielle justeringen er at mens de fleste DNS-servere enten er konsekvent ufølsomme for store og små bokstaver (så dette trikset kan brukes med dem) eller konsekvent ikke (så de er blokkert), som du kanskje forventer...

… noen få maintream-servere faller av og til inn i «case-sensitive»-modus i korte perioder, noe som høres ut som den typen inkonsekvens du håper at store tjenesteleverandører vil unngå.

Hjelper det virkelig?

Svaret på spørsmålet, "Er det verdt det?" er ennå ikke klart.

Hvis du har et fint langt tjenestenavn, f.eks nakedsecurity.sophos.com (22 alfabetiske tegn), så er det nok av ekstra signalkraft, fordi 222 forskjellige store bokstaver betyr 4 millioner kombinasjoner for skurkene å prøve, multiplisert med de 65536 forskjellige ID-numrene, multiplisert med de omtrent 32000 til 64000 forskjellige kildeportene å gjette ...

…men hvis du har betalt en liten formue for et superkort domenenavn, for eksempel Twitter t.co, angriperne dine har bare en jobb som er 2x2x2=8 ganger vanskeligere enn før.

Likevel tror jeg vi kan si "Chapeau" til Google for å prøve dette.

Som cybersikkerhetsobservatører liker å si, blir angrep bare raskere, så alt som kan ta en eksisterende protokoll og legge til ekstra cracking-tid til den, nesten "gratis", er en nyttig måte å slå tilbake på.


Tidstempel:

Mer fra Naken sikkerhet