首页 » 漏洞 » 正文

Confluence未授权 RCE (CVE-2019-3396) 漏洞分析-互联网安全-漏洞

发表于: 知之为知 · 2019-4-15 ·  54 views  ·  0 replies 

看到官方发布了预警,于是开始了漏洞应急。漏洞描述中指出Confluence Server与Confluence数据中心中的Widget连接器存在服务端模板注入漏洞,攻击者能利用此漏洞能够实现目录穿越与远程代码执行。

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析

确认漏洞点是Widget Connector,下载最新版的比对补丁,发现在com\atlassian\confluence\extra\widgetconnector\WidgetMacro.java里面多了一个过滤,这个应该就是这个漏洞最关键的地方。

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析

可以看到

this.sanitizeFields = Collections.unmodifiableList(Arrays.asList(VelocityRenderService.TEMPLATE_PARAM));

TEMPLATE_PARAM的值就是_template,这个所以就是补丁了过滤传入外部的_template参数。

public interface VelocityRenderService {    public static final String WIDTH_PARAM = "width";    public static final String HEIGHT_PARAM = "height";    public static final String TEMPLATE_PARAM = "_template";

翻了一下Widget Connector里面的文件,发现TEMPLATE_PARAM就是模板文件的路径。

public class FriendFeedRenderer implements WidgetRenderer {    private static final String MATCH_URL = "friendfeed.com";    private static final String PATTERN = "friendfeed.com/(\\w+)/?";    private static final String VELOCITY_TEMPLATE = "com/atlassian/confluence/extra/widgetconnector/templates/simplejscript.vm";    private VelocityRenderService velocityRenderService;......    public String getEmbeddedHtml(String url, Map<String, String> params) {        params.put(VelocityRenderService.TEMPLATE_PARAM, VELOCITY_TEMPLATE);        return velocityRenderService.render(getEmbedUrl(url), params);    }

加载外部的链接时,会调用相对的模板去渲染,如上,模板的路径一般是写死的,但是也有例外,补丁的作用也说明有人突破了限制,调用了意料之外的模板,从而造成了模板注入。

在了解了补丁和有了一些大概的猜测之后,开始尝试。

首先先找到这个功能,翻了一下官方的文档,找到了这个功能,可以在文档中嵌入一些视频,文档之类的。

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析

看到这个,有点激动了,因为在翻补丁的过程中,发现了几个参数,urlwidthheight正好对应着这里,那_template的英文不是也。从这里传递进去的?

随便找个的Youtube视频插入试试,点击预览,抓包。

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析

params中尝试插入_template参数,好吧,没啥反应..

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析

开始调试模式,因为测试插入的是的Youtube视频,所以调用的是com/atlassian/confluence/extra/widgetconnector/video/YoutubeRenderer.class

public class YoutubeRenderer implements WidgetRenderer, WidgetImagePlaceholder {    private static final Pattern YOUTUBE_URL_PATTERN = Pattern.compile("https?://(.+\\.)?youtube.com.*(\\?v=([^&]+)).*$");    private final PlaceholderService placeholderService;    private final String DEFAULT_YOUTUBE_TEMPLATE = "com/atlassian/confluence/extra/widgetconnector/templates/youtube.vm";......    public String getEmbedUrl(String url) {        Matcher youtubeUrlMatcher = YOUTUBE_URL_PATTERN.matcher(this.verifyEmbeddedPlayerString(url));        return youtubeUrlMatcher.matches() ? String.format("//www.youtube.com/embed/%s?wmode=opaque", youtubeUrlMatcher.group(3)) : null;    }    public boolean matches(String url) {        return YOUTUBE_URL_PATTERN.matcher(this.verifyEmbeddedPlayerString(url)).matches();    }    private String verifyEmbeddedPlayerString(String url) {        return !url.contains("feature=player_embedded&") ? url : url.replace("feature=player_embedded&", "");    }    public String getEmbeddedHtml(String url, Map<String, String> params) {        return this.velocityRenderService.render(this.getEmbedUrl(url), this.setDefaultParam(params));    }

getEmbeddedHtml下断点,会先调用getEmbedUrl对用户传入的url进行正则匹配,因为我们传入的是个正常的的Youtube视频,所以这里是没有问题的,调用然后setDefaultParam函数对传入的其他参数进行处理。

 private Map<String, String> setDefaultParam(Map<String, String> params) {        String width = (String)params.get("width");        String height = (String)params.get("height");        if (!params.containsKey("_template")) {            params.put("_template", "com/atlassian/confluence/extra/widgetconnector/templates/youtube.vm");        }        if (StringUtils.isEmpty(width)) {            params.put("width", "400px");        } else if (StringUtils.isNumeric(width)) {            params.put("width", width.concat("px"));        }        if (StringUtils.isEmpty(height)) {            params.put("height", "300px");        } else if (StringUtils.isNumeric(height)) {            params.put("height", height.concat("px"));        }        return params;    }

取出width状语从句:height来判断是否为空,为空则设置默认值。的关键_template参数来了,如果外部传入的参数没有_template,则设置默认的的Youtube模板。如果传入了,就使用传入的,也就是说,AAAA是成功的传进来了。

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析

大概翻了一下Widget Connector里面的渲染器,大部分是不能设置_template的,是直接写死了,也有一些例外,如Youtube,Viddler,DailyMotion等,是可以从外部传入_template的。

传递能_template了,接下来看下是如何取模板和渲染模板的。

跟进this.velocityRenderService.render,就是也。com/atlassian/confluence/extra/widgetconnector/services/DefaultVelocityRenderService.class里面的render方法。

