Spring Boot中如何检测SVG文件包含的恶意JavaScript脚本?
Spring Boot 场景下SVG恶意JS代码检测与防护方案
不要依赖文件后缀、MIME类型校验判断文件合法性,这类信息攻击者可以轻易伪造,需要从内容层面做多层检测和防护:
1. 高危特征静态初筛
先对文件原始内容做快速匹配,拦截明显的恶意注入特征,注意匹配逻辑要覆盖大小写变形场景:
- 匹配
<script标签,不管标签是大写、小写还是大小写混写,只要存在这类标签直接拦截 - 匹配所有
on开头的事件属性,包括onload、onerror、onclick、onmouseover等所有可触发脚本执行的事件属性 - 匹配属性值中的
javascript:、vbscript:伪协议,以及XML外部实体声明<!ENTITY、带可执行内容的data:协议引用 - 匹配
<foreignObject>这类可嵌入外部HTML内容的特殊标签,业务无相关需求的话直接拦截
注意:正则匹配仅作为初筛手段,攻击者可以通过插入XML注释、字符编码拆分、属性加空白换行等方式绕过正则规则,不能作为唯一检测手段。
2. 基于XML DOM解析做深度检测
用安全配置的XML解析器把SVG解析成DOM树,逐节点逐属性校验,能覆盖绝大多数绕过场景:
- 首先配置解析器禁用DTD、外部实体,从根源避免XXE风险,参考配置代码如下:
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); // 禁用DOCTYPE声明 factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); // 禁用外部通用实体 factory.setFeature("http://xml.org/sax/features/external-general-entities", false); // 禁用外部参数实体 factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false); factory.setXIncludeAware(false); factory.setExpandEntityReferences(false); DocumentBuilder builder = factory.newDocumentBuilder(); // 传入上传文件的输入流完成解析 Document svgDoc = builder.parse(uploadInputStream);
- 解析完成后递归遍历所有DOM节点:
- 校验节点名称,若为
script等业务不需要的高危标签直接判定为恶意文件 - 遍历节点下的所有属性,只要属性名以
on开头(不区分大小写),或属性值包含危险脚本协议关键字,直接判定为恶意文件
- 校验节点名称,若为
3. 主动内容消毒(可靠性高于单纯检测)
不要只做拦截检测,建议对上传的SVG做主动消毒:保留SVG渲染必需的基础标签(如svg、path、rect、circle、gradient等)和样式属性,直接剥离所有脚本标签、事件属性、外部资源引用,消毒后的文件再存储到服务器,从根源消除注入风险。
4. 多层兜底防护
就算检测逻辑有漏网之鱼,也可以通过配置把攻击危害降到最低:
- 上传的SVG文件存储到独立的静态资源域名,和主业务域名隔离,避免恶意脚本读取主站的用户Cookie、认证信息
- 返回SVG资源时在HTTP响应头加
Content-Security-Policy: script-src 'none',直接禁止浏览器在该资源内执行任何脚本 - 响应头添加
X-Content-Type-Options: nosniff,防止浏览器错误把SVG识别为HTML文件解析执行脚本
内容的提问来源于stack exchange,提问作者Rejaul Karim
相关产品推荐
相关产品推荐

