Spirit帶你瞭解如何安全的引入第三方資源
本文介紹一下如何安全的引入第三方資源
同源策略(SOP)
首先我們來了解一下什麼是同源策略,下面的是wiki百科的定義
✨同源策略是指Web瀏覽器中,允許某個網頁尾本訪問另一個網頁的資料,但前提是這兩個網頁必須有相同的協議號(protocol)
,主機號(host name)
和埠號(port)
,一旦兩個網站滿足上述條件,這兩個網站被認定為具有相同來源.
而同源策略主要表現在三個方面 DOM,Web資料和網路
- DOM:限制了來自不同源的JavaScript指令碼對當前的DOM物件讀和寫的操作
- Web資料: 限制了不同源的站點讀取當前站點的Cookie,indexDB,LocalStorage等資料
- 網路:限制了通過XMLHttpRequest等方式將站點的資料傳送給不同源的站點
但是如果都按同源策略來的話,便利性其實是大打折扣的,所以為了便利,Web讓出了一些安全性,推出了一系列舉措,使得我們的網站能夠引入第三方資源為使用者提供更加豐富的功能
措施
跨域資源共享 - 維基百科(CORS)
我們先看下wiki百科的定義,方便理解
- 跨域資源共享:用於讓網頁的受限資源能夠被其他域名的頁面訪問的一種機制.
- 通過該機制,頁面能夠自由地使用不同源(英語:cross-origin)的圖片、樣式、指令碼、iframes以及視訊。一些跨域的請求(特別是Ajax)常常會被同源策略(英語:Same-origin policy)所禁止的。
- 跨源資源共享定義了一種方式,為的是瀏覽器和伺服器之間能互相確認是否足夠安全以至於能使用跨源請求(英語:cross-origin requests)。比起純粹的同源請求,這將更為自由和功能性的(functionality),但比純粹的跨源請求更為安全。
- 跨域資源共享是一份瀏覽器技術的規範,提供了 Web 服務從不同網域傳來沙盒指令碼的方法,以避開瀏覽器的同源策略
通過wiki百科的定義,我們可以得到以下的3點
- 頁面可以通過該機制,自由的嵌入不同源的圖片,樣式沒指令碼,iframes和videos
- 可以繞過同源策略,傳送跨域請求
- 我們可以這麼理解,同源策略相當於是把所有第三方的源列上黑名單,而CORS則是把第三方的源選擇性的列成白名單,彷彿那些在白名單上的源和自己的源是在一起的
白名單通過伺服器的指令傳遞給客戶端,該指令在HTTP響應頭中傳遞給客戶端,它包含兩個重要的headers
- Access-control-allow-origin:用於定義允許哪些源可以訪問受限的資源的
- Access-control-allow-credentials:確定是否允許使用cookies驗證請求
?大家可能注意到了,CORS提供的白名單實際上是為該域提供內容的源所維護的,並不是客戶端所提供的.並不能由客戶端自己決定,接下來所介紹的CSP則很好的解決了這個問題
內容安全策略(CSP)
老規矩,我們先看下wiki百科的定義
-
內容安全策略(英語:Content Security Policy,簡稱CSP)是一種電腦保安標準,旨在防禦跨站指令碼、點選劫持等程式碼注入攻擊,阻止惡意內容在受信網頁環境中執行。
-
我們可以知道,CSP主要是為了抵禦攻擊手段所發明出來的
-
但wiki百科對於這一塊定義非常的少,接下來介紹的是從MDN上所看到的東西
CSP的主要作用
- 減少和報告XSS攻擊
- CSP可以指定有效域,即客戶端瀏覽器這邊認可的可執行的指令碼來源
使用CSP
通過Content-Security-Policy設定策略,以下是MDN中介紹的常見的安全策略方案例項
-
網站管理者想要所有內容均來自站點的同一個源(不包括其子域名)
Content-Security-Policy: default-src 'self'
-
一個網站管理者允許內容來自信任的域名及其子域名 (域名不必須與CSP設定所在的域名相同)
Content-Security-Policy: default-src 'self' *.trusted.com
-
一個網站管理者允許網頁應用的使用者在他們自己的內容中包含來自任何源的圖片, 但是限制音訊或視訊需從信任的資源提供者(獲得),所有指令碼必須從特定主機伺服器獲取可信的程式碼.
Content-Security-Policy: default-src 'self'; img-src *; media-src media1.com media2.com; script-src userscripts.example.com
在這裡,各種內容預設僅允許從文件所在的源獲取, 但存在如下例外:
- 圖片可以從任何地方載入(注意 "*" 萬用字元)。
- 多媒體檔案僅允許從 media1.com 和 media2.com 載入(不允許從這些站點的子域名)。
- 可執行指令碼僅允許來自於userscripts.example.com。
-
一個線上銀行網站的管理者想要確保網站的所有內容都要通過SSL方式獲取,以避免攻擊者竊聽使用者發出的請求。
Content-Security-Policy: default-src https://onlinebanking.jumbobank.com
-
一個線上郵箱的管理者想要允許在郵件裡包含HTML,同樣圖片允許從任何地方載入,但不允許JavaScript或者其他潛在的危險內容(從任意位置載入)。
Content-Security-Policy: default-src 'self' *.mailsite.com; img-src *
注意這個示例並未指定script-src (en-US)。在此CSP示例中,站點通過
default-src
指令的對其進行配置,這也同樣意味著指令碼檔案僅允許從原始伺服器獲取。
?從上述五個常見例子可以看到,通過自己指定策略,客戶端可以自己管理可以從哪載入外部源,相比之前更加安全了,等同於可以自己設定防火牆,抵禦外部的惡意攻擊,同時也解決了跨域資源共享只能由伺服器端來決定白名單的問題,Web的靈活性大大提高了
子資源完整性Subresource Integrity(SRI)
先來看看mdn的定義吧
子資源完整性(SRI)是允許瀏覽器檢查其獲得的資源是否被篡改的一項安全特性.它是通過驗證獲取檔案的雜湊值是否和你提供的雜湊值一樣來判斷資源是否被篡改
我來給大家講下SRI的應用場景
我們使用cdn分發指令碼和樣式表等檔案時,並不是完全安全的,如果攻擊者獲得對CDN的控制權,則可以將任意惡意內容注入到CDN的檔案上,因此有可能潛在的攻擊所有從該CDN上獲取檔案的站點.而SRI可以極大限度的來降低這種損害
注意:SRI並不能規避所有的風險.第三方庫經常會自己請求額外的資訊,有可能會攜帶使用者的賬號密碼等關鍵資訊.這些經常需要JS功能的支援,比如一個地相簿會需要取<svg>
資料來渲染,但是包含點選事件.通過點選事件就有可能對你的網站造成損害的
使用方法
- 使用base64編碼過後的檔案雜湊值寫入你所引用的
<script>
和<link>
標籤的integrity就可以啟用子資源完整性功能 - 更為詳細的用法 請大家到MDN上瀏覽,本文不做過多介紹
瀏覽器處理SRI
- 當瀏覽器在
<script>
或者<link>
標籤中遇到 integrity 屬性之後,會在執行指令碼或者應用樣式表之前對比所載入檔案的雜湊值和期望的雜湊值。 - 當指令碼或者樣式表的雜湊值和期望的不一致時,瀏覽器必須拒絕執行指令碼或者應用樣式指令碼,並且返回一個網路
引入第三方資源小結
從上面的講述,我們可以看到為了引入第三方資源,其實是做了很多努力的
我們在此也可以總結出一些內容
- 同源策略相當於密不透風的防火牆,任何第三方資源都進不來
- 跨域資源共享(CORS)和內容安全策略相當於是白名單,告訴同源策略,我們是安全的,讓它放行他們進去
- 子資源完整性(SRI)則是鎮守防火牆內的一個尖兵,啟動它的時候,能檢查出這些第三方資源是否是偽裝的惡意進攻
- 他們相互結合,能極大限度的保護我們的網站不受侵害,同時還能很好的為使用者提供更加豐富的功能