zoukankan      html  css  js  c++  java
  • 巡风源码阅读与分析---view.py

     巡风是一款适用于企业内网的漏洞快速应急、巡航扫描系统,通过搜索功能可清晰的了解内部网络资产分布情况,并且可指定漏洞插件对搜索结果进行快速漏洞检测并输出结果报表。

    环境

    巡风是基于python的flask框架写的,数据库为mongodb。

    可安装在Windows OSX Linux Docker

    Python2.7 pip mongodb

    安装

    我安装在window,用于简单阅读代码和调试。

    https://github.com/ysrc/xunfeng

    下载后跟着官网的window安装教程即可。

    然后运行 Run.bat (得使用管理员运行,不然没反应。。)

     

    安装成功。

    阅读:

    使用的ide为pycharm
    Run.bat

     

    mogod.exe 用于启动mongodb

    Run.py 启动web网站

    Aider.py  # 辅助验证脚本

    VulScan.py  # 漏洞检测引擎

    NAScan.py  # 网络资产信息抓取引擎

    Run.py

    from views.View import app
    
    if __name__ == '__main__':
        #app.debug = True
        app.run(threaded=True, port=8888,host='')

    去到views/View.py

    一共有24个方法。

    一个方法一个方法来看。

    1.Search()

    # 搜索页
    @app.route('/filter')
    @logincheck
    def Search():
        return render_template('search.html')

    @logincheck 使用了装饰器函数。跟过去查看views/lib/Login.py

    # 登录状态检查
    def logincheck(f):
        @wraps(f)
        def wrapper(*args, **kwargs):
            try:
                if session.has_key('login'):
                    if session['login'] == 'loginsuccess':
                        return f(*args, **kwargs)
                    else:
                        return redirect(url_for('Login'))
                else:
                    return redirect(url_for('Login'))
            except Exception, e:
                print e
                return redirect(url_for('Error'))
    
        return wrapper

    如果seesion中的login等于loginsuccess 就继续执行view.py下的函数。否则跳转掉Error模板。就是检测是否有登录。

    回到Search()加载search.html模板

    2.Deleteall()

    # 删除所有
    @app.route('/deleteall', methods=['post'])
    @logincheck
    @anticsrf
    def Deleteall():
        Mongo.coll['Task'].remove({})
        return 'success'

    先判断了登录状态,多了一个@anticsrf 装饰器函数。跟过去查看views/lib/AntiCSRF.py

    # 检查referer
    def anticsrf(f):
        @wraps(f)
        def wrapper(*args, **kwargs):
            try:
                if request.referrer and request.referrer.replace('http://', '').split('/')[0] == request.host:
                    return f(*args, **kwargs)
                else:
                    return redirect(url_for('NotFound'))
            except Exception, e:
                print e
                return redirect(url_for('Error'))
    
        return wrapper

    判断是否有referrer头,而且将http://替换成空 再分割取第一部分,也就是取出网站的host,然后与本站host相比较。看是否一致。不一样的话,跳转404页面。否则就继续执行。

    @anticsrf 就是防止CSRF漏洞的。

    回到Deleteall()

    Mongo 跟过去发现是连接mongoDB。选择Task这个数据表,移除所有数据。

    就是将任务总数全部删除。

     

    3.Main()

    # 搜索结果页
    @app.route('/')
    @logincheck
    def Main():
        q = request.args.get('q', '')
        page = int(request.args.get('page', '1'))
        plugin = Mongo.coll['Plugin'].find()  # 插件列表
        plugin_type = plugin.distinct('type')  # 插件类型列表
        if q:  # 基于搜索条件显示结果
            result = q.strip().split(';')
            query = querylogic(result)
            cursor = Mongo.coll['Info'].find(query).sort('time', -1).limit(page_size).skip((page - 1) * page_size)
            return render_template('main.html', item=cursor, plugin=plugin, itemcount=cursor.count(),
                                   plugin_type=plugin_type, query=q)
        else:  # 自定义,无任何结果,用户手工添加
            return render_template('main.html', item=[], plugin=plugin, itemcount=0, plugin_type=plugin_type)

    判断是否登录(下同)

    先获取传入的q page

    plugin = Mongo.coll['Plugin'].find()  #连接数据库,列出Plugin中所有清单。
    
    plugin_type = plugin.distinct('type') #从查询的所有清单里面获取名字是 type的数据。

    然后将q进行分割“;”主要是分割类似这种的 q= 127.0.0.1;127.8.8.1  

    分成列表传入querylogic()函数。 跟过去看看views/lib/QueryLogic.py(详细:https://www.cnblogs.com/zhengjim/p/9406065.html

    将搜索的值q转成mongoDB能查询的语句。

    cursor = Mongo.coll['Info'].find(query).sort('time', -1).limit(page_size).skip((page - 1) * page_size)

    info表里把条件代入查询sort()排序 limit()分页

    最后传给视图

    4.Getplugin()

    # 获取插件信息异步
    @app.route('/getplugin', methods=['get', 'post'])
    @logincheck
    def Getplugin():
        type = request.form.get('type', '')
        risk = request.form.get('risk', '')
        search = request.form.get('search', '')
        query = {}
        if type:
            query['type'] = type
        if risk:
            query['level'] = risk
        if search:
            search = unquote(search)
            query['name'] = {"$regex": search, '$options': 'i'}
        cursor = Mongo.coll['Plugin'].find(query)
        rsp = []
        for i in cursor:
            result = {'name': i['name'], 'info': i['info']}
            rsp.append(result)
        return json.dumps(rsp)

    获取了type risk search 是否有值

    没有的话,就全部查询。有的话 Plugin表代入条件查询。然后将插件名字和信息转json格式返回。

    5.Addtask()

    # 新增任务异步
    @app.route('/addtask', methods=['get', 'post'])
    @logincheck
    @anticsrf
    def Addtask():
        title = request.form.get('title', '')
        plugin = request.form.get('plugin', '')
        condition = unquote(request.form.get('condition', ''))
        plan = request.form.get('plan', 0)
        ids = request.form.get('ids', '')
        isupdate = request.form.get('isupdate', '0')
        resultcheck = request.form.get('resultcheck', '0')
        result = 'fail'
        if plugin:
            targets = []
            if resultcheck == 'true':  # 结果集全选
                list = condition.strip().split(';')
                query = querylogic(list)
                cursor = Mongo.coll['Info'].find(query)
                for i in cursor:
                    tar = [i['ip'], i['port']]
                    targets.append(tar)
            else:  # 当前页结果选择
                for i in ids.split(','):
                    tar = [i.split(':')[0], int(i.split(':')[1])]
                    targets.append(tar)
            temp_result = True
            for p in plugin.split(','):
                query = querylogic(condition.strip().split(';'))
                item = {'status': 0, 'title': title, 'plugin': p, 'condition': condition, 'time': datetime.now(),
                        'target': targets, 'plan': int(plan), 'isupdate': int(isupdate), 'query': dumps(query)}
                insert_reuslt = Mongo.coll['Task'].insert(item)
                if not insert_reuslt:
                    temp_result = False
            if temp_result:
                result = 'success'
        return result

    先获取了页面传了的值 先默认resultfail

    没有plugin的话直接返回fail

    有的话,先判断结果集是否全选,将结果集的ipport都加入列表,否则将当前页的ip将入列表。 然后执行插入。成功返回success

    6.Task()

    # 任务列表页面
    @app.route('/task')
    @logincheck
    def Task():
        page = int(request.args.get('page', '1'))
        cursor = Mongo.coll['Task'].find().sort('time', -1).limit(page_size).skip((page - 1) * page_size)
        return render_template('task.html', item=cursor)

    查询出任务信息,展示。

     

    7.Recheck()

    # 复测任务异步
    @app.route('/taskrecheck')
    @logincheck
    @anticsrf
    def Recheck():
        tid = request.args.get('taskid', '')
        task = Mongo.coll['Task'].find_one({'_id': ObjectId(tid)})
        result = 'fail'
        if task and task['plan'] == 0 and task['status'] == 2:  # 一次性任务,并且已经扫描完成
            result = Mongo.coll['Task'].update({'_id': ObjectId(tid)}, {'$set': {'status': 0}})
            if result:
                result = 'success'
        return result

    找到任务后,判断扫描完成后,更新数据库。返回success

    8.TaskDetail()

    # 任务详情页面
    @app.route('/taskdetail')
    @logincheck
    def TaskDetail():
        id = request.args.get('taskid', '')
        page = int(request.args.get('page', '1'))
        taskdate = request.args.get('taskdate', "")
        plugin_name = ''
        task_info = Mongo.coll['Task'].find_one({'_id': ObjectId(id)})
        if task_info:
            plugin_name = task_info['plugin']
        vulcount = 0
        lastscan = Mongo.coll["Result"].distinct('task_date', {'task_id': ObjectId(id)})
        result_list = []
        if len(lastscan) > 0:
            lastscan.sort(reverse=True)
            if taskdate:  # 根据扫描批次查看结果
                cursor = Mongo.coll['Result'].find(
                    {'task_id': ObjectId(id), 'task_date': datetime.strptime(taskdate, "%Y-%m-%d %H:%M:%S.%f")}).sort(
                    'time', -1).limit(page_size).skip((page - 1) * page_size)
            else:  # 查看最新批次结果
                taskdate = lastscan[0].strftime("%Y-%m-%d %H:%M:%S.%f")
                cursor = Mongo.coll['Result'].find(
                    {'task_id': ObjectId(id), 'task_date': lastscan[0]}).sort('time', -1).limit(page_size).skip(
                    (page - 1) * page_size)
            vulcount = cursor.count()
            for _ in cursor:
                result_list.append(
                    {'ip': _['ip'], 'port': _['port'], 'info': _['info'], 'vul_level': _['vul_info']['vul_level'],
                     'time': _['time']})
    
            # 速度优化,数据量多采取不同的方式查询
            if len(result_list) > 100:
                ip_hostname = {}
                hostname = Mongo.coll['Info'].aggregate(
                    [{'$match': {'hostname': {'$ne': None}}}, {'$project': {'_id': 0, 'ip': 1, 'hostname': 1}}])
                for _ in hostname:
                    if 'hostname' in hostname:
                        ip_hostname[_["ip"]] = _["hostname"]
                for _ in result_list:
                    if 'ip' in ip_hostname:
                        _['hostname'] = ip_hostname[_["ip"]]
                    else:
                        _['hostname'] = ''
            else:
                for _ in result_list:
                    hostname = Mongo.coll['Info'].find_one({'ip': _['ip']})
                    if hostname and 'hostname' in hostname:
                        _['hostname'] = hostname['hostname']
                    else:
                        _['hostname'] = ''
        return render_template('detail.html', item=result_list, count=vulcount, id=id, taskdate=taskdate,
                               plugin_name=plugin_name, scanlist=lastscan)

    通过id找到任务详情,然后将详情展示出来。有taskdate就是可以查询指定的日期。没有这个参数就是查询最新日期。当结果大于100,使用优化的查询语句。

    9.DeleteTask()

    # 删除任务异步
    @app.route('/deletetask', methods=['get', 'post'])
    @logincheck
    @anticsrf
    def DeleteTask():
        oid = request.form.get('oid', '')
        if oid:
            result = Mongo.coll['Task'].delete_one({'_id': ObjectId(oid)})
            if result.deleted_count > 0:
                result = Mongo.coll['Result'].delete_many({'task_id': ObjectId(oid)})
                if result:
                    return 'success'
        return 'fail'

    删除任务操作

    10.Downloadxls()

    # 下载excel报表异步
    @app.route('/downloadxls', methods=['get', 'post'])
    @logincheck
    @anticsrf
    def DownloadXls():
        tid = request.args.get('taskid', '')
        taskdate = request.args.get('taskdate', '')
        result_list = []
        if tid:  # 有任务id
            if taskdate:  # 从任务中拉取指定批次扫描结果
                taskdate = datetime.strptime(taskdate, "%Y-%m-%d %H:%M:%S.%f")
                cursor = Mongo.coll['Result'].find({'task_id': ObjectId(tid), 'task_date': taskdate}).sort(
                    'time', -1)
            else:  # 从任务中直接取该任务最新一次扫描结果
                lastscan = Mongo.coll["Result"].distinct('task_date', {'task_id': ObjectId(tid)})
                if len(lastscan) == 0:
                    cursor = []
                    taskdate = datetime.now()
                else:
                    lastscan.sort(reverse=True)
                    taskdate = lastscan[0]
                    cursor = Mongo.coll['Result'].find({'task_id': ObjectId(tid), 'task_date': taskdate}).sort(
                        'time', -1)
            title = Mongo.coll['Task'].find_one({'_id': ObjectId(tid)})['title']
            for _ in cursor:
                hostname = ''
                result = Mongo.coll['Info'].find_one({'ip': _['ip']})
                if result and 'hostname' in result:
                    hostname = result['hostname']
                result_list.append(
                    {'ip': _['ip'], 'port': _['port'], 'info': _['info'], 'vul_level': _['vul_info']['vul_level'],
                     'time': _['time'], 'vul_name': _['vul_info']['vul_name'], 'lastscan': taskdate, 'title': title,
                     'hostname': hostname})
            response = make_response(CreateTable(result_list, taskdate.strftime("%Y%m%d-%H%M%S")))
            if taskdate == '':
                response.headers["Content-Disposition"] = "attachment; filename=nodata.xls;"
            else:
                response.headers["Content-Disposition"] = "attachment; filename=" + quote(
                    title.encode('utf-8')) + taskdate.strftime(
                    "%Y-%m-%d-%H-%M-%S") + ".xls;"
        else:  # 下载综合报表
            tasks = Mongo.coll['Task'].find({})
            t_list = []
            for t in tasks:
                name = t['title']
                lastscan = Mongo.coll["Result"].distinct('task_date', {'task_id': t['_id']})
                if len(lastscan) == 0:
                    cursor = Mongo.coll['Result'].find({'task_id': t['_id']})
                    taskdate = None
                else:
                    lastscan.sort(reverse=True)
                    taskdate = lastscan[0]
                    cursor = Mongo.coll['Result'].find({'task_id': t['_id'], 'task_date': taskdate})
                for _ in cursor:  # 单任务详情
                    hostname = Mongo.coll['Info'].find_one({'ip': _['ip']})
                    if hostname:
                        _['hostname'] = hostname['hostname']
                    else:
                        _['hostname'] = None
                    _['title'] = name
                    _['vul_level'] = _['vul_info']['vul_level']
                    _['vul_name'] = _['vul_info']['vul_name']
                    _['lastscan'] = taskdate
                    t_list.append(_)
            response = make_response(CreateTable(t_list, 'all_data'))
            response.headers["Content-Disposition"] = "attachment; filename=all_data.xls;"
        response.headers["Content-Type"] = "application/x-xls"
        return response

    216-243行 将扫描结果查询出来后加到result_list

    response = make_response(CreateTable(result_list, taskdate.strftime("%Y%m%d-%H%M%S")))

    CreateTable()函数  View/lib/CreateExcel.py

    def CreateTable(cursor, id):
        item = []
        item.append(['IP', '端口', '主机名', '风险等级', '漏洞描述', '插件类型', '任务名称', '时间', '扫描批次'])
        for i in cursor:
            if i['lastscan']:
                _ = [i['ip'], i['port'], i['hostname'], i['vul_level'], i['info'],
                     i['vul_name'], i['title'], i['time'].strftime('%Y-%m-%d %H:%M:%S'),
                     i['lastscan'].strftime('%Y-%m-%d %H:%M:%S')]
            else:
                _ = [i['ip'], i['port'], i['hostname'], i['vul_level'], i['info'],
                     i['vul_name'], i['title'], i['time'].strftime('%Y-%m-%d %H:%M:%S'), '']
            item.append(_)
        file = write_data(item, id)
        return file.getvalue()

    创建个列表,将数据加入列表和描述对应起来。write_data()函数

    def write_data(data, tname):
        file = xlwt.Workbook(encoding='utf-8')
        table = file.add_sheet(tname, cell_overwrite_ok=True)
        l = 0
        for line in data:
            c = 0
            for _ in line:
                table.write(l, c, line[c])
                c += 1
            l += 1
        sio = StringIO.StringIO()
        file.save(sio)
        return sio

    通过xlwt包,将数据一行行写到文件里, 然后保存,文件名为时间格式。

    回到view/view.py

    make_response()返回文件名。 245-250行设置了http头和下载文件名字。后面返回下载。

    251-277行同上。

    11.search_result_xls()

    # 搜索结果报表下载接口
    @app.route('/searchxls', methods=['get'])
    @logincheck
    @anticsrf
    def search_result_xls():
        query = request.args.get('query', '')
        if query:
            result = query.strip().split(';')
            filter_ = querylogic(result)
            cursor = Mongo.coll['Info'].find(filter_).sort('time', -1)
            title_tup = ('IP', '端口号', '主机名', '服务类型')
            xls = [title_tup, ]
            for info in cursor:
                item = (
                    info.get('ip'), info.get('port'),
                    info.get('hostname'), info.get('server')
                )
                xls.append(item)
            file = write_data(xls, 'search_result')
            resp = make_response(file.getvalue())
            resp.headers["Content-Disposition"] = "attachment; filename=search_result.xls;"
            resp.headers["Content-Type"] = "application/x-xls"
            resp.headers["X-Content-Type-Options"] = "nosniff"
            return resp
        else:
            redirect(url_for('NotFound'))

    搜索结果有个话,写入文件下载。没有的话NotFound

    12.Plugin()

    # 插件列表页
    @app.route('/plugin')
    @logincheck
    def Plugin():
        page = int(request.args.get('page', '1'))
        cursor = Mongo.coll['Plugin'].find().limit(page_size).skip((page - 1) * page_size)
        return render_template('plugin.html', cursor=cursor, vultype=cursor.distinct('type'), count=cursor.count())

    查询-展示

    13.AddPlugin()

    单独分析 https://www.cnblogs.com/zhengjim/p/9406117.html

    14.DeletePlugin()

    # 删除插件异步
    @app.route('/deleteplugin', methods=['get', 'post'])
    @logincheck
    @anticsrf
    def DeletePlugin():
        oid = request.form.get('oid', '')
        if oid:
            result = Mongo.coll['Plugin'].find_one_and_delete({'_id': ObjectId(oid)}, remove=True)
            if not result['filename'].find('.') > -1:
                result['filename'] = result['filename'] + '.py'
            if os.path.exists(file_path + result['filename']):
                os.remove(file_path + result['filename'])
                return 'success'
        return 'fail'

    删除插件,从数据库中删除并且删除文件

    15.Analysis()

    # 统计页面
    @app.route('/analysis')
    @logincheck
    def Analysis():
        ip = len(Mongo.coll['Info'].distinct('ip'))
        record = Mongo.coll['Info'].find().count()
        task = Mongo.coll['Task'].find().count()
        vul = int(Mongo.coll['Plugin'].group([], {}, {'count': 0},'function(doc,prev){prev.count = prev.count + doc.count}')[0]['count'])
        plugin = Mongo.coll['Plugin'].find().count()
        vultype = Mongo.coll['Plugin'].group(['type'], {"count":{"$ne":0}}, {'count': 0},'function(doc,prev){prev.count = prev.count + doc.count}')
        cur = Mongo.coll['Statistics'].find().sort('date', -1).limit(30)
        trend = []
        for i in cur:
            trend.append(
                {'time': i['date'], 'add': i['info']['add'], 'update': i['info']['update'], 'delete': i['info']['delete']})
        vulbeat = Mongo.coll['Heartbeat'].find_one({'name': 'load'})
        scanbeat = Mongo.coll['Heartbeat'].find_one({'name': 'heartbeat'})
        if vulbeat == None or scanbeat == None:
            taskpercent = 0
            taskalive = False
            scanalive = False
        else:
            taskpercent = vulbeat['value'] * 100
            taskalive = (datetime.now() - vulbeat['up_time']).seconds
            scanalive = (datetime.now() - scanbeat['up_time']).seconds
            taskalive = True if taskalive < 120 else False
            scanalive = True if scanalive < 120 else False
        server_type = Mongo.coll['Info'].aggregate(
            [{'$group': {'_id': '$server', 'count': {'$sum': 1}}}, {'$sort': {'count': -1}}])
        web_type = Mongo.coll['Info'].aggregate([{'$match': {'server': 'web'}}, {'$unwind': '$webinfo.tag'},
                                                 {'$group': {'_id': '$webinfo.tag', 'count': {'$sum': 1}}},
                                                 {'$sort': {'count': -1}}])
        return render_template('analysis.html', ip=ip, record=record, task=task, vul=vul, plugin=plugin, vultype=vultype,
                               trend=sorted(trend, key=lambda x: x['time']), taskpercent=taskpercent, taskalive=taskalive,
                               scanalive=scanalive, server_type=server_type, web_type=web_type)

      

    看了页面回来看代码,这个方法就是将数据库中的值查询出来然后显示,不具体分析语句。

    16.Config()

    # 配置页面
    @app.route('/config')
    @logincheck
    def Config():
        val = []
        table = request.args.get('config', '')
        if table in ("vulscan", "nascan"):
            dict = Mongo.coll['Config'].find_one({'type': table})
            if dict and 'config' in dict:
                dict = dict['config']
                for _ in dict:
                    if _.find('_') > 0:
                        item_type = "list"
                    else:
                        item_type = "word"
                    val.append({"show": item_type, "type": _, "info": dict[_]["info"], "help": dict[_]["help"],
                                "value": dict[_]["value"]})
        val = sorted(val, key=lambda x: x["show"], reverse=True)
        return render_template('config.html', values=val)

    判断是爬虫引擎还是扫描引擎,然后分别查询出数据。

    17.UpdateConfig()

    # 配置更新异步
    @app.route('/updateconfig', methods=['get', 'post'])
    @logincheck
    @anticsrf
    def UpdateConfig():
        rsp = 'fail'
        name = request.form.get('name', 'default')
        value = request.form.get('value', '')
        conftype = request.form.get('conftype', '')
        if name and value and conftype:
            if name == 'Masscan' or name == 'Port_list':
                origin_value = Mongo.coll['Config'].find_one({'type': 'nascan'})["config"][name]["value"]
                value = origin_value.split('|')[0] + '|' + value
            elif name == 'Port_list_Flag':
                name = 'Port_list'
                origin_value = Mongo.coll['Config'].find_one({'type': 'nascan'})["config"]['Port_list']["value"]
                value = value + '|' + origin_value.split('|')[1]
            elif name == 'Masscan_Flag':
                name = 'Masscan'
                path = Mongo.coll['Config'].find_one({'type': 'nascan'})["config"]["Masscan"]["value"]
                if len(path.split('|')) == 3:
                    path = path.split('|')[1] + "|" + path.split('|')[2]
                else:
                    path = path.split('|')[1]
                if value == '1':
                    value = '1|' + path
                else:
                    value = '0|' + path
            result = Mongo.coll['Config'].update({"type": conftype}, {'$set': {'config.' + name + '.value': value}})
            if result:
                rsp = 'success'
        return rsp

       

    先判断是更新哪一个配置。

    根据name来判断是哪个配置,就从数据库去取对应的值,然后把提交过来的value加上去更新。

    18.PullUpdate()

    19.checkupdate()

    20.installplugin()

    # 拉取线上最新插件异步
    @app.route('/pullupdate')
    @logincheck
    @anticsrf
    def PullUpdate():
        rsp = 'err'
        f = urlopen('https://sec.ly.com/xunfeng/getlist')
        j = f.read().strip()
        if j:
            try:
                remotelist = json.loads(j)
                #remotelist_temp = copy.deepcopy(remotelist)
                plugin = Mongo.coll['Plugin'].find({'source': 1})
                for p in plugin:
                    for remote in remotelist:
                        if p['name'] == remote['name'] and remote['coverage'] == 0:
                            remotelist.remove(remote)
                locallist = Mongo.coll['Update'].aggregate([{'$project': {'_id': 0, 'unicode': 1}}])
                local = []
                for i in locallist:
                    local.append(i['unicode'])
                ret = [i for i in remotelist if i['unicode'] not in local]
                for i in ret:
                    i['isInstall'] = 0
                    Mongo.coll['Update'].insert(i)
                rsp = 'true'
            except:
                pass
        return rsp
    
    
    # 检查本地已知的线上插件列表异步
    @app.route('/checkupdate')
    @logincheck
    @anticsrf
    def CheckUpdate():
        json = []
        notinstall = Mongo.coll['Update'].find({'isInstall': 0}).sort('unicode', -1)
        for _ in notinstall:
            json.append({'unicode': _['unicode'], 'name': _['name'], 'info': _['info'], 'time': _['pushtime'],
                         'author': _['author']})
        return dumps(json)
    
    
    # 安装/下载插件异步
    @app.route('/installplugin')
    @logincheck
    @anticsrf
    def installplugin():
        rsp = 'fail'
        unicode = request.args.get('unicode', '')
        item = Mongo.coll['Update'].find_one({'unicode': unicode})
        json_string = {'add_time': datetime.now(), 'count': 0, 'source': 1}
        file_name = secure_filename(item['location'].split('/')[-1])
        if os.path.exists(file_path + file_name):
            if ".py" in file_name:
                db_record = Mongo.coll['Plugin'].find_one({'filename': file_name.split('.')[0]})
            else:
                db_record = Mongo.coll['Plugin'].find_one({'filename': file_name})
            if not db_record or not db_record['source'] == 1:
                file_name = file_name.split('.')[0] + '_' + str(datetime.now().second) + '.' + 
                            file_name.split('.')[-1]
            else:
                db_record = Mongo.coll['Plugin'].delete_one({'filename': file_name.split('.')[0]})
        if item['location'].find('/') == -1:
            urlretrieve('https://sec.ly.com/xunfeng/getplugin?name=' + item['location'], file_path + file_name)
        else:
            urlretrieve(item['location'], file_path + file_name)  # 兼容旧的插件源
        if os.path.exists(file_path + file_name):
            try:
                if file_name.split('.')[-1] == 'py':
                    module = __import__(file_name.split('.')[0])
                    mark_json = module.get_plugin_info()
                    json_string['filename'] = file_name.split('.')[0]
                else:
                    json_text = open(file_path + file_name, 'r').read()
                    mark_json = json.loads(json_text)
                    json_string['filename'] = file_name
                    mark_json.pop('plugin')
                json_string.update(mark_json)
                Mongo.coll['Plugin'].insert(json_string)
                Mongo.coll['Update'].update_one({'unicode': unicode}, {'$set': {'isInstall': 1}})
                rsp = 'success'
            except:
                pass
        return rsp

    均为更新插件的,不细分析。

    https://sec.ly.com/xunfeng/getlist 查询出最新插件,然后与数据库比较。

    查看是否本地有安装。

    https://sec.ly.com/xunfeng/getplugin?name= 在这里实现下载。

    21.Login()

    22.Loginout()

    # 登录
    @app.route('/login', methods=['get', 'post'])
    def Login():
        if request.method == 'GET':
            return render_template('login.html')
        else:
            account = request.form.get('account')
            password = request.form.get('password')
            if account == app.config.get('ACCOUNT') and password == app.config.get('PASSWORD'):
                session['login'] = 'loginsuccess'
                return redirect(url_for('Search'))
            else:
                return redirect(url_for('Login'))
    
    
    # 登出异步
    @app.route('/loginout')
    @logincheck
    def LoginOut():
        session['login'] = ''
        return redirect(url_for('Login'))

    一个登陆一个登出。

    23.NotFound()

    24.Error()

    @app.route('/404')
    def NotFound():
        return render_template('404.html')
    
    
    @app.route('/500')
    def Error():
        return render_template('500.html')

    显示404 500

    阅读了view.py 里的每个方法具体都是干嘛的,对巡风扫描器整体有一个大概了解。

    感谢ysrc开源。

  • 相关阅读:
    【JOI2017春季合宿】Port Facility
    LOJ504「LibreOJ β Round」ZQC 的手办
    UOJ37. 【清华集训2014】主旋律
    CF1012F Passports
    AT2370 Piling Up
    CF908G New Year and Original Order
    CF643E Bear and Destroying Subtrees
    CF183D T-shirt
    「JOISC 2016 Day 3」回转寿司
    「LibreOJ β Round #2」计算几何瞎暴力
  • 原文地址:https://www.cnblogs.com/zhengjim/p/9406014.html
Copyright © 2011-2022 走看看