Security awareness · Single-page demo資安宣導 · 單頁 demo

Two links. One is fake.

兩個連結,一個是假的。

An IDN homograph attack swaps a letter in a domain for a lookalike from another script, such as Cyrillic а for Latin a. This demo lets coworkers see it for themselves, then shows how the trick is used and how to defend against it.

IDN 同形異義字攻擊,是把網域裡的字母換成其他文字裡長得一模一樣的字母,例如用西里爾字母 а 取代拉丁字母 a。這個 demo 讓同事親眼看一次,再說明攻擊者怎麼利用、又該怎麼防。

index.html + vercel.json中文 / English toggle中文 / English 切換Hosted on Vercel部署在 Vercel
Why the eye cannot tell為什麼肉眼看不出來Same glyph同一個字形
Latin vs Cyrillic
拉丁字母 vs 西里爾字母
The five pairs in the demo's character tabledemo 字元對照表裡的五組字母
a · аU+0061 · U+0430Identical一模一樣
c · сU+0063 · U+0441Identical一模一樣
e · еU+0065 · U+0435Identical一模一樣
o · оU+006F · U+043EIdentical一模一樣
p · рU+0070 · U+0440Identical一模一樣
What it is這是什麼攻擊

The link text looks right. The domain is not.

看起來一樣,網域卻不同。

Domain names can contain letters from many scripts, and browsers convert those names to an ASCII form that starts with xn-- (Punycode, RFC 3492). An attacker registers a name that swaps one Latin letter for its Cyrillic twin. People see the familiar spelling; the computer sees different code points and connects to a different domain.

網域名稱可以包含各種文字的字母,瀏覽器會把這類名稱轉成以 xn-- 開頭的 ASCII 形式(Punycode,RFC 3492)。攻擊者註冊一個把某個拉丁字母換成西里爾「雙胞胎」的網域:人眼看到的是熟悉的拼法,電腦看到的卻是不同的碼位,連到的也是另一個網域。

User vigilance alone cannot defend against this.
單純靠使用者警覺,幾乎不可能防禦。
What the demo showsDemo 在教什麼

Guess, click, then trace the chain.

先猜,再點,最後看完整條攻擊鏈。

The page works like a short live session. It opens with a question and closes with a checklist.

整個頁面就像一堂簡短的現場課:從一個問題開始,用一份清單收尾。

01

Which link is fake?

哪個連結是假的?

Two links that read the same. The first uses the Latin a (U+0061); the second swaps in the Cyrillic а (U+0430).

兩個看起來一樣的連結。第一個用的是拉丁字母 a(U+0061),第二個換成了西里爾字母 а(U+0430)。

02

Watch the address bar

點下去看網址列

Click the second link and the address bar shows an xn-- Punycode name, and the browser may warn you. The fake link is not meant to load.

點第二個連結,網址列會出現 xn-- 開頭的 Punycode 名稱,瀏覽器也可能跳出警告。假連結本來就不會正常開啟。

03

Follow the kill chain

走一遍攻擊鏈

The demo's own seven-step reconstruction of the Booking.com “reservation hijack” scams that the BBC reported in April 2026: stolen hotel logins, guest data, a message posing as the hotel, and a lookalike payment link.

demo 自己整理的七步攻擊鏈,對應 BBC 在 2026 年 4 月報導的 Booking.com「訂房劫持」詐騙:飯店後台帳密被偷、房客資料外流、有人冒充飯店傳訊息,最後附上一個仿冒的付款連結。

04

End with defenses

最後談防禦

A character table explains why the eye cannot tell the difference, and a checklist covers what people and security teams can do.

用字元對照表說明為什麼肉眼分不出來,再用一份清單整理個人與資安團隊各自能做的事。

They only look the same

長得一樣,不是同一個字

The fake link swaps one letter for a Cyrillic lookalike. The table lists five pairs.

假連結把一個字母換成西里爾字母的形近字。對照表列了五組。

  1. Latin a

    examplebank.example uses U+0061 for the first a.

  2. Cyrillic a

    The fake href writes U+0430 in that same spot. The page does not encode it first.

  3. Same on screen

    The table calls the pairs for a, c, e, o, and p identical.

  4. Two hosts

    One code point of difference means two labels under .example.

  • U+0061 beside U+0430
  • five pairs in the table
  • two labels, not one
Different code points are different names, even when they look identical.
  1. 拉丁的 a

    examplebank.example 裡第一個 a,是 U+0061。

  2. 西里爾的 a

    假連結的 href 在同一個位置直接寫 U+0430。頁面沒有先編碼。

  3. 螢幕上看一樣

    對照表把 a、c、e、o、p 這五組都標成一模一樣。

  4. 兩個主機名稱

    差一個碼位,就是 .example 底下兩個不同的名稱。

  • U+0061 旁邊是 U+0430
  • 表上一共五組
  • 是兩個名稱
碼位不同就是不同的名稱,就算看起來一樣。

