记一次安全漏洞分析
漏洞分析
环境搭建用了 vulhub 的环境,版本为
Confluence Server 6.10.2
Widget Connector
是Confluence
的一个插件,对比一下修复前后的插件
左Confluence 6.13.0
右6.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 数据
url 不为空则进入this.renderManager.getEmbeddedHtml(url, parameters)
DefaultRenderManager#getEmbeddedHtml
这里的会根据输入的 url,遍历这几个 WidgetRenderer 匹配 url,匹配到就进入对应 WidgetRenderer 的 getEmbeddedHtml 方法
如这里 YoutubeRenderer,匹配成功
然后进入YoutubeRenderer#getEmbeddedHtml
之所以会输入 youtube 的 url 是因为 YoutubeRenderer 的参数设置函数中的_template 可控
继续往下
直到 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和ClasspathResourceLoader
的getResourceStream
方法就行了
FileResourceLoader#getResourceStream
这里有过滤函数
循环判断是否以/../开头
所以FileResourceLoader#getResourceStream
不能跨目录读文件,只能读安装路径下的文件
看另外一个加载器ClasspathResourceLoader#getResourceStream
这次将_template
改为file:///etc/passwd
ClassUtils#getResourceAsStream
前几个 ClassLoader 都无法加载,最终需要调用ParallelWebappClassLoader
的getResourceAsStream
最终会调用到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
这里用 ftp 协议,python -m pyftpdlib -p 8888
影响版本
漏洞分析
补丁应该是把 queryString 的 ognl 取值去掉了
因为这里是 ognl 表达式注入,所以可以把断点打到
OgnlValueStack#findValue
调用栈大致可以分为
在 getValue 前一步有安全检查
32 行这里会对表达式进行编译(解析 unicode)然后放入containsUnsafeExpression
检查
具体内容黑名单如下
第一个 hashset 限制了静态方法、字段、构造方法
第二个和第三个 hashset 限制了获取 classloader,如:xxx.class 或者 xxx.getClass()
第四个 hashset 限制了编译后的结果中不能出现特定的变量
可以用反射绕过,然后就是 ognl 注入了,由于要逃逸 expr 的单引号,而直接传单引号会被 html 实体编码,所以可以利用 OgnlUtil.compile 解析 unicode 绕
评论