XSS(Cross Site Scripting),又稱跨站腳本,XSS的重點不在於跨站點,而是在於腳本的執行。在WEB前端應用日益發展的今天,XSS漏洞尤爲容易被開發人員忽視,最終可能形成對我的信息的泄漏。現在,仍然沒有統一的方式來檢測XSS漏洞,可是對於前端開發人員而言,還是能夠在某些細微處避免的,所以本文會結合筆者的學習和經驗總結解決和避免的一些方案,並簡要從webkit內核分析瀏覽器內核對於XSS避免所作的努力,瞭解底層基礎設施對預防XSS所作的貢獻。php
此處不詳細講解XSS的一些細節css
XSS的目標是讓其餘站點的js文件運行在目標站點的上,這主要發生在頁面渲染階段。在該階段發生了某些非預期的腳本行爲,該腳本可能來自用戶的輸入,也可能來自域外的其餘js文件,不一而足。XSS的發生起源來自於用戶輸入,所以XSS根據用戶輸入數據以何種形式、什麼時候觸發XSS、是否有後端服務器的參與劃分爲三種類型,分別是反射型XSS、持久型XSS和DOM XSS。html
反射型XSS,顧名思義在於「反射」這個一來一回的過程。反射型XSS的觸發有後端的參與,而之因此觸發XSS是由於後端解析用戶在前端輸入的帶有XSS性質的腳本或者腳本的data URI編碼,後端解析用戶輸入處理後返回給前端,由瀏覽器解析這段XSS腳本,觸發XSS漏洞。所以若是要避免反射性XSS,則必須須要後端的協調,在後端解析前端的數據時首先作相關的字串檢測和轉義處理;同時前端一樣也許針對用戶的數據作excape轉義,保證數據源的可靠性。前端
e.x.
localhost/test.phpjava
<?php echo $_GET['name'] ?>
若是經過 localhost/test.php?name=alert(document.cookie) 訪問頁面,那麼通過後端服務器的處理,就會形成反射性XSS的發生。web
同理,經過傳入data uri編碼的字符串也會致使XSS,如 localhost/test.php?name=data:text/html;charset=utf-8;base64,PHNjcmlwdD5hbGVydChkb2N1bWVudC5jb29raWUpPC9zY3JpcHQ+ 會致使一樣的問題。該段編碼的字串解碼後是「alert(document.cookie)」。ajax
持久型XSS仍然須要服務端的參與,它與反射型XSS的區別在於XSS代碼是否持久化(硬盤,數據庫)。反射型XSS過程當中後端服務器僅僅將XSS代碼保存在內存中,併爲持久化,所以每次觸發反射性XSS都須要由用戶輸入相關的XSS代碼;而持久型XSS則僅僅首次輸入相關的XSS代碼,保存在數據庫中,當下次從數據庫中獲取該數據時在前端未加字串檢測和excape轉碼時,會形成XSS,並且因爲該漏洞的隱蔽性和持久型的特色,在多人開發的大型應用和跨應用間的數據獲取時形成的大範圍的XSS漏洞,危害尤爲大。這就須要開發人員培養良好的WEB前端安全意識,不只僅不能相信用戶的輸入,也不能徹底相信保存在數據庫中的數據(即後端開發人員忽視的數據安全檢測)。針對持久型XSS沒有好的解決方式,只能由開發人員保證。固然規則是由開發者制定,若是忽略用戶體驗的話,能夠制定一套嚴謹的輸入規則,對相關關鍵詞和輸入類型(如data URI檢測,禁止輸入)的檢測和禁止,儘量規避用戶發現XSS漏洞的可能性,從源頭處理。chrome
DOM XSS徹底在前端瀏覽器觸發,無需服務端的參與,所以這是前端開發工程師的「地盤」,理應得到咱們的關注。數據庫
e.x.
localhost/test.html
<script> eval('alert(location.hash.slice("1"))'); </script>
若是訪問localhost/test.html#document.cookie ,那麼就會觸發最簡單的危害很是大的DOM XSS。它徹底沒有服務端的參與,僅僅由用戶的輸入和不安全的腳本執行形成,固然在本例中僅僅是最簡單的狀況,若是用戶輸入字符串‘’或者text/html格式的data URI,則更難檢測,也危害更大,黑客操做起來更爲容易。
所以預防DOM XSS,須要前端開發人員警戒用戶全部的輸入數據,作到數據的excape轉義,同時儘量少的直接輸出HTML的內容;不用eval、new Function、setTimeout等較爲hack的方式解析外站數據和執行js腳本;禁止內聯事件處理函數;若是在考慮安全性的前提下須要獲取外站腳本的執行結果,能夠採用前端沙盒(創建空的iframe執行腳本,該iframe沒法操做當前文檔對象模型)、worker線程的方式完成,保證DOM的安全。
XSS漏洞難以檢測,可是爲了WEB安全仍須要盡力避免,在本節將會針對三種類型XSS漏洞提出對應解決方法,並從其餘角度提供更具啓發性的意見。
針對反射型XSS,在對應的小節中也提到過,須要服務端和前端共同預防,針對用戶輸入的數據作解析和轉義,對於前端開發而言,則是善於使用escape,針對data URI內容作正則判斷,禁止用戶輸入非顯示信息,如MIME類型爲「text/html,text/plain」類型的內容。
對於存儲型XSS,處理方式仍然類同於反射性XSS。
對於DOM XSS,則須要慎之又慎。因爲形成XSS的緣由在於用戶的輸入,所以在前端,須要特別注意如下的用戶輸入源:
「
document.URL,
location.hash,
location.research,
document.referrer(此處應尤其注意,referrer屬性雖然可用於避免CSRF,但可觸發XSS攻擊),
XHR返回值(跨域返回值),
form表單及各類input框
「
針對以上輸入源,須要作相對於的檢測和轉義。在以上輸入源中獲取數據後,可能會有各類DOM操做或純粹的js計算,這些操做則是真正觸發XSS的罪魁禍首:
「
1,直接輸出HTML內容
document.body.innerHTML = ...
document.body.outterHTML = ...
document.write()
2,HTML標籤內聯腳本
<img src='abc' onerror=alert('error')>
3,直接執行腳本
eval
new Function(){}
setTimeout()
window.execScript()
4,打開新頁面觸發XSS(包括反射型XSS和持久型XSS)
window.open()
location.href = ...
location.hash = ...
」
在操做DOM時,須要尤爲注意上述操做,針對可能形成的XSS須要進行字串轉義。固然,有些操做是徹底能夠避免的:對於innerHTML的拼接操做,須要摒棄jQuery式的鏈式操做而使用前端模版如artTemplate,也可選擇使用由後端渲染好的可靠的數據,這樣既保證性能也確保安全;對於HTML標籤內嵌js,則須要徹底避免,這是一種容錯率很低的實現;直接執行腳本和解析數據,則需避免eval和new Funciton等操做,改成JSON.parse、iframe沙盒和webWorker執行;而針對打開新頁面觸發的XSS則須要開發人員自行把控。
上文提到的僅僅是對應的XSS避免方案,可是若是將目光放置在全局,站在瀏覽器的角度上,則會變的更爲柳暗花明。現階段,大多數瀏覽器都支持多種安全策略,如沙盒機制,跨域機制,跨文檔消息和CSP。在這裏,咱們關注CSP(Content Security Policy),又稱內容安全協議,CSP經過服務端響應的HTTP頭部來制定網頁相關資源的加載域,這些資源限定於js文件、css文件、image、iframe、字體和其餘對象(如object、applet)。
CSP經過HTTP頭部由服務端制定,頭部類型因爲歷史緣由總共由三種,這三種僅僅是兼容性的差異,針對chrome瀏覽器,咱們僅需關注Content-Security-Policy頭部。CSP頭部的定義規則以下:
Content-Security-Policy: 名 值; 名 值; 名 值;
具體的指令名以下圖:
指令值的規範以下圖:
所以,若是咱們要避免XSS攻擊,能夠限定腳本的來源域,如:
Content-Security-Policy: default-src 'self' ajax.googleapis.com;
這樣,非本域和ajax.googleapis.com域下的其餘腳本不會被加載,避免了XSS。
在這裏須要強調一點的是,默認CSP會禁止script代碼塊的執行;禁止內聯事件處理函數;禁止內聯樣式;禁止eval和new Function。對於內聯script代碼塊和內聯樣式,可經過CSP的header設置,如Content-Security-Policy: default-src 'self'; script-src 'unsafe-inline';。
CSP有一個指令須要注意,即report-uri,它會將錯誤信息主動發送至改cgi(sevlet),用於管理員的統一管控。report-uri屬性將會在下文中涉及到。
XSS攻擊主要發生在頁面的渲染時,當瀏覽器的渲染引擎獲取到該頁面並開始解析時,是能夠在該階段進行安全校驗的,具體的時間節點則是在詞法分析後針對每一個token作過濾。
在webkit中,由HTMLDocumentParser解析獲得token後,使用XSSAuditor進行過濾,具體則是在filterToken中執行,不只僅是針對token的名稱,其屬性也是監測重點。在webkit中採用黑名單機制,針對「,,,」作重點排查,當發現相關隱患時,生成相關信息XSSInfo,由XSSAuditorDelegate類發送給對應的cgi,該cgi的地址正是CSP中的指令值report-uri,固然也能夠手動制定該值。
默認,XSSAuditor是啓用的,可是XSSAuditor在發現XSS行爲時卻有多種,這些行爲能夠配置,這就涉及到HTTP頭部X-XSS-Protection。該頭部並非W3C和IETF的規範,而是非標準實現,經過對該頭部的賦值來定製XSSAuditor的相關行爲。
默認狀況,XSSAuditor處於重寫模式(js代碼處在非執行狀態),即X-XSS-Protection:1;若是要禁用XSSAuditor,能夠X-XSS-Protection:0;當設置爲X-XSS-Protection:1;mode=block,則會在XSSAuditor做用時禁止網頁顯示,呈現給用戶的則是空白頁;若設置爲X-XSS-Protection:1;report=... ,則會將相關統計信息發送給CSP中定義的report-uri。XSSAuditor沒法徹底避免XSS,但畢竟在瀏覽器層面提供了一層檢查機制,從HTML tag上保證其可靠性。
XSS漏洞難以發現,可是做爲開發人員須要於細節處避免製造XSS漏洞,而對於CSP規範和webkit的XSSAuditor機制的使用,咱們不該抱着依靠它們的想法來解決XSS,畢竟不是全部的頁面均可以容忍CSP的嚴格,XSSAuditor機制也僅僅針對chrome而言,而且存在多種bypass繞過檢查,如經過各類HTML實體編碼、url編碼和js編碼。所以,咱們仍需以人爲本,規範開發習慣,提升WEB前端安全意識。
參考文章:
1 瀏覽器安全策略說以內容安全策略CSP
2 UNDERSTANDING XSS AUDITOR
3 webkit技術內幕
http://www.cnblogs.com/accordion/p/5446174.html
跨站腳本攻擊(Cross Site Scripting),是一種 Web 應用程序的漏洞,當來自用戶的不可信數據被應用程序在沒有驗證以及反射回瀏覽器而沒有進行編碼或轉義的狀況下進行了處理,致使瀏覽器引擎執行了代碼。
又叫非持久型XSS,當不可信的用戶輸入被服務器在沒有任何驗證下處理並在沒有編碼或轉義的狀況下反射回響應文中,致使代碼在瀏覽器執行的一種 XSS 漏洞。
xss攻擊參數:";alert('xss');// 產生緣由:服務端未對參數就行編碼或者轉義致使 採用任何一種php提供的方法進行編碼均可以過濾XSS $name = htmlspecialchars($_GET['name']);
又叫持久型XSS是當不可信的用戶輸入被處理並在沒有任何驗證的狀況下保存在文件或數據庫,同時該不可信的數據從存儲中被獲取而後在沒有編碼或轉義的狀況下反射回響應文中,致使了永久性的每次存儲數據反射回響應文代碼就會在瀏覽器中執行的一種XSS漏洞。
數據來源在 DOM 中,接收器也在 DOM 中,而數據流歷來沒有離開瀏覽器。它發生在一個不可信的數據在源中被給予並被執行,結果致使修改了 DOM 在瀏覽器中的「環境」。DOM XSS 攻擊發生在不可信數據相對於上下文沒有被編碼或轉義的狀況下。
普通圖片地址:http://p1.qhimg.com/t010c1d27667bbe0417.png
XSS地址:http://p1.qhimg.com/t010c1d27667bbe0417.png" onload="javascript:alert(document.cookie);
mXSS 或突變 XSS 是當不可信數據在 DOM 的 innerHTML 屬性的上下文被處理並經過瀏覽器發生突變,致使變成一種有效的 XSS 向量的一種 XSS 漏洞。在 mXSS,一個看起來無害的能夠經過客戶端或服務端XSS過濾器的用戶指定的數據經過瀏覽器執行引擎發生突變能夠反射回一個有效的 XSS 向量。XSS 過濾器不能防止 mXSS。爲了防止 mXSS,應實施有效的 CSP,框架應該不被容許,HTML 文檔應該定義文檔類型,強制瀏覽器遵循標準呈現內容以及執行腳本。
正常輸入沒有問題,在瀏覽器再次解析的時候出現了問題。
驗證輸入而且基於語境和按照正確的順序轉義不可信數據
瀏覽器的解析順序:html->css->js
瀏覽器的解碼順序:html->url->js
始終遵循白名單優於黑名單的作法
由於黑名單的集合是無限的,咱們不能考慮到各類狀況
使用 UTF-8 爲默認的字符編碼以及設置 content 爲 text/html
使用推薦的 HTTP 響應頭進行 XSS 防禦
HTTP響應頭 | 描述 |
---|---|
X-XSS-Protection: 1; mode=block | 該響應頭會開啓瀏覽器的防XSS 過濾器。 |
X-Frame-Options: deny | 該響應頭會禁止頁面被加載到框架。 |
X-Content-Type-Options: nosniff | 該響應頭會阻止瀏覽器作MIMEtype |
Content-Security-Policy: default-src 'self' | 該響應頭是防止 XSS 最有效的解決方案之一。它容許咱們定義從 URLS 或內容中加載和執行對象的策略 |
Set-Cookie: key=value; HttpOnly | Set-Cookie 響應頭經過HttpOnly 標籤的設置將限制JavaScript 訪問你的 Cookie。 |
Content-Type: type/subtype;charset=utf-8 | 始終設置響應的內容類型和字符集 |
給開發者的終極XSS防禦備忘錄
前端XSS防火牆1
前端XSS防火牆2
前端XSS防火牆3
前端XSS防火牆4
前端XSS防火牆5