每一个工程师都要学的安全测试,老板再也不用担心服务器被黑
2019獨(dú)角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>
本文由云+社區(qū)發(fā)表
本篇包含了XSS漏洞攻擊及防御詳細(xì)介紹,包括漏洞基礎(chǔ)、XSS基礎(chǔ)、編碼基礎(chǔ)、XSS Payload、XSS攻擊防御。
第一部分:漏洞攻防基礎(chǔ)知識(shí)
XSS屬于漏洞攻防,我們要研究它就要了解這個(gè)領(lǐng)域的一些行話,這樣才好溝通交流。同時(shí)我建立了一個(gè)簡易的攻擊模型用于XSS漏洞學(xué)習(xí)。
1. 漏洞術(shù)語
了解一些簡單術(shù)語就好。
VUL
Vulnerability漏洞,指能對(duì)系統(tǒng)造成損壞或能借之攻擊系統(tǒng)的Bug。
POC
Proof of Concept,漏洞證明;可以是可以證明漏洞存在的文字描述和截圖,但更多的一般是證明漏洞存在的代碼;一般不會(huì)破壞存在漏洞的系統(tǒng)。
EXP
exploit,漏洞利用;利用漏洞攻擊系統(tǒng)的代碼。
Payload
(有效攻擊負(fù)載)是包含在你用于一次漏洞利用(exploit)中的攻擊代碼。
PWN
是一個(gè)黑客語法的俚語詞 ,是指攻破設(shè)備或者系統(tǒng)。
0DAY漏洞和0DAY攻擊
零日漏洞或零時(shí)差漏洞(Zero-dayexploit)通常是指還沒有補(bǔ)丁的安全漏洞。
零日攻擊或零時(shí)差攻擊(Zero-dayattack)則是指利用這種漏洞進(jìn)行的攻擊。
零日漏洞不但是黑客的最愛,掌握多少零日漏洞也成為評(píng)價(jià)黑客技術(shù)水平的一個(gè)重要參數(shù)。
CVE漏洞編號(hào)
Common Vulnerabilities and Exposures,公共漏洞和暴露,為廣泛認(rèn)同的信息安全漏洞或者已經(jīng)暴露出來的弱點(diǎn)給出一個(gè)公共的名稱。
可以在https://cve.mitre.org/網(wǎng)站根據(jù)漏洞的CVE編號(hào)搜索該漏洞的介紹。也可以在中文社區(qū)http://www.scap.org.cn/上搜索關(guān)于漏洞的介紹
2. 漏洞攻擊模型
1.png
上圖為一個(gè)簡單的攻擊模型。攻擊就是將Payload通過注入點(diǎn)注入到執(zhí)行點(diǎn)執(zhí)行的過程。過程順暢就表明這個(gè)漏洞被利用了。
第二部分:XSS基礎(chǔ)知識(shí)
基礎(chǔ)知識(shí)看完,現(xiàn)在我們可以開始接觸了解XSS基礎(chǔ)了。XSS基礎(chǔ)不好就不用研究了,大家沒用共同語言。
1. 什么是XSS?
XSS全稱Cross-site scripting,跨站腳本攻擊。攻擊者通過網(wǎng)站注入點(diǎn)注入惡意客戶端可執(zhí)行解析的Payload,當(dāng)被攻擊者訪問網(wǎng)站時(shí)Payload通過客戶端執(zhí)行點(diǎn)執(zhí)行來達(dá)到某些目的,比如獲取用戶權(quán)限、惡意傳播、釣魚等行為。
2. XSS的分類
不了解分類其實(shí)很難學(xué)好XSS,大家對(duì)XSS分類有很多誤解,而且很多文章上都解釋錯(cuò)的,這里我給出一個(gè)相對(duì)好的XSS分類。
2.1 按照Payload來源劃分
存儲(chǔ)型XSS
Payload永久存在服務(wù)器上,所以也叫永久型XSS,當(dāng)瀏覽器請(qǐng)求數(shù)據(jù)時(shí),包含Payload的數(shù)據(jù)從服務(wù)器上傳回并執(zhí)行。
過程如圖:
2.png
存儲(chǔ)型XSS例子:
發(fā)表帖子內(nèi)容包含Payload->存入數(shù)據(jù)庫->被攻擊者訪問包含該帖子的頁面Payload被執(zhí)行
反射型XSS
又稱非持久型XSS,第一種情況:Payload來源在客戶端然后在客戶端直接執(zhí)行。第二種情況:客戶端傳給服務(wù)端的臨時(shí)數(shù)據(jù),直接回顯到客戶端執(zhí)行。
過程如圖:
3.png
反射型XSS例子 :
2.2 按照Payload的位置劃分
DOM-based XSS
由客戶端JavaScript代碼操作DOM或者BOM造成Payload執(zhí)行的漏洞。由于主要是操作DOM造成的Payload執(zhí)行,所以叫做DOM-based XSS,操作BOM同樣也可以造成Payload執(zhí)行,所以這個(gè)名詞有些不準(zhǔn)確,其實(shí)叫JavaScript-based XSS更好。
DOM-based的Payload不在html代碼中所以給自動(dòng)化漏洞檢測(cè)帶來了困難。
過程如圖:
4.png
反射型DOM-based XSS的例子:
在客戶端搜索框輸入包含payload的內(nèi)容->服務(wù)端回顯一個(gè)頁面提示搜索內(nèi)容未找到,payload就被執(zhí)行了。
存儲(chǔ)型DOM-based XSS的例子:
從服務(wù)端接口中獲取包含Payload的內(nèi)容->JavaScript通過操作DOM、BOM造成Payload執(zhí)行
HTML-based XSS
Payload包含在服務(wù)端返回的HTML中,在瀏覽器解析HTML的時(shí)候執(zhí)行。這樣的漏洞易于做自動(dòng)化漏洞檢測(cè),因?yàn)镻ayload就在HTML里面。當(dāng)然HTML-based XSS也有反射型和存儲(chǔ)型的。
過程如圖:
5.png
反射型HTML-based XSS的例子:
在客戶端搜索框輸入包含payload的內(nèi)容->服務(wù)端回顯一個(gè)頁面提示搜索內(nèi)容未找到,payload包含在HTML被執(zhí)行。
存儲(chǔ)型HTML-based XSS的例子:
發(fā)表帖子內(nèi)容包含Payload->存入數(shù)據(jù)庫->被攻擊者訪問包含該帖子的頁面Payload在HTML頁面中被執(zhí)行
3. XSS的攻擊目的及危害
很多寫出不安全代碼的人都是對(duì)漏洞的危害沒有清晰的認(rèn)識(shí),下圖是2017 OWASP 網(wǎng)絡(luò)威脅Top10:
6_頭圖 自截取.jpg
可以看到XSS在網(wǎng)絡(luò)威脅中的地位舉足輕重。
3.1 目的
3.2 危害
第三部分:XSS攻擊的Payload
這部分我們分析下攻擊模型中的Payload,了解Payload必須了解編碼,學(xué)習(xí)好JS也必須要了解好編碼。要想真正做好網(wǎng)絡(luò)安全編碼是最基本的。
1. 編碼基礎(chǔ)
編碼部分是最重要的雖然枯燥但必須要會(huì)。后面很多變形的Payload都建立在你的編碼基礎(chǔ)。這里通16進(jìn)制編碼工具讓你徹底學(xué)會(huì)編碼。
1.1 編碼工具
16進(jìn)制查看器:方便查看文件16進(jìn)制編碼
MAC:HEx Friend
windows: HxD
編輯器Sublime:可以通過Sublime將文件保存不同編碼類型
7.jpg
1.2 ASCII
定義:美國信息交換標(biāo)準(zhǔn)代碼,是基于拉丁字母的一套計(jì)算機(jī)編碼系統(tǒng),主要用于顯示現(xiàn)代英語和其他西歐語言。
編碼方式:屬于單子節(jié)編碼。ASCII碼一共規(guī)定了128個(gè)字符的編碼,只占用了一個(gè)字節(jié)的后面7位,最前面的1位統(tǒng)一規(guī)定為0。0~31及127(共33個(gè))是控制字符或通信專用字符。32~126(共95個(gè))是字符(32是空格。
1.3 ISO-8859-1(Latin1)
定義:Latin1是ISO-8859-1的別名,ISO-8859-1收錄的字符除ASCII收錄的字符外,還包括西歐語言、希臘語、泰語、阿拉伯語、希伯來語對(duì)應(yīng)的文字符號(hào)。歐元符號(hào)出現(xiàn)的比較晚,沒有被收錄在ISO-8859-1當(dāng)中。
編碼方式:ISO-8859-1編碼是單字節(jié)編碼,向下兼容ASCII,其編碼范圍是0x00-0xFF,0x00-0x7F之間完全和ASCII一致,0x80-0x9F之間是控制字符,0xA0-0xFF之間是文字符號(hào)。
注意:ISO-8859-1編碼表示的字符范圍很窄,無法表示中文字符。但是,由于是單字節(jié)編碼,和計(jì)算機(jī)最基礎(chǔ)的表示單位一致,所以很多時(shí)候,仍舊使用ISO-8859-1編碼來表示。比如,雖然”中文”兩個(gè)字不存在iso8859-1編碼,以gb2312編碼為例,應(yīng)該是”d6d0 cec4”兩個(gè)字符,使用iso8859-1編碼的時(shí)候則將它拆開為4個(gè)字節(jié)來表示:”d6 d0 ce c4”(事實(shí)上,在進(jìn)行存儲(chǔ)的時(shí)候,也是以字節(jié)為單位處理的)。所以mysql中l(wèi)atin1可以表示任何編碼的字符。
Latin1與ASCII編碼的關(guān)系:完全兼容ASCII。
1.4 Unicode編碼(UCS-2)
Code Point: 碼點(diǎn),簡單理解就是字符的數(shù)字表示。一個(gè)字符集一般可以用一張或多張由多個(gè)行和多個(gè)列所構(gòu)成的二維表來表示。二維表中行與列交叉的點(diǎn)稱之為碼點(diǎn),每個(gè)碼點(diǎn)分配一個(gè)唯一的編號(hào),稱之為碼點(diǎn)值或碼點(diǎn)編號(hào)。
BOM(Byte Order Mark):字節(jié)序,出現(xiàn)在文件頭部,表示字節(jié)的順序,第一個(gè)字節(jié)在前,就是”大端方式”(Big-Endian),第二個(gè)字節(jié)在前就是”小端方式”(Little-Endian)。
在Unicode字符集中有一個(gè)叫做”ZERO WIDTH NO-BREAK SPACE“的字符,它的碼點(diǎn)是FEFF。而FFFE在Unicode中是不存在的字符,所以不應(yīng)該出現(xiàn)在實(shí)際傳輸中。在傳輸字節(jié)流前,我們可以傳字符”ZERO WIDTH NO-BREAK SPACE“表示大小端,因此字符”ZERO WIDTH NO-BREAK SPACE“又被稱作BOM。
BOM還可以用來表示文本編碼方式,Windows就是使用BOM來標(biāo)記文本文件的編碼方式的。Mac上文件有沒有BOM都可以。
例如:\u00FF :00是第一個(gè)字節(jié),FF是第二個(gè)字節(jié)。和碼點(diǎn)表示方式一樣屬于大端方式。
Unicode編碼字符集:旨在收集全球所有的字符,為每個(gè)字符分配唯一的字符編號(hào)即代碼點(diǎn)(Code Point),用 U+緊跟著十六進(jìn)制數(shù)表示。所有字符按照使用上的頻繁度劃分為 17 個(gè)平面(編號(hào)為 0-16),即基本的多語言平面和增補(bǔ)平面。基本的多語言平面又稱平面 0,收集了使用最廣泛的字符,代碼點(diǎn)從 U+0000 到 U+FFFF,每個(gè)平面有 216=65536 個(gè)碼點(diǎn);
Unicode編碼:Unicode 字符集中的字符可以有多種不同的編碼方式,如 UTF-8、UTF-16、UTF-32、壓縮轉(zhuǎn)換等。我們通常所說的Unicode編碼是UCS-2 將字符編號(hào)(同 Unicode 中的碼點(diǎn))直接映射為字符編碼,亦即字符編號(hào)就是字符編碼,中間沒有經(jīng)過特別的編碼算法轉(zhuǎn)換。是定長雙字節(jié)編碼:因?yàn)槲覀僓CS-2只包括本的多語言平面(U+0000 到 U+FFFF)。
UCS-2的BOM:大端模式:FEFF。小端模式:FFFE。
文件保存成UTF-16 BE with BOM相當(dāng)于UCS-2的大端模式,可以看到16進(jìn)制開頭為FEFF
Latin1與Unicode編碼的關(guān)系:Latin1對(duì)應(yīng)于Unicode的前256個(gè)碼位。
8.png
1.5 UTF-16
定義及編碼:UTF-16是Unicode的其中一個(gè)使用方式,在Unicode基本多文種平面定義的字符(無論是拉丁字母、漢字或其他文字或符號(hào)),一律使用2字節(jié)儲(chǔ)存。而在輔助平面定義的字符,會(huì)以代理對(duì)(surrogate pair)的形式,以兩個(gè)2字節(jié)的值來儲(chǔ)存。是雙字節(jié)編碼。
UTF-16與UCS-2的關(guān)系:UTF-16可看成是UCS-2的父集。在沒有輔助平面字符(surrogate code points)前,UTF-16與UCS-2所指的是同一的意思。但當(dāng)引入輔助平面字符后,就稱為UTF-16了。現(xiàn)在若有軟件聲稱自己支援UCS-2編碼,那其實(shí)是暗指它不能支援在UTF-16中超過2bytes的字集。對(duì)于小于0x10000的UCS碼,UTF-16編碼就等于UCS碼。
UTF-16的BOM:大端模式:FEFF。小端模式:FFFE。
1.6 UTF-8
定義及編碼:UTF-8就是在互聯(lián)網(wǎng)上使用最廣的一種Unicode的實(shí)現(xiàn)方式,這是為傳輸而設(shè)計(jì)的編碼,并使編碼無國界,這樣就可以顯示全世界上所有文化的字符了。UTF-8最大的一個(gè)特點(diǎn),就是它是一種變長的編碼方式。它可以使用1~4個(gè)字節(jié)表示一個(gè)符號(hào),根據(jù)不同的符號(hào)而變化字節(jié)長度,當(dāng)字符在ASCII碼的范圍時(shí),就用一個(gè)字節(jié)表示,保留了ASCII字符一個(gè)字節(jié)的編碼作為它的一部分,注意的是unicode一個(gè)中文字符占2個(gè)字節(jié),而UTF-8一個(gè)中文字符占3個(gè)字節(jié))。從unicode到utf-8并不是直接的對(duì)應(yīng),而是要過一些算法和規(guī)則來轉(zhuǎn)換。
| 0000 0000-0000 007F | 0xxxxxxx |
| 0000 0080-0000 07FF | 110xxxxx 10xxxxxx |
| 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx |
| 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx |
UTF8的BOM:EFBBBF。UTF-8不存在字符序列的問題,但是可以用用BOM表示這個(gè)文件是一個(gè)UTF-8文件。
文件保存成UTF-8 BE with BOM,可以看到16進(jìn)制開頭為EFBBBF
9.png
1.7 GBK/GB2312
定義及編碼:GB2312是最早一版的漢字編碼只包含6763漢字,GB2312只支持簡體字而且不全,顯然不夠用。GBK編碼,是對(duì)GB2312編碼的擴(kuò)展,完全兼容GB2312標(biāo)準(zhǔn),支持簡體字繁體字,包含全部中文字符。GBK編碼采用單雙字節(jié)編碼方案,單字節(jié)和Latin1一致,雙字節(jié)是漢字部分,其編碼范圍:8140-FEFE,剔除xx7F碼位,共23940個(gè)碼位。
GBK與Latin1的關(guān)系:GBK單字節(jié)編碼區(qū)和Latin1編碼一致。
GBK與Unicode的關(guān)系:GBK與Unicode字符集編碼不同但是兼容的。如"漢"的Unicode值與GBK雖然是不一樣的,假設(shè)Unicode為a040,GBK為b030,但是可以對(duì)應(yīng)轉(zhuǎn)化的。漢字的Unicode區(qū):4E00-u9FA5。
GBK與UTF-8:GBK漢字采用雙字節(jié)編碼比在UTF-8中的三字節(jié)要小。但是UTF-8更通用。GBK與UTF-8轉(zhuǎn)化:GBK—> Unicode —> UTF8
2. 前端中的編碼
有了編碼基礎(chǔ)就可以來認(rèn)識(shí)一下前端中的編碼,這樣你才能真正認(rèn)識(shí)Payload。我這里的應(yīng)該是總結(jié)最全的。
2.1 Base64
Base64可以用來將binary的字節(jié)序列數(shù)據(jù)編碼成ASCII字符序列構(gòu)成的文本。使用時(shí),在傳輸編碼方式中指定Base64。使用的字符包括大小寫拉丁字母各26個(gè)、數(shù)字10個(gè)、加號(hào)+和斜杠/,共64個(gè)字符及等號(hào)=用來作為后綴用途。所以總共65個(gè)字符。
將3字節(jié)的數(shù)據(jù),先后放入一個(gè)24位的緩沖區(qū)中,先來的字節(jié)占高位。數(shù)據(jù)不足3字節(jié)的話,于緩沖器中剩下的比特用0補(bǔ)足。每次取出6bit對(duì)原有數(shù)據(jù)用Base64字符作為編碼后的輸出。編碼若原數(shù)據(jù)長度不是3的倍數(shù)時(shí)且剩下1個(gè)輸入數(shù)據(jù),則在編碼結(jié)果后加2個(gè)=;若剩下2個(gè)輸入數(shù)據(jù),則在編碼結(jié)果后加1個(gè)=。可以看出Base64編碼數(shù)據(jù)大約是原來數(shù)據(jù)的3/4。
標(biāo)準(zhǔn)的Base64并不適合直接放在URL里傳輸,因?yàn)閁RL編碼器會(huì)把標(biāo)準(zhǔn)Base64中的/和+字符變?yōu)樾稳?XX的形式,而這些%號(hào)在存入數(shù)據(jù)庫時(shí)還需要再進(jìn)行轉(zhuǎn)換,因?yàn)锳NSI SQL中已將%號(hào)用作通配符。為解決此問題,可采用一種用于URL的改進(jìn)Base64編碼,它不在末尾填充=號(hào),并將標(biāo)準(zhǔn)Base64中的+和/分別改成了-和_,這樣就免去了在URL編解碼和數(shù)據(jù)庫存儲(chǔ)時(shí)所要做的轉(zhuǎn)換,避免了編碼信息長度在此過程中的增加,并統(tǒng)一了數(shù)據(jù)庫、表單等處對(duì)象標(biāo)識(shí)符的格式。
window.btoa/window.atob base64編碼(binary to ascii)和解碼僅支持Latin1字符集。
2.2 JS轉(zhuǎn)義字符
js字符字符串中包含一些反斜杠開頭的特殊轉(zhuǎn)義字符,用來表示非打印符、其他用途的字符還可以轉(zhuǎn)義表示unicode、Latin1字符。
| \’ | 單引號(hào) |
| \” | 雙引號(hào) |
| & | 和號(hào) |
| \ | 反斜杠 |
| \n | 換行符 |
| \r | 回車符 |
| \t | 制表符 |
| \b | 退格符 |
| \f | 換頁符 |
| \n … \nnn | 由一位到三位八進(jìn)制數(shù)(1到377)指定的Latin-1字符 |
| \xnn | 以16進(jìn)制nn(n:0~F)表示一個(gè)Latin1字符。\x41表示字符A |
| \unnnn | 以16進(jìn)制nnnn(n:0~F)表示一個(gè)Unicode字符。只限于碼點(diǎn)在\u0000~\uFFFF范圍內(nèi) |
| \u{n} … \u{nnnnnn} | Unicode碼點(diǎn)值表示一個(gè)Unicode字符 |
特別注意:
例子:
function toUnicode(theString) { //字符串轉(zhuǎn)換為unicode編碼字符串,切記這個(gè)字符串是復(fù)制用的,不是讓你拿來直接執(zhí)行的。var unicodeString = '';for (var i = 0; i < theString.length; i++) {var theUnicode = theString.charCodeAt(i).toString(16).toUpperCase();while (theUnicode.length < 4) {theUnicode = '0' + theUnicode;}theUnicode = '\\u' + theUnicode;unicodeString += theUnicode;}return unicodeString; } var xssStr = "alert('xss')"; var xssStrUnicode = toUnicode(xssStr); //輸出:"\u0061\u006C\u0065\u0072\u0074\u0028\u0027\u0078\u0073\u0073\u0027\u002" eval("\u0061\u006C\u0065\u0072\u0074\u0028\u0027\u0078\u0073\u0073\u0027\u002"); //彈出xss彈窗2.3 URL編碼
RFC 1738做出規(guī)定”只有字母和數(shù)字0-9a-zA-Z、一些特殊符號(hào)”$-_.+!*’(),”不包括雙引號(hào)、以及某些保留字,才可以不經(jīng)過編碼直接用于URL”。所以當(dāng)鏈接中包含中文或者其他不符合規(guī)定的字符的時(shí)候都需要經(jīng)過編碼的。然而由于瀏覽器廠商眾多,對(duì)url進(jìn)行編碼的形式多種多樣,如果不對(duì)編碼進(jìn)行統(tǒng)一處理,會(huì)對(duì)代碼開發(fā)造成很大的影響,出現(xiàn)亂碼現(xiàn)象。
URL編碼規(guī)則:需要編碼的字符轉(zhuǎn)換為UTF-8編碼,然后在每個(gè)字節(jié)前面加上%。
例如:
'牛'-->UTF-8編碼E7899B-->URL編碼是%E7%89%9BJS為我們提供了3個(gè)對(duì)字符串進(jìn)行URL編碼的方法:escape ,encodeURI,encodeURIComponent
escape:由于eccape已經(jīng)被建議放棄所以大家就不要用了
encodeURI:encodeURI不編碼的82個(gè)字符:!#$&’()*+,/:;=?@-._~0-9a-zA-Z,從中可以看不會(huì)對(duì)url中的保留字符進(jìn)行編碼,所以適合url整體編碼
encodeURIComponent:這個(gè)對(duì)于我們來說是最有用的一個(gè)編碼函數(shù),encodeURIComponent不編碼的字符有71個(gè):!, ‘,(,),*,-,.,_,~,0-9,a-z,A-Z。
可以看出對(duì)url中的保留字進(jìn)行的編碼,所以當(dāng)傳遞的參數(shù)中
包含這些url中的保留字(@,&,=),就可以通過這個(gè)方法編碼后傳輸
這三個(gè)方法對(duì)應(yīng)的解碼方法: unescape、decodeURI、decodeURIComponent
2.4 HTML字符實(shí)體
HTML中的預(yù)留字符必須被替換為字符實(shí)體。這樣才能當(dāng)成字符展示,否則會(huì)當(dāng)成HTML解析。
字符實(shí)體編碼規(guī)則:轉(zhuǎn)義字符 = &#+ascii碼; = &實(shí)體名稱;
XSS字符串需要防御字符的實(shí)體轉(zhuǎn)換表:
10.png
轉(zhuǎn)化方法:
function encodeHTML (a) {return String(a).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'"); };2.5 頁面編碼
頁面編碼設(shè)置:
<meta charset="UTF-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
腳本編碼設(shè)置:
<script type="text/javascript" src="myscripts.js" charset="UTF-8"></script>
注意:要想JS即可在UTF-8中正常使用又可以在GBK中正常使用,可以對(duì)JS中所有包含中文的字符串做字符轉(zhuǎn)義。
例子:
alert("網(wǎng)絡(luò)錯(cuò)誤"); //彈出網(wǎng)絡(luò)錯(cuò)誤 alert("\u7f51\u7edc\u9519\u8bef"); //彈出網(wǎng)絡(luò)錯(cuò)誤3. Payload的分類
現(xiàn)在可以認(rèn)識(shí)Payload的了,我不得不說這里對(duì)Payload的分類可以很好的讓你認(rèn)識(shí)Payload。也幫助你更好的對(duì)應(yīng)到執(zhí)行點(diǎn)。
3.1 原子Payload
最低層級(jí)的Payload。
javascript代碼片段
可在eval、setTimeout、setInterval中直接執(zhí)行,也可通過HTML等構(gòu)成高階Payload
javascript:javascript偽協(xié)議
結(jié)構(gòu):javascript:+js代碼。可以在a標(biāo)簽的href屬性被點(diǎn)擊和window.location.href賦值的時(shí)候執(zhí)行。
DATA URI協(xié)議
DATA URI結(jié)構(gòu):data:, 。DATA URI數(shù)據(jù)在包含在iframe的src屬性和object data屬性中將會(huì)變成可執(zhí)行的Payload.
字符串轉(zhuǎn)義變種javascript代碼片段
unicode或者Latin-1表示字符串。
eval("\u0061\u006C\u0065\u0072\u0074\u0028\u0027\u0078\u0073\u0073\u0027\u002"); //可執(zhí)行的JS3.2 純HTMLPayload
這種Payload特點(diǎn)不具有可執(zhí)行的JS,但是存在傳播風(fēng)險(xiǎn),可以把別的站點(diǎn)注入到被攻擊網(wǎng)站。
包含鏈接跳轉(zhuǎn)的HTML片段
主要是傳播危害
<a href="http://ha.ck">哈哈,我來釣魚了</a>3.3 包含原子Payload的HTML片段Payload
script標(biāo)簽片段
script標(biāo)簽片段這種Payload可以引入外部JS或者可直接執(zhí)行的script。這種Payload一般不能通過直接復(fù)制給innerHTML執(zhí)行,不過在IE上可以。不過通過document.write是可以執(zhí)行。
例子:
// Payload原始值:data:text/html,<script>alert('xss');</script> var inputStr ="<script>alert('xss');<\/script>"; document.write(inputStr);包含事件處理的HTML片段
例如:包含img的onerror, svg的onload,input的onfocus等的HTML片段,都可以變成可執(zhí)行的Payload。
var inputStr ="<img src=x onerror=alert('xss');>"; var inputStr ="<svg/onload=alert('xss')>"; var inputStr ="<input autofocus onfocus=alert('xss')>"; xssDom.innerHTML = inputStr;包含可執(zhí)行JS屬性的HTML片段
例子:
// Payload原始值:data:text/html,<script>alert('xss');</script> //var inputStr = '<iframe src="data:text/html,<script>alert("xss");</script>"></iframe>'; // var inputStr = '<object data="data:text/html;base64,ZGF0YTp0ZXh0L2h0bWwsPHNjcmlwdD5hbGVydCgneHNzJyk7PC9zY3JpcHQ+"></object>'; xssDom.innerHTML = inputStr; //彈出alert("xss")這里只是介紹了主要的Payload,還有很多不常見的Payload。
第四部分:XSS攻擊模型分析
這部分我們根據(jù)漏洞攻擊模型分析一下XSS的執(zhí)行點(diǎn)和注入點(diǎn)。分析這兩點(diǎn)其實(shí)就是找漏洞的過程。
1. XSS漏洞執(zhí)行點(diǎn)
2. XSS漏洞注入點(diǎn)
看看我們可以在哪些位置注入我們的Payload
上面內(nèi)容基本包含了所有的執(zhí)行點(diǎn)和注入點(diǎn)。對(duì)大家進(jìn)行XSS漏洞攻防很有幫助。
第五部分 XSS攻擊防御策略
1. 騰訊內(nèi)部公共安全防御及應(yīng)急響應(yīng)
2. 安全編碼
2.1 執(zhí)行點(diǎn)防御方法
| 頁面直出Dom | 服務(wù)端XSS過濾 |
| 客戶端跳轉(zhuǎn)鏈接 | 域名白名單(例如:只允許qq.com域)、鏈接地址XSS過濾 |
| 取值寫入頁面 | 客戶端XSS過濾 |
| 腳本動(dòng)態(tài)執(zhí)行 | 確保執(zhí)行Js字符串來源可信 |
|
| 不安全屬性設(shè)置 | 內(nèi)容XSS過濾,包含鏈接同客戶端跳轉(zhuǎn)鏈接 |
|HTML5 postMessage|origin限制來源|
| 有缺陷的第三方庫 | 不使用
2.2 其他安全防御手段
3. 代碼審查
總結(jié)XSS檢查表做代碼自測(cè)和檢視
4. 自動(dòng)化檢測(cè)XSS漏洞的工具
手工檢測(cè)XSS漏洞是一件比較費(fèi)時(shí)間的事情,我們能不能寫一套自動(dòng)檢測(cè)XSS自動(dòng)檢測(cè)工具。竟然我知道了注入點(diǎn)、執(zhí)行點(diǎn)、Payload自動(dòng)化過程是完全有可能的。
XSS自動(dòng)化檢測(cè)的難點(diǎn)就在于DOM型XSS的檢測(cè)。因?yàn)榍岸薐S復(fù)雜性較高,包括靜態(tài)代碼分析、動(dòng)態(tài)執(zhí)行分析都不容易等。
第六部分 總結(jié)
上面內(nèi)容文字比較多,看完還是很累的,總結(jié)起來就一句話:安全大于一切,不要心存僥幸,希望以上內(nèi)容對(duì)您有幫助,不過以上內(nèi)容僅代表個(gè)人理解,如有不對(duì)歡迎指正討論。
此文已由作者授權(quán)騰訊云+社區(qū)發(fā)布
轉(zhuǎn)載于:https://my.oschina.net/qcloudcommunity/blog/2989852
與50位技術(shù)專家面對(duì)面20年技術(shù)見證,附贈(zèng)技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的每一个工程师都要学的安全测试,老板再也不用担心服务器被黑的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux运维之——每日小技巧,使用aw
- 下一篇: BZOJ 4516 [Sdoi2016]