 public String render(String url, Map<String, String> params) {        String width = (String)params.get("width");        String height = (String)params.get("height");        String template = (String)params.get("_template");        if (StringUtils.isEmpty(template)) {            template = "com/atlassian/confluence/extra/widgetconnector/templates/embed.vm";        }        if (StringUtils.isEmpty(url)) {            return null;        } else {            Map<String, Object> contextMap = this.getDefaultVelocityContext();            Iterator var7 = params.entrySet().iterator();            while(var7.hasNext()) {                Entry<String, String> entry = (Entry)var7.next();                if (((String)entry.getKey()).contentEquals("tweetHtml")) {                    contextMap.put(entry.getKey(), entry.getValue());                } else {                    contextMap.put(entry.getKey(), GeneralUtil.htmlEncode((String)entry.getValue()));                }            }            contextMap.put("urlHtml", GeneralUtil.htmlEncode(url));            if (StringUtils.isNotEmpty(width)) {                contextMap.put("width", GeneralUtil.htmlEncode(width));            } else {                contextMap.put("width", "400");            }            if (StringUtils.isNotEmpty(height)) {                contextMap.put("height", GeneralUtil.htmlEncode(height));            } else {                contextMap.put("height", "300");            }            return this.getRenderedTemplate(template, contextMap);        }    }

_template取出来赋值给template,其他传递进来的参数取出来经过判断之后放入到contextMap,调用getRenderedTemplate函数,也就是调用VelocityUtils.getRenderedTemplate

