目錄javascript
XSS,即(Cross Site Scripting)中文名稱爲「跨站腳本攻擊」。
XSS的重點不在於跨站攻擊而在於腳本攻擊。攻擊者能夠利用 web應用的漏洞或缺陷之處,向頁面注入惡意的程序或代碼,以達到攻擊的目的。
通俗的來講就是咱們的頁面在加載而且渲染繪製的過程當中,若是加載並執行了意料以外的程序或代碼(腳本、樣式),就能夠認爲是受到了 XSS攻擊。php
document.cookie
盜取 cookie中的信息window.location.href
定位到其餘頁面)XSS 根據攻擊是否持久,能夠分爲 「反射型XSS」與「存儲型XSS」兩種。
「反射型XSS」攻擊者經過包裝特定的鏈接,並將連接發送給實際的用戶來進行攻擊。
「反射型XSS」攻擊通常是利用前端代碼的漏洞或缺陷,好比使用 Eval來解析執行動態傳入的數據,或者是一些被後端接受處理後再返回前端展現的 URL參數等,其操做手法很相似於釣魚攻擊。
「存儲型XSS」攻擊是經過表單提交,抓包工具,直接調用接口等形式向後端數據庫注入數據。一旦被注入成功,並在輸出的頁面上沒有作任何防範措施,那麼全部訪問這個頁面的用戶都會被攻擊。
總的來講,「反射型XSS」是一種局部非持久的針對性攻擊,而「存儲型XSS」就要嚴重的多,它是一個全面大範圍可持久型的攻擊。css
正常頁面連接:html
http://xss-example.com/index.html?data={}
攻擊者包裝後的連接(data多是須要Eval解析的Json數據)前端
http://xss-example.com/index.html?data=alert(documet.cookie)
前端會被攻擊的代碼java
var data = eval('('+ getUrlParams('data') +')');
PS:固然在實際狀況下,攻擊者是不會把攻擊代碼這麼明顯的暴漏出來,通常都會通過編碼。web
http://xss-example.com/index.html?data=\u0061\u006c\u0065\u0072\u0074(1)
若是你認爲在解析 URL參數時不使用 Eval
便能保證安全,那就大錯特錯了,由於攻擊者每每會主動的幫你執行 eval
。ajax
http://xss-example.com/index.html?url=http://exmaple.com
而後前端代碼去解析並埋入一個 <a>
標記中。數據庫
var _href = getUrlParams('url'); $('a').attr('href', _href);
可是,如今若是攻擊者利用了您這個功能包裝了這樣的一條連接呢?express
http://xss-example.com/index.html?url=javascript:eval(alert(document.cookie));
編碼以後:
http://xss-example.com/index.html?url=javascript:\u0065\u0076\u0061\u006c(\u0061\u006c\u0065\u0072\u0074(document.cookie));
如今有這樣一個連接,URL參數會被後端的程序解析並返回給前端頁面。
http://xss-example.com/index.html?name="xiaoming";
後端代碼示例:
app.get('index.html', function (req, res) { res.send(req.query.name); })
若是如今用戶訪問的是這樣的鏈接,有會怎麼樣呢?
http://xss-example.com/index.html?name=<script>alert(document.cookie)</script>
此時一個腳本標記就會被後端代碼從新下發給前端,而後前端將其加入頁面中,便會觸發攻擊行爲。
固然,實際中並無這麼可怕,由於 web程序自己就已經很好的進行了阻攔過濾,可是通過個人實際測試發現 Firefox與老版本的IE依然有這些問題,只有 Chrome 與新版本的IE進行了阻止。
若是你想再Chrome與新版本的IE瀏覽器中看到實際可產生的效果,能夠經過設置 HTTP 的 Header頭來關閉瀏覽器自動阻攔與過濾XSS功能。
app.get('index.html', function (req, res) { res.set('X-XSS-Protection', 0); //此處是關鍵 res.send(req.query.name); });
注入型攻擊常見的地方就是留言評論或者是含有表單提交的地方。
例以下面咱們就以要給留言評論爲例子來講明注入型攻擊:
首先,攻擊者向一個textarea輸入如下內容:
<script>alert(document.cookie)</script>
而後,前端調用 ajax
向後端傳值
$('.send').click(function(){ $.post('message.htm',{'msg':$('textarea').val()},function(){}); });
接着,後端接收值寫入數據庫,同時又返回給前端展現。
app.post('message.htm',function(req,res,next){ //寫入數據庫 //... //響應前端 res.json({ test: req.body.msg }) });
最終當前端原樣展現以前輸入的攻擊代碼時,頁面便發生了存儲型攻擊。
不管是反射型攻擊仍是存儲型,攻擊者總須要找到兩個要點,即「輸入點」與"輸出點",也只有這二者都知足,XSS攻擊纔會生效。「輸入點」用於向 web頁面注入所需的攻擊代碼,而「輸出點」就是攻擊代碼被執行的地方。
大體上,攻擊者進行XSS攻擊要通過如下幾個步驟:
首先是分析程序尋找漏洞,而後構建攻擊代碼,好比上面做爲留言內容的 script
標籤,實際上能夠執行前端JS代碼,遠程加載JS腳本CSS樣式文件的 HTML標籤也很是多,好比:
#當圖片不存在時,必然觸發 onerror事件 <img src="null" onerror='alert(document.cookie)' /> #加載遠程CSS文件,破壞當前頁面的樣式 <link href="test.css"> #點擊的時候 <a onclick="alert(document.cookie)" onmouseover onmouseout></a> #鼠標移動的時候 <div onmouseover=‘do something here’> #破壞頁面樣式 <style>*{font-size:100px}</style> #利用IE7-的 css expression表達式的行爲。 <div style="width:expression(alert('XSS'))">
當代碼注入成功後,攻擊者每每就須要去尋找所注入代碼的輸出點,例如百度網盤以前就有一個修改暱稱的 XSS漏洞,雖然前端設置了字符長度爲10個字符,可是攻擊者經過使用抓包工具構建了一個 的執行腳本,併成功的注入到了數據庫,後面測試發現,最終攻擊的輸出位置處於用戶分享資源給其它好友時,展開好友列表的時刻。
實際上簡單的經過正則判斷 script、link、style、img 等HTML標記並不可取,由於,首先輸入點的狀況變化多樣,很難把全部的 html標記的特性都考慮進來,其次對html標記的限制,也會讓產品的可用性大大下降(好比有些特殊的關鍵字會被程序阻止,使得用戶使用很是不便),最後這種判斷自己也不安全,好比攻擊者會在關鍵字中插入空格、製表符以及其它HTML實體編碼來躲避偵測。
既然咱們前面說到攻擊必須有兩個要點:「輸入點」,「輸出點」,因此防護的時候,咱們只要作好這兩個點的控制,就基本上能夠萬無一失!
document.cookie
讀取 cookie,此 HTTP頭由服務端設置。JSON.parse()
方法。就目前而言,應對XSS攻擊的主要手段仍是編碼與過濾兩種,編碼用於將特殊的符號 "<、>、&、'、""進行轉義,而過濾則是阻止特定的標記、屬性、事件。
若是你不肯意爲了嚴格的安全而限制產品自己的靈活,那麼我更建議採用「編碼」的方案。
首先看下京東的搜索功能:
接着,再看下知乎提交評論時接口的數據:
最後,咱們再看下知乎時如何展現提交後的評論:
實際上實現上述的編碼功能很是簡單,咱們能夠對照 HTML實體編碼表 來進行正則匹配替換。
function encode(str) { if (!str || str.length === 0) return ''; str = str.replace(/>/gm, '>'); str = str.replace(/</gm, '<'); str = str.replace(/"/gm, '"'); str = str.replace(/'/gm, '''); return str; }
固然在實際應用中很難避免本身寫的匹配規則就能萬無一失,而且XSS攻擊又一直是在變化的過程當中,所以我的更推薦使用第三方專門防護XSS攻擊的庫。
前面都是針對輸入點的防護說明,在輸出的狀況下,前端開發人員應當要對本身採用的輸出方法與輸出方式要有必定的瞭解:
原生JS中
方法 | 說明 |
---|---|
innerHTML | 安全,可是IE8下危險(IE8支持可見的含有defers屬性的script標記,例如:_) |
appendChild, insertBefored等 | 危險 |
innerText | 安全 |
Jquery中
方法 | 說明 |
---|---|
html() | 危險 |
before,after,append等 | 危險 |
text() | 安全 |
EJS模版
輸出格式 | 說明 |
---|---|
<%= > | 危險,非轉義的HTML輸出 |
<%- > | 安全,轉義的HTML輸出 |
首先咱們瞭解了 XSS的定義,XSS即跨站點腳本攻擊,只要瀏覽器加載,解析,執行了意料以外的JS,CSS等均可以被認爲是受到了 XSS攻擊,而 XSS攻擊的分類主要有「反射型」與「存儲型」兩種。
「反射型」攻擊者經過包裝改造URL參數,而後利用前端代碼的缺陷或漏洞來攻擊,它更偏向與前端層面,而且在實際攻擊中攻擊者會根據 HTML實體編碼、URL編碼、uniocde編碼等進行編碼而後欺騙用戶點擊訪問。而「存儲型」攻擊者則會經過抓包工具或者是直接調用接口的方式想盡一切辦法來向後端數據庫注入數據。
XSS攻擊有兩個要點,一個是「輸入點」,針對輸入點咱們能夠對關鍵的特殊的字符進行編碼,而在「輸出點」咱們要對本身採用的輸出方式以及方法要有必定的安全風險認知。
https://www.owasp.org/index.php/DOM_based_XSS_Prevention_Cheat_Sheet (查看更多XSS攻擊案例)