├── .gitignore ├── AutoScanUseSqlmapapi.py ├── HTIndex.py ├── LICENSE ├── README.md ├── param.py ├── parse_target.py ├── static └── 1.png └── templates ├── about.html ├── add.html ├── add_success.html ├── addtag.html ├── foot.html ├── head.html ├── index.html ├── status.html └── xunfeng.html /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | 27 | # PyInstaller 28 | # Usually these files are written by a python script from a template 29 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 30 | *.manifest 31 | *.spec 32 | 33 | # Installer logs 34 | pip-log.txt 35 | pip-delete-this-directory.txt 36 | 37 | # Unit test / coverage reports 38 | htmlcov/ 39 | .tox/ 40 | .coverage 41 | .coverage.* 42 | .cache 43 | nosetests.xml 44 | coverage.xml 45 | *,cover 46 | .hypothesis/ 47 | 48 | # Translations 49 | *.mo 50 | *.pot 51 | 52 | # Django stuff: 53 | *.log 54 | local_settings.py 55 | 56 | # Flask stuff: 57 | instance/ 58 | .webassets-cache 59 | 60 | # Scrapy stuff: 61 | .scrapy 62 | 63 | # Sphinx documentation 64 | docs/_build/ 65 | 66 | # PyBuilder 67 | target/ 68 | 69 | # IPython Notebook 70 | .ipynb_checkpoints 71 | 72 | # pyenv 73 | .python-version 74 | 75 | # celery beat schedule file 76 | celerybeat-schedule 77 | 78 | # dotenv 79 | .env 80 | 81 | # virtualenv 82 | venv/ 83 | ENV/ 84 | 85 | # Spyder project settings 86 | .spyderproject 87 | 88 | # Rope project settings 89 | .ropeproject 90 | -------------------------------------------------------------------------------- /AutoScanUseSqlmapapi.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding:utf-8 -*- 3 | 4 | import json 5 | import threading 6 | import time 7 | import urllib 8 | 9 | import requests 10 | from bson import ObjectId 11 | from pymongo import MongoClient 12 | 13 | import param 14 | 15 | count = 0 16 | 17 | import pymongo 18 | 19 | a = pymongo.MongoClient()['demo']['data'] 20 | 21 | 22 | class Autoinj(threading.Thread): 23 | """ 24 | sqlmapapi 接口建立和管理sqlmap任务 25 | by zhangh (zhanghang.org#gmail.com) 26 | php install requests 27 | """ 28 | 29 | def __init__(self, server='', target='', method='', data='', cookie='', referer=''): 30 | threading.Thread.__init__(self) 31 | self.server = server 32 | if self.server[-1] != '/': 33 | self.server = self.server + '/' 34 | # if method == "GET": 35 | # self.target = target + '?' + data 36 | # else: 37 | # self.target = target 38 | self.target = target 39 | self.taskid = '' 40 | self.engineid = '' 41 | self.status = '' 42 | self.method = method 43 | self.data = data 44 | self.referer = referer 45 | self.cookie = cookie 46 | self.start_time = time.time() 47 | # print "server: %s \ttarget:%s \tmethod:%s \tdata:%s \tcookie:%s" % (self.server, self.target, self.method, self.data, self.cookie) 48 | 49 | def task_new(self): 50 | code = urllib.urlopen(self.server + param.task_new).read() 51 | self.taskid = json.loads(code)['taskid'] 52 | return True 53 | 54 | def task_delete(self): 55 | url = self.server + param.task_del 56 | url = url.replace(param.taskid, self.taskid) 57 | requests.get(url).json() 58 | 59 | def scan_start(self): 60 | headers = {'Content-Type': 'application/json'} 61 | url = self.server + param.scan_task_start 62 | url = url.replace(param.taskid, self.taskid) 63 | data = {'url': self.target} 64 | t = requests.post(url, data=json.dumps(data), headers=headers).text 65 | t = json.loads(t) 66 | self.engineid = t['engineid'] 67 | return True 68 | 69 | def scan_status(self): 70 | url = self.server + param.scan_task_status 71 | url = url.replace(param.taskid, self.taskid) 72 | self.status = requests.get(url).json()['status'] 73 | 74 | def scan_data(self): 75 | url = self.server + param.scan_task_data 76 | url = url.replace(param.taskid, self.taskid) 77 | return requests.get(url).json() 78 | 79 | def option_set(self): 80 | headers = {'Content-Type': 'application/json'} 81 | url = self.server + param.option_task_set 82 | url = url.replace(param.taskid, self.taskid) 83 | data = {} 84 | if self.method == "POST": 85 | data["data"] = self.data 86 | if len(self.cookie) > 1: 87 | data["cookie"] = self.cookie 88 | # print data 89 | data['crawlDepth'] = 5 90 | data['threads'] = 10 91 | data['forms'] = True 92 | data['smart'] = True 93 | data['is-dba'] = True 94 | t = requests.post(url, data=json.dumps(data), headers=headers).text 95 | t = json.loads(t) 96 | 97 | def option_get(self): 98 | url = self.server + param.option_task_get 99 | url = url.replace(param.taskid, self.taskid) 100 | return requests.get(url).json() 101 | 102 | def scan_stop(self): 103 | url = self.server + param.scan_task_stop 104 | url = url.replace(param.taskid, self.taskid) 105 | return requests.get(url).json() 106 | 107 | def scan_kill(self): 108 | url = self.server + param.scan_task_kill 109 | url = url.replace(param.taskid, self.taskid) 110 | return requests.get(url).json() 111 | 112 | def scan_log(self): 113 | url = self.server + param.scan_task_log 114 | url = url.replace(param.taskid, self.taskid) 115 | return requests.get(url).json() 116 | 117 | def start_test(self): 118 | global count 119 | # 开始任务 120 | # self.target=que.get() 121 | self.start_time = time.time() 122 | if not self.task_new(): 123 | print("Error: task created failed.") 124 | return False 125 | # 设置扫描参数 126 | self.option_set() 127 | # 启动扫描任务 128 | if not self.scan_start(): 129 | print("Error: scan start failed.") 130 | return False 131 | # 等待扫描任务 132 | 133 | while True: 134 | self.scan_status() 135 | if self.status == 'running': 136 | time.sleep(5) 137 | elif self.status == 'terminated': 138 | break 139 | else: 140 | print "unkown status" 141 | break 142 | if time.time() - self.start_time > 3000: # 多于五分钟 143 | error = True 144 | print('删除一个不怎么带劲的IP:%s' % self.target) 145 | count += 1 146 | self.scan_stop() 147 | self.scan_kill() 148 | return [self.target, {'status': 'speed too much time'}] 149 | 150 | # 取结果 151 | res = self.scan_data() 152 | # 删任务 153 | # self.task_delete() 154 | 155 | 156 | print(res['data']) 157 | if res['data']: 158 | count += 1 159 | print("耗时:" + str(time.time() - self.start_time)) 160 | print('已经检测%d个网站' % count) 161 | return {self.target: {'data': self.scan_data(), 'log': self.scan_log()}} 162 | else: 163 | count += 1 164 | print("耗时:" + str(time.time() - self.start_time)) 165 | print('已经检测%d个url %s' % (count, self.target)) 166 | return {self.target: 0} 167 | 168 | def run(self): 169 | while True: 170 | target = a.find_one_and_update({'scanned': {'$exists': False}}, {'$set': {'scanned': 0}}) 171 | if not target: 172 | print 'no target' 173 | time.sleep(100) 174 | continue 175 | # a.update({'_id': ObjectId(target['_id'])}, ) 176 | self.target = target['target'] 177 | t = self.start_test() 178 | try: 179 | a.update({'_id': ObjectId(target['_id'])}, {'$set': {'scanned': 1, 'scan_result': t.values()}}) 180 | except Exception: 181 | a.update({'_id': ObjectId(target['_id'])}, {'$set': {'scanned': 1, 'scan_result': None}}) # 懒得想了 182 | 183 | 184 | if __name__ == '__main__': 185 | start_time = time.time() 186 | cl = MongoClient()['demo']['scanner'] 187 | things = [i['target'] for i in cl.find()] 188 | print things 189 | used_tag = set() 190 | for i in things: 191 | if i not in used_tag: 192 | print i 193 | used_tag.add(i) # @todo 在Scan的过程中连接失败的话把这个节点移除 194 | Autoinj(i).start() # adminid 5d6b91ceb538c08299e4a5d0cb22912a 195 | Autoinj(i).start() 196 | Autoinj(i).start() 197 | Autoinj(i).start() 198 | Autoinj(i).start() 199 | Autoinj(i).start() 200 | Autoinj(i).start() 201 | -------------------------------------------------------------------------------- /HTIndex.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | import os 3 | 4 | from bson.objectid import ObjectId 5 | from flask import Flask 6 | from flask import jsonify 7 | from flask import render_template 8 | from flask import request 9 | from pymongo import MongoClient 10 | 11 | tmpl_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'templates') 12 | static_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'static') 13 | app = Flask('app', template_folder=tmpl_dir, static_folder=static_dir) 14 | app = Flask(__name__) 15 | 16 | demo_db = MongoClient()['demo']['data'] 17 | t = MongoClient()['demo']['temp'] 18 | m_cli = demo_db 19 | 20 | 21 | @app.route('/') 22 | def hello_world(): 23 | global m_cli 24 | if request.method == 'GET': 25 | c = [] 26 | d = 0 27 | count = m_cli.count() 28 | c = m_cli.find().limit(50) 29 | return render_template('index.html', host=c, count=count, key='all', Title='资产概览'.decode('utf-8')) 30 | 31 | 32 | @app.route('/info/<_id>') 33 | def info(_id): 34 | print _id 35 | a = m_cli.find_one({'_id': ObjectId(_id)}) 36 | a['_id'] = None 37 | return jsonify(a) 38 | 39 | 40 | @app.route('/add_scanner/', methods=['POST', 'GET']) 41 | def add_scanner(): 42 | cl = MongoClient()['demo']['scanner'] 43 | if request.method == 'GET': 44 | scanner = '\r\n'.join([i['target'] for i in cl.find()]) 45 | print scanner 46 | return render_template('addtag.html', current_scanner=scanner) 47 | else: 48 | req = request.form['comment'] 49 | print 'xxx' 50 | for i in req.split('\n'): 51 | # print {'target':i.strip()} 52 | target = i.strip() 53 | print 'insert %s' % target 54 | if 'http' not in target[0:5]: 55 | target = 'http://%s' % target 56 | cl.insert({'target': target}) 57 | print 'insert %s' % target 58 | return render_template('add_success.html') 59 | 60 | 61 | @app.route('/scanner_status') 62 | def scanner_status(): 63 | pass 64 | 65 | 66 | @app.route('/sqlinj') 67 | def return_sqlinj(): 68 | c = [i for i in demo_db.find({'scan_result.data.success': True})] 69 | print 'None' 70 | return render_template('index.html', host=c, key='all') 71 | 72 | 73 | @app.route('/add', methods=['GET', 'POST']) 74 | def return_add(): 75 | if request.method == 'GET': 76 | return render_template('add.html') 77 | else: 78 | req = request.form['comment'] 79 | for i in req.split('\n'): 80 | target = i.strip() 81 | if 'http' not in target[0:5]: 82 | target = 'http://%s' % target 83 | t.insert_one({'target': target}) 84 | return render_template('add_success.html') 85 | 86 | 87 | @app.route('/xunfeng') 88 | def return_xunfeng(): 89 | return render_template('xunfeng.html') 90 | 91 | 92 | @app.route('/scanner_add') 93 | def scanner_add(): 94 | return render_template('addtag.html') 95 | 96 | 97 | @app.route('/about') 98 | def about_page(): 99 | return render_template('about.html') 100 | 101 | 102 | @app.route('/status') 103 | def status(): 104 | inj_count = demo_db.find({'scan_result.data.success': True}).count() 105 | all = demo_db.find().count() 106 | scanned = demo_db.find({'scanned': {'$exists': True}}).count() 107 | return render_template('status.html', has_scaned=scanned, inj_count=inj_count, remain=all - scanned) 108 | 109 | 110 | @app.route('/search/') 111 | def search(): 112 | domain = request.args['domain'] 113 | count = m_cli.find({'target': {'$regex': '%s' % domain}}).count() 114 | host = m_cli.find({'target': {'$regex': '%s' % domain}}).limit(200) 115 | return render_template('index.html', host=host, count=count, key=domain) 116 | 117 | 118 | if __name__ == '__main__': 119 | # app.run(debug=True) 120 | app.run(debug=True, host='0.0.0.0') 121 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 小巡风 2 | 国内第二套开源的资产管理系统,适合于对多个站点进行扫描 3 | ![https://github.com/fiht/xiaoxunfeng/raw/master/static/1.png](https://github.com/fiht/xiaoxunfeng/raw/master/static/1.png) 4 | ## 写在前面 5 | 致敬[xunfeng](https://github.com/ysrc/xunfeng), 是巡风为我打开了一扇大门,原来还有个叫资产管理的事情。 6 | ## Why 小巡风 7 | 搭建过巡风的朋友可能会比较清楚,巡风是用来管理IP的,但是不管域名,而据我所知现在的对大批量域名的扫描公开的内容还比较有限(除了Wooyun老和尚的扫描工具)。 8 | 9 | 我从一年之前接触到Web安全,在自动化刷洞这方面也做了一些自己的探索,比如给我带来follower的 [ScanSql](https://github.com/fiht/ScanSql)和[my-tools](https://github.com/fiht/my-tools)以及 10 | [educn-sqlScan](https://github.com/fiht/educn-sqlScan). 给大家说声抱歉..因为当时经验不足,几个项目的源代码我现在感觉实在是太乱了。 11 | 12 | 进入了大三的晚期,以考研的名义拒绝找实习,以考研的名义翘课,以考研的名义写代码,深感罪过。经过清明节假期的努力,对比了现在一些开源的扫描器,最终完成了这个小demo。在我的博客里面横向对比了两个提供api的扫描器(比较low), 13 | 如果你感兴趣的话可以去看看[https://blog.fiht.me/archives/247/](https://blog.fiht.me/archives/247/). 14 | ## 特色功能 15 | 可以调用sqlmapapi对上万个域名进行sql注入检测,支持form解析。(真尼玛low...) 16 | 17 | ## 安装 18 | 挖坑待填 19 | ## 常见问题 20 | ### 1. [问] 你好,我看到小巡风有个联动巡风的功能,为什么不能使用? 21 | [回复] 因为...巡风默认使用了auth的方式...我感觉比较麻烦...有需求的话提issue我一定加 22 | ### 2. [问] 为什么从子域名超找系统导入资产不能用? 不能用你为什么要加这一项? 23 | [回复] 是这样的,我从 [scans.io](scans.io) 下载了20亿条全球DNS解析记录,并且把他们加入到了MongoDB中,本想做个二级域名查找系统,发现时间和机器都不够用,于是就暂时搁置了。 24 | 等有时间我一定补上。(有大佬赞助服务器就最好了) 25 | ### 3. [问] 这套系统的漏洞扫描能力如何? 26 | [回复] 整套系统是基于sqlmap做的,使用了sqlmapapi,在options中添加crawl(爬行网站)选项,所以整套系统只能找sql注入,漏洞扫描效果如sqlmap -u 'www.target.com' --crawl 5 --batch 27 | 特别要注意的是,这套系统不能解析网站中的js,所以**对ajax无力**。 28 | ### 4. [问] 为什么不接入更厉害的扫描器? 29 | [回复] 在我的本地有一个分支接入了arachni的restapi,但是效果不理想(当有上万个站点需要扫描的时候arachni基本是残废的状态),关于破解版本的大型扫描器(AppScan和AWVS)暂时不考虑接入。 30 | 如果有需要的话可以联系我进行付费开发。 31 | ### 5. [问] 你这个能不能出一个网站爬行的功能,比如说我输入访问 www.sdu.edu.cn,然后你的爬虫自动分析出这个页面有哪些友情链接然后再进行扫描? 32 | [回复] 我的系统中暂时未加入此项功能,如果有需要的话可以联系我定制或者等待我的后续版本更新。没有加入的原因是因为我觉得子域名查找然后手动添加可以满足我现在的需求了 33 | ### 34 | ### 6. [问] 你这个扫描器和老和尚的扫描器哪个牛逼? 35 | [回复] 不回答 36 | -------------------------------------------------------------------------------- /param.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding:utf-8 -*- 3 | 4 | ''' 5 | sqlmapapi restful interface 6 | by zhangh (zhanghang.org#gmail.com) 7 | ''' 8 | # api 9 | task_new = "task/new" 10 | task_del = "task//delete" 11 | admin_task_list = "admin//list" 12 | admin_task_flush = "admin//flush" 13 | option_task_list = "option//list" 14 | option_task_get = "option//get" 15 | option_task_set = "option//set" 16 | scan_task_start = "scan//start" 17 | scan_task_stop = "scan//stop" 18 | scan_task_kill = "scan//kill" 19 | scan_task_status = "scan//status" 20 | scan_task_data = "scan//data" 21 | scan_task_log = "scan//log" 22 | download_task = "download///" 23 | # config 24 | taskid = "" 25 | dbOld = 0 26 | dbNew = 1 27 | host = '172.22.1.44' 28 | port = 2000 29 | password = 'SEC' 30 | 31 | joblist = 'job.set' 32 | sqlinj = 'sqlinj' -------------------------------------------------------------------------------- /parse_target.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import hashlib 3 | import re 4 | import socket 5 | import time 6 | from urlparse import urlparse 7 | 8 | import pymongo 9 | import requests 10 | from bson import ObjectId 11 | 12 | temp_cli = pymongo.MongoClient()['demo']['temp'] 13 | cli = pymongo.MongoClient()['demo']['data'] 14 | 15 | 16 | def do_sth(i): 17 | def get_ip(host): 18 | try: 19 | return socket.gethostbyname(host) 20 | except Exception: 21 | return None 22 | 23 | host = urlparse(i)[1] 24 | ip = get_ip(host) 25 | title = None 26 | if ip: 27 | try: 28 | req = requests.get(i, timeout=10) 29 | except Exception as e: 30 | return 31 | pass 32 | try: 33 | req.encoding = req.apparent_encoding 34 | title = re.findall('(.*?)', req.text, flags=re.I | re.M) 35 | if title: 36 | title = title[0] 37 | uniq_hash = hashlib.md5(req.content).hexdigest() 38 | cli.insert_one( 39 | {'target': i, 'ip': ip, 'title': title, 'add_time': datetime.datetime.utcnow(), 'domain': host, 40 | 'hash': uniq_hash 41 | } 42 | ) 43 | except Exception as e: 44 | print e 45 | pass 46 | 47 | while True: 48 | for i in temp_cli.find({}): 49 | do_sth(i['target']) 50 | temp_cli.remove({'_id': ObjectId(i['_id'])}) 51 | time.sleep(10) 52 | print 'fick' 53 | -------------------------------------------------------------------------------- /static/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/957204459/xiaoxunfeng/46d4c18ca65abcde83dcb65d7e8ccf84ad3305a4/static/1.png -------------------------------------------------------------------------------- /templates/about.html: -------------------------------------------------------------------------------- 1 | {% include "head.html" %} 2 |

