Lookalike Domains: Punycode, Homoglyphs, Typosquats and Combosquats

Two strings, one picture

Look at paypal.com and pаypal.com. On most screens they are indistinguishable. The second one uses U+0430, CYRILLIC SMALL LETTER A, in place of the Latin a. To DNS they are unrelated names, owned by unrelated people.

Lookalike domains are the cheapest infrastructure in phishing. They cost a few euros, they survive casual inspection, and they work in email links, SMS, ads and QR codes. This article covers the main families, how the encoding works underneath, and how to detect them before your users do.

The families

Family Example (defanged) Trick Who it fools
Typosquat examlpe[.]com, exampel[.]com Keyboard errors, transpositions, omissions People typing the address
Visual squat rnicrosoft[.]com, examp1e[.]com ASCII lookalikes: rn vs m, 1 vs l, 0 vs o People reading the address
IDN homoglyph exаmple[.]com (Cyrillic а) Unicode characters from other scripts Readers, and naive string matching
Combosquat example-login[.]com, secure-example[.]com Brand plus a plausible word Almost everyone
TLD swap example[.]co, example[.]support Same label, different TLD Readers who check the name only
Subdomain abuse example.com.verify-acct[.]net Brand as a subdomain of attacker domain Mobile users with truncated URL bars

Two are worth calling out. Combosquatting is the most common in practice: academic measurement work (Kintis et al., 2017) found combosquats far outnumber classic typosquats, and they are harder to catch with edit distance because example-account-security is a long way from example. Subdomain abuse works because mobile browsers show the left end of the hostname first, and the left end is exactly what the attacker controls.

How punycode works

DNS was designed for a limited ASCII character set: letters, digits and hyphens. Internationalized Domain Names (IDNA) let people register names in their own scripts, like münchen.de or Arabic, Chinese or Cyrillic domains. To keep DNS unchanged, each non-ASCII label is converted to ASCII with Punycode (RFC 3492) and prefixed with xn--:

münchen.de          ->  xn--mnchen-3ya.de
exаmple.com (Cyr а) ->  xn--exmple-4nf.com

The xn-- form is what lives in DNS, certificates and logs. The Unicode form is what a browser may display. Attackers live in the gap between the two.

You can decode any label and flag mixed scripts with the punycode detector, which shows both forms side by side. Python's standard library does it too:

python3 -c 'print("xn--mnchen-3ya".encode().decode("idna"))'
# münchen

Mixed-script versus whole-script

The original homoglyph attacks mixed scripts in one label: Latin letters with one Cyrillic swap. Browsers learned to catch that, displaying the raw xn-- form when scripts mix. In 2017 researcher Xudong Zheng showed the next step: a label written entirely in Cyrillic characters that resemble Latin ones, spelling something that looked like apple.com. No mixing, so the old rule passed it.

Browsers now apply more elaborate policies (Chromium documents its IDN display rules publicly), including checks against Unicode's confusables data (UTS #39) and comparisons with top domains. These help a lot. They do not help when:

  • the link is shown by an email client, chat app, or SMS app with its own rendering rules,
  • the lookalike uses ASCII tricks (rn for m) that involve no Unicode at all,
  • the user never sees a URL bar, as with QR codes and in-app browsers.

Do not rely on the browser for detection. The browser's job is to protect a user at click time. Yours is to find the domain before the email is sent, and that means working on the xn-- form in DNS, certificate and mail logs.

Detection: generate, observe, score

There are two complementary approaches, and you want both.

1. Generate permutations and check them

Start from your brand domains and generate candidates: omissions, insertions, transpositions, adjacent-key swaps, homoglyph substitutions (ASCII and Unicode), bit flips, hyphenation, common combo words and TLD swaps. Open-source tools such as dnstwist do this well. Then check which candidates are registered, resolve, have MX records, or serve content.

This catches typosquats and homoglyphs reliably. It is weak on combosquats, because the space of brand + word combinations is effectively unbounded.

2. Watch new registrations and certificates

The second approach inverts the search: take the stream of newly observed names and score each one against your brands. Sources include newly registered domain feeds, passive DNS first-seen data, and Certificate Transparency logs (we covered that pipeline in CT for phishing hunters).

normalise(name):
    decode punycode labels to Unicode
    map confusables to their skeleton (UTS #39), e.g. Cyrillic а -> a, 0 -> o, rn -> m
    lowercase, strip hyphens and digits for a second "squashed" form

score(name, brand):
    +3  skeleton contains brand exactly
    +2  edit distance(skeleton label, brand) <= 1
    +2  original label used Unicode but skeleton is pure ASCII brand
    +1  lure word present (login, secure, verify, account, support, pay, wallet)
    +1  registered in the last 30 days
    -5  on our allowlist of owned and partner domains

The skeleton step is the important one. Comparing raw strings misses every homoglyph; comparing skeletons collapses exаmple, examp1e and exarnple into the same thing.

Figure 1
What each method tends to catch
Qualitative assessment for typical tooling, scored 0 to 3. Illustrative, not measured.

Triage: is this lookalike dangerous?

Monitoring produces a lot of hits, and most are not attacks: defensive registrations by your own legal team, unrelated businesses with similar names, domain investors parking anything plausible. Rank them by readiness to attack:

  1. Registered only: note it, check again later.
  2. Resolves to a parking page: low priority, but watch for DNS changes.
  3. Has MX records: can send and receive mail as your lookalike. Raise priority, especially for BEC (see business email compromise).
  4. Has a certificate or serves content: inspect from an isolated scanner. A cloned login page is an incident.
  5. Seen in your mail or proxy logs: someone already targeted you. Hunt for other recipients.

For each candidate, look the domain up on /domain/ for registration age, DNS, and related infrastructure, and pivot on hosting and name servers. Lookalikes from the same operator often share them.

Response options

  • Block at the mail gateway, DNS resolver and web proxy. This is immediate and fully under your control. Blocking all xn-- domains in corporate DNS is too blunt for international organisations, but blocking IDN labels whose skeleton matches your brand is reasonable.
  • Takedown via the registrar's or host's abuse contact for active phishing. Include evidence: screenshots, the decoded name, timestamps.
  • Dispute (UDRP or the relevant ccTLD procedure) for persistent squatting where you want the domain transferred. Slow, and a legal process, so involve counsel.
  • Defensive registration of your most obvious typos and TLDs. Useful for the top handful; you cannot buy the whole permutation space.
  • Educate on the right signal. Teaching users to "check the URL" fails against homoglyphs. Teaching them to navigate via bookmarks and to report unexpected login prompts works better.

Add your own lookalikes to mail rules. A rule that flags inbound mail whose From domain skeleton matches yours but is not yours catches a large share of display-level impersonation with very few false positives.

What to do Monday

  • List your brand domains and the brand words that appear in URLs (product names count).
  • Run a permutation scan and record which lookalikes are already registered, and by whom.
  • Implement skeleton-based matching (decode punycode, map confusables) in whatever feed you watch.
  • Rank hits by readiness: MX records and certificates first.
  • Block confirmed lookalikes at mail, DNS and proxy, and keep an allowlist of your own and partner domains so the feed stays quiet enough to read.