攻擊者利用網站漏洞把惡意的腳本代碼(一般包括HTML代碼和JavaScript腳本)注入到網頁中,當其餘用戶瀏覽這些網頁時,就會執行其中的惡意代碼,對受害用戶可能採起cookie竊取、會話劫持、釣魚欺騙。javascript
發出請求時,XSS代碼出如今URL中,做爲輸入提交到服務器端,服務器解析後響應,XSS代碼隨響應內容一塊兒傳回瀏覽器,最後瀏覽器解析執行XSS代碼。這個過程像一次反射,故叫反射XSS。html
本例使用nodejs構建項目,演示反射型XSS攻擊。java
首先,咱們先建立一個目錄xssfilter
而且進入該目錄node
$ mkdir xssfilter
$ cd xssfilter
複製代碼
在該目錄繼續建立一個目錄xss
,用於建立咱們整個的XSS攻擊的模擬服務。web
$ mkdir xss
$ cd xss
複製代碼
使用express框架快速搭建整個的應用服務ajax
$ express -e ./
複製代碼
安裝一下全部的依賴數據庫
$ npm install
複製代碼
看一下目錄結構express
$ npm start
複製代碼
訪問localhost:3000
,看是否展現成功npm
接下來咱們就要開始反射型XSS的演示了json
xss:req.query.xss
複製代碼
咱們在此設置一個查詢的字段來獲取用戶在URL中寫的search內容
<div class="">
<%- xss%>
</div>
複製代碼
咱們在視圖層展現這個內容
接下來重啓一下,查看一下帶有值後展現的是啥樣的
由此,咱們發現,值已經展現。
接下來,咱們開始一些有攻擊性的腳本
xss=<img src="null" onerror="alert(1);"/>
複製代碼
打開頁面發現
這是由於Chrome會自動攔截XSS攻擊
咱們設置下不讓瀏覽器對XSS攔截
res.set('X-XSS-Protection',0);
複製代碼
重啓服務,打開瀏覽咱們會看到XSS攻擊成功
黑客會將一些攻擊腳本在網頁上經過引誘式點擊植入廣告、頁面篡改等,典型的好比
存儲型XSS與反射型XSS的差異僅在於,提交的代碼會存儲到服務器端(內存,數據庫,文件系統等),下次調用的時候就不須要再提交XSS代碼。
存儲型XSS只能讀取緩存或者數據庫了
對用戶輸入的數據進行HTML Entity編碼
將用戶輸入的不安全的內容給過濾掉
好比:
移除用戶上傳的DOM屬性,如onerror等
移除用戶上傳的Style節點、Script節點、Iframe節點等
避免直接對HTML Entity解碼
使用DOM Parse轉換,校訂不配對的DOM標籤
經過構建Node服務和創建一個評論功能,實例演示XSS的攻擊與預防。
如何構建Node服務我就不重複贅述了,在以前介紹反射型XSS中已經講過,這邊我依然使用這個服務來實戰。
var comments = {};
複製代碼
function html_encode(str){
var result = "";
if(str.length==0){
return "";
}
result = str.replace(/&/g,">");
result = result.replace(/</g,"<");
result = result.replace(/>/g,">");
result = result.replace(/\s/g," ");
result = result.replace(/\'/g,"'"); result = result.replace(/\"/g,"""); result = result.replace(/\n/g,"</br>"); return result; }; 複製代碼
router.get('/comment', function(req, res, next) {
comments.v = html_encode(req.query.comment);
})
複製代碼
router.get('/getComment', function(req, res, next) {
res.json({
comment:comments.v
})
})
複製代碼
<textarea name="name" rows="8" cols="80" id="text">
<p>sks<img src="null" alt="" onerror="alert(1)" /></p>
</textarea>
<button type="button" name="button" id="btn">評論</button>
<button type="button" name="button" id="get">獲取評論</button>
複製代碼
<textarea>
用於用戶輸入區域
<button>
用於提交評論和拉取評論信息
經過這樣,咱們就實現了一個模擬的XSS攻擊
var btn = document.getElementById("btn");
var get = document.getElementById("get");
var txt = document.getElementById("text");
複製代碼
btn.addEventListener("click",function(){
......
}
複製代碼
var xhr = new XMLHttpRequest();
複製代碼
var url = '/comment?comment='+txt.value;
複製代碼
由於是get請求
在客戶端向服務端發送以前,首先打開對象,告訴對象是以GET
方式打開
xhr.open('GET',url,true);
複製代碼
xhr.onreadystatechange = function(){
if(xhr.readyState==4){
if(xhr.status==200){
console.log(xhr);
}else{
console.log("error");
}
}
}
複製代碼
xhr.send();
複製代碼
get.addEventListener("click",function(){
......
}
複製代碼
var xhr = new XMLHttpRequest();
複製代碼
var url = '/getComment';
複製代碼
由於是get請求
在客戶端向服務端發送以前,首先打開對象,告訴對象是以GET
方式打開
xhr.open('GET',url,true);
複製代碼
導入js
<script src='/public/javascripts/encode.js'></script>
<script src='/public/javascripts/domParse.js'></script>
複製代碼
自行去第三方庫下載
定義一個函數
var prase = function(str){
var results = '';
try{
}catch(e){
//TODO handle the exception
}finally{
}
}
複製代碼
解碼
HTMLParse(he.unescape(str,{strict:true}),{});
複製代碼
he
是encode.js
提供的
unescape()
對輸入一種反轉義的過程
HTMLParse()
在反轉義的基礎上進行domParse,得到咱們能正常使用的結果
配對校驗
start:function(tag,attrs,unary){//tag:標籤;attrs:將屬性組成數組;unary:是不是單標籤
results += '<'+tag;
for(int i=0,len=attrs.length;i<len;i++){
results += " "+attrs[i].name+'="'+attrs[i].escaped+'"';
}
results += (unary?"/";"")+">";
},
end:function(tag){
results += "</"+tag+">";
},
chars:function(text){
results += text;
},
comment:function(text){//註釋
results += "<!--"+text+"-->"
}
複製代碼
查看一下完整代碼
<script type="text/javascript">
var prase = function(str){
var results = '';
try{
HTMLParse(he.unescape(str,{strict:true}),{
start:function(tag,attrs,unary){//tag:標籤;attrs:將屬性組成數組;unary:是不是單標籤
results += '<'+tag;
for(int i=0,len=attrs.length;i<len;i++){
results += " "+attrs[i].name+'="'+attrs[i].escaped+'"';
}
results += (unary?"/";"")+">";
},
end:function(tag){
results += "</"+tag+">";
},
chars:function(text){
results += text;
},
comment:function(text){//註釋
results += "<!--"+text+"-->"
}
});
return results;
}catch(e){
console.log(e);
}finally{
}
}
</script>
複製代碼
定義對象客戶端響應方式
xhr.onreadystatechange = function(){
if(xhr.readyState==4){
if(xhr.status==200){
var com = prase(JSON.parse(xhr.response).comment);
}else{
console.log("error");
}
}
}
複製代碼
xhr.send();
複製代碼
var info = document.createElement('span');
info.innerHTML(com);
document.body.appendChild(info);
複製代碼
重啓一下,打開瀏覽器
點擊評論,而後再點擊獲取評論,來模擬瀏覽器加載服務端評論內容的行爲
看下怎麼執行的
這邊有p
標籤、sks
文本、img
標籤,在img
標籤裏,有個src
屬性,爲null,看下控制檯,報錯:Failed to load resource
,所以觸發了onerror
屬性。
點擊評論,再點擊獲取評論
點擊攻擊我
這就是引誘式攻擊
到此,咱們發現,並無屏蔽掉XSS攻擊,那是由於咱們並無進行過濾
if(tag=='script'||tag=='style'||tag=='link'||tag=='iframe'||tag=='frame'){
return;
}
複製代碼
這個就是去過濾這些標籤
把以前的代碼刪掉,由於這段代碼就包含了那些含有XSS攻擊的腳本,從而保證咱們獲取信息的安全性,避免XSS腳本執行的空間。
for(int i=0,len=attrs.length;i<len;i++){
results += " "+attrs[i].name+'="'+attrs[i].escaped+'"';
}
複製代碼
打開瀏覽器,從新操做,發現已經成功攔截了XSS攻擊,看下控制檯,咱們發現img
標籤下的屬性被自動過濾掉了。