XSLT注入与安全修复方法
XSLT注入概述
XSLT注入是一种安全漏洞,攻击者通过操纵XSLT(可扩展样式表语言转换)的输入参数或样式表内容,执行恶意操作(如文件读取、远程代码执行、服务端请求伪造)。当用户输入未经严格过滤直接嵌入XSLT处理流程时,可能触发此类漏洞。
常见攻击场景与危害
敏感文件读取
xslt
<!-- 用户控制参数读取系统文件 --> <xsl:value-of select="document('/etc/passwd')"/>
危害:泄露服务器敏感信息。
远程代码执行(依赖扩展函数)
xslt
<!-- 调用Java扩展(Java处理器) --> <xsl:value-of select="java:java.lang.Runtime.getRuntime().exec('rm -rf /')"/>
危害:服务器被完全控制。
SSRF(服务端请求伪造)
xslt
<!-- 访问内部网络资源 --> <xsl:copy-of select="document('http://internal-server/secret-data')"/>
危害:探测内网、攻击内部系统。
拒绝服务(DoS)
xslt
<!-- 恶意递归消耗资源 --> <xsl:template name="attack"><xsl:call-template name="attack"/> </xsl:template>
危害:服务器资源耗尽崩溃。
修复方法
1. 严格输入验证与过滤
策略:对所有用户输入的参数进行白名单校验。
示例(Java):
java
// 仅允许字母数字 if (!input.matches("[a-zA-Z0-9]+")) {throw new SecurityException("非法输入"); }
2. 禁用危险函数
配置XSLT处理器:
java
// Java示例:禁用外部文档访问 TransformerFactory factory = TransformerFactory.newInstance(); factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
3. 安全传递参数
使用
<xsl:param>
代替字符串拼接:
错误方式(危险拼接):xslt
<xsl:variable name="userInput" select="'ATTACKER_INPUT'"/>
正确方式(安全传参):
java
// Java代码 Transformer transformer = ...; transformer.setParameter("userParam", sanitizedInput);
xslt
<!-- XSLT中直接使用参数 --> <xsl:param name="userParam"/> <xsl:value-of select="$userParam"/>
4. 限制处理器功能
.NET示例:禁用
document()
函数csharp
XsltSettings settings = new XsltSettings {EnableDocumentFunction = false // 关键配置 }; XslCompiledTransform xslt = new XslCompiledTransform(); xslt.Load("style.xslt", settings, null);
5. 输出编码
对输出内容进行XML编码:
xslt
<xsl:output method="text" encoding="UTF-8"/> <xsl:value-of select="..."/> <!-- 自动编码 -->
6. 沙箱环境运行
使用低权限用户执行XSLT转换
容器化处理进程(如Docker)
最佳实践总结
措施 | 实现方式 |
---|---|
输入验证 | 白名单过滤特殊字符(< , > , ' , " , & ) |
禁用外部实体 | 设置FEATURE_SECURE_PROCESSING |
参数化传递 | 用setParameter() 代替字符串拼接 |
最小化处理器权限 | 关闭document() , xsl:message 等危险功能 |
输出编码 | 强制指定<xsl:output method="text"> |
💡 关键原则:绝不信任用户输入。XSLT注入防御的核心是控制输入源与限制处理器能力,而非依赖黑名单过滤。