Browsers write xn--

瀏覽器才寫 xn--

This page does not encode the name. The browser turns it into Punycode (RFC 3492) before sending the label.

頁面自己不會編碼。送出前,瀏覽器才把它轉成 Punycode(RFC 3492)。

  1. Raw label

    The fake label is ex, then U+0430, then mplebank. The suffix .example is a separate label.

  2. Copy ASCII

    Punycode copies the ASCII letters in order and gets exmplebank.

  3. Record the gap

    After a hyphen, the label records the missing letter and its place. Here that suffix is 0qi.

  4. Add xn--

    IDNA adds the prefix xn-- to that label only, giving xn--exmplebank-0qi.example.

  • exmplebank is the ASCII part
  • the gap code is 0qi
  • only that label gets xn--
DNS is given xn--exmplebank-0qi.example, not the Cyrillic letter. The page states that result and does not run an encoder.
  1. 原本的標籤

    假標籤是 ex、接著 U+0430、再來 mplebank。後綴 .example 是另一段。

  2. 先留 ASCII

    Punycode 依序抄下 ASCII 字母,得到 exmplebank。

  3. 記下缺的字

    連字號後面記下被拿掉的字和位置。這個名稱的後綴是 0qi。

  4. 補上 xn--

    IDNA 只在這段前面加 xn--,變成 xn--exmplebank-0qi.example 這個主機名稱。

  • exmplebank 是 ASCII 那段
  • 缺字的碼是 0qi
  • 只有這段加上 xn--
送給 DNS 的是 xn--exmplebank-0qi.example,不是那個西里爾字母。頁面只寫出這個結果,自己沒有編碼器。

It still won't open

點了也打不開

Both links on the page are real links, but neither one opens a site.

頁面上兩個都是真的連結,但點了都不會打開任何網站。

  1. Both labeled

    The question asks which one is fake. The badges already mark which one is real and which is fake.

  2. Open the fake

    Its href is the Unicode lookalike, with rel=noopener and target=_blank.

  3. Read the bar

    The hint says the address bar will show the xn-- host, and the browser may warn you.

  4. Nothing loads

    RFC 2606 reserves .example, so neither name is registered and neither one resolves.

  • both links are already badged
  • the bar will show xn--
  • .example will not resolve
Some browsers also show the xn-- form in the link text itself. The error page is the result this demo wants.
  1. 兩個都標好

    問題在問哪一個是假的。徽章已經標出哪個是真的、哪個是假的。

  2. 打開第二個

    它的 href 是 Unicode 形近名稱,並帶 rel=noopener 和 target=_blank。

  3. 讀網址列

    頁面說網址列會出現 xn-- 主機名稱,瀏覽器也可能跳出警告。

  4. 沒有網站

    兩個名稱都在 .example。RFC 2606 保留這個網域,所以不能註冊,也不會解析。

  • 徽章兩邊都標了
  • 網址列會出現 xn--
  • .example 解析不了
有些瀏覽器連連結文字都顯示 xn--。錯誤頁就是這個 demo 要你看到的結果。

Not the name you see

看著像,主機不是

The letters on screen can match a familiar name while the request uses a different host.

螢幕上的字母可以像一個熟悉的名稱,請求用的卻是另一個主機。

  1. Visible text

    The fake link's visible text is the lookalike spelling, which matches the real name to the eye.

  2. Browser policy

    The checklist tells you to watch for xn--, and it names Chrome, Edge, and Firefox.

  3. Punycode host

    A lookup that resolved would use xn--exmplebank-0qi.example. This demo never resolves.

  • the eye can match the real name
  • watch the bar for xn--
  • the DNS name is different
  • what you read
  • the browser
  • the request
If the address bar shows xn--, stop and read the name again.
  1. 畫面上的字

    假連結畫面上的字是形近拼法,肉眼和正牌名稱一樣。

  2. 瀏覽器政策

    清單要你留意 xn--,並寫了 Chrome、Edge、Firefox 的 IDN 顯示政策。

  3. 另一個主機

    如果名稱能解析,請求會用 xn--exmplebank-0qi.example。這個 demo 不會解析。

  • 肉眼可以看成正牌
  • 網址列要看 xn--
  • DNS 名稱並不一樣
  • 你讀到的
  • 瀏覽器
  • 送出去的
網址列如果出現 xn--,就停下來,把名稱再讀一次。
Spot it, defend against it辨識與防禦

What the demo teaches people to do.

這個 demo 要教的事。

Taken from the demo's closing section. The first five are habits anyone can keep; the last one is for security and IT teams.

整理自 demo 的最後一段。前五項是每個人都做得到的習慣,最後一項是給資安與 IT 團隊的。

01

Read the rightmost root domain

看網址最右邊的根網域

Check the root domain at the right end of the address, not the words in front of it. secure-example.com is not example.com.

檢查網址最右邊的根網域,不要被前面那串字騙了。secure-example.com 不是 example.com。

