DNS Tunneling
In deze post wil ik jullie graag vertellen over “DNS Tunneling” ofwel verkeer verpakken in DNS pakketjes om op die manier bepaalde security boundaries te omzeilen. DNS Tunneling is een zeer gevaarlijke techniek die toegepast wordt om malware te verpakken in DNS pakketjes zodat de security controls van de organisatie niet gaan rinkelen. Ook kan DNS tunneling toegepast worden voor het opzetten van een “covert channel” waarlangst gestolen informatie ontsloten kan worden. DNS tunneling wordt vaak toegepast en daarom wil ik deze techniek toelichten en een klein voorbeeld geven. Put on your hackers hat!
DNS kennen we allemaal toch? Domain Name System. DNS maakt het mogelijk om domeinnamen om te zetten in IP adressen. Zie het als een adresboek. Elke website is beschikbaar op een bepaald IP adres. Maar het is onmogelijk om alle IP adressen te onthouden. Namen en dus domeinnamen zijn een stuk gemakkelijker te onthouden. DNS maakt de omzetting en routeert het verkeer naar het juiste IP adres. Met DNS Tunneling kunnen we dus DNS als attack vector gebruiken. Op het moment dat we een domeinnaam opvragen welke we niet eerder bezocht hebben en waarvan het IP adres nog niet bij de computer bekend is zal de computer de volgende volgorde aanhouden om het IP adres van de domeinnaam te achterhalen:
1. Controleer local Hosts file
2. Gebruik DNS om de naam op te zoeken
3. Gebruik NetBIOS of LLMNR
Om DNS te gebruiken moet de computer weten wat zijn DNS servers zijn. Vaak worden deze settings meegegeven door de DHCP server (indien DHCP gebruikt wordt). Deze DNS server kan als deze over de juiste informatie beschikt de naam resolven en de output retourneren of de DNS server kan deze doorsturen naar een andere (recursive) DNS server (vaak van je ISP). Als deze ook niet over de juiste informatie beschikt zal deze de informatie opvragen bij de authoritive DNS server. Dit is de server die de DNS setting voor dat specifieke domein host.
Bovenstaande proces is essentieel. Het blokkeren van DNS zou dus resulteren in een niet functionerend internet alsmede vele niet functionerende diensten op het eigen netwerk die ook afhankelijk zijn van DNS. Daarom kan DNS verkeer vaak zonder restricties door het netwerk en naar buiten gerouteerd worden. De firewall vindt het allemaal prima en dat is het gevaar. Als verkeer over DNS getunneld kan worden dan zijn er weinig security mechanismes die dit verkeer tegen houden.
DNS tunneling kan gebruikt worden om geblokkeerde websites te benaderen, captive portals te omzeilen, om malware te downloaden en om gestolen data te uploaden. Hoe? Nou, als volgt:
Hoe werkt DNS Tunneling
Om te begrijpen hoe DNS tunneling werkt is het interessant om te weten hoe een DNS pakketje is opgebouwd. DNS is een level 7 OSI protocol. Dit betekent dat deze verpakt zit in een Ethernet, IP en UDP frame.
Schematisch ziet het pakketje er als volgt uit:
Binnen het DNS pakketje is dus ruimte voor een DNS query (question) en een DNS response (answer). Het DNS query gedeelte bevat de “uitvraag” en het DNS response gedeelte bevat het antwoord van de nameserver. Wanneer ik een nslookup uitvoer naar “jarnobaselier.nl” dan voer ik een A query (DNS to IP) uit. DNS kent nog andere type queries maar we beperken ons voor deze tot de A query. Normaliter zal het DNS query gedeelte de volgende query vragen:
jarnobaselier.nl |
Maar deze payload kan veranderd worden naar iets anders. Het gehele DNS pakketje kan maximaal 512 bytes groot zijn (UDP en als het groter wordt kan TCP worden gebruikt). Het query gedeelte is hier slechts een fractie van. Dit gedeelte is meestal niet groter dan 24 bytes. Het response gedeelte is hier vaak een veelvoud van omdat de retourinformatie veel meer kan zijn. Dit loopt vaak op tot 150 bytes of meer. Er kan dus slechts een beperkte hoeveelheid data meegestuurd worden in een DNS pakketje. Spoiler: dit betekend dus dat het toepassen van DNS tunneling ontzettend traag is. Ik bedoel echt heel traag! Daarnaast is DNS een recursive protocol. Het verkeer wordt eerst naar diverse servers gestuurd voor het zijn eindpunt bereikt. Ook dat draagt niet bij in de snelheid.
Het principe van DNS tunneling is gebruikelijk als volgt:
- De cliënt stuurt 1 of meerdere DNS pakketjes met encoded data naar een domein welke hij beheerd.
- Het pakketje gaat van DNS server naar DNS server tot deze bij jou domein / server arriveert.
- Op de server wordt het DNS pakketje ontmanteld en de encoded data wordt decoded zodat het bruikbaar wordt.
Het principe kan ook de andere kant op werken wanneer een rogue DNS server gebruikt wordt.
- De cliënt wilt malafide data ontvangen en stuurt een DNS request naar een domein welke door hem beheerd wordt.
- Het verzoek wordt door de rogue DNS server ontvangen en verwerkt.
- De DNS server maakt een reply verzoek en stuurt DNS reply pakketten mat malafide encoded data.
- Deze pakketten worden door de cliënt ontvangen, ontmanteld en decoded zodat de data weer bruikbaar is.
Er zijn meerdere soorten software die deze functionaliteit faciliteren. De bekendste is wellicht Iodine. Iodine (ofwel “jodium”) is een toepasselijke naam. Het atomische nummer van iodine is 53, net zoals de DNS poort. Daarnaast begint de naam iodine met IOD ofwel IP over DNS. Maar naast Iodine zijn er diverse andere toepassingen die je hierbij kunnen ondersteunen. Wat je moet doen om DNS tunneling te kunnen toepassen is het volgende:
- Een server welke beschikbaar is op een publiek IP adres via een geregistreerde domeinnaam. Dit mag een TLD naar wens zijn want de domeinnaam maakt in deze helemaal niet uit. Als het A record van deze domeinnaam maar verwijst naar het publieke IP adres van de server. Let op, hou de domeinnaam zo kost mogelijk. Hoe korter de domeinnaam des te meer data je kunt verpakken in de pakketjes. Als de server achter een firewall staat moet UDP poort 53 geforeward (NAT) zijn naar de server toe.
- Installeer Iodine op de server. Dit mag overigens ieder type apparaat zijn. Iodine vereist niet veel resources. Een Raspberry Pi is voldoende. Iodine kan zowel op Linux als op Windows draaien.
sudo iodined -c -f %public-ip% -P %wachtwoord% %domeinnaam%
- Controleer of de Iodine setup van de server succesvol functioneert. Je kunt hiervoor de online Iodine check tool gebruiken op: https://code.kryo.se/iodine/check-it/
- Als de Iodine server succesvol functioneert dan is het raadzaam om het publieke IP adres van je client te noteren (https://www.watismijnip.nl/).
- Installeer en start Iodine op de cliënt.
iodine -I 50 -f -P %wachtwoord-van-server% %domeinnaam%.
Er wordt na het starten van Iodine een nieuwe NIC aangemaakt op de computer. Deze NIC wordt geconfigureerd met de juiste settings in hetzelfde netwerk als de server. Je kunt nu dus de NIC en het IP adres van de server pingen (indien ping ook doorgelaten wordt door de firewall). De tunnel zorgt ervoor dat je publieke IP adres nu gelijk is aan die van de server.
- Tenslotte moet er nog een route ingesteld worden om het verkeer over de nieuwe NIC (ifconfig) te routeren. Op Linux zou je het volgende commando kunnen uitvoeren:
ip route add %public-ip-server-subnet% dev eth1
Als alles geconfigureerd is zal al het verkeer naar de domeinnaam door Iodine verpakt worden in DNS pakketten, gerouteerd worden naar de Iodine server alwaar de DNS pakketten weer opgepakt en ontleed zullen worden zodat de gewenste data beschikbaar komt.
DNS is echter plain-text en dus gemakkelijk de identificeren. Je kunt het geheel nog een stuk veiliger maken door een SSH tunnel op te zetten over de reeds beschikbare DNS tunnel.
Op de cliënt maak je een SSH tunnel aan:
ssh -D 8080-N %ip-van-iodine-server% |
Vervolgens maak je in je browser een aanpassing waarmee je een SOCKS proxy instelt naar je eigen localhost op poort 8080.
Beveiligen tegen DNS Tunneling
Het is erg lastig om je netwerk te beveiligen tegen DNS tunneling, zeker als dit verkeer over een SSH tunnel verstuurd wordt. Er zijn een aantal zaken die je kunt overwegen. Een van de betere methodes is het configureren van een degelijk IDS/IPS systeem (Intrusion Detection & Prevention System). Laat deze systemen zoeken naar Iodine specifiek verkeer. Voor SNORT ziet dit er als volgt uit:
alert udp $EXTERNAL_NET 53 -> $HOME_NET any (msg:”APP-DETECT iodine dns tunnelling handshake server ACK”; flow:to_client; byte_test:1,&,0x80,2; content:”|00 01 00 01 00|”; depth:5; offset:4; content:”v”; within:1; distance:4; content:”VACK”; within:200; fast_pattern; metadata:service dns; |
Veel professionele firewalls hebben application detection tools om IP-over-DNS te herkennen en te blokkeren.
Een andere, minder effectieve en minder mooie oplossing is om een filter op de DNS pakketten te plaatsen welke alle DNS pakketten blokkeert die groter zijn dan 512 bytes (UDP) en 1024 bytes (voor TCP).
De essentie om het verkeer te kunnen blokkeren is eerst om het verkeer te herkennen. Als je geen Man-in-the-middle tools op je firewall / router kunt instellen om dit te doen dan komt het neer op handmatige herkenning. Analyseer je netwerkverkeer en gebruik slimme filters om “vreemd” of extreem veel DNS verkeer te herkennen. Omdat de payload in DNS pakketjes niet heel groot is moeten er veel DNS verkeer verstuurd worden alvorens data overgebracht kan worden. Dit genereert naast de eerder genoemde traagheid ook heel veel DNS verkeer.
Conclusie
DNS Tunneling is een zeer effectieve methode om “ongezien” barrières te ontwijken die netwerkbeheerder implementeren op het netwerk. Omdat traagheid echter een grote bottleneck van deze methode is kan DNS Tunneling alleen toegepast worden als je exact weet wat je doet en welk verkeer je er overheen wilt sturen. Bij voorkeur dus zo min mogelijk. DNS Tunneling is overigens niet onoverwinnelijk. Door het inzetten van de juiste hulpmiddelen kan DNS Tunneling herkend en geblokkeerd worden. In de praktijk zien we echter dat het blokkeren van IP-over-DNS vrijwel niet gebeurt.
Gaf deze post je voldoende informatie? Heb je er iets van opgestoken of vond je hem leuk? Laat het me even weten in een leuk berichtje, like of deel dit bericht op je eigen website of social media kanalen. Deze acties blijven me voorzien van de juiste motivatie om dit soort posts te blijven schrijven. Dankjewel!