Skip to content
KitploitKITPLOIT
工具博客
Log in
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
cve-2019-3396 — Confluence 未授权模板注入 | Kitploit
工具/GitHubGitHub/petrusviet/cve-2019-3396
漏洞分析代码分析漏洞利用Web应用程序漏洞利用渗透测试学习与教育
GitHubpetrusviet/cve-2019-3396

cve-2019-3396

Confluence 未授权模板注入

查看仓库
2125年前尚未审核

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

Confluence unauthorize template injection (CVE-2019-3396)

I) 构建

  • 此漏洞影响以下版本:
    • 所有 1.x.x、2.x.x、3.x.x、4.x.x 和 5.x.x 版本
    • 所有 6.0.x、6.1.x、6.2.x、6.3.x、6.4.x 和 6.5.x 版本
    • 所有 6.6.12 之前的 6.6.x 版本
    • 所有 6.7.x、6.8.x、6.9.x、6.10.x 和 6.11.x 版本
    • 所有 6.12.3 之前的 6.12.x 版本
    • 所有 6.13.3 之前的 6.13.x 版本
    • 所有 6.14.2 之前的 6.14.x 版本
  • 下载源码后,你需要:
    • 将 ./confluence/WEB-INF/classes/confluence-init.properties 文件中的 confluence.home 值修改为 confluence home 的地址
    • 添加 CATALINA_OPTS 值,使程序能够以远程调试模式运行

对于 Windows,文件 ./bin/setenv.bat

set CATALINA_OPTS=-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005

对于 Linux,文件 ./bin/setenv.sh

CATALINA_OPTS="-Xrunjdwp:transport=dt_socket,suspend=n,server=y,address=5005 ${CATALINA_OPTS}"  
  • 在 IDE(Intellij)中,我们创建一个调试配置:Remote JVM Debug,host 和 port 值为 localhost:5005,以及 Command line arguments for remote JVM
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005
  • 我们可以使用 Postgresql 作为数据库:
$ su - postgres
postgres@ubuntu:~$ psql -U postgres
postgres@ubuntu:~$ psql -U postgres
psql (10.6 (Ubuntu 10.6-0ubuntu0.18.04.1))
Type "help" for help.
 
postgres=# CREATE USER wiki WITH PASSWORD 'wiki';
CREATE ROLE
postgres=# CREATE DATABASE wiki OWNER wiki;
CREATE DATABASE
postgres=# GRANT ALL PRIVILEGES ON DATABASE jira TO wiki;
GRANT
  • 我们需要将以下 jar 添加到 lib:./confluence/WEB-INF/atlassian-bundled-plugins/widgetconnector-x.x.x.jar、./confluence/WEB-INF/lib/confluence-x.x.x.jar、./confluence/WEB-INF/lib/velocity-x.x.x-atlassian-x.jar,这样调试时我们就能看到所需的源码。

  • 我们接着运行 ./bin/start-confluence.bat 文件,你也可以参考这份指南从源码进行安装。

II) 分析

  • 阅读描述后,我们可以知道这个漏洞始于 Widget Connector 功能,所以我立刻用谷歌搜索,以了解该功能是什么以及如何使用:

    2 进入编辑页面

    3
    选择其他宏

    4 选择 Widget Connector

    image

  • 我随便选择了一些参数然后点击预览,接着转到 Burp 查看是否有异常。 image

  • 在这个数据包中,我注意到有一个参数 "pluginKey":"com.atlassian.confluence.extra.widgetconnector",因此我猜测 Widget Connector 功能定义在类 com.atlassian.confluence.extra.widgetconnector 中,于是我在路径中查找是否有可疑的 jar 包。

image

  • 我尝试将 ./confluence/WEB-INF/atlassian-bundled-plugins/widgetconnector-x.x.x.jar 文件添加到项目的 lib 中,以便阅读源代码并进行调试。

    1
    将 jar 文件添加到 lib 的方法

  • 打开 widgetconnector 包后,我对 WidgetMacro 类很有兴趣,于是在该类的构造函数和 execute 方法上设置断点,以查看我在使用 Preview 功能时这个类是否会被调用 🕵️

    • image

    • execute 函数已被调用,随后程序调用 DefaultRenderManager.getEmbeddedHtml

    • image

    • 我们看到要进入 if,需要满足条件 widgetRenderer.matches(url)。我们接下来检查 YoutubeRenderer 类中的 widgetRenderer.matches(url) 函数

    • image

    • image

    • 因此,我需要将参数 url 设置为 YouTube 视频的链接(或 Vimeo、Twitter……)。我将 url 设置为任意 YouTube 视频的 URL,程序便进入了 if 语句,接着调用 widgetRenderer.getEmbeddedHtml(url, params) 函数(YoutubeRenderer 类)

    • image

    • 程序跳转到 setDefaultParam 函数,在这里我们看到一个隐藏参数 _template,看起来相当可疑 :)

    • image

    • 退出 setDefaultParam 函数后,程序调用 DefaultVelocityRenderService.render 函数

    • image

    • 接着经过 getRenderedTemplate 函数和 VelocityUtils.getRenderedTemplate(String templateName, Map<?, ?> contextMap)

    • image

    • image

    • 接下来是 VelocityUtils.getRenderedTemplate(String templateName, Context context) 和 getRenderedTemplateWithoutSwallowingErrors(templateName, context)

    • image

    • renderTemplateWithoutSwallowingErrors 函数

    • image

    • 程序调用 getTemplate 函数,然后是 VelocityEngine.getTemplate 和 RuntimeInstance.getTemplate,在这里我们看到程序使用参数 _template 的值作为输入调用了 getResource 函数。在 Java 中,getResource 函数可以用来加载本地文件形式的资源,也可以加载互联网上的资源(通过 HTTP 协议)。

    • 停下来想想:这是否允许攻击者通过在请求中插入额外的 _template 参数,将任意模板(来自本地服务器或来自攻击者的主机)注入程序中??

    • image

    • 我们继续向前跟踪,看看获得模板后程序如何处理:

    • 获得模板后,程序调用 VelocityUtils.renderTemplateWithoutSwallowingErrors(template, context, writer); 函数

    • image

    • 然后进入 template.merge(context, writer);

    public void merge(Context context, Writer writer, List macroLibraries) throws ResourceNotFoundException, ParseErrorException, MethodInvocationException {
          if (this.errorCondition != null) {
              throw this.errorCondition;
          } else if (this.data == null) {
              String msg = "Template.merge() failure. The document is null, most likely due to parsing error.";
              throw new RuntimeException(msg);
          } else {
              InternalContextAdapterImpl ica = new InternalContextAdapterImpl(context);
              ica.setMacroLibraries(macroLibraries);
              if (macroLibraries != null) {
                  for(int i = 0; i < macroLibraries.size(); ++i) {
                      try {
                          this.rsvc.getTemplate((String)macroLibraries.get(i));
                      } catch (ResourceNotFoundException var17) {
                          this.rsvc.getLog().error("template.merge(): cannot find template " + (String)macroLibraries.get(i));
                          throw var17;
                      } catch (ParseErrorException var18) {
                          this.rsvc.getLog().error("template.merge(): syntax error in template " + (String)macroLibraries.get(i) + ".");
                          throw var18;
                      } catch (Exception var19) {
                          throw new RuntimeException("Template.merge(): parse failed in template  " + (String)macroLibraries.get(i) + ".", var19);
                      }
                  }
              }
    
下载工具