1. 程式人生 > >【前端安全】JavaScript防XSS攻擊

【前端安全】JavaScript防XSS攻擊

什麼是XSS

XSS(Cross Site Scripting),跨站指令碼攻擊,是一種允許攻擊者在另外一個使用者的瀏覽器中執行惡意程式碼指令碼的指令碼注入式攻擊。本來縮小應該是CSS,但為了和層疊樣式(Cascading Style Sheet,CSS)有所區分,故稱XSS。

對於攻擊者來說,能夠讓受害者瀏覽器執行惡意程式碼的唯一方式,就是把程式碼注入到受害者從網站下載的網頁中。

xss攻擊的種類

1、持續型XSS攻擊:惡意指令碼來源於網站的資料庫

我們來看這種攻擊的一個場景

 

1、攻擊者通過評論表單提交將<script>alert(‘aaa’)</script>提交到網站

2、網站後端對提交的評論資料不做任何操作,直接儲存到資料庫中

3、其他使用者訪問正常訪問網站,並且需要請求網站的評論資料

4、網站後端會從資料庫中取出資料,直接返回給使用者

5、使用者得到頁面後,直接執行攻擊者提交的程式碼<script>alert(‘aaa’)</script>,所有使用者都會在網頁中彈出aaa的彈窗

這種攻擊方式惡意程式碼會被儲存在資料庫中,其他使用者在正常訪問的情況下,也有會被攻擊,影響的範圍比較大

2、反射型XSS攻擊:惡意指令碼來源於受害者的請求

在一個反射型XSS攻擊中,惡意文字屬於受害者傳送給網站的請求中的一部分。隨後網站又把惡意文字包含進用於響應使用者的返回頁面中,發還給使用者。

我們來看下面這個場景

 

1、使用者誤點開了帶攻擊的url :http://xxx?keyword=<script>alert('aaa')</script>

2、網站給受害者的返回中包含了來自URL的的惡意文字

3、使用者的瀏覽器收到文字後執行頁面,會在網頁中彈窗aaa

反射型的攻擊需要使用者主動的去訪問帶攻擊的連結,攻擊者可以通過郵件或者簡訊的形式,誘導受害者點開連結。如果攻擊者配合短連結URL,攻擊成功的概率會更高

3、基於DOM的XSS攻擊

基於DOM的XSS攻擊是反射型攻擊的變種。伺服器返回的頁面是正常的,只是我們在頁面執行js的過程中,會把攻擊程式碼植入到頁面中

下面展示的是這種攻擊的場景

 

1、使用者誤點開了帶攻擊的url :http://xxx?name=<script>alert('aaa')</script>

2、網站給受害者的返回中正常的網頁

3、使用者的瀏覽器收到文字後執行頁面合法指令碼,這時候頁面惡意指令碼會被執行,會在網頁中彈窗aaa

這種攻擊方式發生在我們合法的js執行中,伺服器無法檢測我們的請求是否有攻擊的危險

攻擊的危害

攻擊者把程式碼注入進了訪問的頁面,所以惡意指令碼都在網站的上下文環境中執行,這就意味著惡意程式碼被當做網站提供的正常指令碼一樣對待:他有權訪問頁面與網站的關鍵資料(比如cookie),瀏覽器會認為他是網站的合法部分,允許他做任何事情。比如拿到使用者的cookie資訊,然後傳送到攻擊者自己的伺服器,從cookie中提取敏感資訊,拿到使用者的登入資訊,或者攻擊者可以通過修改DOM在頁面上插入一個假的登陸框,也可以把表單的`action`屬性指向他自己的伺服器地址,然後欺騙使用者提交自己的敏感資訊。

如何防止攻擊

XSS攻擊其實就是程式碼的注入。使用者的輸入被編譯成惡意的程式程式碼。所以,為了防範這一類程式碼的注入,需要確保使用者輸入的安全性。對於攻擊驗證,我們可以採用以下兩種措施:

1、編碼,就是轉義使用者的輸入,把使用者的輸入解讀為資料而不是程式碼

2、校驗,對使用者的輸入及請求都進行過濾檢查,如對特殊字元進行過濾,設定輸入域的匹配規則等

對於驗證輸入,我們既可以在服務端驗證,也可以在客戶端驗證

對於永續性和反射型攻擊,服務端的驗證是必須的,服務端支付的任何語言都能夠做到

而對於基於DOM的XSS攻擊,驗證輸入在客戶端必須執行,因為從服務端來說,所有發出的頁面內容是正常的,只是在客戶端js程式碼執行的過程中才發生可攻擊

但是對於各種攻擊,我們最好做到客戶端和服務端都進行處理。這裡,我們主要討論的是客戶端的驗證,至於服務端如何過濾驗證,可以檢視其它資料

編碼

在客戶端使用javascript對使用者輸入進行編碼時,有一些內建的方法和屬效能夠自動感知對上下文的情況下自動對所有的資料進行編碼

下表就是一些自動編碼的方式:

 這些內建的方法會對使用者的輸入自動編碼

但是對於使用者的自動輸入進行編碼也會有弊端,惡意文字也有可能插入進上下文中。看下面的例子:

document.querySelector(‘a’).href = “javascript:alert(‘aaa’)”

雖然給href屬性的時候會被自動編碼,但是這已不能組織攻擊者嵌入執行指令碼。

另外,如果需求是可以讓使用者自定義頁面的程式碼,對輸入進行編碼也不是一個很好的解決方案。編碼會把使用者的輸入當成純文字輸出,這樣就跟需求不符了。

針對這樣的情況,我們只能對文字進行校驗了。

校驗

校驗是一種過濾使用者輸入以至於讓程式碼中惡意部分被移除的行為。校驗都是通過一定的經驗和規則,對使用者的輸入進行匹配,過濾,去除掉存在攻擊風險的部分。我們可以通過黑名單的方式和白名單的方式來設定我們的規則

比如: 我們在檢測a 標籤的時候,只要輸入帶入javascript欄位的時候,我們就認為非法,javascript欄位就成為我們黑名單的匹配規則

同時,我們可以採用另外一種檢測方式,只要a標籤有href屬性的時候,我們只允許http協議的連結,如果是我們通過,不是就認為非法,這裡就需要我們建立一張白名單的匹配規則

白名單和黑名單都可以對資料進行過濾,但是黑名單會隨著攻擊方式的變化而改變,對於規則的使用,白名單更具長效性。所以對於匹配規則最好採用白名單的機制

下面有一個類庫是針對防XSS攻擊的,可以引入到我們日常專案中使用:

Content Security Policy(CSP)

只使用驗證輸入來防止XSS攻擊的劣勢在於即使存在一絲的漏洞也會使得你的網站遭到攻擊。最近的一個被稱為Content Security Policy(CSP)的標準能夠減少這個風險。

CSP對你用於瀏覽頁面的瀏覽器做出了限制,以確保它只能從可信賴來源下載的資源。*資源*可以是指令碼,樣式,圖片,或者其他被頁面引用的檔案。這意味著即使攻擊者成功的在你的網站中注入了惡意內容,CSP也能免於它被執行。

CSP也是採用白名單的方式來匹配網頁的解析和程式碼的執行,只不過,執行的層次上升到了瀏覽器的高度,對於CSP如何設定,可以參考以下的文章:

https://mp.weixin.qq.com/s/Pz7gS9_7J16wZGrR8zgR8g