A homograph attack uses characters that look identical to others. Not similar — identical, in most typefaces. The defences against it exist, and they exist in fewer places than people assume.
How non-ASCII names work at all
DNS carries a restricted character set. Internationalised domain names are encoded into ASCII as punycode, always prefixed xn--. The encoding is the wire format; applications decode it for display.
Displayed: münchen.example On the wire: xn--mnchen-3ya.example
The attack
Unicode contains many characters that render identically to Latin letters. Cyrillic а, е, о, р, с and х are the most-used, and in most fonts they are indistinguishable from the Latin letters they resemble.
| Looks like | Actually | Codepoint |
|---|---|---|
| a | Cyrillic small letter a | U+0430 |
| e | Cyrillic small letter ie | U+0435 |
| o | Cyrillic small letter o | U+043E |
| p | Cyrillic small letter er | U+0440 |
| c | Cyrillic small letter es | U+0441 |
Substitute one and you have a domain that is visually identical to the target and is, to DNS, an entirely unrelated name that anyone may register.
Where the defences are — and are not
Browsers largely handle this. The mitigation is a script-mixing rule: if a label mixes scripts in a way flagged as confusable, the browser displays the punycode instead of the decoded form. xn--pypal-4ve.com in the address bar is obviously wrong, which is the point.
The mitigation only exists where something implements it
The browser address bar is one place a domain name appears. It is not the most common one in an attack.
| Where the name appears | Homograph protection |
|---|---|
| Browser address bar | Good. Script-mixing rules, punycode fallback. |
| Mail client sender display | Inconsistent. Many render the decoded form with no warning. |
| Link text in a message body | None. The visible text is whatever the sender wrote. |
| Documents, chat, tickets, slides | None. |
| Terminals and logs | Varies by font and encoding. |
| Printed material | None, by definition. |
So the protection is strong precisely where a careful user was already going to look, and absent in the places where the decision is actually made — reading a sender name in a mail client, or clicking a link in a message.
Detecting one
# Does this name contain non-ASCII? If it encodes to xn--, yes.
python3 -c "print('pаypal.com'.encode('idna'))"
# Inspect the actual codepoints
python3 -c "print([hex(ord(c)) for c in 'pаypal.com'])"The first is the quick test: any name that encodes to something beginning xn--contains non-ASCII characters, and for a Latin-script brand that is immediately suspicious. The second tells you exactly which character is not what it appears to be.
Keeping it in proportion
Homograph attacks are the most visually striking technique in this module and they are not the most common. Combosquatting and plain display-name spoofing account for far more real incidents, because they need no special characters and no encoding tricks and are just as effective against a reader who is not looking carefully.
Include homographs in monitoring — the permutation generation is cheap and mechanical — and do not let the novelty pull attention away from the plainer techniques that are doing more damage.