Punycode によるホモグラフ攻撃例とその回避
たとえば,以下の Go 言語コードで2つの “apple" を考える(元ネタはここ)。
package main
import "fmt"
func main() {
for _, value := range "apple" {
fmt.Printf("%#U\n", value)
}
fmt.Println()
for _, value := range "аррӏе" {
fmt.Printf("%#U\n", value)
}
}
見た目では分かりにくいかもしれないが,最初の “apple" は US ASCII で2番目の “аррӏе" はキリル文字なんだそうだ1。 このコードの実行結果は以下の通り。
U+0061 'a'
U+0070 'p'
U+0070 'p'
U+006C 'l'
U+0065 'e'
U+0430 'а'
U+0440 'р'
U+0440 'р'
U+04CF 'ӏ'
U+0435 'е'
現在,国際化ドメイン名(Internationalized Domain Name; IDN)については xn--
から始まる punycode を使った表記が認められている。
更に punycode を使った「ホモグラフ攻撃(homograph attack)」については以前から議論があり,少なくとも複数の言語の文字が混在する場合はブラウザ側で Unicode 文字による表記がキャンセルされる。
たとえば xn-pple-43d.com
は Unicode 表記では аpple.com
(先頭の а がキリル文字)だが, Chrome や Firefox といった主要ブラウザでは punycode のまま xn-pple-43d.com
と表記される(試さないように)。
しかし複数言語が混在しない場合,つまり最初に挙げたキリル文字だけの “аррӏе" のような場合にはこの制約は効かない。
その言語による真っ当な名前なのかホモグラフ攻撃なのか見分けがつかないからである。
たとえば xn--80ak6aa92e.com
は аррӏе.com
だが “аррӏе" の部分は全てキリル文字なので主要ブラウザでも аррӏе.com
と表示される。
PoC として https://www.xn--80ak6aa92e.com/ が用意されているので,皆さんが使っているブラウザで(証明書の詳細情報も含めて)ドメイン名がどう表示されるか確認して欲しい。
さて,この手の攻撃の回避法だが, Chrome についてはバージョン 58 以降であれば xn--80ak6aa92e.com
も punycode 表記になる。
どういうロジックなのかは不明2。
Firefox については,設定の network.IDN_show_punycode
項目3 を true にすれば強制的に punycode 表記になる。
個人的には国際化ドメイン名は要らんのじゃないかと思うのだが,どうなんだろうねぇ。 果てしなく紛らわしい。
ブックマーク
-
Chrome, Firefox, and Opera users beware: This isn’t the apple.com you want | Ars Technica
-
Chrome And Firefox Adding Protection Against This Nasty Phishing Trick | McAfee Blogs
-
683314 - Security: Whole-script confusable domain label spoofing (Cyrillic) - chromium - Monorail
-
1332714 - IDN Phishing using whole-script confusables on Windows and Linux