XSS攻擊基礎講解及預防攻略

XSS攻擊

XSS介紹

XSS攻擊一般指的是經過利用網頁開發時留下的漏洞,經過巧妙的方法注入惡意指令代碼到網頁,使用戶加載並執行攻擊者惡意製造的網頁程序。這些惡意網頁程序一般是JavaScript,但實際上也能夠包括Java、 VBScript、ActiveX、 Flash 或者甚至是普通的HTML。攻擊成功後,攻擊者可能獲得包括但不限於更高的權限(如執行一些操做)、私密網頁內容、會話和cookie等各類內容。(內容摘自百度百科)javascript

xss攻擊類型可分爲兩種,反射型存儲型,顧名思義一種是保存進了數據庫,另外一種是在url中直接觸發,沒保存進數據庫,下面一一介紹。html

反射型

url參數直接注入前端

場景說明:在網站的搜索框內直接輸入攻擊腳本java

// 搜索框搜索
http://localhost/?keyWord=<script>alert(111)</script>
複製代碼

存儲型

存儲到DB後讀取時注入git

場景說明:攻擊腳本做爲留言內容,提交給後臺保存,刷新頁面後端返回攻擊腳本給前端github

// 留言板插入數據庫
留言測試<script>alert(222)</script>//留言內容 複製代碼
  • HTML節點內容

攻擊腳本經過接口存入數據庫中,當頁面刷新時,插入的腳本替換頁面HTML節點內容,腳本隨即執行,引起漏洞攻擊正則表達式

<!-- content變量被攻擊腳本替換 -->
<div>
    {{content}}
</div>
<div>
    <script>
    </script>
</div>

複製代碼
  • HTML屬性

經過修改或者添加HTML屬性,觸發攻擊事件數據庫

<!-- 圖片地址異常後,引起錯誤事件 -->
<img src="#{image}"/>
<img src=" 1"onerror="alert(1)" />
複製代碼
  • JavaScript代碼

經過獲取用戶輸入的變量或者其餘保存的變量,在腳本中打印後端

<script>
    var data = params;
    console.log(data)
    // 輸入內容
    params = "hello":alert(1)
</script>
複製代碼
  • 富文本

富文本須要保留HTML
HTML有XSS攻擊風險瀏覽器

處理方法

總體思路:轉義

轉義時機:

  1. 存入數據庫時轉義
  2. 返回給前端時轉義

轉義方式更傾向於第一種:由於輸入是一次性性能消費,而輸出會是屢次,形成性能浪費,本文的示例代碼內容因爲我的編譯、演示方便緣由是採用第二種方式-返回時轉義,請各位讀者知曉

HTML節點內容

處理思路:轉義< >,使之不能以html標籤的形式保存或者返回給前端

//轉義函數
var escapeHtml = function(str){
    str = str.replace(/</g,'&lt;');
    str = str.replace(/>/g,'&gt;')
    return str
}
複製代碼
// 轉義前
<script>alert(111)</script>
// 轉移後
&lt;script&gt;alert(111)&lt;/script&gt;
// 頁面dom呈現
<script>alert(111)</script>//字符串類型
              ||
<span><script>alert(111)</script></span>
複製代碼

HTML屬性

處理思路:轉義"引號,使標籤內屬性不能自閉合,引發觸發事件