3 | 1. 我是谁 4 |

5 |

6 | 大核桃 7 |

8 |

9 | 2. 这系统好难用 10 |

11 |

12 | 同意 13 |

14 |

15 | 3. 听说你本人长得很帅 16 |

17 |

18 | 是的,非常帅 19 |

20 |

21 | 4. 我可以看一下你的照片吗大佬? 22 |

23 |

24 | 好的,可以。 25 |

26 | {% include "foot.html" %} -------------------------------------------------------------------------------- /templates/add.html: -------------------------------------------------------------------------------- 1 | {% include "head.html" %} 2 |
3 |

1. 手动添加资产

4 |

一行一个网站ε٩(๑> ₃ <)۶з

5 |
6 |
7 | {# #} 8 | 9 | 10 |
11 |
12 |
13 |
14 |

2. 从帅核桃的子域名查找系统中导入资产

15 |
16 | 20 |
21 |
22 | 23 | {% include "foot.html" %} -------------------------------------------------------------------------------- /templates/add_success.html: -------------------------------------------------------------------------------- 1 | {% include "head.html" %} 2 |

3 | 添加成功。 4 |

5 | {% include "foot.html" %} -------------------------------------------------------------------------------- /templates/addtag.html: -------------------------------------------------------------------------------- 1 | {% include 'head.html' %} 2 |
3 |

添加扫描节点(sqlmap)

4 |

添加sqlmapapi的节点

5 |
6 |
7 | {# #} 8 | 9 | 10 |
11 |
12 |
13 | {% include "foot.html" %} -------------------------------------------------------------------------------- /templates/foot.html: -------------------------------------------------------------------------------- 1 | {# #} 10 | {#
#} 11 | {# #} 12 | {# #} 13 | {# #} 14 | {# #} 15 | {# #} 16 | {#
#} 17 | 18 | 19 | >.< 20 | 21 | -------------------------------------------------------------------------------- /templates/head.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 没有女朋友title都不会写了... 7 | 8 | 10 | 11 | 13 | 16 | 17 | 20 | 21 | 22 | 23 | 41 | -------------------------------------------------------------------------------- /templates/index.html: -------------------------------------------------------------------------------- 1 | {% include 'head.html' %} 2 | 3 |
4 |
5 |
6 |

7 | {{ Title }} 8 |

9 | 13 |

14 | 一共有{{ count }}条关于{{ key }}数据 15 |

16 | 17 | 18 | 19 | 22 | 25 | 28 | 31 | 32 | 33 | 34 | {% for i in host %} 35 | 36 | 41 | 44 | 47 | 51 | 52 | {% endfor %} 53 | 54 |
20 | 标题 21 | 23 | 网址 24 | 26 | IP 27 | 29 | 页面hash 30 |
37 | {% if i.title %} 38 | {{ i.title }} 39 | {% endif %} 40 | 42 | {{ i.target }} 43 | 45 | {{ i.ip }} 46 | 48 | {{ i.hash }} 49 | 50 |
55 |
56 | {% include "foot.html" %} -------------------------------------------------------------------------------- /templates/status.html: -------------------------------------------------------------------------------- 1 | {% include "head.html" %} 2 |

当前已扫描 「{{ has_scaned }}」,其中存在Sql注入点的网站为」「{{ inj_count }}」, 剩下「{{ remain }}」 3 |

4 | {% include "foot.html" %} -------------------------------------------------------------------------------- /templates/xunfeng.html: -------------------------------------------------------------------------------- 1 | {% include "head.html" %} 2 |

3 | 1. 如果你不知道巡风是什么,请不要使用这个功能。 4 |

5 |

6 | 2. 如果你想知道巡风是什么,请移步--> https://github.com/ysrc/xunfeng 7 |

8 |
9 | 10 |
11 | 13 |
14 |
15 | {% include "foot.html" %} --------------------------------------------------------------------------------