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

18次阅读
没有评论

xss-labs Level3 代码审计报告

目标文件: level3.php | 漏洞类型: 反射型 XSS —— 单引号属性上下文注入 | CWE: CWE-79 / CWE-80 | 危害等级: 中危(依赖 PHP 版本,见备注)
风险路径: GET /level3.php?keyword=<payload> → <input value='...'> 单引号属性注入


一、漏洞代码定位

level3.php 第 17-22 行:

$str = $_GET["keyword"];
echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>"."<center>
<form action=level3.php method=GET>
<input name=keyword  value='".htmlspecialchars($str)."'>   // L20 单引号包裹 + htmlspecialchars
<input type=submit name=submit value=搜索 />
</form>
</center>";

漏洞点: L20。属性值用单引号包裹,并做了 htmlspecialchars()。看似"既转义又引号包裹",但:

  • htmlspecialchars() 的默认标志位是 ENT_COMPAT(旧版 PHP 默认只转义双引号 ",不转义单引号 '),因此单引号 ' 仍能原样穿出属性。
  • 开发者误以为"转义了"就是安全的,忽略了单引号包裹 + 默认标志位这一组合。

二、漏洞原理

  • 属性 value='...' 用单引号定界,而 htmlspecialchars($str) 在旧版 PHP 下不转义 ',攻击者用一个 ' 即可闭合属性,再注入事件属性。
  • 注意与 Level2 的区别:Level2 是"完全没转义",Level3 是"转义了但定界符用错了(单引号)+ 默认标志位漏转义"。

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

Payload(URL 解码后):

?keyword=' onfocus=alert(1) autofocus='

渲染结果: <input name=keyword value='' onfocus=alert(1) autofocus=''> → 单引号闭合 value,注入 onfocus + autofocus,autofocus 自动聚焦并触发 onfocus。

Yakit 可重放原始请求:

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

触发方式: 页面加载后输入框被 autofocus,onfocus 触发 alert(1) → 命中通关逻辑跳转 level4。


四、修复建议

$str = $_GET["keyword"] ?? "";
$safe = htmlspecialchars($str, ENT_QUOTES, 'UTF-8');   // 明确 ENT_QUOTES,同时转义单引号与双引号
echo "<h2 align=center>没有找到和".$safe."相关的结果.</h2>"
   . '<center>
      <form action=level3.php method=GET>
      <input name=keyword  value="'.$safe.'">           // 属性定界符统一改用双引号
      <input type=submit name=submit value=搜索 />
      </form></center>';

要点:

  1. 永远显式指定转义标志位 ENT_QUOTES,不要依赖 htmlspecialchars() 的默认值(不同 PHP 版本默认值不同,极易被误用)。
  2. 属性定界符统一用双引号,与转义策略保持一致。
  3. 配置 php.ini/代码中显式声明默认编码,避免编码推断导致的转义失效。

五、备注

  • PHP 版本依赖(重要): 本关经典利用仅在 PHP < 8.1 有效 —— 旧版 htmlspecialchars() 默认 ENT_COMPAT,不转义单引号。PHP 8.1+ 已把默认值改为 ENT_QUOTES,默认就会转义 '(输出为 &#039;,浏览器解析后是属性值内部的字符而非定界符),该利用默认失效。
  • 因此审计结论: 旧环境(PHP 5.x / 7.x)中危可利用;新环境(PHP 8.1+)该点默认已免疫,但仍建议按"修复建议"统一加固,因为这是"靠默认值碰巧安全"的脆弱代码。
  • 若需在 PHP 8.1+ 复现教学场景,可在 php.ini 或代码里手动 htmlspecialchars($str, ENT_COMPAT) 模拟旧行为。
正文完
 0