代码审计 | DedeCMS v 5.7 sp2 RemoveXSS bypass
字数 1278 2025-08-18 11:37:33
DedeCMS v5.7 SP2 RemoveXSS函数绕过分析与防御
漏洞概述
DedeCMS(织梦CMS)v5.7 SP2版本中的XSS过滤函数RemoveXSS存在设计缺陷,攻击者可以通过多种方式绕过其过滤机制,导致反射型XSS漏洞。该漏洞位于/include/helpers/filter.helper.php文件中。
漏洞分析
RemoveXSS函数工作原理
- 解码阶段:函数首先将十进制和十六进制编码(如
&#xxxxxxxxxx;)转换回原始字符 - 过滤阶段:使用
$ra1和$ra2中的黑名单进行过滤替换- 例如:
javascript:alert(1)会被过滤为ja<x>vasc<x>ript:alert(1)
- 例如:
绕过方法一:双重编码
- 输入:
javascrip%26%2338%3B%26%2335%3B%26%2349%3B%26%2349%3B%26%2354%3B%26%2359%3B:alert(1); - URL解码后:
javascrip&#116;:alert(1); - RemoveXSS第一次处理:将
&#xxxxxxxxxx;转换后得到javascript:alert(1); - 黑名单过滤:
javascript不在黑名单内,不被过滤 - 最终HTML输出:
t被解析为字母t,形成javascript:alert(1);
绕过方法二:省略分号
- 正则表达式匹配
&#xxxxxx;需要分号结尾 - 但

等于换行符,不需要分号结尾也能被浏览器解析 - 例如:
jªvascript(无分号)可绕过正则匹配但仍能执行
绕过方法三:超长十六进制编码
- 正则表达式匹配
&#[xX]0{0,8}([9ab]);,限制在0-8个字符 - 十六进制格式可包含多个前导零,超过8位则无法匹配
- 例如:
t(超过8个前导零)
- 例如:
漏洞总结
RemoveXSS函数存在三个主要问题:
- 双重编码绕过:对双重编码的输入处理不当,导致黑名单失效
- 分号依赖问题:正则表达式依赖分号结尾,但某些HTML实体可不使用分号
- 长度限制问题:对十六进制实体长度限制不足,允许超长编码绕过
防御建议
- 输入规范化:在处理前先统一解码所有编码形式的输入
- 严格实体解析:要求所有HTML实体必须包含分号
- 白名单替代黑名单:使用允许的安全模式而非过滤危险模式
- 输出编码:在输出时根据上下文进行适当的编码
- 更新正则表达式:修正长度限制和分号要求的问题
测试验证
测试Payload示例:
javascrip%26%2338%3B%26%2335%3B%26%2349%3B%26%2349%3B%26%2354%3B%26%2359%3B:alert(1);
jªvascript:alert(1);
javascript:alert(1);
修复方案
- 升级到官方最新版本
- 手动修改
filter.helper.php文件:- 加强编码处理逻辑
- 修正正则表达式限制
- 增加对双重编码的防护
参考
- 漏洞发现者:q601333824
- 原始文章发布时间:2018-08-30
- 相关CVE:无公开CVE编号
- 影响版本:DedeCMS-V5.7-UTF8-SP2及之前版本