在 《前端資源加載失敗優化》文章中,我們聊到了前端資源加載失敗的監控方式,以及資源加載失敗時的優化方案。通過對加載失敗的資源更換域名動態重新加載、同時確保最終代碼正常的執行順序,從而有效地減少了因為資源加載失敗導致的網頁異常。到此,資源文件成功加載了!但加載到的是否就是正確的資源呢?是否會在加載過程中被半路劫持?此時又該如何監控?是否還能做更多的防護措施呢?本文將逐步進行分析。
流量劫持
流量劫持在 Web 項目中是一個老生常談的話題了,常見的劫持方式是往 JS 代碼文件中注入一段腳本,從而實現一段廣告 “完美” 植入,而當注入的位置稍有偏差,導致代碼執行異常,頁面將完全不可用。
HTTPS
上面現象在使用以明文傳輸、不帶加密的 HTTP 協議中經常遇到,畢竟流量在傳輸過程中裸奔,劫持輕而易舉。HTTPS 應運而生,通過證書加密等方式保證了傳輸過程中的數據完整性,開啟 HTTPS 后,這類劫持問題基本不復存在了。
原本以為就此安穩一生,直到有一天,鐘聲再次響起,有用戶反饋訪問頁面時看到了廣告、還有的打開頁面后白屏。通過具體的定位分析,最終發現返回的 CDN 文件只剩一半內容。
難道 HTTPS 協議被破譯了嗎?其實并不是。
HTTPS 是可以有效應對流量劫持的問題,然而很多提供 HTTPS 的 CDN 服務在回源的時候采用的 HTTP 協議,流量劫持便有機可乘,那么開啟全鏈路的 HTTPS 是否就萬無一失了呢?大部分情況確實如此。但如果遇到 CDN 服務入侵、源頭污染,或者用戶信任了異常證書導致的中間人劫持,千里之堤,潰于蟻穴,防御之門被摧毀后,依然任人宰割。為了盡可能的安全,或許我們可以再加一道防線,那就是 SRI。
SRI(Subresource Integrity)
SRI 是用來校驗資源是否完整的安全方案。通過為頁面引用的資源指定信息摘要,當資源被劫持篡改內容時,瀏覽器校驗信息摘要不匹配,將會拒絕代碼執行并拋出加載異常,保證加載資源的完整性。
啟用 SRI
使用 SRI 只需要給頁面標簽添加 integrity 屬性,屬性值為簽名算法(sha256、sha384、sha512)和摘要簽名內容組成,中間用 - 分隔。
1 2 3 4 5 6 7 8 |
function getIntegrity() { const hashFuncName = 'sha256'; const hash = crypto .createHash(hashFuncName) .update(source, 'utf8') .digest('base64'); return hashFuncName + '-' + hash; } |
我們也可以借助 webpack-subresource-integrity 輕易實現 integrity 的添加過程,保持對開發者透明。
開啟 SRI,瀏覽器會對相關資源進行 CORS 校驗,所以被加載的資源要么在同域下,要么得滿足 CORS 機制(具體方式可查看 腳本錯誤量極致優化-監控上報與 Script error 中 跨源資源共享機制 ( CORS ) 章節)。
至此,當資源內容被劫持篡改時,瀏覽器校驗簽名不匹配將使得異常資源不被執行,并觸發加載失敗。從而進入到資源加載失敗的監控流程中,最終可以通過切換 CDN 域名或主域名進行加載重試,直到加載上正確資源,避免資源被劫持篡改內容后注入廣告或白屏等情況。
監控劫持
監控及重加載的具體方式可見 《前端資源加載失敗優化》。加載失敗的原因有很多,那么該如何區分哪些是由 SRI 機制觸發的呢?可以采用下面思路:
- 當加載失敗時,切換域名重加載到正確資源;
- 分別請求加載失敗的和最終正常的 URL,抽樣對比兩份內容是否存在差異,存在則說明內容被篡改,屬于 SRI 機制觸發。
最終搭配上報和告警機制,當遇到劫持問題時,及時收到消息。
應對劫持
上面是我們遇到的劫持問題,上報量急劇上升,處理后快速下降。遇到劫持問題之后,我們該如何應對呢?
向運營商客服投訴或工信部投訴或許是個辦法。不過在此之前我們可以先主動觸發刷新 CDN 節點緩存的資源,避免被劫持的資源被繼續訪問。除此之外,對于已經緩存到異常資源的用戶,特別是在不方便強制刷新頁面的環境下,下次訪問會先接著訪問異常緩存造成二次傷害,對此通過修改文件 hash,重新發布強制刷新資源,問題得以解決。
CSP(Content Security Policy)
資源內容完整(不被篡改)加載下來了,但加載的是否就都是我們需要的資源呢?是否會因為代碼問題導致 XSS、或是瀏覽器使用了異常插件,最終導致加載了其他不需要的資源而影響業務呢?
對此,我們可以開啟 CSP 機制來保證加載的是需要的資源文件、執行的是正常的腳本。
一方面通過制定 CSP 的外鏈白名單機制,限制了不可信域名的資源加載;另一方面通過開啟 nonce 模式,確保執行的是正常的內聯腳本。相關內容可以查看 [《XSS 終結者-CSP 理論與實踐》和 《Csp Nonce - 守護你的 inline Script》這兩篇文章。
總結
HTTPS 可以有效應對流量劫持的問題,SRI 在資源完整性再上一道屏障,CSP 也進行了其他方面的補充?!叭{馬車” 為頁面資源安全 “保駕護航”。當然這也絕非銀彈,安全之路充滿著荊棘與挑戰,任重道遠。
以上為本文所有內容,如有不妥,懇請斧正,謝謝。