Atlassian Confluence 模板注入漏洞(CVE-2023-22527)
type
status
date
slug
summary
tags
category
icon
password
AI summary
文章首发自奇安信攻防社区
漏洞分析
漏洞原理
在Confluence中,.vm文件是使用Velocity模板语言创建的模板文件。Velocity是一个基于Java的模板引擎,它允许你使用简单的标记语言来引用Java对象和方法,从而动态生成HTML、XML或任何文本格式的内容。
处理.vm文件的主要类是ConfluenceVelocityServlet。这个Servlet负责接收和处理来自浏览器的请求,加载和解析.vm模板,执行其中的Velocity代码,然后将生成的HTML发送回浏览器。
这次的漏洞点位于:/template/aui/text-inline.vm文件,可以直接通过/template/aui/text-inline.vm访问
$stack.findValue("getText('$parameters.label')")
意味着从请求中获取的label参数的值传入了$stack.findValue
,由此可以判断这里存在模版注入!调用分析
.vm文件由
ConfluenceVelocityServlet
处理
继续跟进
这里跟进
handleRequest()
,可以发现从URI中获取vm文件路径,传入getTemplate()
来返回模版对象

然后传入
mergeTemplate()
函数处理
这里创建新的PageContext,获取其输出流,准备进行模板合并和输出操作。
继续跟进
template.merge()

跟进到merge的重载函数
由于传入的macroLibraries为空,所以直接执行try逻辑
- 调用
ica.pushCurrentTemplateName(this.name);
将当前模板的名称压入到ica
的模板名堆栈中。这是为了在嵌套模板的情况下能够追踪到当前正在处理的模板名称。
- 调用
ica.setCurrentResource(this);
将当前模板对象设置为ica
的当前资源。这是为了让ica
知道当前正在处理的模板资源。
- 最后,通过调用
((SimpleNode)this.data).render(ica, writer);
进行模板渲染
省略中间的部分渲染过程,跟进到
ASTReference#execute()

这里从上下文中获取OgnlValueStack,继续跟进


这里从请求中获取到参数,然后通过
Object obj = method.invoke(o, params);
执行,继续跟进
经过几层invoke调用后,来到了最终vm文件模版的位置——
OgnlValueStack.findValue()

随后,传给label参数的OGNL表达式语句被执行

绕过沙箱RCE
对于Velocity模版引擎,可以使用如下方法:
.KEY_velocity.struts2.context
-> (StrutsVelocityContext
)ognl
(org.apache.struts2.views.jsp.ui.OgnlTool
)struts
(org.apache.struts2.views.velocity.result.VelocityStrutsUtils
)
org.apache.struts2.views.jsp.ui.OgnlTool 类在没有 OgnlContext 的情况下调用了 Ognl.getValue()。需要注意的是,该类属于 OGNL 库,而不是 Struts 的一部分。因此,这个"findValue"调用在 Struts 的沙箱限制之外运行。

漏洞复现
- 网站首页如下图:

- 使用如下POC进行漏洞复现

Loading...