摘要:跨站腳本攻擊,縮寫為。這就是攻擊最簡(jiǎn)單的一個(gè)案例。漏洞產(chǎn)生的原因是攻擊者注入的數(shù)據(jù)反映在響應(yīng)中。而且富文本攻擊的防御相對(duì)比較麻煩。默認(rèn)配置下不允許執(zhí)行內(nèi)聯(lián)代碼塊內(nèi)容,內(nèi)聯(lián)事件,內(nèi)聯(lián)樣式,以及禁止執(zhí)行和。
跨站腳本攻擊(Cross Site Scripting),縮寫為XSS。惡意攻擊者往Web頁面里插入惡意javaScript代碼,當(dāng)用戶瀏覽該頁之時(shí),嵌入其中Web里面的javaScript代碼會(huì)被執(zhí)行,從而達(dá)到惡意攻擊用戶的目的。
一個(gè)簡(jiǎn)單的XSS攻擊
代碼:
async function(ctx, next){ ctx.set("X-XSS-Protection",0); ctx.render("index",{from:ctx.query.from}); };
注意:插入X-XSS-Protection頭部使瀏覽器XSS攔截器失效。
開始攻擊:
大家發(fā)現(xiàn)網(wǎng)頁執(zhí)行了一段腳本,而且這段腳本是用戶惡意輸入的。這就是XSS攻擊最簡(jiǎn)單的一個(gè)案例。把原本應(yīng)該顯示純文本的地方,執(zhí)行了一段黑客寫入的腳本。
那XSS攻擊有什么危害呢?
1、盜取各類用戶帳號(hào)
2、控制企業(yè)數(shù)據(jù),包括讀取、篡改、添加、刪除企業(yè)敏感數(shù)據(jù)的能力
3、盜竊企業(yè)重要的具有商業(yè)價(jià)值的資料
4、非法轉(zhuǎn)賬
5、強(qiáng)制發(fā)送電子郵件
6、網(wǎng)站掛馬
7、控制受害者機(jī)器向其它網(wǎng)站發(fā)起攻擊
XSS攻擊的分類
1、反射型
又稱為非持久性跨站點(diǎn)腳本攻擊。漏洞產(chǎn)生的原因是攻擊者注入的數(shù)據(jù)反映在響應(yīng)中。非持久型XSS攻擊要求用戶訪問一個(gè)被攻擊者篡改后的鏈接,用戶訪問該鏈接時(shí),被植入的攻擊腳本被用戶游覽器執(zhí)行,從而達(dá)到攻擊目的。也就是我上面舉的那個(gè)簡(jiǎn)單的XSS攻擊案例,通過url參數(shù)直接注入。然后在響應(yīng)的數(shù)據(jù)中包含著危險(xiǎn)的代碼。
當(dāng)黑客把這個(gè)鏈接發(fā)給你,你就中招啦!
2、存儲(chǔ)型
又稱為持久型跨站點(diǎn)腳本,它一般發(fā)生在XSS攻擊向量(一般指XSS攻擊代碼)存儲(chǔ)在網(wǎng)站數(shù)據(jù)庫,當(dāng)一個(gè)頁面被用戶打開的時(shí)候執(zhí)行。持久的XSS相比非持久性XSS攻擊危害性更大,容易造成蠕蟲,因?yàn)槊慨?dāng)用戶打開頁面,查看內(nèi)容時(shí)腳本將自動(dòng)執(zhí)行。
該網(wǎng)頁有一個(gè)發(fā)表評(píng)論的功能,該評(píng)論會(huì)寫入后臺(tái)數(shù)據(jù)庫,并且訪問主頁的時(shí)候,會(huì)從數(shù)據(jù)庫中加載出所有的評(píng)論。
當(dāng)我添加一個(gè)評(píng)論,并且暗藏一個(gè)腳本,如下圖:
當(dāng)別人訪問主頁的時(shí)候,剛剛黑客寫入的評(píng)論里面的腳本被瀏覽器當(dāng)成代碼執(zhí)行了,用戶莫名其妙受到攻擊:
上面就是兩種XSS攻擊的兩種基本類型。當(dāng)然黑客不會(huì)彈出一個(gè)框框給你,告訴你被攻擊,黑客不會(huì)這么傻的~他可以在用戶不知情的情況下,盜取用戶的cookie,改變網(wǎng)頁業(yè)務(wù)邏輯等等。
XSS攻擊的注入點(diǎn)
1、HTML節(jié)點(diǎn)內(nèi)容
這個(gè)其實(shí)就是我之前演示的,HTML節(jié)點(diǎn)中暗藏攻擊腳本。
2、HTML屬性
這里img的src屬性是由用戶傳遞過來的值,當(dāng)用戶把圖片地址寫成:1"%20onerror="alert(%27哈哈被攻擊%27)
大家看下面發(fā)生了什么:
3、JavaScript代碼 (字符串提前關(guān)閉)
當(dāng)JavaScript代碼中有一個(gè)變量是由用戶提供的數(shù)據(jù),這個(gè)數(shù)據(jù)也有可能之前被寫入了數(shù)據(jù)庫。如下圖,當(dāng)用戶輸入的內(nèi)容為:
小柚子";alert(%27哈哈你被攻擊了!%27);"
4、富文本
大家都知道,富文本其實(shí)就是一段HTML。既然它是一段HTML,那么就存在XSS攻擊。而且富文本攻擊的防御相對(duì)比較麻煩。
XSS攻擊防御
chrome瀏覽器自帶防御,可攔截反射性XSS(HTML內(nèi)容和屬性),js和富文本的無法攔截,所以我們必須得自己做一些防御手段。
1、HTML節(jié)點(diǎn)內(nèi)容的防御
將用戶輸入的內(nèi)容進(jìn)行轉(zhuǎn)義:
var escapeHtml = function(str) { str = str.replace(/"); return str; }
ctx.render("index", {comments, from: escapeHtml(ctx.query.from || "")});
2、HTML屬性的防御
對(duì)空格,單引號(hào),雙引號(hào)進(jìn)行轉(zhuǎn)義
var escapeHtmlProperty = function (str) { if(!str) return ""; str = str.replace(/"/g,"&quto;"); str = str.replace(/"/g,"'"); str = str.replace(/ /g," "); return str; }
ctx.render("index", {posts, comments, from:ctx.query.from || "", avatarId:escapeHtmlProperty(ctx.query.avatarId || "")});
3、JavaScript的防御
對(duì)引號(hào)進(jìn)行轉(zhuǎn)義
var escapeForJS = function(str){ if(!str) return ""; str = str.replace(//g,""); str = str.replace(/"/g,"""); return str; }
4、富文本的防御
富文本的情況非常的復(fù)雜,js可以藏在標(biāo)簽里,超鏈接url里,何種屬性里。
所以我們不能過用上面的方法做簡(jiǎn)單的轉(zhuǎn)義。因?yàn)榍闆r實(shí)在太多了。
現(xiàn)在我們換個(gè)思路,
提供兩種過濾的辦法:
1)黑名單
我們可以把 onerror 這種危險(xiǎn)標(biāo)簽或者屬性納入黑名單,過濾掉它。但是我們想,這種方式你要考慮很多情況,你也有可能漏掉一些情況等。
2)白名單
這種方式只允許部分標(biāo)簽和屬性。不在這個(gè)白名單中的,一律過濾掉它。但是這種方式編碼有點(diǎn)麻煩,我們需要去解析html樹狀結(jié)構(gòu),然后進(jìn)行過濾,把過濾后安全的html在輸出。
這里提供一個(gè)包,幫助我們?nèi)ソ馕鰄tml樹狀結(jié)構(gòu),它使用起來和jquery非常的類似。
npm install cheerio --save
var xssFilter = function(html) { if(!html) return ""; var cheerio = require("cheerio"); var $ = cheerio.load(html); //白名單 var whiteList = { "html" : [""], "body" : [""], "head" : [""], "div" : ["class"], "img" : ["src"], "a" : ["href"], "font":["size","color"] }; $("*").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(); } console.log(xssFilter("你好大家可以看到: