Browsers such as Chrome, Firefox, and Opera are vulnerable to a new variation of an older attack that allows phishers to register and pass fake domains as the websites of legitimate services, such as Apple, Google, eBay, and others.

Discovered by Chinese security researcher Xudong Zheng, this is a variation of a homograph attack, first identified by Israeli researchers Evgeniy Gabrilovich and Alex Gontmakher, and known since 2001.

A homograph attack

A few years back, ICANN voted to allow non-ASCII (Unicode) characters in web domains. Because some Unicode characters look the same, such as Cyrillic "а" (U+0430) and Latin "a" (U+0041), ICANN ruled that using Unicode characters would have led to confusions, and made it harder to distinguish legitimate domains from phishing sites.

That’s why, they voted to use Punycode instead of the real Unicode, in registering Unicode domains. Punycode is specifically equipped to handle this, as it's a standard for representing Unicode text using ASCII characters. For example, the Chinese character ““ is represented in Punycode as “xn—s7y.”

By default, browser makers were supposed to read the Punycode URL and transform it into Unicode characters inside the browser. Nevertheless, browser makers were quick to understand that Punycode could be used to disguise phishing sites as legitimate sites.

For example, if an attacker registered xn-pple-43d.com, this would be the equivalent of apple.com, but spelled with a Cyrillic “а” at the beginning.

That’s why, some browser makers introduced filters to render URLs as Punycode (instead of Unicode) if the URL contained characters from different languages (eg., Cyrillic + Latin), deeming such URLs as phishing attempts. This meant that only Punycode URLs in one language would be rendered as Unicode (eg., only Chinese, or only Japanese characters).

The variation

In a blog post from last Friday, Zheng was first to catch on how this could be exploited for attacks. Since many Unicode character families contain variations on the Latin alphabet characters, the researcher registered a domain in one of these languages.

When rendered inside browsers, because the Punycode characters were from one Unicode language set, they would bypass the mixed language security filter and would be rendered as Unicode characters, which would be near replicas of original Latin characters.

For example, in this demo page that Zheng set up, the domain xn-80ak6aa92e.com is rendered as аррӏе.com (in Cyrillic characters). Such page would trick almost anyone. The only way to spot the phishing site would be to look at the page’s certificate information, where the domain would still show up in its Punycode form.

Not all browsers are vulnerable

Of all the browsers Bleeping Computer tested, three rendered the page using Unicode characters, as аррӏе.com. These are Chrome, Firefox, and Opera (including the new Opera Neon variant).

Punycode attack in Chrome
Punycode attack in Chrome
Punycode attack in Firefox
Punycode attack in Firefox
Punycode attack in Opera
Punycode attack in Opera
Punycode attack in Opera Neon
Punycode attack in Opera Neon

Other browsers, such as Edge, Internet Explorer, Safari, Vivaldi, and Brave, did not render the page using Unicode characters and displayed the Punycode URL. The reasons are unknown, but we suspect there's a filter that checks if the Punycode URL is in the same character set as the user's default OS settings.

Punycode attack in IE
Punycode attack in IE
Punycode attack in Edge
Punycode attack in Edge
Punycode attack in Vivaldi
Punycode attack in Vivaldi
Punycode attack in Brave
Punycode attack in Brave

Zheng says he contacted Google and Mozilla on January 20. Google has already fixed this issue in Chrome Canary 59, and a permanent fix will land in Chrome Stable 58, set to be launched later this month.

Mozilla is currently still discussing a fix, but in the meantime, users have an option that will disable Punycode support and mitigate this attack.

Step 1: Type about:config in the Firefox address bar and hit enter.
Step 2: Type network.IDN_show_punycode and set this option to “true” (by double-clicking on it).