xss-labs Level1 代码审计报告
目标文件:
level1.php| 漏洞类型: 反射型 XSS(Reflected Cross-Site Scripting) | CWE: CWE-79 / CWE-80 | 危害等级: 高危
风险路径:GET /level1.php?name=<payload>→echo直接输出 → 浏览器执行
一、漏洞代码定位
level1.php 第 15-23 行:
<?php
ini_set("display_errors", 0);
$str = $_GET["name"]; // L17 直接取 GET 参数,无任何过滤/校验
echo "<h2 align=center>欢迎用户".$str."</h2>"; // L18 未经任何编码直接拼接进 HTML 输出
?>
漏洞点: L18。$_GET["name"] 未经 htmlspecialchars()/过滤,直接拼入 HTML 上下文。
二、漏洞原理
- 服务端把用户可控的
name参数原样回显到<h2>标签的文本内容中,且页面没有任何 CSP、无转义。 - 攻击者传入闭合标签后注入的任意 HTML/JS,浏览器会把它当作页面结构解析并执行。
- 该关卡属于"无任何防护"的基准关,是其余 19 关过滤/编码绕过的对照组。
- 附带问题(次要):
$_GET["name"]未判断是否存在,直接访问无参数时会触发 PHP Notice;display_errors虽已关闭,但更应检查并给默认值。
三、利用方式与 Yakit 可重放数据包
Payload(URL 解码后):
?name=<script>alert(1)</script>
Yakit 可重放原始请求(在 Yakit「Web Fuzzer / 数据包重放」中粘贴发送,Host 与路径按实际部署调整):
GET /level1.php?name=%3Cscript%3Ealert(1)%3C%2Fscript%3E HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0
Accept: text/html
Connection: close
触发方式: 直接发送后,页面回显 欢迎用户<script>alert(1)</script>,alert(1) 自动执行 → 命中通关逻辑(alert 被劫持为 confirm"完成的不错!"并跳转 level2)。
四、修复建议
$str = $_GET["name"] ?? ""; // 1. 参数存在性兜底
echo "<h2 align=center>欢迎用户"
.htmlspecialchars($str, ENT_QUOTES, 'UTF-8') // 2. 输出编码,同时转义单双引号
."</h2>";
要点:
- 输出上下文转义: 对拼接进 HTML 的用户输入一律
htmlspecialchars(..., ENT_QUOTES, 'UTF-8')。 - 优先使用模板引擎 / 视图层自动转义,避免手写
echo拼接。 - 全局启用
Content-Security-Policy(如default-src 'self')作为纵深防御,防止反射型 XSS 落地执行。 - 参数使用前做类型/长度校验,
$_GET加??兜底。
五、备注
- 该关在所有 PHP 版本下均可利用(无任何编码),可作为 XSS 基线用例。
- 参考: OWASP XSS Prevention Cheat Sheet(使用上下文感知编码)。
正文完