XSS-labs安裝以及解題思路
0x00 xss-labs
一個專門練習xss
的漏洞平台、cwth。https://pan.baidu.com/s/1eEbtIKrEzSvhtBDG0svIFAxss-labs
一共有level 20
,盡力去做着看看,GOGOGO
。
0x01 Level 1 without filter
看了好半天才看出來是啥意思。。。前端里面只有一個跳轉到第二關的JS
而且還記錄了payload
的長度,看來挑戰還是挑戰,還希望xss
用最小長度去完成,算了玩不起,現在能通關就可以了(手動狗頭),這里使用<script>alert('xss')</script>
就可以了。
這里很好奇為什么可以自動到第二關,所以就去查了下php
源碼。
<?php ini_set("display_errors", 0); $str = $_GET["name"]; echo "<h2 align=center>歡迎用戶".$str."</h2>"; ?>
這里有個ini_set("display_errors", 0)
,結果是用來看控制php
錯誤報告的,看來原因就是在前端剛剛的那個腳本上了,其實就是當彈框的時候就會自動重定向到下一跳,感覺是把windows.alert
函數進行重寫了,同時查了下幾個彈窗函數的區別,詳細區別請點我。
0x02 Level 2 close label
直接輸入上一關的腳本,查看結果。
腳本完全輸入了,這里應該是被實體轉義了,查看前端代碼。
一共有兩處,第一處就是顯示的地方,這里應該是被做轉義了,嘗試第二次,先將<input>
閉合,構造payload
為"><script>alert('xss')</script>
,成功彈窗。
0x03 level 3 htmlspecialchar() and close with ’
沒想到第三關開始圖片居然做懶了,不過這個紅色的括號不曉得是不是提示,哈哈。
一樣的,先走一波。
結果完全輸出了,但是很奇怪輸入框中怎么就少了一部分,看前端去。
原來這次下面也做了實體轉義,但是明顯看到前面的一部分沒有被轉義,之前在Pikachu
遇到過,閉合再構造就可以了'onclick='alert("xss")
,之所以不用<script>
是因為<>
仍然會被轉義,只是由於當作字符串來顯示,所以看到的是正常的而已。
到這里還需要最后一步,在空白的框里點擊一下,就會成功進行第四關。
這里除了onclick
以外還可以使用onmouseover
,'onmouseover='alert(/xss/)
,這個時候只需要把鼠標放上去就可以了。
0x04 level 4 filter <> and close with "
不曉得是不會再也不會有騷話看了。。按上一關的方式扔進去,必然失敗,看前端。
發現'
原樣輸出,不知道是實體了還是沒過濾,用'"&<>
試一下。
發現只有一個'
了,而且還有一個提示,payload
的長度只有3
,我明明打的是5
個,這里說明應該是有過濾的,查看前端。
結果應該是<>
被過濾了,嘗試一下。
果然是所有的<>
都被過濾了。那這個題,就沿用上一題的思路,用onclick
,但是用上一關的payload
失敗了,仔細觀察代碼。
那這次直接使用"
閉合嘗試。
有戲,構造"onclick="alert(/xss/)
,然后點擊框即可。
0x05 level 5 href
用上一關的payload
,失敗,看前端。
不曉得發生了啥,o
后面多了個_
。。。。嘗試了下,好像就是on
被針對了,再試試其余的特殊符號。
看來確實是"
閉合的,然后嘗試了<script>
發現同樣被針對了。。
還嘗試了大小寫,但是均輸出為小寫,應該也是做了轉換的。
看來前面幾關的用法都不行了,再試試href
,構造一個"><a href='javascript:alert(/xss/)'>
。
點一下,點一下就好了!!!
另外去看了下源代碼,基本都猜對了。
0x06 level 6 Case Sensitive
又看到騷圖了,沒看懂。。。。老規矩,直接將上一關的扔進來,肯定失敗,看前端。
這次連href
也干掉了。。。都扔進去試試看。
哎喲,大小寫給取消了。構造"><a+hRef='javascript:alert(/xss/)'>
。
順利搞定了,但是有個地方感覺很奇怪,前端里面多出來不少東西,不曉得哪來的,我以為是圖片的提示。。。
看源碼了,沒發現什么,到是多過濾了一個data
,可能就是下一關的提示,說得我都信了。。。
$str = $_GET["keyword"]; $str2=str_replace("<script","<scr_ipt",$str); $str3=str_replace("on","o_n",$str2); $str4=str_replace("src","sr_c",$str3); $str5=str_replace("data","da_ta",$str4); $str6=str_replace("href","hr_ef",$str5);
0x07 level 7 double writing
7
的力量,有點慌。。。老規矩走一波。
似乎這次不管大小寫都給過濾掉了,雙寫???
可行,構造"><a hrhRefef='javascrscriptipt:alert(/xss/)'>
,果然777777
,搞定。
0x08 level 8 with htmlspecialchar()
感覺這是href
直接搞上去了阿。
試了下,但是發現又搞了些騷東西
估計是script
不讓用了,用大寫也是一樣的,其它的幾個方法也都用了,但是同樣也被針對搞了。沒辦法,只能先去看源碼了。
<?php ini_set("display_errors", 0); $str = strtolower($_GET["keyword"]); $str2=str_replace("script","scr_ipt",$str); $str3=str_replace("on","o_n",$str2); $str4=str_replace("src","sr_c",$str3); $str5=str_replace("data","da_ta",$str4); $str6=str_replace("href","hr_ef",$str5); $str7=str_replace('"','"',$str6); echo '<center> <form action=level8.php method=GET> <input name=keyword value="'.htmlspecialchars($str).'"> <input type=submit name=submit value=添加友情鏈接 /> </form> </center>'; ?> <?php echo '<center><BR><a href="'.$str7.'">友情鏈接</a></center>'; ?>
都差不多猜對了,看完源碼后,覺得這題的突破點在友情鏈接
那沒有用實體轉義,所以可以這么搞一下,直接把scirpt
轉成實體script
,這樣就可以突破過濾了,反正在友情鏈接那的時候會轉成script
,當點擊的時候就可以觸發了,Go
一把。
點擊就可以搞定了。
0x09 level 9 include detect
哎,圖越來越沒意思,差評!老規矩,走一波。
牛逼了。。。試了半天,只有http://
開頭的才行,百度了半天XSS payload
都沒找到能用的,只能去看源碼了。。。
<?php if(false===strpos($str7,'http://')) { echo '<center><BR><a href="您的鏈接不合法?有沒有!">友情鏈接</a></center>'; } else { echo '<center><BR><a href="'.$str7.'">友情鏈接</a></center>'; } ?>
原來不是開頭,而是包含就可以了。。。服了,那和上一題一樣,彈框的信息里面包含就可以了,javascript:alert('xsshttp://')
點擊友情鏈接
就行了,被自己蠢到了。
0x10 level 10 leak_information
又沒有框了,莫得了靈魂。。。走一波走一波。
完全輸出了,應該是做了實體轉換的,但是在看前端的地方發現了奇怪的表單。。。burpsuite
里面走一下,並沒有發現什么東西。。。
有點傻,看源碼吧。。。
<?php ini_set("display_errors", 0); $str = $_GET["keyword"]; $str11 = $_GET["t_sort"]; $str22=str_replace(">","",$str11); $str33=str_replace("<","",$str22); echo "<h2 align=center>沒有找到和".htmlspecialchars($str)."相關的結果.</h2>".'<center> <form id=search> <input name="t_link" value="'.'" type="hidden"> <input name="t_history" value="'.'" type="hidden"> <input name="t_sort" value="'.$str33.'" type="hidden"> //???????????? </form> </center>'; ?>
這源碼里面的t_sort
啥鬼,一點提示都沒。。。構造"onclick="alert(/xss/)
,此時改變url
為keyword=nidaye&t_sort="onmouseover="alert(/xss/)
,查看結果
感覺沒問題,但是,這玩意在哪,鼠標好像沒地方放啊。。。。。。。還得把hidden
給取消掉,服了。。。"type='text' onclick="javascript:alert(/xss/)
,然后會出來一個框,點擊一下就行了。
0x11 level 11 referer
我現在懷疑他的圖就是找的而不是做的,沒有美工,差評!!!我不會再上當了,直接看源碼
<?php ini_set("display_errors", 0); $str = $_GET["keyword"]; $str00 = $_GET["t_sort"]; $str11=$_SERVER['HTTP_REFERER']; $str22=str_replace(">","",$str11); $str33=str_replace("<","",$str22); echo "<h2 align=center>沒有找到和".htmlspecialchars($str)."相關的結果.</h2>".'<center> <form id=search> <input name="t_link" value="'.'" type="hidden"> <input name="t_history" value="'.'" type="hidden"> <input name="t_sort" value="'.htmlspecialchars($str00).'" type="hidden"> <input name="t_ref" value="'.$str33.'" type="hidden"> </form> </center>'; ?>
這次還得有'HTTP_REFERER'
了,和上一題沒差別,用modify headers
構造就可以了。
同樣也會有個框,點擊即可。
0x12 level 12 UA
沒有長鼻子的烏索普??
<?php ini_set("display_errors", 0); $str = $_GET["keyword"]; $str00 = $_GET["t_sort"]; $str11=$_SERVER['HTTP_USER_AGENT']; $str22=str_replace(">","",$str11); $str33=str_replace("<","",$str22); echo "<h2 align=center>沒有找到和".htmlspecialchars($str)."相關的結果.</h2>".'<center> <form id=search> <input name="t_link" value="'.'" type="hidden"> <input name="t_history" value="'.'" type="hidden"> <input name="t_sort" value="'.htmlspecialchars($str00).'" type="hidden"> <input name="t_ua" value="'.$str33.'" type="hidden"> </form> </center>'; ?>
這次用UA
了,換換換。GOGOGO
0x13 level 13 cookie
講道理,這個圖片有點那個吧。。。咳咳
<?php setcookie("user", "call me maybe?", time()+3600); ini_set("display_errors", 0); $str = $_GET["keyword"]; $str00 = $_GET["t_sort"]; $str11=$_COOKIE["user"]; $str22=str_replace(">","",$str11); $str33=str_replace("<","",$str22); echo "<h2 align=center>沒有找到和".htmlspecialchars($str)."相關的結果.</h2>".'<center> <form id=search> <input name="t_link" value="'.'" type="hidden"> <input name="t_history" value="'.'" type="hidden"> <input name="t_sort" value="'.htmlspecialchars($str00).'" type="hidden"> <input name="t_cook" value="'.$str33.'" type="hidden"> </form> </center>'; ?>
很好,換成cookie
了,這次換burpsuite
來改了,我這垃圾插件有bug
,誰有52版firefox
的cookie
插件賞我一個吧。。。GOGOGO
就完事了。
0x14 level 14 exif xss
有點意思,看了半天發現了一個302
的鏈接
有點沒看明白,看源碼吧。
<body> <h1 align=center>歡迎來到level14</h1> <center><iframe name="leftframe" marginwidth=10 marginheight=10 src="http://www.exifviewer.org/" frameborder=no width="80%" scrolling="no" height=80%></iframe></center><center>這關成功后不會自動跳轉。成功者<a href=/xsschallenge/level15.php?src=1.gif>點我進level15</a></center> </body>
好吧,現在這個網站無法訪問,我這邊也沒有辦法測試了,查了下writeup
,稱之為exit xss
。。。
就當漲姿勢了,哈哈
0x15 level 15 angularjs
看到這里有點傻眼,但是想到上一關進不去的時候,好像url
里面有參數,回去看一眼。。
雖然這里的目錄不對,但是可以看到url
里面有個src
,應該是往里面傳參數吧,嘗試了下,又發現一個東西。
又在前端看到了這么個東西。
去搜索了下ng-include
,之前都沒見過這個,沒怎么看明白。。。,然后因為代碼里面的資源失效了,所以得重新改一下。
https://cdn.staticfile.org/angular.js/1.4.6/angular.min.js
修改完了以后還是不能執行,真的是對這個angularjs
不了解,又換了幾個,最終在一個writeup
中找到了這么一段。'level1.php?name=<IMG SRC=1 onerror=alert("xss")>'
,利用第一關的鏈接來完成,而且我把后面的img
換成其他的也不可以,這個哥們說的有點像,其實沒太理解。。。
這兩關玩的有點難受,希望下一關能夠快樂一點。。。
0x16 level 16 %0a
這是個啥游戲。。。走一波。
發現script
直接被刪除了,</script>
中的/
也被刪除過濾了,那就再換成上一關的<img src=1 onerror=alert("xss")>
好像空格也被搞了,被實體轉換了,使用%0a
替代空格。
搞定搞定,去看下源代碼
<?php ini_set("display_errors", 0); $str = strtolower($_GET["keyword"]); $str2=str_replace("script"," ",$str); $str3=str_replace(" "," ",$str2); $str4=str_replace("/"," ",$str3); $str5=str_replace(" "," ",$str4); echo "<center>".$str5."</center>"; ?>
我還以為做了實體轉換和過濾,原來只是做了替換,難怪之前嘗試了雙寫也不行。。
0x17 level 17 args
哎,圖都沒有了。。。<embed>
用來定義嵌入的內容,所以這里應該是插入了一個swf
圖片,后面那個?a=b
又是啥玩意。。。還是看源碼吧。
<?php ini_set("display_errors", 0); echo "<embed src=xsf01.swf?".htmlspecialchars($_GET["arg01"])."=".htmlspecialchars($_GET["arg02"])." width=100% heigth=100%>"; ?>
原來只是需要提交兩個參數,用a
和b
代替,參數還被轉義了。。。突然看到這個,我瞎了
構造一個arg01=%20onclick&arg02=alert(/xss/)
感覺都是對的,哪都點了,就是不行,折騰了半天發現,firefox
這個swf
好像讀不出來。。。切換到chrome
,想罵人,對不起,我錯了不該噴作者偷懶。。。。。。。。。。。
然后點了圖片還是不行,於是想着換了一個payload
,鼠標放上去就行的那種onmouseover
或者onfocus
都行。。
哭了。。。
0x18 level 18 ??????
能不能用心點,什么破圖,都快結束了,還搞這么爛。。。
用上一關的payload
直接過了,看源碼也沒看出啥區別,什么鬼???????????
0x19 level 19 flash xss
嘗試了一翻后再結合源碼發現好像怎么都不太行了。
只能用"
閉合,但是"
會被轉義,無法閉合,所以即使看起來是好的,也無法彈框。。。
查了下,好像得要做flash
反編譯才行,提不起興趣。。。以后再說吧,先記個答案 。arg01=version&arg02=<a href="javascript:alert(1)">123</a>
來了,來了,點我進詳解
level 19 flash xss
查看前端代碼,發現訪問swf
的時候在傳參
接下來直接訪問這個鏈接。
這里可以看到flash
里面提示sifr.js
是沒有定義的,這不僅僅是個圖片。。。
需要對flash
進行反編譯查看源碼,使用的是jpexs,沒想到有一天我也會干這樣的事了,羞恥啊。。。
通過sifr
找到了對應的腳本位置,比較長,就一點點說明過程了。
在此腳本中找到了flash
顯示的信息,關鍵在%s
這里。
接着去定位%s
,
這里先把VERSION.WARNING
以%s
打散成數組,然后再以version
的方式組合成字符串。搜索了一圈,並沒有version
,哎,對flash
太不熟悉了,只通過p-code
發現了這樣的一個東西。。。
感覺是通過url
里面獲取變量的,於是構造了一個嘗試arg01=version&arg02=123
,原因是php
里面是這樣傳參的,必須是兩個值。
<?php ini_set("display_errors", 0); echo '<embed src="xsf03.swf?'.htmlspecialchars($_GET["arg01"])."=".htmlspecialchars($_GET["arg02"]).'" width=100% heigth=100%>'; ?>
結果和預期一樣,123
出現了。
嘗試了大量xss
語句發現,只有<a>
這種可以,如果是img
或者svg
后面都會不完整,所以就構造了語句arg01=version&arg02=<a href="javascript:alert(/xss/)">xss</a>
點擊xss
就可以進入下一關了。
花了3
小時,第一次干這種事,刺激、蛋疼、掉頭發、成就感,哈哈。不過中間還是有不少函數沒搞得太懂,暫時就不深究了,慢慢積累,改天回來看就能看懂,不急。。。
0x20 level 20 flash xss
換成了白色的flash
,和19關一樣,暫時沒啥興趣,記個答案再說,以后單獨開一個寫,肯定不使鴿,哈哈哈 。。。arg01=id&arg02=\%22))}catch(e){}if(!self.a)self.a=!alert(1)//%26width%26height
詳細解釋請點我,兩天就更了,沒想到吧~
level 20 Flash XSS
一片空白的flash
,上一關的思路的沒有了,只有來審計代碼了。。。
package { import flash.display.LoaderInfo; import flash.display.Sprite; import flash.display.StageScaleMode; import flash.events.Event; import flash.events.MouseEvent; import flash.external.ExternalInterface; import flash.system.Security; import flash.system.System; public class ZeroClipboard extends Sprite { private var button:Sprite; private var id:String = ""; private var clipText:String = ""; public function ZeroClipboard() { super(); stage.scaleMode = StageScaleMode.EXACT_FIT; Security.allowDomain("*"); var flashvars:Object = LoaderInfo(this.root.loaderInfo).parameters; id = flashvars.id; button = new Sprite(); button.buttonMode = true; button.useHandCursor = true; button.graphics.beginFill(13434624); button.graphics.drawRect(0,0,Math.floor(flashvars.width),Math.floor(flashvars.height)); button.alpha = 0; addChild(button); button.addEventListener(MouseEvent.CLICK,clickHandler); button.addEventListener(MouseEvent.MOUSE_OVER,function(param1:Event):* { ExternalInterface.call("ZeroClipboard.dispatch",id,"mouseOver",null); }); button.addEventListener(MouseEvent.MOUSE_OUT,function(param1:Event):* { ExternalInterface.call("ZeroClipboard.dispatch",id,"mouseOut",null); }); button.addEventListener(MouseEvent.MOUSE_DOWN,function(param1:Event):* { ExternalInterface.call("ZeroClipboard.dispatch",id,"mouseDown",null); }); button.addEventListener(MouseEvent.MOUSE_UP,function(param1:Event):* { ExternalInterface.call("ZeroClipboard.dispatch",id,"mouseUp",null); }); ExternalInterface.addCallback("setHandCursor",setHandCursor); ExternalInterface.addCallback("setText",setText); ExternalInterface.call("ZeroClipboard.dispatch",id,"load",null); } public function setHandCursor(param1:Boolean) : * { button.useHandCursor = param1; } private function clickHandler(param1:Event) : void { System.setClipboard(clipText); ExternalInterface.call("ZeroClipboard.dispatch",id,"complete",clipText); } public function setText(param1:*) : * { clipText = param1; } } }
還好不是很長,這個和上一關代碼明顯不一樣,上一關是getlURL
,而這一關是ExternalInterface.call
。
首先通過LoaderInfo
從URL
中取值
除了上面的id
以外還要取兩個值width
和height
。
接下來構造payload
就可以了,arg01=id&arg02=xss\"))}catch(e){alert(/xss/)}//%26width=123%26height=123
首先arg01=id
這個就不用解釋了,arg02=xss\"))}catch(e){alert(/xss/)}//
這個地方有不少要說明的,首先為什么要加"
,來看看不加的結果
所以要加一個"
進行閉合,讓id
不等於xss))}catch(e){alert(/xss/)}//
,因為等下會直接將id
的值全部都傳到flash
中,flash
中仍然也有需閉合的部分,再來看看有\"
的結果
你會發現好像沒有什么變化,這因為php
做了htmlspecialchar()
過濾,至於為什么這樣寫,那就得看flash
的代碼了,等會id
就會傳到下面來
后面的可以不用管,因為會被我后面的//
給注釋掉,這里注意,由於是通過LoaderInfo
取值的,所以就會變成這個樣子
{ "id" = "xss\"))}catch(e){alert(/xss/)}//" }
可以看到,如果不加\
轉義id
就會變成xss
,也就是下面的這個樣子,當id
再傳到里面的函數里面時就起不到報錯的作用了。
{ "id" = "xss"))}catch(e){alert(/xss/)}//" }
接下來有許多函數都使用了id
,ExternalInterface.call(a,b)
相當於JS
中的函數名(代碼)
我們可以看到上面函數名
已經固定了,要是沒固定直接改成alert
美滋滋,所以我們就從id
這里着手,把id
的值代進去。
ExternalInterface.call("xxxx","xss\"))}catch(e){alert(/xss/)}//"),這樣不太容易看的話,換種方式 private function clickHandler(param1:Event) : void { System.setClipboard(clipText); ExternalInterface.call("ZeroClipboard.dispatch","xss\"))}catch(e){alert(/xss/)}//","complete",clipText); }
把多余的去掉就會變成這樣
private function clickHandler(param1:Event) : void { ExternalInterface.call("ZeroClipboard.dispatch","xss\"))}catch(e){ alert(/xss/) } //","complete",clipText); }
然后你就會發現這樣一搞,由於前面少了一個真正可以閉合的"
於是會報錯,所以后面拋出異常的catch
就可以生效了,於是執行后面的alert(/xss/)
。
再來說下//
后面的%26width=123&26height=123
,%26
其實是&
,那為啥非得寫%26
呢,先來看一個&
的。
你會發現啥都沒有,因為php
就拿前兩個參數,再看%26
可以了,訪問這個地址就搞定了,不得不說我覺得我能耐心把這兩題做完,感覺這一年學習真的有進步,哈哈。
其實通過這個我還搞出來了兩個其它的payload
也可以過關,大家就自己想吧~