Web安全-XSS

Null指標發表於2018-11-27

XSS的定義

攻擊者利用網站漏洞把惡意的指令碼程式碼(通常包括HTML程式碼和JavaScript指令碼)注入到網頁中,當其他使用者瀏覽這些網頁時,就會執行其中的惡意程式碼,對受害使用者可能採取cookie竊取、會話劫持、釣魚欺騙。

XSS的攻擊方式

反射型

發出請求時,XSS程式碼出現在URL中,作為輸入提交到伺服器端,伺服器解析後響應,XSS程式碼隨響應內容一起傳回瀏覽器,最後瀏覽器解析執行XSS程式碼。這個過程像一次反射,故叫反射XSS。

舉例

本例使用nodejs構建專案,演示反射型XSS攻擊。

建立目錄

首先,我們先建立一個目錄xssfilter並且進入該目錄

$ mkdir xssfilter
$ cd xssfilter
複製程式碼

在該目錄繼續建立一個目錄xss,用於建立我們整個的XSS攻擊的模擬服務。

$ mkdir xss
$ cd xss
複製程式碼

image

搭建web專案

使用express框架快速搭建整個的應用服務

$ express -e ./
複製程式碼

image

依賴

安裝一下所有的依賴

$ npm install
複製程式碼

image

目錄結構

看一下目錄結構

image

啟動服務

$ npm start
複製程式碼

image

頁面

訪問localhost:3000,看是否展示成功

image

演示

接下來我們就要開始反射型XSS的演示了

js
xss:req.query.xss
複製程式碼

image

我們在此設定一個查詢的欄位來獲取使用者在URL中寫的search內容

檢視層
<div class="">
	<%- xss%>
</div>
複製程式碼

我們在檢視層展示這個內容

image

接下來重啟一下,檢視一下帶有值後展示的是啥樣的

image

由此,我們發現,值已經展示。

接下來,我們開始一些有攻擊性的指令碼

xss=<img src="null" onerror="alert(1);"/>
複製程式碼

開啟頁面發現

image

這是因為Chrome會自動攔截XSS攻擊

我們設定下不讓瀏覽器對XSS攔截

res.set('X-XSS-Protection',0);
複製程式碼

image

重啟服務,開啟瀏覽我們會看到XSS攻擊成功

image

黑客會將一些攻擊指令碼在網頁上通過引誘式點選植入廣告、頁面篡改等,典型的比如

儲存型

儲存型XSS與反射型XSS的差別僅在於,提交的程式碼會儲存到伺服器端(記憶體,資料庫,檔案系統等),下次呼叫的時候就不需要再提交XSS程式碼。

儲存型XSS只能讀取快取或者資料庫了

image

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,"&gt;");
	result = result.replace(/</g,"&lt;");
	result = result.replace(/>/g,"&gt;");
	result = result.replace(/\s/g,"&nbsp;");
	result = result.replace(/\'/g,"&#39;");
	result = result.replace(/\"/g,"&quot;");
	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
	})
})
複製程式碼

image

防範措施

ejs

<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>
複製程式碼

image

<textarea>用於使用者輸入區域

<button>用於提交評論和拉取評論資訊

通過這樣,我們就實現了一個模擬的XSS攻擊

js

獲取物件

var btn = document.getElementById("btn");
var get = document.getElementById("get");
var txt = document.getElementById("text");
複製程式碼

新增評論點選事件

btn.addEventListener("click",function(){
	......
}
複製程式碼
ajax請求
var xhr = new XMLHttpRequest();
複製程式碼
url
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();
複製程式碼

image

新增請求評論點選事件

get.addEventListener("click",function(){
	......
}
複製程式碼
ajax請求
var xhr = new XMLHttpRequest();
複製程式碼
url
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}),{});
    複製程式碼

    heencode.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>
    複製程式碼

    image

  • 定義物件客戶端響應方式

    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();
複製程式碼

過濾、校正

把獲取的com轉換成DOM節點
var info = document.createElement('span');
info.innerHTML(com);
document.body.appendChild(info);
複製程式碼

重啟一下,開啟瀏覽器

Web安全-XSS

點選評論,然後再點選獲取評論,來模擬瀏覽器載入服務端評論內容的行為

image.png

看下怎麼執行的

這邊有p標籤、sks文字、img標籤,在img標籤裡,有個src屬性,為null,看下控制檯,報錯:Failed to load resource,因此觸發了onerror屬性。

image.png

引誘式攻擊

image.png

點選評論,再點選獲取評論

image.png

點選攻擊我

image.png

這就是引誘式攻擊

到此,我們發現,並沒有遮蔽掉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標籤下的屬性被自動過濾掉了。

image.png

相關文章