這應該是視覺混淆、同形異意攻擊集中爆發的一個時期。
作者:慢霧區夥伴 xisigr
一、前言
2022 年 9 月 13 日,Unicode 15.0 正式版發布。在 Unicode 15.0 中增加了 4,489 個字符,總共字符數量達到了 149,186 個。這些新增內容包括 2 個新腳本,總共腳本數量達到 161 個,以及 20 個新的表情符號字符。同時,幾個重要的 Unicode 規範也隨著 15.0 版本進行了更新,這其中就包括 Unicode 安全機制(UTS#39)這個規範,它意在減少因 Unicode 字符視覺欺騙帶來的同形異意攻擊(Homoglyph Attack)。
同形異意攻擊(Homoglyph Attack)是非常古老的一種視覺欺騙攻擊方式。在機械打字機時代,很多打字機為了簡化設計和降低製造及維護成本,鍵盤上沒有單獨的 1 和 0。打字員會使用小寫字母 L 和大寫字母 i 來代替數字 1,使用大寫字母 O 來代替數字 0。當這些相同的打字員在 70 年代和 80 年代初轉變為計算機鍵盤操作員時,他們的舊鍵盤習慣在他們的新職業中繼續存在,並成為極大混亂的源泉。這應該是視覺混淆、同形異意攻擊集中爆發的一個時期。
在此之後,打字機被文字處理器所代替,信息化時代逐步到來,字符編碼也開始由 ASCII 字符集逐漸擴充到 Unicode 字符集。我們開始使用瀏覽器或其他應用客戶端來呈現文本,那些在某些語境中不適合使用同形字書寫 URL、公式、源代碼、ID 等等,其相似的外觀繼續使得用戶可能在視覺上無法區分。
Unicode 視覺欺騙取決於視覺上可以混淆的字符串:兩個 Unicode 字符串外觀上非常相似,在通常的屏幕分辨率下,它們以小尺寸的普通字體出現,很容易讓人們誤認為是另一個。視覺混淆沒有明顯的規則:當尺寸足夠小時,許多字符都看起來像其他字符。“屏幕分辨率下的小尺寸” 是指大多數腳本使用 9-12 像素的字體。易混淆性還取決於字體的風格:對於傳統的希伯來字體,許多字符只能通過細微的差別來區分,而這些細微差別可能在小尺寸時丟失。在某些情況下,字符序列也可用於欺騙:例如,“rn”(“r” 後跟 “n”)在許多 sans-serif 字體中與 “m” 在視覺上混淆。
近些年來,因 Unicode 編碼欺騙發生了很多惡意攻擊事件,人為或編譯器或 AI 都可能因 Unicode 欺騙產生錯誤的判斷和解析。例如 2021 年有研究人員在谷歌等商業系統中使用 Unicode 的這些特殊字符對 NLP 模型進行對抗攻擊。他們通過一些不可察覺的編碼注入——比如一個不可見字符、同形符、重新排序或刪除的操作字符,可以顯著降低一些模型的性能,大多數模型都可能在功能上失靈(https://arxiv.org/abs/2106.09898)。
2022 年 Trezor 這款知名的硬件錢包出現了大量的網絡釣魚網站,釣魚鏈接 https://suite.trẹzor.com。這個釣魚鏈接和真實 Trezor 官方網站 trezor.io 極為相似。(此案例來源於《區塊鏈黑暗森林自救手冊》:https://github.com/slowmist/Blockchain-dark-forest-selfguard-handbook/blob/main/README_CN.md)
雖然基於客戶端的尤其是瀏覽器端的抵禦視覺欺騙的防禦措施一直在完善,但並沒有辦法完全封堵住這種攻擊。第一,視覺欺騙是一種很難被完全消亡的攻擊,因為在足夠小的尺寸情況下人自身的生理視覺體係也是無法分辨的;第二,Unicode 字符集非常龐大,並且在不斷的增加;第三,需要標準組織、瀏覽器開發商、域名註冊商等多方共同協作去完成。
本文主要研究當下 Unicode 中因字形渲染、混合腳本、PunyCode、雙向文本、組合字符引起的視覺欺騙問題,結合作者發現的不同類型的 Unicode 視覺欺騙漏洞,分享漏洞挖掘過程方法並給出一些防禦的思路。
二、字形渲染帶來的安全風險
當字體或渲染引擎對字符或字符序列的支持不足時,就使得本應該在視覺上可以區分的字符或字符序列出現新的問題--視覺混淆。尤其是這些字符被做為關鍵的信息出現時,比如在瀏覽器重要的安全指示器地址欄中,這種視覺欺騙的危害就會顯而易見。瀏覽器廠商對於地址欄上的 IDN 欺騙問題,一直在做積極的防禦,通常是在瀏覽器里維護一個重要域名列表,如果一個域名和列表中的域名同形異議,則將其轉化為 Punycode 編碼顯示。
渲染支持不足,直接導致每一個字符的字形含義往往超出我們的預期,這種不確定性使得視覺欺騙隨時都可能發生。那麼字形到底是什麼,它和字型、字符、字體有什麼關係,包括 Unicode 中越來越火的 Emoji 表情它是字符嗎?其中一些基本的名詞概念非專業人士經常混淆,我們先簡要了解下。
字體(英語:Typeface)指的是一組字符的設計,通常包括字母、一組數字和一組標點符號。也常包括表意字符以及製圖符號。每個字體都是字形的集合,比如宋體、黑體等。有些字體技術非常強大,比如 TrueType/OpenType,它們可以根據分辨率、系統平台、語言等來選擇顯示最佳的形狀。但是,它也可以用於安全攻擊,因為它足夠強大,可以在打印時將屏幕上的 “$ 100.00” 外觀更改為 “$ 200.00”。此外,層疊樣式表(CSS)可以更改為不同的字體,用於打印與屏幕顯示,這可以使用更多可混淆字體。這些問題並非特定於 Unicode。為了降低此類漏洞利用的風險,程序員和用戶應該只允許可信任的字體。
字型(英語:font;傳統英式英語:fount)是指印刷行業中某一整套具有同樣樣式和尺碼的字形,例如一整套用於內文的宋體 5 號字、一整套用於標題的 10 號字就叫一套字型。電腦早期用點陣字,仍然有字型概念,同樣一套風格如中易宋體,一套字型是指一整套 15×16 像素或一整套 24×24 像素的字。矢量字型出現後,同一套風格字型已不用製作不同像素字型,只需製作一套即可隨意縮放,“字型” 與 “字體” 之間的界限開始模楜。一般的英語使用者同樣分不清 “字型”(Font)與 “字體”(Typeface)的分別。
字形(英語:glyph),又稱字圖或書形,是指字的形體。中華人民共和國國家標準 GB/T 16964《信息技術·字型信息交換》中定義字形為 “一個可以辨認的抽象的圖形符號,它不依賴於任何特定的設計”。在語言學中,字(character)是語意的最基本單位,即語素;字形是指為了表達這個意義的具體表達。同一字可以有不同的字形,而不影響其表達的意思,例如拉丁字母第一個字母可以寫作 a 或ɑ,漢字中的 “強/強”、“戶/戶/戸”。
在復雜的腳本(如阿拉伯語和南亞語腳本)中,字符可能會根據周圍的字符更改形狀。
(1)字形可以隨周圍環境所改變
3 個 arabic letter heh (U+0647) 組合在一起
(2)多個字符可以產生一個字形
f = latin small letter f (U+0066)
i = latin small letter i (U+0069)
我們來看一個和視覺有關的,當多個不同字符組合後可能視覺外觀是相同的。例如字符 U + 0BB6 SHA 和 U + 0BB8 SA 通常非常不同。但這兩個組合的字符序列,視覺感官上完全相同。底層的二進制是不同的。
其實多字符組合不僅僅是視覺欺騙,有時這種多字符組合也可以導致系統內存崩潰。CVE-2018-4124 這個漏洞可導致 macOS High Sierra 10.13.3 在處理惡意製作的字符串時致堆損壞。జ్ఞా 的原始序列是 U+0C1C U+0C4D U+0C1E U+200C U+0C3E,這是一個泰盧固語字符序列:輔音 ja (జ)、virama (్)、輔音 nya (ఞ)、零-width 非連接符和元音 aa (ా)。當 macOS 在處理జ్ఞా 這個字符序列時,即可導致系統崩潰。
表情符號(英文:Emoji)是像形文字(圖形符號),通常以彩色卡通形式呈現並在文本中內聯使用。它們代表面部,天氣,車輛和建築物,食物和飲料,動物和植物,或代表情感,感覺或活動的圖標。Emoji 已經無處不在,它正在成為跨越不同文化的所有人通用的語言。但不同人對 Emoji 的使用理解以及各個操作系統碎片化的支持,也使得帶來了一些問題。比如:短期內你也不會看到步槍的表情符號,U+1F946。Unicode 組織包括蘋果和微軟都反對加入步槍符號。手槍和其他武器的 Emojis 已經使人們陷入了法律的困擾。之前一家法國法院裁定手槍表情符號可能構成死亡威脅,將一名把槍的表情發給前女友的男子判處三個月監禁。
在瀏覽器地址欄中直接渲染 U+1F512 這個編碼也是相當危險的。因為它和 HTTPS 安全小鎖外觀上非常相似。攻擊者可以對其進行安全小鎖的偽造。U+1F512 編碼曾在 Chrome/Firefox 瀏覽器中出現過這樣的安全問題。
三、混合腳本帶來的安全風險
混合腳本是有很多合法的用途的,例如Ωmega。但視覺上容易混淆的字符通常不會放在一個腳本中。在視覺上容易混淆的字符為欺騙提供了許多機會,例如下面這兩個域名,希臘小寫字母 Omicron 和拉丁文 o 外觀是非常相似的。
很久之前,域名只允許包含拉丁字母 AZ,數字和一些其他字符(ASCII 字符集)。之後大家發現,僅僅支持 ASCII 碼的域名可能是有問題的,因為世界上還有很多非拉丁文語系的國家和地區,他們也渴望在域名中使用自己的語言符號。後來經過多次提案討論,在 2003 年發布了國際化域名的規範 [rfc3490],它允許大多數的 Unicode 在域名中使用,普遍將這個規範稱為 IDNA2003。之後在 2010 年批准發布了對 IDNA2003 的修訂版 [rfc5895],稱這個修訂版為 IDNA2008。但 IDNA2003 和 IDNA2008 並沒有有效的解決國際化域名中的某些問題。隨後,Unicode 聯盟發布了 [UTS-46] 解決了某些兼容性的問題。
在 IDNA 中使用 PunyCode 算法來實現非 ASCII 域名到 ASCII 域名的轉換。PunyCode 算法可以將任何一個非 ASCII 的 Unicode 字符串唯一映射為一個僅使用英文字母、數字和連字符的字符串,編碼的域名在前面都加上了 xn-- 來表明這是一個 PunyCode 編碼。
國際化域名(IDN)是在 Unicode 中定義的任何字符集或腳本中註冊的二級或三級域名或 Web 地址。直到 2009 年底之前,頂級域名僅限於拉丁字母 az,之後隨著 Web 全球化發展,IDN TLDs 也開始逐漸推廣和普及,這加速了全球化進展的同時,也帶來了一些安全風險,這點在後面我們會談到。
在前文中我們已經了解到,Unicode 15.0 中的字符總量 149,186 個,腳本數 161 個。這些腳本中大部分都可以被用於域名註冊,並且數量還在增加中。以頂級域名(TLD)COM 為例,Verisign 制定了 IDN 註冊的策略,規定了允許和禁止的代碼點。並製定了 IETF 標準、對特定語言的限制、對腳本混淆的限制、ICANN 受限 Unicode 代碼、特殊字符這五條驗證規則,遵循這五條規則的 IDN 被認為是有效的註冊。
在這五條 IDN 註冊規則中,我們會重點關注 “腳本混淆的限制” 這條規則,因為這對發現 IDN 上的視覺欺騙問題有幫助意義。
【對腳本混淆的限制】
Verisign 不允許使用混合的 Unicode 腳本進行註冊。如果 IDN 中包含兩個或多個 Unicode 腳本代碼,將拒絕註冊。例如拉丁文腳本中的字符不能和任何西里爾字符在同一個 IDN 中使用。IDN 中的所有代碼必須來自同一個 Unicode 腳本。這樣做是為了避免混淆的代碼出現在同一個 IDN 中。
下表列出了允許使用的 Unicode 腳本。
列舉我之前發現的一個漏洞,[CVE-2018-4277] Spoof All Domains Containing 'd' in Apple Products 。我在研究中發現,在蘋果產品中編碼 latin small letter dum (U+A771) 渲染的字形和 latin small letter d (U+0064) 極為相似。從 Unicode 中 (U+A771) 的字形標準可以發現(http://www.unicode.org/charts/PDF/UA720.pdf),d 後面應該還有一個小撇,但是在蘋果產品中把這個完全忽略掉了。
接下來,我去註冊了一個真實的域名,使這個 IDN Spoof 可以正常運行。我們知道在 Verisign 制定的 IDN 註冊的規則中,不允許使用混合的 Unicode 腳本進行註冊。如果 IDN 中包含兩個或多個 Unicode 腳本代碼,將拒絕註冊。而(U+A771)也是屬於 Latin,應該是符合域名註冊商規則的。於是域名成功註冊成功了。
我又註冊了一個 SSL 證書,使這個 IDN Spoof 看的會更加真實完美。效果如下,Safari 並沒有將這個域名轉化為 punycode 顯示,所以我們成功了。
到這裡我們確定了整個欺騙流程是完全可行的,那麼攻擊者可以偽造域名中有 d 的所有域名。在 Ggoogle 統計的 Top 10k 域名中,大約有超過 25% 的網站域名中有 d 這個字符。這些網站的域名都可以被偽造。
•linkedin.com
•baidu.com
•jd.com
•adobe.com
•wordpress.com
•dropbox.com
•godaddy.com
•reddit.com
…………
【蘋果修復的補丁】
【受影響產品】
watchOS 4.3.2 https://support.apple.com/zh-cn/HT208935
iOS 11.4.1 https://support.apple.com/zh-cn/HT208938
tvOS 11.4.1 https://support.apple.com/zh-cn/HT208936
macOS High Sierra 10.13.5 https://support.apple.com/zh-cn/HT208937
四、雙向文本帶來的安全風險
某些字符(例如阿拉伯語和希伯來語腳本中使用的字符)具有固有的從右到左的書寫方向。當這些字符與從左到右顯示的其他腳本或符號集的字符混合時,生成的文本稱為雙向(縮寫為 bidi)。文檔的內存表示(邏輯順序)與雙向文本的顯示外觀(可視順序)之間的關係由 UAX#9:Unicode 雙向算法 [UAX9] 管理。
由於某些字符具有弱或中性的方向性,而不是強左向右或從右到左,因此 Unicode 雙向算法使用一組精確的規則來確定最終的視覺呈現。然而,任意文本序列的呈現,可能導致文本序列無法清晰地被閱讀,或者可能在視覺上混淆。
在一個 URL 中,經常會遇到多種方向性(弱性、中性、強性)的字符同時存在的情況。雖然 Unicode 雙向算法使用一組精確的規則來確定最終的視覺呈現,但是多種方向性的文本序列在呈現時,還是可能導致文本序列無法清晰地被閱讀,或者可能在視覺上混淆。
Chrome 之前出過這樣一個漏洞,在 Chrome 裡訪問:
在地址欄中實際渲染為:
CVE-2018-4205 是我之前發現的一個漏洞,利用了 RTL 和空白符導致了 URL 地址欄欺騙。下面就以這個漏洞為例進行講解。
(1)構造 POC-1
訪問 http://www.apple.com.xn--ggbla3j.xn--ngbc5azd/。可以看到 Chrome/Firefox/Safari 三個瀏覽器地址欄,顯示都是一樣的。Edge 顯示 punycode。
(2)構造 POC-2
在四個瀏覽器中訪問 POC-2,我們此時已經發現了問題。在 Safari 中出現了 RTL 和空白字符。
(3)構造 POC-3
(4)根因分析
針對 POC-3,在 Safari 中的地址欄欺騙已經比較完美。在 Safari 中當設置為只顯示域名不顯示完整 URL 時,意味著 pathname 部分是去掉的不會顯示的。這個字符串 http://www.apple.com.xn--ggbla3j.xn--ngbc5azd/999...html,如果按常理顯示就是這樣。但اماء.شبكة 是 RTL,使字符串產生了亂序。http://www.apple.comاماء.شبكة/9999..html,9999 pathname 部分和اماء.شبكة 調換了位置。字符串變為 999999/شبكة اماء.html 顯示。而瀏覽器設置是不顯示 path 部分,所以將以空白顯示,最終造成了 URL Spoof。這也是一個邏輯漏洞。多個 9999 把真正的域名滾動到了地址欄之外。
(5)POC-4
可以看到,這個 POC-4 在 Chrome 和 Firefox 瀏覽器中的渲染欺騙性非常強。
通過上面的幾個案例分析,可以看到大多是和 pathname 有關,如果只顯示 origin 是否可以解決這個問題?以 Safari 為代表,它就只顯示域名,但在上面的例子中我們看到了,也會存在問題,pathname 被隱藏替換成空白符導致 Spoof 發生。那麼,如果只是純顯示 origin 呢,把 pathname 在地址欄中徹底去掉?這也可能存在問題,並不能徹底解決 RTL Spoof 的問題。因為 origin 中也可以使用多個方向的字符,整體上產生亂序,造成用戶從視覺上難以理解,從而產生欺騙。
五、組合字符序列帶來的安全風險
在字體排印學中組合字符(Combining character)是用來改變其它字符所用的字符。在拉丁文字中,最常見的組合字符為附加符號(包含重音號)。例如組合字符序列(Combining character sequence):ḱṷṓn(U + 006B U + 0301 U + 0075 U + 032D U + 006F U + 0304 U + 0301 U + 006E)。字符和組合字符序列是否相同,這取決於對於程序員來說,多數情況一個 Unicode 代碼點代表一個單獨的字符。但對於最終用戶來說,它可能不是。對於最終用戶認為的字符而言,更好的詞是字形:在特定的書寫系統中最小的獨特的書寫單位。攻擊者可以利用組合字符序列,繞過很多類似 “黑名單” 策略的防禦。
如果組合字符序列的域名不被瀏覽器解析為 punycode 編碼,就有可能產生視覺欺騙。例如 google.com 域名中的字符+組合字符後,如果也不被使用 punycode 編碼,視覺上就可能發生欺騙。googlè.com 和 google.com ,用戶很難分清楚,並且在分辨率很高的顯示器中,需要 “鷹睛” 去識別。但是,Chrome 顯然是對例子中的組合字符做了 punycode 編碼。很多情況下,IDN 域名都會被轉換為 punycode 去解析。
CVE-2018-4260 是我之前發現的一個漏洞,利用了字符組合序列導致了 URL 地址欄欺騙。下面就以這個漏洞為例進行講解。
在這個漏洞中,我們用到希伯來字符的 U+05D5 U+05B9 U+05E1 來完成漏洞攻擊。
將字符 U+05D5 和組合字符 U+05B9 合成字符組合序列。
我註冊了希伯來的這個域名,拉丁文的 io.com 和希伯來的סוֹ.com 在瀏覽器中的顯示如下。希伯來的סוֹ.com 域名在 Safari 瀏覽器中沒有轉換為 punycode。
最終的效果如下圖,可以看下圖中,左邊是真實的 io.com,右邊是סוֹ.com。這兩個域名在 Safari 中的視覺顯示幾乎一樣。
是否應支持組合字符序列進行註冊?能否在註冊階段嚴格檢查和防止此類惡意意圖?在 URL 中思考這些問題,你可能會發現一些新的東西。
六、結語
Unicode 標準的出現和支持它的工具的使用是最近全球軟件最重要的趨勢之一,Unicode 為每個字符提供一個唯一編號,無論平台、程序或語言是什麼,每個軟件開發者都繞不開 Unicode 字符集。Unicode 目前分為 17 個平面,每個平面擁有 65,536 個代碼點,也就是說 Unicode 目前可以編碼 65536*17 = 1114112 個字符。Unicode 1.0.0 從當年 1991 年發布的 24 個腳本 7161 個字符,發展到現在 2022 年 9 月 Unicode 15.0 的 161 個腳本 149,186 個字符。在這之後 Unicode 中一直會源源不斷增加新的字符,軟件處理這些字符時都可能因字形渲染不足、混合腳本、PunyCode、雙向文本、組合字符等而導致漏洞觸發,進而發起各式各樣的網絡攻擊。在由安全漏洞核心驅動的網絡攻擊事件大量爆發的今天,對現有及尚未開發的 Unicode 編碼、區域進行深入安全研究,從根技術出發去分析和控制漏洞收斂進而保護數據安全,是看似艱難卻又是捷徑的一條路。
免責聲明:作為區塊鏈信息平台,本站所發布文章僅代表作者及嘉賓個人觀點,與 Web3Caff 立場無關。本文內容僅用於信息分享,均不構成任何投資建議及要約,並請您遵守所在國家或地區的相關法律法規。