XSS攻擊的解決方法

在我上一篇《前端安全之XSS攻擊》文中,並無把XSS攻擊的解決辦法說完整,而XSS的攻擊又那麼五花八門,有沒有一招「獨孤九劍」可以抗衡,畢竟那麼多狀況場景,開發人員沒法一一照顧過來,而今天經過閱讀《白帽子講Web安全》這本書,對應對方式有了更好的總結,分爲兩類,一是服務端能夠乾的事,二是客戶端能夠乾的事。html

前提前端

在說XSS解決方式時,有一個前提。就是同源策略——瀏覽器的同源策略(瀏覽器安全的基礎,即便是攻擊腳本也要遵照這法則),限制了來自不一樣源的「document」或腳本,對當前「document」讀取或設置某些屬性。除了DOM、Cookie、XMLHttpRequest會受到同源策略的限制外,瀏覽器加載的一些第三方插件也有各自的同源策略。不過script、img、iframe、link等標籤均可以跨域加載資源,而不受同源策略的限制。jquery

服務端能夠乾的事後端

1. HttpOnly跨域

其實就是如今HTTP協議(HTTPS也是能夠的)才能讀取cookies,JavaScript是讀取不到cookies的。支持瀏覽器是IE6+、Firefox2+、Google、Safari4+。瀏覽器

JavaEE給Cookie添加HttpOnly的代碼:安全

response.setHeader("Set-Cookie","cookiename=value; Path=/;Domain=domainvalue;Max-Age=seconds;HTTPOnly");

PS:對於HTTPS,仍是能夠設置Secure字段,對Cookie進行安全加密。服務器

這是本質上不是預防XSS,而是在被攻破時候不容許JS讀取Cookie。cookie

2.處理富文本app

有些數據由於使用場景問題,並不能直接在服務端進行轉義存儲。不過富文本數據語義是完整的HTML代碼,在輸出時也不會拼湊到某個標籤的屬性中,因此能夠當特殊狀況特殊處理。處理的過程是在服務端配置富文本標籤和屬性的白名單,不容許出現其餘標籤或屬性(例如script、iframe、form等),即」XSS Filter「。而後在存儲以前進行過濾(過濾原理沒有去探明)。

Java有個開源項目Anti-Samy是很是好的XSS Filter:

Policy ploicy = Policy.getInstance(POLICY_FILE_LOCATION);
AntiSamy as = new AntiSamy();
CleanResults cr = as.scan(dirtyInput, policy);
MyUserDao.storeUserProfile(cr.getCleanHTML());

PS:固然也能夠在前端顯示前過濾,可是我以爲,讓前端人員少作東西好,而且服務端只須要轉一次。

客戶端能夠乾的事

1. 輸入檢查

輸入檢查的邏輯,必須放在服務器端代碼中實現(由於用JavaScript作輸入檢查,很容易被攻擊者繞過)。目前Web開發的廣泛作法,是同時在客戶端JavaScript中和服務器代碼中實現相同的輸入檢查。客戶端JavaScript的輸入檢查,能夠阻擋大部分誤操做的正經常使用戶,從而節約服務資源。

PS:簡單說,就是輸入檢查,服務端和客戶端都要作。

另外攻擊者可能輸入XSS的地方,例如:

1.頁面中全部的input框
2.window.location(href、hash等)
3.window.name
4.document.referrer
5.document.cookie
6.localstorage
7.XMLHttpRequest返回的數據

PS:固然不止這些

2. 輸出檢查

通常就是在變量輸出到HTML頁面時,使用編碼或轉義的方式來防護XSS攻擊。XSS的本質就是「HTML注入」,用戶的數據被當成了HTML代碼一部分來執行,從而混淆了本來的語義,產生了新的語義。

觸發XSS的地方

1.document.write
2.xxx.innerHTML=
3.xxx.outerHTML=
4.innerHTML.replace
5.document.attachEvent
6.window.attachEvent
7.document.location.replace
8.document.location.assign

PS:若是使用jquery,就是那些append、html、before、after等,其實就是拼接變量到HTML頁面時產生。大部分的MVC框架在模板(view層)會自動處理XSS問題,例如AngularJS。

用什麼編碼轉義

主要有HTMLEncode和JavaScriptEncode這兩個,客戶端和服務端都能作。可是讓後端去作,我感受是不大靠譜的,由於數據的使用場景可能有幾種,能夠在標籤、屬性、或腳本里(甚至其餘終端使用),單單以一種方式去encode是很極限的。

1.HTMLEncode,就是將字符轉換成HTMLEntities,通常會轉(&、<、>、"、'、/)這6個字符。

2.JavaScriptEncode,是使用」\「對特殊字符進行轉義。

PS:我在《HtmlEncode和JavaScriptEncode(預防XSS)》一文總結了比較完整的HTMLEncode和JavaScriptEncode兩個前端函數的寫法,以及一點示例。

哪些地方須要編轉義

1.在HTML標籤、屬性中輸出——用HTMLEncode

2.在script標籤中輸出——用JavaScriptEncode

3.在事件中輸出——用JavaScriptEncode

<a href="#" onclick="funcA('$var')">test</a>

4.在CSS中輸出

用相似JavaScriptEncode的方式。將除了字母、數字外的全部字符都編碼成十六進制形式」\uHH「。

5.在地址中輸出

通常若是變量是整個URL,則先檢查變量是否以「http」開頭(不是則幫忙添加http),保證不會出現僞協議類的XSS攻擊。而後再對變量進行URLEncode。

PS:URLEncode會將字符轉換成」%HH「形式。

總結

前端開發人員要注意在正確的地方使用正確的編碼方式,有時爲了防護XSS,在一個地方咱們須要聯合HTMLEncode、JavaScriptEncode進行編碼,甚至是疊加,並非固定一種方式編碼(又是具體狀況具體分析)。

通常存儲型XSS風險高於反射型XSS。反射型XSS通常要求攻擊者誘使用戶點擊一個包含XSS代碼的URL連接;而存儲型只須要用戶查看一個正常的URL連接,當用戶打開頁面時,XSS Payload就會被執行。這樣漏洞極其隱蔽,且埋伏在用戶的正常業務中,風險很高。(引自白帽子講Web安全原文)

本文爲原創文章,轉載請保留原出處,方便溯源,若有錯誤地方,謝謝指正。

本文地址 :http://www.cnblogs.com/lovesong/p/5223989.html

相關文章
相關標籤/搜索