Internationella domännamn (IDN) och typosquatting-domäner
Domännamn med icke-ASCII-tecken blir allt vanligare och vanligare. Dessa används både av legitima aktörer men också av illegitima aktörer, ofta för så kallade typosquatting-domäner.
IDN (internationella domännamn) möjliggör till exempel att den påhittade domänen fragnas.se
skulle kunna typosquattas av den snarlika domänen fragnаs.se
Ser ni någon skillnad? Nej, inte jag heller.
Detta är för att a (LATIN SMALL LETTER A) [UTF-8 0x61
] är utbytt mot а (CYRILLIC SMALL LETTER A) [UTF-8 0xd0b0
]. Det går att hitta många fler utbytbara teckenpar som visuellt är snarlika då Unicode tilldelar olika kodpunkter för visuellt mycket snarlika grafem om de är från olika skript såsom latinska, grekiska och kyrilliska alfabetet. Unicode stödjer även historiska alfabet såsom koptiska, varianter såsom diakritiska tecken (á, à, â, å
) och fullbreddstecken (exempel
) vilka används i asiatiska skriftsystem där det finns ett behov av bokstäver med samma bredd som kinesiska tecken.
Skydd mot typosquatting i en svensk kontext
För att skydda t.ex. en organisation mot typosquatting-domäner kan det vara önskvärt att sätta larm på IDN-domäner i till exempel URL-länkar i e-post. Detta är ganska enkelt i det engelska språkområdet då få icke-ASCII-tecken förekommer. Men det visar sig svårare för svenska där å, ä och ö används. Ja idag 2023 används IDN-domäner i Sverige mer än vad jag förväntade mig.
För att matcha alla IDN-domäner kan man enkelt sträng-söka efter --xn
velket är ACE (ASCII compatible encoding)-prefixet som används i IDN-domäner. Men för att undanta med å, ä, ö, Å, Ä, Ö
i matchningen blir det genast svårare.
Detta på grund av att IDN är implementerat på ett ganska obskyrt sätt där domännamn med icke-ASCII-tecken normaliseras med punycode som har tillkortakommanden i textsökning som jag kommer att gå igenom.
Punycode för IDN-domäner utförs på varje DNS-nivå separat och har tre delar:
- Del ett är ACE prefixet
xn--
- Del två är alla ASCII-tecken i domännamnet
- Del tre är en en följd av alla icke-ASCII-tecknen som kodas med en bootstring-algoritm som utgår från tecknets position och icke-ASCII-tecknet i en 36-baskodning (0 -> ’a’, …, 25 -> ’z’, 26 -> ’0’, …, 35 -> ’9’)
Detta gör att man inte kan söka efter specifika icke-ASCII-tecken eller strängfragment med icke-ASCII-tecken utan att av-punyfiera domäner. Icke-ASCII tecken kommer uppträda utanför sin position i strängen och med helt olika kodrepresentation beroende på position och andra icke-ASCII tecken.
Till exempel:
IDN-domännamn | Punycode |
---|---|
åc.se | xn--c-5ca.se |
cå.se | xn--c-2fa.se |
cåå.se | xn--c-2faa.se |
Bootstrap algoritmen finns att finna i RFC 3492 med pseudokod och en implementation i C [1].
Implementation av detektion av domäner med icke-svenska tecken
Nedan har jag implementerat en Microsoft Defender Advanced Detection regel i Kusto Query Language för e-postlänkar med tecken utanför det svenska alfabetet. Tyvärr jobbar funktionen punycode_to_string
[2] inte på strängar med hela domännamn utan man behöver iterera igenom varje nivå i domännamnet och ta ut det av-punyfierade namnet och kollar om det inte matchar ett ett reguljärt uttryck med alfabetet man vill vitlista.
Som övning för läsaren sparas uppgiften att extrahera ut det fullständiga av-punyfierade domännamnet.
EmailEvents
| join EmailUrlInfo on NetworkMessageId
| where UrlDomain contains "xn--"
| extend SplitDomain = split(UrlDomain, ".")
| project Timestamp, SenderFromAddress, RecipientEmailAddress, Subject, UrlDomain, SplitDomain, Url, ReportId
| mv-apply with_itemindex=index element=SplitDomain to typeof(long) on (
where tostring(SplitDomain[index]) startswith "xn--"
and punycode_to_string(replace_string(tostring(SplitDomain[index]), "xn--", ""))
matches regex "[a-zA-Z0-9åäöÅÄÖ]+" == false
) | summarize by Timestamp, SenderFromAddress, RecipientEmailAddress, Subject, Url, ReportId
Referenser
- [1] ICANN – RFC 3492 Punycode: A Bootstring encoding of Unicode for Internationalized Domain Names in Applications – https://www.rfc-editor.org/rfc/rfc3492.txt
- [2] Microsoft – Kusto Query Language punycode_to_string() – https://learn.microsoft.com/en-us/azure/data-explorer/kusto/query/punycode-to-string