用于安全測(cè)試的站點(diǎn)間腳本攻擊(XSS)
前言
隨著互聯(lián)網(wǎng)的不斷發(fā)展,web應(yīng)用程序的交互也越來(lái)越強(qiáng)。
但正如一個(gè)硬幣會(huì)有兩面一樣,在用戶(hù)體驗(yàn)提升的同時(shí)安全風(fēng)險(xiǎn)也會(huì)跟著有所增加。今天,我們就來(lái)講一講web滲透中常見(jiàn)的一種攻擊方式:XSS攻擊。(一)什么是XSS攻擊
先上一段標(biāo)準(zhǔn)解釋?zhuān)ㄕ园俣劝倏疲?/p>
“XSS是跨站腳本攻擊(Cross Site Scripting),為不和層疊樣式表(Cascading Style Sheets, CSS)的縮寫(xiě)混淆,故將跨站腳本攻擊縮寫(xiě)為XSS。惡意攻擊者往Web頁(yè)面里插入惡意Script代碼,當(dāng)用戶(hù)瀏覽該頁(yè)之時(shí),嵌入其中Web里面的Script代碼會(huì)被執(zhí)行,從而達(dá)到惡意攻擊用戶(hù)的目的?!?/p>
相信以上的解釋也不難理解,但為了再具體些,這里舉一個(gè)簡(jiǎn)單的例子,就是留言板。我們知道留言板通常的任務(wù)就是把用戶(hù)留言的內(nèi)容展示出來(lái)。正常情況下,用戶(hù)的留言都是正常的語(yǔ)言文字,留言板顯示的內(nèi)容也就沒(méi)毛病。然而這個(gè)時(shí)候如果有人不按套路出牌,在留言?xún)?nèi)容中丟進(jìn)去一行
<script>alert(“hey!you are attacked”)</script>
那么留言板界面的網(wǎng)頁(yè)代碼就會(huì)變成形如以下:
<html>
<head>
<title>留言板</title>
</head>
<body>
<div id=”board”
<script>alert(“hey!you are attacked”)</script>
</div>
</body>
</html>
那么這個(gè)時(shí)候問(wèn)題就來(lái)了,當(dāng)瀏覽器解析到用戶(hù)輸入的代碼那一行時(shí)會(huì)發(fā)生什么呢?答案很顯然,瀏覽器并不知道這些代碼改變了原本程序的意圖,會(huì)照做彈出一個(gè)信息框。就像這樣。
(二)XSS的危害
其實(shí)歸根結(jié)底,XSS的攻擊方式就是想辦法“教唆”用戶(hù)的瀏覽器去執(zhí)行一些這個(gè)網(wǎng)頁(yè)中原本不存在的前端代碼。
可問(wèn)題在于盡管一個(gè)信息框突然彈出來(lái)并不怎么友好,但也不至于會(huì)造成什么真實(shí)傷害啊。的確如此,但要說(shuō)明的是,這里拿信息框說(shuō)事僅僅是為了舉個(gè)栗子,真正的黑客攻擊在XSS中除非惡作劇,不然是不會(huì)在惡意植入代碼中寫(xiě)上alert(“say something”)的。
在真正的應(yīng)用中,XSS攻擊可以干的事情還有很多,這里舉兩個(gè)例子。
· 竊取網(wǎng)頁(yè)瀏覽中的cookie值
在頁(yè)瀏覽中我們常常涉及到用戶(hù)登錄,登錄完畢之后服務(wù)端會(huì)返回一個(gè)cookie值。這個(gè)cookie值相當(dāng)于一個(gè)令牌,拿著這張令牌就等同于證明了你是某個(gè)用戶(hù)。
如果你的cookie值被竊取,那么攻擊者很可能能夠直接利用你的這張令牌不用密碼就登錄你的賬戶(hù)。如果想要通過(guò)script腳本獲得當(dāng)前頁(yè)面的cookie值,通常會(huì)用到document.cookie。
試想下如果像空間說(shuō)說(shuō)中能夠?qū)懭離ss攻擊語(yǔ)句,那豈不是看了你說(shuō)說(shuō)的人的號(hào)你都可以登錄(不過(guò)某些廠商的cookie有其他驗(yàn)證措施如:Http-Only保證同一cookie不能被濫用)
· 劫持流現(xiàn)惡意跳轉(zhuǎn)
這個(gè)很簡(jiǎn)單,是在網(wǎng)頁(yè)中想辦法插入一句像這樣的語(yǔ)句:
<script>window.loca;;;</script>
那么所訪問(wèn)的網(wǎng)站就會(huì)被跳轉(zhuǎn)到百度的首頁(yè)。
早在2011年新浪就曾爆出過(guò)嚴(yán)重的xss漏洞,導(dǎo)致大量用戶(hù)自動(dòng)關(guān)注某個(gè)微博號(hào)并自動(dòng)轉(zhuǎn)發(fā)某條微博。具體各位可以自行百度。
利用與繞過(guò)
那xss漏洞很容易被利用嗎?那倒也未必。
畢竟在實(shí)際應(yīng)用中web程序往往會(huì)通過(guò)一些過(guò)濾規(guī)則來(lái)組織代有惡意代碼的用戶(hù)輸入被顯示。
不過(guò),這里還是可以給大家總結(jié)一些常用的xss攻擊繞過(guò)過(guò)濾的一些方法,算是拋磚引玉。(以下的繞過(guò)方式皆通過(guò)滲透測(cè)試平臺(tái)Web For Pentester 演示)
· 大小寫(xiě)繞過(guò)
這個(gè)繞過(guò)方式的現(xiàn)是因?yàn)榫W(wǎng)站僅僅只過(guò)濾了<script>標(biāo)簽,而沒(méi)有考慮標(biāo)簽中的大小寫(xiě)并不影響瀏覽器的解釋所致。具體的方式就像這樣:
利用語(yǔ)句:h
;sCript>alert("hey!")</scRipt>
· 利用過(guò)濾后返回語(yǔ)句再次構(gòu)成攻擊語(yǔ)句來(lái)繞過(guò)
這個(gè)字面上不是很好解,用實(shí)例來(lái)說(shuō)。
如下圖,在這個(gè)例子中我們直接敲入script標(biāo)簽發(fā)現(xiàn)返回的網(wǎng)頁(yè)代碼中script標(biāo)簽被去除了,但其余的內(nèi)容并沒(méi)有改變。
于是我們就可以為
制造一種巧合,讓過(guò)濾完script標(biāo)簽后的語(yǔ)句中還有script標(biāo)簽(畢竟alert函數(shù)還在),像這樣: ;sCri<script>pt>alert("hey!")</scRi</script>pt>
發(fā)現(xiàn)問(wèn)題了吧,這個(gè)利用原理在于只過(guò)濾了一個(gè)script標(biāo)簽。
· 并不是只有script標(biāo)簽才可以插入代碼
在這個(gè)例子中,我們嘗試前面兩種方法都沒(méi)能成功,原因在于script標(biāo)簽已經(jīng)被完全過(guò)濾,但不要方,能植入腳本代碼的不止script標(biāo)簽。
例如這里我們用<img>標(biāo)簽做一個(gè)示范。
我們利用如下方式:
;imgsrc='w.123' onerror='alert("hey!")'>
就可以再次愉快的彈窗。原因很簡(jiǎn)單,我們指定的圖片地址根本不存在也就是一定會(huì)發(fā)生錯(cuò)誤,這時(shí)候onerror里面的代碼自然就得到了執(zhí)行。
以下列舉幾個(gè)常用的可插入代碼的標(biāo)簽。
<a onmousemove=’do something here’>
當(dāng)用戶(hù)鼠標(biāo)移動(dòng)時(shí)即可運(yùn)行代碼
<div onmouseover=‘do something here’>
當(dāng)用戶(hù)鼠標(biāo)在這個(gè)塊上面時(shí)即可運(yùn)行(可以配合weight等參數(shù)將div覆蓋頁(yè)面,鼠標(biāo)不劃過(guò)都不行)
類(lèi)似的還有onclick,這個(gè)要點(diǎn)擊后才能運(yùn)行代碼,條件相對(duì)苛刻,就不再詳述。
· 編碼腳本代碼繞過(guò)關(guān)鍵字過(guò)濾
有的時(shí)候,服務(wù)器往往會(huì)對(duì)碼中的關(guān)鍵字(如alert)進(jìn)行過(guò)濾,這個(gè)時(shí)候我們可以嘗試將關(guān)鍵字進(jìn)行編碼后再插入,不過(guò)直接顯示編碼是不能被瀏覽器執(zhí)行的,我們可以用另一個(gè)語(yǔ)句eval()來(lái)實(shí)現(xiàn)。eval()會(huì)將編碼過(guò)的語(yǔ)句解碼后再執(zhí)行,簡(jiǎn)直太貼心了。
例如alert(1)編碼過(guò)后就是
\u0061\u006c\u0065\u0072\u0074(1)
所以構(gòu)建出來(lái)的攻擊語(yǔ)句如下:
;script>eval(\u0061\u006c\u0065\u0072\u0074(1))</script>
· 主動(dòng)閉合標(biāo)簽實(shí)現(xiàn)注入代碼
來(lái)看這份代碼:
乍一看哇!自帶scri
標(biāo)再一看,WTF!填入的內(nèi)容被放在了變量里! 這個(gè)時(shí)候就要我們手動(dòng)閉合掉兩個(gè)雙引號(hào)來(lái)實(shí)現(xiàn)攻擊,別忘了,javascript是一個(gè)弱類(lèi)型的編程語(yǔ)言,變量的類(lèi)型往往并沒(méi)有明確定義。 思路有了,接下來(lái)要做的就簡(jiǎn)單了,利用語(yǔ)句如下: ;;alert("I amcoming again~");"
效果如圖。
回看以下注入完代碼的網(wǎng)頁(yè)代碼,
一直都在制造巧合。。
先是閉合引號(hào),然后分號(hào)換行,加入代,
· 閉合一個(gè)引號(hào),搞定! 組合各種方式
在實(shí)際運(yùn)用中漏洞的利用可能不會(huì)這么直觀,需我們不斷的嘗試,甚至組合各種繞過(guò)方式來(lái)達(dá)到目的。
介紹完一些常用的繞過(guò)方式,再倒回來(lái)講一下XSS分類(lèi),因?yàn)橄旅嬷v具體的應(yīng)用時(shí)會(huì)用到。
(三)XSS分類(lèi):
我們一般把xss分為三類(lèi):反射型xss,存儲(chǔ)型xss,DOM型xss
00001. 反射型xss
反射型xss又被稱(chēng)為非持久型xss。當(dāng)用戶(hù)訪問(wèn)一個(gè)帶有xss攻擊代碼的url請(qǐng)求的時(shí)候,向服務(wù)器發(fā)送請(qǐng)求,服務(wù)器接受請(qǐng)求后處理,并把客戶(hù)端發(fā)送的xss攻擊代碼返回給客戶(hù)端,客戶(hù)端解析這段代碼的時(shí)候,就有可能遭受xss攻擊。
下面是一個(gè)典型的反射型xss攻擊示例:
· 用戶(hù)瀏覽某個(gè)網(wǎng)站A,攻擊者在這個(gè)網(wǎng)站中嵌入了惡意的腳本用于盜取用戶(hù)的cookie等信息攻擊者誘導(dǎo)用戶(hù)觸發(fā)xss攻擊(比如誘導(dǎo)用戶(hù)點(diǎn)擊非法鏈接),當(dāng)用戶(hù)觸發(fā)了xss攻擊的時(shí)候就會(huì)將自己的用戶(hù)信息發(fā)送給攻擊者攻擊者在獲取用戶(hù)的cookie后,就有可能盜用用戶(hù)的身份信息進(jìn)行非法操作
2. 存儲(chǔ)型xss
存儲(chǔ)型xss又被稱(chēng)為持久化的xss,也是最危險(xiǎn)的xss攻擊方式。一旦攻擊成功,就有可能造成大規(guī)模的xss攻擊,也就是我們通常所說(shuō)的xss蠕蟲(chóng)。
存儲(chǔ)型xss攻擊的一般原理是,客戶(hù)端將帶有xss攻擊的數(shù)據(jù)發(fā)送給服務(wù)器,服務(wù)器接收并存儲(chǔ)在數(shù)據(jù)庫(kù)。當(dāng)用戶(hù)下次再訪問(wèn)這個(gè)頁(yè)面的時(shí)候,服務(wù)器會(huì)讀取數(shù)據(jù)庫(kù)并將之前的xss代碼取出發(fā)送給瀏覽器。瀏覽器解析這段數(shù)據(jù)的時(shí)候,就會(huì)遭受xss攻擊。
所以,反射型xss攻擊一般需要用戶(hù)手動(dòng)觸發(fā),而存儲(chǔ)型xss攻擊卻是能夠自動(dòng)觸發(fā)的。一般來(lái)說(shuō),反射型xss攻擊的危害要比存儲(chǔ)型xss攻擊的危害要小的多。
3. DOM型xss
我們可以通過(guò)JavaScript來(lái)操作dom樹(shù),所以,xss攻擊也是能夠做到這一點(diǎn)的。dom型xss攻擊最大的危害就是改變我們網(wǎng)頁(yè)的布局。這種類(lèi)型的xss是不需要和服務(wù)器進(jìn)行交互的,只發(fā)生在客戶(hù)端處理階段。比如一段xss攻擊的代碼是:
const div = document.createElement('div')
div.innerText = 'xss攻擊的代碼'
document.body.appendChild(div)
(四)xss攻擊點(diǎn)
知道了xss的基本類(lèi)型后我們就要了解xss的攻擊點(diǎn)一般在哪里?可以這樣說(shuō),有輸入和輸出的地方就有可能遭受xss攻擊。所以,我們一定要對(duì)客戶(hù)端的輸入和服務(wù)端的輸出做嚴(yán)格的校驗(yàn),但是這種校驗(yàn)往往是比較復(fù)雜的,因?yàn)閤ss攻擊的變法太多太多了。下面幾個(gè)點(diǎn)是需要我們格外注意的。
· html節(jié)點(diǎn)的內(nèi)容:如果一個(gè)節(jié)點(diǎn)的內(nèi)容是動(dòng)態(tài)生成的,里面包含了用戶(hù)的輸入信息就有可能遭受xss攻擊。
<div>
#{content}
</div>
上面的content有可能會(huì)攜帶xss攻擊,比如:
<div>
<script>alert(123)</script>
</div>
· html屬性:某個(gè)節(jié)點(diǎn)的屬性是通過(guò)用戶(hù)的輸入生成的,那這些輸入就有可能包含xss攻擊的代碼。
<img src="#{src}" />
src的內(nèi)容可能是:
#" onerror="alert(123)
會(huì)造成html的內(nèi)容如下:
<img src="#" onerror="alert(123)" />
· javascript代碼:JavaScript代碼中存在后臺(tái)注入的變量,或者包含用戶(hù)輸入的信息
const content = '#{content}'
content的內(nèi)容可能是:';alert(123);'
· 富文本:富文本一般是需要保留html的。這些html就有可能造成xss攻擊。
實(shí)例應(yīng)用:
1、劫持訪問(wèn)
劫持訪問(wèn)就是在惡意腳本中插入諸如的代碼,那么頁(yè)面就會(huì)跳轉(zhuǎn)到百度首頁(yè)。
劫持訪問(wèn)在持久型和非持久型XSS中都比較常被利用。持久型XSS中劫持訪問(wèn)的危害不用說(shuō)大家都清楚,但有人會(huì)問(wèn)非持久型XSS中劫持訪問(wèn)有什么作用呢?
很簡(jiǎn)單,試想下像,這樣的域名下出現(xiàn)非持久型XSS,那么在發(fā)送釣魚(yú)鏈接時(shí)就可以通過(guò)等域名進(jìn)行跳轉(zhuǎn),一般人一看到之類(lèi)的域名警惕性會(huì)下降,也就更容易上當(dāng)了。
2、盜用cookie實(shí)現(xiàn)無(wú)密碼登錄
具體原理上文已經(jīng)提到,這里做一個(gè)具體演示。由于盜取的cookie需要傳回給攻擊者,因此往往需要一個(gè)服務(wù)器來(lái)接收盜取的cookie,這也就是xss平臺(tái)的作用了。網(wǎng)上的xss平臺(tái)很多,但動(dòng)手搭建一個(gè)也不難,建議有條件的自己搭建。
首先登錄平臺(tái)后臺(tái)獲取到j(luò)s腳本地址為,所以我們需要做的是把這段代碼植入指定頁(yè)面。
(這里以DVWA滲透測(cè)試平臺(tái)為例)
我們發(fā)現(xiàn)網(wǎng)頁(yè)對(duì)于message長(zhǎng)度有限制
素看一下。
發(fā)現(xiàn)最大長(zhǎng)度有限制,但這僅僅是前端的限制,直雙
修改成更大的數(shù)字即可。再次嘗試,沒(méi)問(wèn)題,我們已經(jīng)將腳本植入完畢。
然后就是坐等別的用戶(hù)訪問(wèn)這個(gè)界面。 這時(shí),另一用
gordonb登錄并訪問(wèn)了留言界面,那么他的cookie就會(huì)被竊取。我們可以從xss平臺(tái)的后臺(tái)獲取到。
拿到cookie之后要登錄他的帳號(hào)就好辦了。 打開(kāi)
界面,調(diào)出火狐的firebug插件,調(diào)至cookie選項(xiàng)卡(注意,如果你的firebug插件沒(méi)有cookie選項(xiàng)卡,請(qǐng)?jiān)侔惭bfirecookie插件即可看到)
然后依次點(diǎn)擊cookies-create cookie,隨后再?gòu)棾龅慕缑嬷刑钊雰蓚€(gè)xss平臺(tái)獲取到的cookie,如圖
這里注意要把我箭頭所指的地方勾上,這是設(shè)置cooki
的地方,不然會(huì)在設(shè)置完下一秒cookie就失效。
完成之后再次刷新頁(yè)面,發(fā)現(xiàn)已經(jīng)不是之前的登錄界面了,而是錄
的界面。至此,一個(gè)從cookie竊取到利用的過(guò)程就已完成。
3、配合csrf攻擊完成惡意請(qǐng)求 先簡(jiǎn)單解釋以下csrf攻擊
f攻擊就是在未經(jīng)你許可的情況下用你的名義發(fā)送惡意請(qǐng)求(比如修改密碼,銀行轉(zhuǎn)賬等),下面演示一個(gè)用xss配合csrf修改用戶(hù)密碼的例子。
首先對(duì)修改用戶(hù)密碼的界面進(jìn)行抓包。
發(fā)現(xiàn)沒(méi)有對(duì)原密碼進(jìn)行校驗(yàn)。于是一股邪惡的力量油然而生:要是在xss
本中自動(dòng)提交get請(qǐng)求修改密碼的話。。
說(shuō)干就干,具體插入語(yǔ)句如下:
<script type="text/javascript" src=";password_conf=123456&Change=Change#"></script>
有人會(huì)問(wèn),這不是引用腳本嗎?其實(shí)不然,本質(zhì)上這還是發(fā)起了一起get請(qǐng)求,因此可以直接使用。與上例一樣,插入到message中,再坐等上鉤。等下一個(gè)用戶(hù)訪問(wèn)該界面時(shí),密碼就會(huì)被改為123456了。
我們?cè)倏聪略L問(wèn)該頁(yè)面時(shí)的抓包情況,發(fā)現(xiàn)每次訪問(wèn)該頁(yè)面都發(fā)送了更改密碼的請(qǐng)求
效果看數(shù)據(jù)庫(kù)(密碼md5加密)
訪問(wèn)了該頁(yè)面的用戶(hù)密碼都被更改了。
都說(shuō)知己知彼方能百戰(zhàn)不殆,知道x
· s攻擊的原理那么防御的方法也就顯而易見(jiàn)了。 首先是過(guò)濾。對(duì)諸如<script>、<img>、<a>等標(biāo)簽進(jìn)行過(guò)濾。其次是編碼。像一些常見(jiàn)的符號(hào),如<>在輸入的時(shí)候要對(duì)其進(jìn)行轉(zhuǎn)換編碼,這樣做瀏覽器是不會(huì)對(duì)該標(biāo)簽進(jìn)行解釋執(zhí)行的,同時(shí)也不影響顯示效果。
· 最后是限制。通過(guò)以上的案例我們不難發(fā)現(xiàn)xss攻擊要能達(dá)成往往需要較長(zhǎng)的字符串,因此對(duì)于一些可以預(yù)期的輸入可以通過(guò)限制長(zhǎng)度強(qiáng)制截?cái)鄟?lái)進(jìn)行防御。
后話
安全攻防雙方的博弈永遠(yuǎn)都不會(huì)停止,也正是這種博弈推進(jìn)了信息安全的發(fā)展。究竟是道高一尺還是魔高一丈很難定論。其實(shí)安全問(wèn)題歸根結(jié)底還是一個(gè)信任的前提。什么輸入值得信任?什么輸入不值得信任需要特殊處理是安全人員常常要思考的一個(gè)問(wèn)題。
(五)xss防御
明確了xss的切入點(diǎn)后,我們就可以針對(duì)不同的切入點(diǎn)進(jìn)行不同的防御了。其實(shí)瀏覽器內(nèi)部是有自己的xss防御策略的。
· 瀏覽器自動(dòng)防御
瀏覽器是可以自動(dòng)防御某些xss攻擊,但是這種防御一般都是比較有限。只能防御部分反射型xss攻擊。而且是不會(huì)攔截出現(xiàn)在js中的腳本的。比如
比如我們的url是:
;script>alert(123)</script>
我們的html中有:#{content}
這個(gè)html中的content是后端通過(guò)獲取我們的查詢(xún)字符串后重新渲染到頁(yè)面上的。如果我們此時(shí)訪問(wèn)頁(yè)面,就會(huì)被瀏覽器攔截掉
我們可以通過(guò)在響應(yīng)頭中添加`X-XSS-Protection: 0`來(lái)關(guān)閉瀏覽器的自動(dòng)防御
· html節(jié)點(diǎn)內(nèi)容的防御
對(duì)于html節(jié)點(diǎn)內(nèi)容,我們能夠通過(guò)轉(zhuǎn)義的手段來(lái)防御xss攻擊。這里我們并不需要轉(zhuǎn)義太多的東西。因?yàn)閔tml中識(shí)別的是標(biāo)簽,所以,我們通過(guò)把'<'和'>'進(jìn)行轉(zhuǎn)義,就能很好的防御這部分的xss攻擊。
const escapeHtml = str => (/</g, '<').replace(/>/g, '>')
· 轉(zhuǎn)義html的屬性
轉(zhuǎn)義html屬性的內(nèi)容的時(shí)候,我們需要知道什么字符能夠分離html屬性?其實(shí)我們所常見(jiàn)的html屬性的表示方法一般有如下三種:
id = "app"
id = 'app'
id = app
所以,在對(duì)這部分內(nèi)容進(jìn)行轉(zhuǎn)義的時(shí)候可以把",',和空格全給轉(zhuǎn)義了。
const escapeAttr = str => (/"|'/g, '&quto;').replace(/\s/g, ' ')
但是,這里的轉(zhuǎn)義只能防御部分xss攻擊的情況,比如下面這種就束手無(wú)策了。
<a href="javascript:alert(0)">鏈接</a>
對(duì)于這中形式的防御,我們就需要使用下面防御富文本xss攻擊的手段來(lái)阻止。
· javascript代碼防御
對(duì)于js中的內(nèi)容的防御,只需要將引號(hào)轉(zhuǎn)義(不是轉(zhuǎn)義成實(shí)體,而是使用轉(zhuǎn)義符\)或者將待輸入的內(nèi)容序列化。
const escapeJs = str => (/"/g, '\\"').replace(/'/g, "\\'").replace(/\\/g, '\\\\')
上面只能保證大部分情況的安全,最保險(xiǎn)的是對(duì)數(shù)據(jù)進(jìn)行一次序列化;
JSON.stringify(str)
· 富文本防御
富文本其實(shí)就是一大段的html,這些html中會(huì)包含大量的格式和html標(biāo)簽。對(duì)于富文本的防御,我們不能使用轉(zhuǎn)義的方式,因?yàn)閔tml我們要原樣保留。因此,我們需要使用過(guò)濾的方式來(lái)防御富文本的xss攻擊。
過(guò)濾的方式有兩種:
1. 按照黑名單進(jìn)行過(guò)濾--過(guò)濾掉我們認(rèn)為不安全的btml屬性和標(biāo)簽。
2. 按照白名單過(guò)濾--只允許我們定義好的標(biāo)簽和屬性存在。
這兩種方式,黑名單的實(shí)現(xiàn)比較簡(jiǎn)單,但是稍不留神就可能留下漏洞。白名單實(shí)現(xiàn)比較麻煩,需要將html進(jìn)行完全的解析,然后過(guò)濾,再組裝成html。
// 黑名單的方式const xssFilter = html => {
// 黑名單的方式過(guò)濾 // 過(guò)濾script標(biāo)簽 html = (/<\s*\/?script\s*>/g, '')
// 過(guò)濾屬性值javascript:開(kāi)頭 html = (/javascript:[^'"]*/g, '')
// 過(guò)濾onerror屬性 html = (/onerror\s*=\s*['"]?[^'"]*['"]/g, '')
// ...其他很多需要過(guò)濾的屬性,xss的變種太多了 // 這個(gè)時(shí)候可以使用白名單進(jìn)行過(guò)濾}
// 白名單的方式過(guò)濾// 首先需要將html解析成一個(gè)樹(shù)狀結(jié)構(gòu),然后針對(duì)這個(gè)樹(shù)遍歷元素,判斷標(biāo)簽或者屬性是否在白名單中,如果不在// 直接干掉。// 可以直接在node端使用cheerio實(shí)現(xiàn)上述功能const xssFilter = html => {
const cheerio = require('cheerio')
const $ = c(html)
const whiteList = {
// 可以添加更多的規(guī)則 'img': ['src'],
}
$('*').each((index, element) => {
// 不在白名單中 if (!whiteList[element.name]) {
$(element).remove()
return;
}
// 在白名單中,處理屬性 for (let attr in element.attribs) {
if (whiteList[element.name].indexOf(attr) === -1) {
// 不在白名單中的屬性,移除 $(element).attr(attr, null)
}
}
})
return $.html()}
上面所做的一系列措施都是從開(kāi)發(fā)的角度去做的。然是xss攻擊千變?nèi)f化,要想徹底的杜絕他們,僅僅依靠編程的hack方法是十分麻煩的。所以,瀏覽器就提出了一個(gè)從根本上解決xss攻擊的方法:CSP。
csp的全稱(chēng)是內(nèi)容安全策略。是Content Security Policy的簡(jiǎn)稱(chēng)。
csp的策略和上面我們提到的白名單策略比較相似,開(kāi)發(fā)者要明確的告訴客戶(hù)端哪些腳本可以被執(zhí)行。它的解析和執(zhí)行都是由客戶(hù)端決定的,而開(kāi)發(fā)者所需要做的就是告訴瀏覽器可執(zhí)行的腳本規(guī)則即可。
為了啟用csp,我們可以從兩個(gè)方面進(jìn)行設(shè)置:
· 服務(wù)端,設(shè)置`Content-Security-Policy`響應(yīng)頭
· 客戶(hù)端,設(shè)置meta標(biāo)簽
<meta http-equiv="Content-Security-Policy" content="script-src 'self'; object-src 'none'; style-src cdn.exam ; child-src https:">
csp的限制策略一般是如下格式:`限制選項(xiàng) 選項(xiàng)值`。
csp提供了很多的限制選項(xiàng),其實(shí)就是設(shè)置了加載資源的時(shí)候需要采取的策略。對(duì)于csp,其加載策略主要有如下幾種:
· `script-src`:加載腳本的時(shí)候采取的策略
· `style-src`:加載樣式表的時(shí)候采取的策略
· `img-src`:加載圖像的時(shí)候采取的策略
· `media-src`:加載媒體文件(音頻和視頻)采取的策略
· `font-src`:加載字體采取的策略
· `object-src`:加載插件(如flash)采取的策略
· `child-src`:加載框架采取的策略
· `frame-ancestors`:嵌入的外部資源(比如<frame>、<iframe>、<embed>和<applet>)采取的策略
· `connect-src`:進(jìn)行http連接時(shí)候的限制策略(通過(guò) XHR、WebSockets、EventSource等)
· `worker-src`:加載worker腳本的時(shí)候采取的策略
· `manifest-src`:加載manifest文件時(shí)候采取的策略。
上面的限制選項(xiàng)幾乎涉及了瀏覽器加載資源的方方面面,除了上述限制,還有一個(gè)`default-src`限制。這個(gè)限制是用來(lái)設(shè)置上面各個(gè)選項(xiàng)的默認(rèn)值的。比如:
Content-Security-Policy: default-src 'self'
上面的這個(gè)請(qǐng)求頭限制了所有的外部資源必須和當(dāng)前域名同域。
明確了限制選項(xiàng),我們可以設(shè)置如下限制選項(xiàng)值。這些值其實(shí)就是我們對(duì)瀏覽器設(shè)置的白名單。
我們可以明確資源加載的域名,如:`exam`,``
我們可以明確資源加載的路徑,如:`exam/resources/js`
我們可以通過(guò)通配符來(lái)設(shè)置限制,如:`*.exam`,表示任意的子域名都是可以的
我們可以明確加載的協(xié)議,http或者h(yuǎn)ttps
我們可以通過(guò)關(guān)鍵字self指定,表示當(dāng)前域名
我們可以通過(guò)關(guān)鍵字none指定,表示禁止加載任何的外部資源
上面的這些選項(xiàng)值可以同時(shí)指定多個(gè),需要使用空格分開(kāi)。
Content-Security-Policy: script-src 'self' https:
對(duì)于xss的防御,我們可以通過(guò)設(shè)置`script-src`和`object-src`來(lái)限制,同時(shí)`script-src`也包含了一些特殊的選項(xiàng)值。
· unsafe-inline:允許執(zhí)行頁(yè)面內(nèi)嵌的script和事件監(jiān)聽(tīng)函數(shù)
· unsafe-eval:允許將字符串代碼執(zhí)行,比如使用eval、setTimeout、setInterval和Function等函數(shù)。
· nonce值:每次http響應(yīng)都會(huì)給客戶(hù)端發(fā)送一個(gè)token,頁(yè)面內(nèi)嵌的腳本必須有這個(gè)token才會(huì)被允許執(zhí)行
比如:Content-Security-Policy: script-src 'nonce-EDNnf03nceIOfn39fn3e9h3sdfa'
// 只有明確了這個(gè)nonce值才會(huì)被執(zhí)行<script nonce=EDNnf03nceIOfn39fn3e9h3sdfa>
// some code</script>
· hash值:列出允許執(zhí)行的腳本代碼的Hash值,頁(yè)面內(nèi)嵌腳本的哈希值只有吻合的情況下,才能執(zhí)行。
// 指定hash值
Content-Security-Policy: script-src 'sha256-qznLcsROx4GACP2dm0UCKCzCG-HiZ1guq6ZZDob_Tng='
只有script標(biāo)簽中內(nèi)容的hash和指定的相同時(shí)才會(huì)執(zhí)行
所以,只要我們能設(shè)置好csp的安全規(guī)則,就能從根本上避免xss攻擊。
1.《0061開(kāi)頭的銀行卡看這里!安全測(cè)試之XSS》援引自互聯(lián)網(wǎng),旨在傳遞更多網(wǎng)絡(luò)信息知識(shí),僅代表作者本人觀點(diǎn),與本網(wǎng)站無(wú)關(guān),侵刪請(qǐng)聯(lián)系頁(yè)腳下方聯(lián)系方式。
2.《0061開(kāi)頭的銀行卡看這里!安全測(cè)試之XSS》僅供讀者參考,本網(wǎng)站未對(duì)該內(nèi)容進(jìn)行證實(shí),對(duì)其原創(chuàng)性、真實(shí)性、完整性、及時(shí)性不作任何保證。
3.文章轉(zhuǎn)載時(shí)請(qǐng)保留本站內(nèi)容來(lái)源地址,http://f99ss.com/caijing/2025855.html