現如今,網民的網絡賬戶被盜,很有可能是被“釣魚”了。去年的一份安全報告中指出:“近85%的資金損失是通過釣魚網址泄露支付信息造成的”。
傳統的釣魚網站通常是申請一個和被冒充網站相似的域名,比如 taobao000.com ,或者直接利用三四級域名來冒充,比如 taobao.com.evil.com。
釣魚網址一般是通過郵件、短信、聊天工具等傳輸系統發送給目標群體的,於是這些傳輸系統的運營商會責無旁貸的采取措施,來盡可能的檢測並屏蔽那些釣魚網址,而且即便它們不做,現代的瀏覽器也都會做這件事。最常見的釣魚網址檢測技術就是維護一個釣魚網站域名的黑名單,或者使用別的組織共享出來的黑名單(比如谷歌的 Safe Browsing)。一旦某個釣魚網站被添加進了這個黑名單,那么它的主人釣魚成功的概率就會大幅降低。
如何跳過這些檢測?如何不使用常規的網址來存放網頁?於是有人想到了利用 Data URI。僅僅在 2017 年,我就看到已經有兩家網絡安全公司發文,分別講了兩個利用 Data URI 來釣魚的真實案例,一個是針對 Gmail,一個是針對 Yahoo Mail。我這里做了一個仿冒淘寶登錄頁的釣魚頁面 的demo,你可以體驗一下。
利用 Data URI,可以把整個網頁的內容都放到這個 URL 里。由於 Data URI 完全沒有域名的概念,所以黑名單屏蔽技術對他無效。而且除此之外,還有一個 bonus,那就是你可以在一個 Data URI 的頭部放置任意你想冒充的網站的網址,像這樣:
在這個真實的 Gmail 登錄網址的后面是一連串的、比被釣魚者的屏幕還要寬的空格,隱藏在這些空格后面的,才是真正的網頁源碼:
普通網民很容易忽略 “data:text/html,” 這幾個多出來的字符。有了這個 bonus,釣魚者的釣魚成功率更高了,而且不用總花錢去換域名了。
為此,Chrome 從 56 開始,在地址欄左側把 Data URI 標記成了“不安全”網址:
這可能會減少一些釣魚事件的發生,但考慮到一些網民完全沒有看地址欄的習慣(尤其是現在有一些瀏覽器故意弱化地址欄)、以及在移動端 WebView 打開網頁完全沒有地址欄,於是 Chrome 從 60 開始,采取了一種更徹底的方式:屏蔽從頁面打開的 Data URI 網址(相對應的行為是在地址欄回車打開 Data URI 網址)。
比如下面這個 <a> 鏈接:
<a href="data:text/html,foo">
如果你單擊這個鏈接的話,會直接報錯,Not allowed to navigate top frame to data URL:
但在右鍵菜單中點擊 “在新標簽中打開鏈接”、“在新窗口中打開鏈接” 不受影響。此外,這次還會屏蔽下面這些跳轉方式(30x 跳轉若干年前就已經屏蔽了):
1. html 里添加 <meta http-equiv="refresh" content="0;url=data:text/html,foo" />
2. 響應頭里添加 refresh: 0;url=data:text/html,foo
3. JS 里執行 window.open("data:text/html,foo")
4. JS 里執行 location.href = "data:text/html,foo"
等一切能讓頁面跳轉到 Data URI 的方式都會被屏蔽,其中 open() 方法打開的新標簽頁面會被強制替換成 about:blank。其實 Chrome 的這些屏蔽措施之前就已經應用到了 file: 和 chrome: 等協議上了。
例外情況除了上面說的右鍵菜單中的各種操作,還有:
1. <a download>
2. 當指定的 MIME 觸發了瀏覽器下載邏輯的情況,比如 open("data:application/zip,foo")
3. 直接在地址欄上輸入 Data URI 並回車
當然還有我們常用的,Data URI 沒有用在頂層頁面網址的情況,比如作為 <img> 的 src 屬性,<iframe> 的 src 屬性,CSS 里的 url() 的參數等,都不受影響。
在 Chrome 60 之前的三個版本 Chrome 57、58、59 中,當你打開一個 Data URI 頁面,會有一句警告信息,提醒開發者提前做遷移:
Chrome 的人做了統計,說從非 Data URI 頁面跳到 Data URI 頁面的情況只有不到萬分之五的概率,如果你的網站恰巧用到了這種在前端生成頁面的方式,可以嘗試遷移到后端來生成。