  protected String getRenderedTemplate(String template, Map<String, Object> contextMap){        return VelocityUtils.getRenderedTemplate(template, contextMap);    }

一路调用,调用链如下图,来到求最后/com/atlassian/confluence/util/velocity/ConfigurableResourceManager.classloadResource函数,来获取模板。

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析

这里调用了4个ResourceLoader去取模板。

com.atlassian.confluence.setup.velocity.HibernateResourceLoaderorg.apache.velocity.runtime.resource.loader.FileResourceLoaderorg.apache.velocity.runtime.resource.loader.ClasspathResourceLoadercom.atlassian.confluence.setup.velocity.DynamicPluginResourceLoader

这里主要看下速度的自带FileResourceLoader状语从句:ClasspathResourceLoader

FileResourceLoader用户会对传入的模板路径使用normalizePath函数进行校验

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析

可以看到,过滤了/../,这样就导致没有办法跳目录了。
Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析

过滤路径后调用findTemplate查找模板,可看到,会拼接一个固定的path,这是合流的安装路径。

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析

现在也就是说可以利用FileResourceLoader来读取合流目录下面的文件了。

读取尝试/WEB-INF/web.xml文件,可以看到,是成功的加载到了该文件。

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析

但是这个无法跳出合流的目录,因为不能用/../

再来看下ClasspathResourceLoader

public InputStream getResourceStream(String name) throws ResourceNotFoundException {
       InputStream result = null;
       if (StringUtils.isEmpty(name)) {
           throw new ResourceNotFoundException(“No template name provided”);
       } else {
           try {
               result = ClassUtils.getResourceAsStream(this.getClass(), name);
……
           }

跟进ClassUtils.getResourceAsStream

  public static InputStream getResourceAsStream(Class claz, String name) {        while(name.startsWith("/")) {            name = name.substring(1);        }        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();        InputStream result;        if (classLoader == null) {            classLoader = claz.getClassLoader();            result = classLoader.getResourceAsStream(name);        } else {            result = classLoader.getResourceAsStream(name);            if (result == null) {                classLoader = claz.getClassLoader();                if (classLoader != null) {                    result = classLoader.getResourceAsStream(name);                }            }        }        return result;    }

会跳到/org/apache/catalina/loader/WebappClassLoaderBase.class

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析跟进,发现会拼接/WEB-INF/classes,其中而且也是调用了normalize对传入的路径进行过滤..

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析跟进,发现会拼接/WEB-INF/classes,其中而且也是调用了normalize对传入的路径进行过滤..

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析还是这里可以用../跳一级目录。

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析还是这里可以用../跳一级目录。

尝试读取一下../web.xml,可以看到,也是可以读取成功的,但是仍然无法跳出目录。

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析我这里测试用的版本是6.14.1,而后尝试了file://http://https://都没有成功。后来我尝试把曲奇删掉,发现还是可以读取文件,确认了这个漏洞不需要权限,但是跳不出目录。应急就在这里卡住了。

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析我这里测试用的版本是6.14.1,而后尝试了file://http://https://都没有成功。后来我尝试把曲奇删掉,发现还是可以读取文件,确认了这个漏洞不需要权限,但是跳不出目录。应急就在这里卡住了。

而后的几天,大佬有说用file://协议可以跳出目录限制,我惊了,我确定当时是已经试过了,没有成功的。看了大佬的截图,发现用的是6.9.0的版本,我下载了,尝试了一下,发现真的可以。

还是问题在ClasspathResourceLoader上面,步骤和之前的是一样的,到断/org/apache/catalina/loader/WebappClassLoaderBase.classgetResourceAsStream方法

拼接前面/WEB-INF/classes电子杂志失败后,继续往下进行。

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析跟进findResource,函数前面仍然获取失败

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析跟进findResource,函数前面仍然获取失败

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析关键的地方就在这里,会调用super.findResource(name),这里返回了网址,也就是能获取到对象。

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析关键的地方就在这里,会调用super.findResource(name),这里返回了网址,也就是能获取到对象。

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析不仅如此,这里还可以使用其他协议(HTTPS,FTP等)获取远程的对象,意味着可以加载远程的对象。

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析不仅如此,这里还可以使用其他协议(HTTPS,FTP等)获取远程的对象,意味着可以加载远程的对象。

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析获取到URL对象之后,继续回到之前的getResourceAsStream,可以看到,当返回的URL不为空时,

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析获取到URL对象之后,继续回到之前的getResourceAsStream,可以看到,当返回的URL不为空时,

调用会url.openStream()电子杂志数据。

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析最终获取到数据给速度渲染。

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析最终获取到数据给速度渲染。

尝试一下
Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析至于6.14.1为啥不行,赶着应急,后续会跟,如果有新的发现,会同步上来,只目前看到ClassLoader不一样。

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析至于6.14.1为啥不行,赶着应急,后续会跟,如果有新的发现,会同步上来,只目前看到ClassLoader不一样。

6.14.1
21.pngConfluence 未授权 RCE (CVE-2019-3396) 漏洞分析6.9.0

21.pngConfluence 未授权 RCE (CVE-2019-3396) 漏洞分析6.9.0

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析这两个装载机的关系如下

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析这两个装载机的关系如下

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析现在可以加载本地和远程模板了,可以尝试进行RCE。

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析现在可以加载本地和远程模板了,可以尝试进行RCE。

关于速度的RCE,基本上有效载荷都来源于15年入侵者的服务端模板注入的议题,但是在合流上用不了,因为在调用方法的时候会经过velocity-htmlsafe-1.5.1.jar,里面多了一些过滤和限制。但是仍然可以利用反射来执行命令。

python -m pyftpdlib -p 2121开启一个简单的FTP服务器,将有效载荷保存成rce.vm,保存在当前目录。

_template设置分类中翻译ftp://localhost:2121/rce.vm,发送,成功执行命令。

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析对于命令回显,同样可以使用反射构造出有效载荷,执行ipconfig的查询查询结果。

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析对于命令回显,同样可以使用反射构造出有效载荷,执行ipconfig的查询查询结果。

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析漏洞影响

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析漏洞影响

根据ZoomEye网络空间搜索引擎对关键字“X-Confluence”进行搜索,共得到61,856条结果,主要分布美国,德国,中国等国家。

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析全球分布(非漏洞影响范围)

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析全球分布(非漏洞影响范围)

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析
Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析
Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析

中国分布(非漏洞影响范围)

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析

漏洞检测

2019年4月4日,404实验室公布了该漏洞的检测PoC,可以利用这个PoC检测Confluence是否受该漏洞影响。

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析

Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析

参考链接

漏洞检测的PoC

通过Widget连接器宏执行远程代码 – CVE-2019-3396

漏洞预警| Confluence Server远程代码执行漏洞

*本文作者:Badcode @知道创宇404实验室,转载请注明来自FreeBuf。

本文链接: http://www.znlrs.cn/3518.html
0 like+
«上一篇: :下一篇»

相关文章

内网穿透Windows(SMB)自认证的利用-互联网安全-漏洞

SMB又名网络文件共享文件,顾名思义其作用是用于用户与服务...

挖洞经验丨看我如何获取Facebook用户的隐私好友列表-互联网安全-漏洞

当拥有个人信息的组织机构发生数据失窃或遭受未授权访问行...

Oracle WebLogic远程命令执行漏洞预警-互联网安全-漏洞

2019年04月17日,国家信息安全漏洞共享平台(CNVD)官方发...

Spring Cloud Config目录遍历漏洞(CVE-2019-3799)预警-互联网安全-漏洞

近日,Spring官方团队在最新的安全更新中披露了一则Spring ...

看我如何揪出远控背后的幕后黑手-互联网安全-漏洞

*本文原创作者:日理万鸡, 0×01 前言 写这篇文章时,...

ThinkPHP 5.1框架结合RCE漏洞的深入分析-互联网安全-漏洞

前言 在前几个月,Thinkphp连续爆发了多个严重漏洞。由于框...

0 thoughts on “Confluence未授权 RCE (CVE-2019-3396) 漏洞分析-互联网安全-漏洞”

  1. 还没有任何评论,你来说两句吧

Leave a reply