渗透开发-XSS扫描器
– 自動(dòng)刷SRC
w13scan的xss掃描功能進(jìn)行優(yōu)化
靈感注入xray所引起的基于語(yǔ)義的掃描技術(shù)。
xss掃描之前是w3afxss payload,通常在以下幾個(gè)部分。
Xsstrike,Xray,Awvs中的檢測(cè)技巧以及檢測(cè)參數(shù)
XSStrike
先說(shuō)說(shuō)Xsstrike,里面帶有xss掃描和fuzz,
DOM XSS
Xsstrike的dom掃描,是通過(guò)正則來(lái)分析敏感函數(shù)
通過(guò)將script腳本內(nèi)的內(nèi)容提取出來(lái),通過(guò)一些正則來(lái)獲取,最后輸出。
準(zhǔn)確度很低,只能用于輔助,不太適合自動(dòng)化掃描
內(nèi)置參數(shù)
它里面有內(nèi)置一些參數(shù),在檢測(cè)時(shí)轉(zhuǎn)化這些參數(shù)也一起發(fā)送
很好的思路,后面我的掃描器中也使用了這一點(diǎn)
從烏云鏡像XSS分類(lèi)中提取出了top10參數(shù)
在掃描時(shí)也會(huì)將這些參數(shù)加上
HTML解析和分析反射
如果參數(shù)可以回顯,
那么通過(guò)html解析就可以獲得參數(shù)位置,分析回顯的環(huán)境
(是否在html標(biāo)簽內(nèi),是否在html屬性?xún)?nèi),是否在注釋中,是否在js中)
等等,否則來(lái)確定檢測(cè)的payload。
后面我的掃描器的檢測(cè)流程也是這樣,
非常準(zhǔn)確和效率,不過(guò)Xsstrike分析html是自己寫(xiě)的分析函數(shù),
剛開(kāi)始我也想直接用它的來(lái)著,但是這個(gè)函數(shù)內(nèi)容過(guò)多,調(diào)試?yán)щy,代碼也很難理解。
其實(shí)如果把html解析理解為html的語(yǔ)義分析,用python3自帶的html提取函數(shù)很容易就能完成這一點(diǎn)。
Xray
XSStrike讓我學(xué)習(xí)到了新一代xss掃描器應(yīng)該如何編寫(xiě),
但新一代xss掃描器的payload是在Xray上學(xué)到的。
由于Xray沒(méi)有開(kāi)源,所以就通過(guò)分析日志的方式來(lái)看它的工作原理。
<html> <body> <a href="?q=1&w=2&e=3&r=4&t=5" /> <script> <php foreach($_GET as $key => $value){// $_GET[$key] = htmlspecialchars($value); } $q = $_GET["q"]; $w = $_GET["w"]; $e = $_GET["e"]; $r = $_GET["r"]; $t = $_GET["t"]; if(stripos($q,"prompt") > 0){die("error"); } $var = 'var a = "'.$q.'";'; echo $var; > </script> <div> <textarea><?php echo $w;?></textarea> </div> <input style="color:<?php echo $e;?>" value="<?php echo $r;?>"/><!--this is comment<?php echo $t;?>--> </body> </html>用來(lái)分別測(cè)試xss在script,style內(nèi),html標(biāo)簽內(nèi),注釋這幾種情況下xray的發(fā)包過(guò)程
對(duì)于在script的腳本內(nèi)的回顯內(nèi)容,對(duì)于以下case
X射線(xiàn)順序發(fā)送了以下payload:pdrjzsqc,“-pdrjzsqc-”,
最后會(huì)給出payload,但這個(gè)包并沒(méi)有發(fā)送。
后面把prompt作為關(guān)鍵詞屏蔽,發(fā)現(xiàn)最后還是給出這個(gè)payload。
還有一種情況,在script中的注釋中輸出
<html><body><script>var a = 11;// inline <?php echo $_GET["a"];?>/* <?php echo $_GET["b"];?> */</script></body></html>xray會(huì)發(fā)送
xray會(huì)發(fā)送\n;chxdsdkm;//來(lái)判定,最后給出payload \n;prompt(1);//
.對(duì)于在標(biāo)簽內(nèi)的內(nèi)容,針對(duì)以下case
<textarea><?php echo $_GET["w"];?></textarea>xray順序發(fā)送了以下payload
:spzzmsntfzikatuchsvu,,
當(dāng)確定尖括號(hào)沒(méi)有被過(guò)濾時(shí),會(huì)繼續(xù)發(fā)送以下payload:
sCrIpTjhymehqbkrScRiPt,
iMgSrCoNeRrOrjhymehqbkr>,
SvGoNlOaDjhymehqbkr>,
IfRaMeSrCjAvAsCrIpTjhymehqbkr>,
aHrEfJaVaScRiPtjhymehqbkrClIcKa,
iNpUtAuToFoCuSoNfOcUsjhymehqbkr>,
進(jìn)行關(guān)鍵詞的試探,最后給出payload為
對(duì)于在style里內(nèi)容,以下case
<input style="color:<?php echoxray順序發(fā)送了以下payload:kmbrocvz,expression(a(kmbrocvz))
對(duì)于在html標(biāo)簽內(nèi)的內(nèi)容,以下case
<input style="color:3" value="<?php echo $_GET["r"];?>"/>xray順序發(fā)送了以下payload:
spzzmsntfzikatuchsvu,
“l(fā)jxxrwom=”,
‘ljxxrwom=’,
ljxxrwom=,當(dāng)確認(rèn)引號(hào)沒(méi)有被過(guò)濾時(shí),會(huì)繼續(xù)發(fā)送以下payload:
">,
">ScRiPtvkvjfzrtgiScRiPt,
">ImGsRcOnErRoRvkvjfzrtgi>,
">SvGoNlOaDvkvjfzrtgi>,
">iFrAmEsRcJaVaScRiPtvkvjfzrtgi>,
">aHrEfJaVaScRiPtvkvjfzrtgicLiCkA,
">InPuTaUtOfOcUsOnFoCuSvkvjfzrtgi>,
" OnMoUsEoVeR=xviinqws,最后可以確定payload為
">,"OnMoUsEoVeR=prompt(1)//
如果針對(duì)此類(lèi)case:
<img src=1 onerror="a<?php echo htmlspecialchars($_GET["a"]);?>" />xray返回payload為prompt(1),
說(shuō)明xray會(huì)把onerror后面的內(nèi)容當(dāng)作JavaScript腳本來(lái)執(zhí)行,
如果把onerror改為onerror1,同樣會(huì)返回prompt。
在awvs規(guī)則中也看到過(guò)類(lèi)似的規(guī)則
parName == "ONAFTERPRINT" || parName == "ONBEFOREPRINT" || parName == "ONBEFOREONLOAD" || parName == "ONBLUR" || parName == "ONERROR" || parName == "ONFOCUS" || parName == "ONHASCHANGE" || parName == "ONLOAD" || parName == "ONMESSAGE" || parName == "ONOFFLINE" || parName == "ONONLINE" || parName == "ONPAGEHIDE" || parName == "ONPAGESHOW" || parName == "ONPOPSTATE" || parName == "ONREDO" || parName == "ONRESIZE" || parName == "ONSTORAGE" || parName == "ONUNDO" || parName == "ONUNLOAD" || parName == "ONBLUR" || parName == "ONCHANGE" || parName == "ONCONTEXTMENU" || parName == "ONFOCUS" || parName == "ONFORMCHANGE" || parName == "ONFORMINPUT" || parName == "ONINPUT" || parName == "ONINVALID" || parName == "ONRESET" || parName == "ONSELECT" || parName == "ONSUBMIT" || parName == "ONKEYDOWN" || parName == "ONKEYPRESS" || parName == "ONKEYUP" || parName == "ONCLICK" || parName == "ONDBLCLICK" || parName == "ONDRAG" || parName == "ONDRAGEND" || parName == "ONDRAGENTER" || parName == "ONDRAGLEAVE" || parName == "ONDRAGOVER" || parName == "ONDRAGSTART" || parName == "ONDROP" || parName == "ONMOUSEDOWN" || parName == "ONMOUSEMOVE" || parName == "ONMOUSEOUT" || parName == "ONMOUSEOVER" || parName == "ONMOUSEUP" || parName == "ONMOUSEWHEEL" || parName == "ONSCROLL" || parName == "ONABORT" || parName == "ONCANPLAY" || parName == "ONCANPLAYTHROUGH" || parName == "ONDURATIONCHANGE" || parName == "ONEMPTIED" || parName == "ONENDED" || parName == "ONERROR" || parName == "ONLOADEDDATA" || parName == "ONLOADEDMETADATA" || parName == "ONLOADSTART" || parName == "ONPAUSE" || parName == "ONPLAY" || parName == "ONPLAYING" || parName == "ONPROGRESS" || parName == "ONRATECHANGE" || parName == "ONREADYSTATECHANGE" || parName == "ONSEEKED" || parName == "ONSEEKING" || parName == "ONSTALLED" || parName == "ONSUSPEND" || parName == "ONTIMEUPDATE" || parName == "ONVOLUMECHANGE" || parName == "ONWAITING" || parName == "ONTOUCHSTART" || parName == "ONTOUCHMOVE" || parName == "ONTOUCHEND" || parName == "ONTOUCHENTER" || parName == "ONTOUCHLEAVE" || parName == "ONTOUCHCANCEL" || parName == "ONGESTURESTART" || parName == "ONGESTURECHANGE" || parName == "ONGESTUREEND" || parName == "ONPOINTERDOWN" || parName == "ONPOINTERUP" || parName == "ONPOINTERCANCEL" || parName == "ONPOINTERMOVE" || parName == "ONPOINTEROVER" || parName == "ONPOINTEROUT" || parName == "ONPOINTERENTER" || parName == "ONPOINTERLEAVE" || parName == "ONGOTPOINTERCAPTURE" || parName == "ONLOSTPOINTERCAPTURE" || parName == "ONCUT" || parName == "ONCOPY" || parName == "ONPASTE" || parName == "ONBEFORECUT" || parName == "ONBEFORECOPY" || parName == "ONBEFOREPASTE" || parName == "ONAFTERUPDATE" || parName == "ONBEFOREUPDATE" || parName == "ONCELLCHANGE" || parName == "ONDATAAVAILABLE" || parName == "ONDATASETCHANGED" || parName == "ONDATASETCOMPLETE" || parName == "ONERRORUPDATE" || parName == "ONROWENTER" || parName == "ONROWEXIT" || parName == "ONROWSDELETE" || parName == "ONROWINSERTED" || parName == "ONCONTEXTMENU" || parName == "ONDRAG" || parName == "ONDRAGSTART" || parName == "ONDRAGENTER" || parName == "ONDRAGOVER" || parName == "ONDRAGLEAVE" || parName == "ONDRAGEND" || parName == "ONDROP" || parName == "ONSELECTSTART" || parName == "ONHELP" || parName == "ONBEFOREUNLOAD" || parName == "ONSTOP" || parName == "ONBEFOREEDITFOCUS" || parName == "ONSTART" || parName == "ONFINISH" || parName == "ONBOUNCE" || parName == "ONBEFOREPRINT" || parName == "ONAFTERPRINT" || parName == "ONPROPERTYCHANGE" || parName == "ONFILTERCHANGE" || parName == "ONREADYSTATECHANGE" || parName == "ONLOSECAPTURE" || parName == "ONDRAGDROP" || parName == "ONDRAGENTER" || parName == "ONDRAGEXIT" || parName == "ONDRAGGESTURE" || parName == "ONDRAGOVER" || parName == "ONCLOSE" || parName == "ONCOMMAND" || parName == "ONINPUT" || parName == "ONCONTEXTMENU" || parName == "ONOVERFLOW" || parName == "ONOVERFLOWCHANGED" || parName == "ONUNDERFLOW" || parName == "ONPOPUPHIDDEN" || parName == "ONPOPUPHIDING" || parName == "ONPOPUPSHOWING" || parName == "ONPOPUPSHOWN" || parName == "ONBROADCAST" || parName == "ONCOMMANDUPDATE" || parName == "STYLE"awvs會(huì)比較參數(shù)名稱(chēng)來(lái)確定。
在后面的自動(dòng)化掃描中,發(fā)現(xiàn)這種方式的誤報(bào)還是很高,
最后我將這種情況調(diào)整到了awvs的方式,
只檢測(cè)指定的屬性key。
從這兩處細(xì)微的差異可以看到
awvs寧愿漏報(bào)也不誤報(bào),結(jié)果會(huì)很準(zhǔn)確,
xray更多針對(duì)白帽子,結(jié)果會(huì)寬泛一些。
對(duì)于在html注釋內(nèi)的內(nèi)容,以下case
<!--this is comment<?php echo $t;?>-->xray順序發(fā)送了以下payload:
spzzmsntfzikatuchsvu,
–>,
–!>,
和上面類(lèi)似,當(dāng)確定–>或–!>沒(méi)有過(guò)濾時(shí),
會(huì)發(fā)送
Avvs
Awvs的掃描規(guī)則很多,針對(duì)的情況也很多,
沒(méi)有仔細(xì)看它的工作方式是怎樣的,
主要是看它的payload以及檢測(cè)的情況,
和上面兩種查漏補(bǔ)缺,最終合成了我的xss掃描器~
比如它會(huì)對(duì)meta標(biāo)簽的content內(nèi)容進(jìn)行處理,
會(huì)對(duì)你srcipt,src等tag的屬性處理,
也有一些對(duì)AngularJs等一些流行的框架的XSS探測(cè)payload。。
我的掃描器
我的XSS掃描器就是綜合上面的幾種掃描器而來(lái),
如果仔細(xì)觀(guān)察,將會(huì)發(fā)現(xiàn)上面的掃描器的一些不同尋常的細(xì)節(jié)。
比如xray不會(huì)發(fā)送xss的payload,
都是用一些隨機(jī)字符來(lái)代替,同時(shí)也會(huì)隨機(jī)大小寫(xiě)對(duì)一些標(biāo)簽名稱(chēng),屬性名稱(chēng)等等。
這些精致的技巧吸取
掃描流程
我的掃描器掃描流程是這樣的
發(fā)送隨機(jī)flag -> 確定參數(shù)回顯 ->
確定回顯位置以及情況(html,js語(yǔ)法解析) ->
根據(jù)情況根據(jù)不同payload探測(cè) -> 使用html,js語(yǔ)法解析確定是否多出來(lái)了標(biāo)簽,
屬性,js語(yǔ)句等等
使用html語(yǔ)法樹(shù)檢測(cè)有很多優(yōu)勢(shì),
可以準(zhǔn)確判定回顯所處的位置,然后通過(guò)發(fā)送一個(gè)隨機(jī)payload,
例如,再使用語(yǔ)法檢測(cè)是否有Asfaa這個(gè)標(biāo)簽,就能確定payload是否執(zhí)行成功了。
html語(yǔ)法樹(shù)用python自帶的庫(kù)
from html.parser import HTMLParser
js檢測(cè)也是如此,
如果回顯內(nèi)容在JavaScript腳本中,發(fā)送隨機(jī)flag后,
通過(guò)js語(yǔ)法解析只需要確定Identifier和Literal這兩個(gè)類(lèi)型中是否包含,
如果flag是Identifier類(lèi)型,就能直接判斷存在xss,
payload是alert(1)//,
如果flag是Literal類(lèi)型,再通過(guò)單雙引號(hào)來(lái)閉合進(jìn)行檢測(cè)。
Debug之旅
本地靶機(jī)測(cè)試后就對(duì)在線(xiàn)的靶機(jī)進(jìn)行了測(cè)試 https://brutelogic.com.br/knoxss.html
查漏補(bǔ)缺后就就開(kāi)始了自動(dòng)化掃描。
整個(gè)自動(dòng)化架構(gòu)如下
1. 提供url ->
爬蟲(chóng)爬取 ->
參數(shù)入庫(kù) ->
消息隊(duì)列 ->
xss掃描器 ->
子域名入庫(kù)->
url入庫(kù)
1.爬蟲(chóng)使用的crawlergo,效果挺不錯(cuò)的,但還是不太滿(mǎn)足我的需求(造輪子的心態(tài)又膨脹了)
2.數(shù)據(jù)庫(kù)使用的mongodb
3.用celery分散調(diào)用,由于用到了celery,又用到了rabbitmq消息編碼,鮮花監(jiān)控
4.用了服務(wù)器醬進(jìn)行微信推送(得到一個(gè)擴(kuò)展微信就會(huì)響一次)
優(yōu)化了檢測(cè)邏輯,加入了去重處理后,現(xiàn)在既掃描的慢且推動(dòng)的消息也變少了
經(jīng)過(guò)縮短對(duì)src的掃描后,成功還是挺多的(很多都?xì)w功于爬蟲(chóng))
總結(jié)
以上是生活随笔為你收集整理的渗透开发-XSS扫描器的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 2、Scala下载、安装、环境搭建、及基
- 下一篇: 数字图像相关(Digital Image