root domain
02

Notice xn-- in the address bar

注意網址列的 xn--

A lookalike name often shows up as xn-- Punycode. When the browser shows that form instead of the familiar spelling, its homograph protection is working.

仿冒網域常會以 xn-- 開頭的 Punycode 顯示。瀏覽器不顯示熟悉的拼法、改顯示這種形式,就代表它的同形字防護正在運作。

xn--
03

Never log in or pay from a message

不從訊息裡的連結登入或付款

Open the app, type the address, or use a bookmark. Any message that asks for a wire transfer is almost always a scam.

自己打開 App、手動輸入網址,或用書籤。任何要求銀行轉帳的訊息,幾乎都是詐騙。

bookmark
04

Turn on MFA, ideally a passkey

啟用 MFA,最好用 passkey

With multi-factor authentication, a stolen password alone does not get in. FIDO2 keys and passkeys also resist credential phishing.

有了多因素驗證,只偷到密碼也登不進去。FIDO2 金鑰與 passkey 還能抵擋帳密釣魚。

FIDO2 · passkey
05

Keep the browser updated

保持瀏覽器更新

Chrome, Edge, and Firefox ship an IDN display policy for homograph detection. Staying current keeps that check working.

Chrome、Edge、Firefox 都內建 IDN 顯示政策來偵測同形字,保持更新,這道檢查才會持續有效。

IDN display policy
06

Controls for the security team

資安團隊的控管

Defensive domain registration, DMARC, SPF, and DKIM, DNS monitoring, and regular phishing drills. A SOC can watch newly registered and Punycode domains and scan for brand lookalikes with dnstwist.

防禦性註冊網域、DMARC / SPF / DKIM、DNS 監控與定期釣魚演練。SOC 可以監控新註冊的網域與 Punycode 網域,並用 dnstwist 掃描仿冒自家品牌的變體。

DMARC · dnstwist
Run or rebuild執行與重建

One file. Nothing to build.

一個檔案,不用建置。

Preview it locally, then deploy your own copy. vercel.json adds security headers and keeps the page out of search results.

先在本機預覽,再部署自己的版本。vercel.json 會加上安全標頭,並讓頁面不被搜尋引擎收錄。

Preview locally

本機預覽

Open index.html in a browser. Or clone the repository, serve the folder, and visit http://localhost:8000.

直接用瀏覽器開啟 index.html;或 clone repo 後在資料夾裡啟動本機伺服器,再開 http://localhost:8000。

cd idn-homograph-example
python3 -m http.server 8000

Deploy with the Vercel CLI

用 Vercel CLI 部署

The first deploy of a new project goes straight to production. After that, vercel makes a preview and vercel --prod updates production.

新專案第一次部署會直接上正式環境;之後執行 vercel 只會產生預覽版,要更新正式版請用 vercel --prod。

npm install -g vercel
vercel
vercel --prod
Honest status誠實的現況

Where it stands.

目前的樣子。

Written in April 2026 as a study note for showing coworkers the attack, and changed in October 2026 to use a fictional bank. Small and finished, and the Vercel copy is still live.

2026 年 4 月寫給同事看的學習筆記,2026 年 10 月改用虛構的銀行當範例。規模小、內容已完成,Vercel 上的版本仍在線上。

Works today

目前可用

  • One index.html with a 中文 / English toggle and no build step
  • 單一 index.html,可切換中文 / English,不需要建置
  • Live experiment, seven-step kill chain, character table, and defense checklist
  • 現場實驗、七步攻擊鏈、字元對照表與防禦清單
  • vercel.json sends nosniff, frame DENY, no-referrer, and noindex headers
  • vercel.json 會送出 nosniff、禁止被嵌入框架(DENY)、no-referrer 與 noindex 標頭
  • The live demo responded on 2026-09-30
  • 2026-09-30 確認線上 demo 正常回應

Limits and not yet

限制與尚未完成

  • The example domain and branding are hard-coded in several places; adapting the demo means editing them by hand and recomputing the Punycode string
  • 範例網域與品牌寫死在好幾個地方,要改成自己的版本,得手動修改,並重新計算 Punycode 字串
  • The fake link is not meant to load; expect an error page or a browser block
  • 假連結本來就不會正常開啟,會看到錯誤頁或被瀏覽器擋下
  • The $2,000 and 580% figures in the kill chain are not in the linked BBC article and were not verified here
  • 攻擊鏈裡的 2,000 美元與 580% 這兩個數字,不在所附的 BBC 文章裡,這裡也沒有查證
Files檔案
index.html · vercel.json
Stack技術
HTML · CSS · JS
Hosting部署
Vercel
Languages語言
中文 · English
License授權
MIT
Verified查核日期
2026-10-06

More from Ted Huang. Every public project has a page like this one, in English and Traditional Chinese.

Ted Huang 的其他作品。每個公開專案都有一頁像這樣的中英雙語介紹。

All projects →全部專案 →