// 轉義函數
var escapeHtmlProperty = function(str){
    if(!str)return '';
    str = str.replace(/"/g,'&quto;');//替換雙引號
    str = str.replace(/'/g,'&#39;');//替換單引號
    str = str.replace(/ /g,'&#32;');//替換空格
    return str;
}
複製代碼
// 轉義前
<img src=" 1"onerror="alert(1)" />
// 轉義後
<img src="1&quto; onerror=&quto;alert(1)" />
// 頁面dom呈現
<img src="1&quto; onerror=&quto;alert(1)" />
複製代碼

那麼問題來了,轉義了HTML屬性中的大於號、小於號,會對元素產生其餘影響嗎?轉義了HTML節點內容中的單引號、雙引號、空格,會對元素產生其餘影響嗎?
答案是不會產生影響的,讀者能夠自行驗證。
此時能夠合併上面的兩個函數,總體處理HTML節點和屬性,合併函數以下:

// 轉義函數
var escapeHtml = function(str){
    str = str.replace(/&/g,'&amp;');//&符號也須要轉義,可是必定放在第一個轉
    str = str.replace(/</g,'&lt;');
    str = str.replace(/>/g,'&gt;')
    str = str.replace(/"/g,'&quto;');//替換雙引號
    str = str.replace(/'/g,'&#39;');//替換單引號
    // 空格的轉義影響其實並不大,能夠省略
    // str = str.replace(/ /g,'&#32;');//替換空格 
    return str
}

複製代碼

JavaScript代碼

處理思路:轉義雙引號或者JSON_encode

//轉義函數
var escapeForJs =function(str){
	if(!str)return '';
	str = str.replace(/"/g,'\\"');//js中雙引號的轉義和HTML中不一樣,不能使用HTML轉義方法
	return str;
}
複製代碼
原函數:
<script>
var str = "!{keyWord}";
console.log(str)
</script>

//hello world";alert(1);"
//轉義前
<script> hello world alert(1)已經被彈出 </script>

//轉義後
hello world";alert(1);"
複製代碼

然而這樣就安全了嗎?
答案確定不是!
單引號、script標籤、雙引號、空格...均可以引起攻擊,更爲安全的方式-JSON_encode轉義

JavaScript代碼_JSON_encode轉義

JSON_encode轉義-JSON.stringify
演示代碼:

// 轉義函數
JSON.stringify(參數)
複製代碼
//轉義前
hello world";alert(1);"
//轉義後
hello world";alert(1);"
複製代碼

富文本

處理思路:過濾

  1. 黑名單過濾

好比 script標籤、onerror標籤...所有過濾掉

  • 利:實現簡單-正則表達式就可處理
  • 弊:HTML標籤過於龐雜,不免會留有漏洞
  1. 白名單過濾

按照白名單過濾保留部分標籤和屬性,只容許保留名單內的標籤、屬性

  • 利:比較完全,只容許指定的標籤、屬性存在
  • 弊:實現起來相對麻煩,將HTML徹底解析成數據結構,再對數據結構過濾,再組裝成HTML

黑名單過濾:

示例攻擊代碼:

<!-- 可能輸入的攻擊腳本 -->
<font color=\"red\">這是紅色字</font><script>alert('富文本')</script>
<a href=\"javascript:alert(1)\"></a>
<img src=\"abc\" onerror=\"alert(1)\">
..onfocus,
..onmounseover,
..onmenucontext,
...
複製代碼
//過濾函數
var xssFilter = function (html) {
	if (!html) return '';
	html = html.replace(/<\s*\/?script\s*>/g,'');
	html = html.replace(/javascript:[^'"]*/g,'');
	html = html.replace(/onerror\s*=\s*['"]?[^'"]*['"]?/g,'');
    ...
	return html
}
複製代碼

HTML中帶有事件觸發的都有可能成爲攻擊的突破口,面對這種狀況,怎麼防護呢?下面介紹白名單過濾。

白名單過濾:

處理思路:整理富文本中全部的標籤屬性,過濾只容許這些屬性經過,其餘屬性則不容許經過
處理方式:將HTML解析成樹狀結構,和瀏覽器解析HTML過程相似,再去遍歷樹狀結構元素,在過濾範圍內的容許經過,沒在過濾範圍內的,則去掉

示例攻擊代碼:

//可能輸入的攻擊腳本
<font color=\"red\">這是紅色字</font><script>alert('富文本')</script>
<a href=\"javascript:alert(1)\"></a>
<img src=\"abc\" onerror=\"alert(1)\">
..onfocus,
..onmounseover,
..onmenucontext,
...
複製代碼
//過濾代碼
var xssFilter = function (html) {
	if (!html) return '';
	//白名單 
	var whiteList = {
		'img': ['src'],
		'font':['color','size'],
		'a':['href']
	};
	var cheerio = require('cheerio');
	var $ = cheerio.load(html);
	$('*').each(function (index, elem) {
		if (!whiteList[elem.name]) {
			$(elem).remove();
			return;
		}
		for (var attr in elem.attribs) {
			if (whiteList[elem.name].indexOf(attr) === -1) {
				$(elem).attr(attr, null);
			}
		}
	})
	return $.html()
}
複製代碼

cheerio介紹

cheerio是爲服務器特別定製的,快速、靈活、實施的以jQuery爲核心實現的對DOM操做方案

//基礎用法
const cheerio = require('cheerio');
const $ = cheerio.load('<h2 class="title">Hello world</h2>');

$('h2.title').text('Hello there!');
$('h2').addClass('welcome');

$.html();
//=> <html><head></head><body><h2 class="title welcome">Hello there!</h2></body></html>

複製代碼

安裝方式、語法等此處不過多介紹,須要的讀者請跳轉官網閱讀
代碼中主要使用它把HTML結構轉換成可直接使用的數據結構,再循環去比較、移除。
那有沒有現有的可直接使用的第三方框架嗎?答案是確定的

js-XSS

xss是一個用於對用戶輸入的內容進行過濾,以免遭受 XSS 攻擊的模塊。主要用於論壇、博客、網上商店等等一些可容許用戶錄入頁面排版、格式控制相關的 HTML 的場景,xss模塊經過白名單來控制容許的標籤及相關的標籤屬性,另外還提供了一系列的接口以便用戶擴展,比其餘同類模塊更爲靈活中文官網地址
示例代碼:

//過濾函數
var xssFilter = function (html) {
	if (!html) return '';
	var xss = require('xss');
	var ret = xss(html);
	return ret;
}
複製代碼

就是如此的簡單,固然還須要調整,此處就不過多介紹了,下面介紹下xss模塊的特性及基本使用方法。

特性

  • 白名單控制容許的 HTML 標籤及各標籤的屬性
  • 經過自定義處理函數,可對任意標籤及其屬性進行處理

使用方法:

Node.js中使用

var xss = require("xss");
var html = xss('<script>alert("xss");</script>');
console.log(html);
複製代碼

在瀏覽器端使用

<script src="https://rawgit.com/leizongmin/js-xss/master/dist/xss.js"></script>
<script> // 使用函數名 filterXSS,用法同樣 var html = filterXSS('<script>alert("xss");</scr' + 'ipt>'); alert(html); </script> 複製代碼

其餘使用模式及用法請參考官網案例

若是須要簡單、快速、安全的開發選用第三方的庫固然更好,可是使用過程可能會有這樣或者那樣的問題,達不到業務的要求等等,相較於第三方的庫本身設置白名單去處理的話,就更容易控制、定製化效果明顯,相對問題可能會更少,仁者見仁智者見智,讀者根據實際狀況可自行選擇。

CSP

內容安全策略 (CSP) 是一個額外的安全層,用於檢測並削弱某些特定類型的攻擊,包括跨站腳本 (XSS) 和數據注入攻擊等。不管是數據盜取、網站內容污染仍是散發惡意軟件,這些攻擊都是主要的手段。

  • Content Security Policy
  • 內容安全策略
  • 用於指定那些內容可執行

使用方法:

配置內容安全策略涉及到添加 Content-Security-Policy HTTP頭部到一個頁面,並配置相應的值,以控制用戶代理(瀏覽器等)能夠爲該頁面獲取哪些資源。

常見用例:

示例1

一個網站管理者想要全部內容均來自站點的同一個源 (不包括其子域名)

Content-Security-Policy: default-src 'self'
複製代碼

示例2

一個在線郵箱的管理者想要容許在郵件裏包含HTML,一樣圖片容許從任何地方加載,但不容許JavaScript或者其餘潛在的危險內容(從任意位置加載)。

Content-Security-Policy: default-src 'self' *.mailsite.com; img-src *
複製代碼

更多示例及用法請參考MDN-CSP

結語

安全做爲系統的壁壘,重要程度不用多說。 XSS攻擊更是安全防護的重中之中。 本文記錄的是筆者在開發過程當中遇到的問題及處理的思路。可供有相似問題的讀者參考。 其餘安全方面的文章筆者會持續更新,歡迎各位讀者提出意見和建議。

相關文章
相關標籤/搜索