XSS和CSRF詳解與防禦
開年遇到的第一個問題就是解決XSS攻擊>_<,可見要時刻保證網站的安全性至關重要。做好網站安全,不僅維護網站的穩定性,更保證使用者資料的一致性。對此,總結一下筆者在工作中遇到的安全問題以及防禦方法。
前端中常見的兩種網站應用安全漏洞攻擊的方式是 XSS 與 CSRF,本文詳細介紹兩種攻擊方式的概念、原理以及防禦方式。
XSS
XSS(Cross-site scripting)跨站指令碼攻擊是惡意使用者在網站中注入的指令碼,當正常使用者開啟網站時受到影響並可能獲取使用者cookie等資訊一種安全攻擊行為。常見的例子是使用者進入某個網站的時候一直彈出alert
框等。
常見的 XSS 方式分為兩類:永續性和非永續性,也有機構將其分為傳統型(由伺服器端程式碼缺陷引起)和基於 DOM 型(有客戶端引起)。下面介紹三種類型:
-
反射型
反射型跨站指令碼攻擊最常見的方式是客戶端輸入查詢資訊,伺服器端將其返回並且顯示在頁面上造成攻擊。如直出頁面,後面根據引數查詢返回對應的查詢資訊和結果。或者使用者在input輸入框中進行查詢等,值得注意的是,使用 innerHTML 插入
<script>alert(document.cooke)</script
並不會執行 script 中的程式碼,需要構造對應事件觸發。如:<img src="xxx.jpg" width="0" height="0" border="0" onload="javascript:alert(document.cookie);">
- 儲存型 儲存型與反射型 XSS 攻擊的區別在於是否儲存在資料庫中,如使用者寫部落格和評論等,這種方式的影響是持久的。
-
基於 DOM
惡意使用者構造的指令碼並不會經過伺服器端,完全發生在客服端,如通過連結(
?userName=<img onload="javascript:alert(document.cookie)"/>
)的查詢引數來顯示使用者名稱等。
針對 XSS 攻擊,經常有以下兩個方式來進行防禦:
- 設定重要的cookie資訊為 httpOnly 對於重要的 cookie欄位,如:可以通過 cookie 某個欄位和某個介面獲取好友關係的,需要將其設定為 httpOnly,使得惡意使用者無法獲取。
- 對輸入進行檢測和轉義 對使用者輸入的或者從連結獲取引數需要展示到頁面中需要校驗合法性和使用轉義函式進行轉義,如常見的函式如下:
function escHTML(str) { if (!str) return ''; return str.replace(/&/g, '&') .replace(/</g, '<') .replace(/>/g, '>') .replace(/x27/g, ' ') .replace(/x22/g,'&quto;'); }
CSRF
CSRF(Cross-site request forgery)是一種攻擊,迫使使用者在受信任網站上執行不需要的一些操作。具體過程如下:
- 使用者向信任站點如example.com傳送請求
- 使用者驗證通過、獲得信任站點的身份資訊,並放入cookie中,使用者此時可以在站內進行其他請求;
- 使用者未退出登入example.com,然後訪問hack.com網站,該網站返回攻擊性程式碼並且在頁面中存在訪問example.com的請求;
- 瀏覽器在使用者可能不知情的情況下向example.com傳送請求;
- 由於同域名可以帶上cookie資訊,因此資訊認證通過,請求偽造成。
針對 CSRF 攻擊,常用的防禦方式如下:
- 檢測請求來源 在請求頭中有一個refree欄位,refree記錄了傳送請求的域名,比如:hack.com向example.com中傳送請求,那麼refree就為hack.com,只要在處理請求中做相應的校驗就可以中斷請求。
- 加入token校驗 crsf之所以能夠偽造請求成功,其原因之一在於所有的使用者資訊放於cookie中;因此可以在每次請求中加入token,然後後臺進行校驗,如果校驗通過則進行處理。生成token方式之一如下:
function getToken (token) { var str = token || ''; var hash = 5381; for (var i = 0, len = str.length; i < len; ++i) { hash += (hash << 5) + str.charCodeAt(i); } return hash & 0x7fffffff; }
具體攻擊示例點選檢視