xss-labs 是一套基于 PHP 的 XSS 靶场,以闯关的形式让我们体验各种 XSS 漏洞利用方式。虽然已经是很多年前的了,但其中基本的 XSS 漏洞依然很有意义。
一共有 20 关,每一关的目标都是实现弹窗(alert(1)),如果成功就会自动进入下一关。
(本文首发于 blog.skywt.cn,建议 查看原文以获得更好的阅读体验。)
环境搭建
克隆这个代码仓库的代码,其中是 xss-labs 的 PHP 源文件。只要放在 PHP 环境下即可,推荐使用 XAMPP 或者 Docker。
部署完成后,访问 index.php,就可以看到入口了:

Warm Up
前两关是对于 XSS 基本原理的应用,没有任何的防御。
Level 1:文本解析为 HTML
URL 为 level1.php?name=test 时,传入的参数是 test,显示的是「欢迎用户 test」。显然,这个页面会将我们传入的名字显示出来。
传入参数 <h1>test</h1> 作为 name,发现确实显示为了一级标题。看来传入的 name 直接被作为 HTML 显示了。于是尝试传入 <script>alert(1);</script> 作为 name,成功弹窗。
?name=<script>alert(1);</script>
Level 2:input 标签 value 注入
这关多了一个文本框。如果依然尝试传入 <script>alert(1);</script>,会发现在 h2 元素中符号被转义了(查看网页源代码能看到),比如 < 被转义成了 < 等,所以不会被解析成 HTML。
然而,可以看到后面的文本框 input 元素,其 value 值并没有被转义。
<h2 align=center>没有找到和<script>alert(1)</script>相关的结果.</h2><center>
<input name=keyword value="<script>alert(1)</script>">
既然如此,我们可以闭合 value 的内容的后引号,然后闭合这个 input 标签,接下来再加入我们想要注入的 <script>alert(1);</script>。只需要在其之前加上 "> 即可。
?keyword="><script>alert(1);</script>
字符过滤绕过
Level 3:htmlspecialchars() 的弱点
本题要求 PHP 版本低于 8.1.0。在 8.1.0 版本中此漏洞已经修复。
HTML 标准规定了一个叫做**实体(Entity)**的概念。在 HTML 中,<h1> 会被解释为标题标签,那我们如何以文本形式显示出 <h1> 这四个字符呢?答案是使用字符实体,将 < 用 < 替代,将 > 用 > 替代。在 HTML 中,如果我们写 <h1>,就会显示为 <h1> 而不会被解析。
在 PHP 中,后端需要渲染出一个 HTML 给前端,对传来的字符串就要进行这样的处理,将 < 这样的字符转换为 < 这样的实体。Level 1 就是没有进行这种处理的下场。
一个通常的做法就是:使用 PHP 自带的 htmlspecialchars() 函数处理字符串,进行字符转义。具体用法可以参考官方文档。
在 8.1.0 及以上的 PHP 版本中,这个函数默认会转义 <、>、&、'、" 这五个字符,基本可以防范这里的 XSS 攻击。
但是,8.1.0 以下版本的 PHP 默认只会转义 <、>、&、" 这四个字符,不会转义单引号 '。这就给这个函数带来了巨大的安全隐患。
回到这题,我们仍然尝试 ?keyword=<script>alert(1)</script>,打开页面源码,观察这个 input 输入框:
<input name=keyword value='<script>alert(1)</script>'>
没错,我们的字符被转义了。
然而,可以发现这里 value 的值用的是单引号。既然单引号不会被转义,我们可以闭合 value 这个字符串。
但是,<> 都会被转义,似乎不能闭合这个标签。有什么办法能够不用 <script> 标签来注入 JavaScript 代码呢?答案是使用触发器,比如 onfocus 或者 onmouseover。

文章详细介绍了XSS靶场xss-labs的各个关卡,通过实际操作演示了多种XSS攻击方式,包括字符过滤绕过、HTML实体利用、URI注入等,强调了PHP的htmlspecialchars()函数在防止XSS攻击中的作用以及其局限性,展示了XSS攻击的常见手段和防御策略。
最低0.47元/天 解锁文章
3876

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



