• 巡风视图函数源码学习--view.py


    记录一下巡风扫描器view.py这个脚本里的视图函数的学习,直接在代码里面做的注释,里面有一些print 代码是为了把数据打印出来小白我自己加的,勿怪勿怪。可能存在一些理解错误和不到位的地方,希望大佬多多指正。。

    0x01:跳转到登陆页面##

    第二遍看这个脚本的源码时,想到一个问题,如果你在浏览器地址栏里输入http://127.0.0.1/login可以跳转到登陆页面,如果只输入127.0.0.1,这时候并没有运行Login这个视图函数,却也能直接跳转到登陆页面,这是为什么呢?原来,在Main视图函数上面有这样两行代码:

    @app.route('/')
    @logincheck
    def Main():
    

    只输入127.0.0.1时,相当于访问了根目录,会运行Main视图函数,而要运行Main函数,要先运行logincheck这个用于判断是否已经登陆的修饰函数,因为此时还未登陆,在logincheck函数里给我们跳转到了Login函数。

    return redirect(url_for('Login'))
    

    好了,下面开始看代码(掉头发)。。

    0x02:Login视图函数##

    为什么先看这个呢?因为你要先登陆啊(ps:屁话,不登陆怎么进入)

    @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'))
    

    调转到登陆页面后,就要输入账号密码了,前端输入的账号密码,传到login.html这个页面,并命名为account和password,是login.html里的这两行代码:

    <input class="form-control" type="text" required="" placeholder="Account" name="account">
    
    <input class="form-control" type="password" required="" placeholder="Password" name="password">
    

    通过request.form.get获取到输入的账号密码之后,在数据库里面做验证,验证通过后,设置session['login'] = 'loginsuccess',用于后面的登陆验证,然后跳转到Search函数。

    0x03:logincheck登陆验证函数##

    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
    

    如果session的login字段等于loginsuccess,则说明已经登陆,否则跳转到Login函数,让用户登陆

    0x04:Search视图函数##

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

    这个函数的功能就是接受前端用户输入的搜索条件,并名为为q,是Search.html里面的这行代码

    <input type="text" class="form-control" placeholder="Example:  ip: 192.168.1.1; port: 22" style="color: #797979;" id="filter" name="q">
    

    0x05:Deleteall视图函数##

    @app.route('/deleteall', methods=['post'])
    @logincheck
    def Deleteall():
        # 移除仓库下的Task数据库
        Mongo.coll['Task'].remove({})
        return 'success'
    

    Mongo是从__init.py__里面引入过来的,是数据库的连接对象,这个函数的作用是,使用Mongo,找到Task这个数据库并移除

    0x06:Main视图函数##

    def Main():
    # 获取前端的q
    q = request.args.get('q', '')
    page = int(request.args.get('page', '1'))
    plugin = Mongo.coll['Plugin'].find()  # 插件列表,列出Plugin中的所有列表
    plugin_type = plugin.distinct('type')  # 插件类型列表
    if q:  # 基于搜索条件显示结果
        # 分开多条件查询
        result = q.strip().split(';')
        print result
        query = querylogic(result)  # 判断搜索类型,返回字典{"port": ,"ip": , "banner": ,"hostname"}
        # 在info表里把条件代入查询sort()根据time字段排序 limit()分页
        # .find返回<class 'pymongo.cursor.Cursor'>类型对象
        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就是你在前端输入的搜索条件,鼠标放在“搜索”旁边的问号图标上,可以查到所支持的搜索方式,

    0x07:Getplugin视图函数##

    @app.route('/getplugin', methods=['get', 'post'])
    @logincheck
    def Getplugin():
        # 获取了type risk search 是否有值
        # 没有的话,就全部查询。
        # 有的话 在Plugin表代入条件查询。然后将插件名字和信息转json格式返回。
        type = request.form.get('type', '')
        risk = request.form.get('risk', '')
        search = request.form.get('search', '')
        print type,risk,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)
        print list(cursor)
        rsp = []
        # 把插件的name和info添加到列表中
        for i in cursor:
            result = {'name': i['name'], 'info': i['info']}
            rsp.append(result)
        return json.dumps(rsp)
    

    type、risk在新增任务的那个弹窗里或偶的,search还没找到是从哪里获取的

    0x08:Addtask视图函数##

    @app.route('/addtask', methods=['get', 'post'])
    @logincheck
    def Addtask():
        # 先获取了页面传了的值 先默认result为fail
        # 没有plugin的话直接返回fail
        # 有的话,先判断结果集是否全选,将结果集的ip和port都加入列表,否则将当前页的ip将入列表。
        title = request.form.get('title', '')   # 任务名称
        plugin = request.form.get('plugin', '')	# 从插件列表里所选择的插件
        condition = unquote(request.form.get('condition', ''))	# 所选结果的ip地址
        plan = request.form.get('plan', 0)		# 执行周期
        ids = request.form.get('ids', '')			# 所选地址的 ip:端口
        isupdate = request.form.get('isupdate', '0')    # 是否自动更新列表
        resultcheck = request.form.get('resultcheck', '0')  # 结果集是否全选
        print title,plugin,condition,plan,ids,isupdate,resultcheck
        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
    

    这个函数的作用,在搜索之后,如果要根据搜索结果新增任务,就获取你新增任务时的一些参数,任务名、是否自动更新、是都全选等。

    0x09: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)
    

    利用Mongo查询出Task数据库里面的所有任务,排序、分页并在前端展示

    0x10:Recheck视图函数##

    # 复测任务异步
    @app.route('/taskrecheck')
    @logincheck
    def Recheck():
        # 获取前端需要复测的任务
        tid = request.args.get('taskid', '')
        # 找到任务,判断扫描完成后更新数据库,返回success
        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
    

    在任何一个任务框里,点击沙漏图标,可以对该任务进行复测。

    0x11:TaskDetail视图函数##

    # 任务详情页面
    @app.route('/taskdetail')
    @logincheck
    def TaskDetail():
        # 获取任务id
        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)})
        print id,taskdate
        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,获取到该任务的数据,传到detail.html页面,并在前端展示

    0x12:DeleTask视图函数##

    # 删除任务异步
    @app.route('/deletetask', methods=['get', 'post'])
    @logincheck
    def DeleteTask():
        # 获取将要删除任务的id
        oid = request.form.get('oid', '')   # 点击删除时,获取参数
        print oid
        if oid:
            # delete_one(): 删除符合条件的一条文档,返回pymongo对象
            # ObjectId将字符串id转化为ObjectId对象
            result = Mongo.coll['Task'].delete_one({'_id': ObjectId(oid)})
            print result
            # deleted_count删除的数量
            if result.deleted_count > 0:
                # delete_many():删除Result数据库中符合条件的所有文档,就是删除这个任务的所有结果
                result = Mongo.coll['Result'].delete_many({'task_id': ObjectId(oid)})
                if result:
                    return 'success'
        return 'fail'
    

    0x13:DownloadXls视图函数##

    # 下载excel任务报表异步
    @app.route('/downloadxls', methods=['get', 'post'])
    @logincheck
    def DownloadXls():
        tid = request.args.get('taskid', '')
        taskdate = request.args.get('taskdate', '')
        print 1111,tid, 1111,taskdate
        print type(tid),len(tid), type(taskdate),len(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:  # 从任务中直接取该任务最新一次扫描结果
                # distinct获取集合中指定字段的不重复值,并以数组的形式返回
                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]
                    # sort函数用来排序,1为升序,-1为降序
                    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
                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:  # 下载任务页面里面所有的任务
            # 找到Task数据库里面所有的数据
            tasks = Mongo.coll['Task'].find({})
            t_list = []
            for t in tasks:
                name = t['title']
                # distinct获取集合中指定字段的不重复值,并以数组的形式返回
                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:
                    # 降序排列,recerse=False升序(默认)
                    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
    

    这个视图函数有两个功能,比可以单独下载某一个任务,也可以下载全部任务

    0x14:search_result_xls视图函数##

    # 搜索结果报表下载接口
    @app.route('/searchxls', methods=['get'])
    @logincheck
    def search_result_xls():
        # query为前端用户输入的搜索条件
        query = request.args.get('query', '')
        print 11111,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'))
    

    功能一上面的DownloadXls函数类似,只不过它下载的是搜索结果页面

    0x15:Plugin视图函数##

    # 插件列表页
    @app.route('/plugin')
    @logincheck
    def Plugin():
        # 获取前端页面
        page = int(request.args.get('page', '1'))
        print 1111,page
        # 从数据库里面找到有关插件数据
        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())
    

    0x16:AddPlugin视图函数##

    # 新增插件异步
    @app.route('/addplugin', methods=['get', 'post'])
    @logincheck
    def AddPlugin():
        result = 'fail'
        isupload = request.form.get('isupload', 'false')    # 是否共享
        print 99999,isupload
        # 插件格式
        methodurl = request.form.get('methodurl', '')
        print 999999,methodurl
        file_name = ''
        # 上传script格式,也就是python文件
        if methodurl == '':
            # 获取上传的文件
            f = request.files['file']
            # 获取所上传的文件名
            fname = secure_filename(f.filename)
            if fname.split('.')[-1] == 'py':
                path = file_path + fname
                # 重命名并保存
                if os.path.exists(file_path + fname):
                    fname = fname.split('.')[0] + '_' + str(datetime.now().second) + '.py'
                    path = file_path + fname
                f.save(path)
                if os.path.exists(path):
                    file_name = fname.split('.')[0]
                    # __import__()加载这个文件, 获取到里面的get_plugin_info()的信息。
                    # 我们编写插件的格式要有get_plugin_info()这个方法,返回插件信息。
                    # 然后再加入了文件名 时间。保存到数据库。
                    module = __import__(file_name)
                    mark_json = module.get_plugin_info()
                    mark_json['filename'] = file_name
                    mark_json['add_time'] = datetime.now()
                    mark_json['count'] = 0
                    if 'source' not in mark_json:
                        mark_json['source'] = 0
                    insert_result = Mongo.coll['Plugin'].insert(mark_json)
                    if insert_result:
                        result = 'success'
                        file_name = file_name +'.py'
        # 上传json格式
        else:
            # 从前端获取插件信息数据,然后插入数据库,并写入json文件里
            name = request.form.get('name', '') # 插件名字
            info = request.form.get('info', '')  # 插件说明
            author = request.form.get('author', '') # 插件作责
            level = request.form.get('level', '') # 危害等级
            type = request.form.get('vultype', '') # 插件类型
            keyword = request.form.get('keyword', '')   # 查询条件
            pluginurl = request.form.get('pluginurl', '')   # 插件说明链接
            methodurl = request.form.get('methodurl', '')   # 插件内容
            pdata = request.form.get('pdata', '')      # post数据
            analyzing = request.form.get('analyzing', '')   # 判断类型
            analyzingdata = request.form.get('analyzingdata', '')   # 判断依据
            tag = request.form.get('tag', '')
            print info,level,keyword,pluginurl,methodurl,pdata,analyzing,analyzingdata,tag
            try:
                query = {'name': name, 'info': info, 'level': level, 'type': type, 'author': author, 'url': pluginurl,
                         'keyword': keyword, 'source': 0}
                query['plugin'] = {'method': methodurl.split(' ', 1)[0], 'url': methodurl.split(' ', 1)[1],
                                   'analyzing': analyzing, 'analyzingdata': analyzingdata, 'data': pdata, 'tag': tag}
                file_name = secure_filename(name) + '_' + str(datetime.now().second) + ".json"
                with open(file_path + file_name, 'wb') as wt:
                    wt.writelines(json.dumps(query))
                query.pop('plugin')
                query['add_time'] = datetime.now()
                query['count'] = 0
                query['filename'] = file_name
                # 插入到数据库
                insert_result = Mongo.coll['Plugin'].insert(query)
                if insert_result:
                    result = 'success'
            except:
                pass
        # 如果同意共享插件,且上传成功则增加到巡风的插件里面
        if isupload == 'true' and result == 'success':
            # 读取文件
            code_tuple = open(file_path+file_name).read()
            code = ''
            for _ in code_tuple:
                code += _
            params = {'code': code}
            req = urllib2.Request('https://sec.ly.com/xunfeng/pluginupload')
            req.add_header('Content-Type','application/x-www-form-urlencoded')
            rsp = urllib2.urlopen(req,urlencode(params))
            print 'upload result:' + rsp.read()
        return result
    

    0x17:DeietePlugin视图函数##

    # 删除插件异步
    @app.route('/deleteplugin', methods=['get', 'post'])
    @logincheck
    def DeletePlugin():
        # 获取插件id
        oid = request.form.get('oid', '')
        print 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'
    

    与删除任务类似

    0x18:Analysis视图函数##

    # 统计页面
    @app.route('/analysis')
    @logincheck
    def Analysis():
        # distinct获取集合中指定字段的不重复值,以集合的形式返回,就是去重
        ip = len(Mongo.coll['Info'].distinct('ip'))
        print 'ip总数', ip
        # 获取数量
        record = Mongo.coll['Info'].find().count()
        print '记录总数', record
        # 获取任务数量
        task = Mongo.coll['Task'].find().count()
        print '任务总数', task
        # group是mongodb中自带的三种聚合函数之一
        # count:简单统计集合中符合某种条件的文档数量。
        # distinct:用于对集合中的文档针进行去重处理。
        # group:用于提供比count、distinct更丰富的统计需求,可以使用js函数控制统计逻辑
        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()
        print "插件总数", plugin
        vultype = Mongo.coll['Plugin'].group(['type'], {"count":{"$ne":0}}, {'count': 0},'function(doc,prev){prev.count = prev.count + doc.count}')
        print "漏斗类型", vultype
        # sort根据date字段降序排列,limit指定读取的数据数量
        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']})
        # 找到Heartbeat集合中的两个文档
        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)	
    

    这个方法就是将数据库中的值查询出来然后显示.

    0x19: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)
    

    0x20:UpdateConfig视图函数##

    # 配置更新异步
    @app.route('/updateconfig', methods=['get', 'post'])
    @logincheck
    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:
            # 判断所要更新的配置
            # 端口列表或MAsscan配置
            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
            # 判断是否启用存活探测ICMP
            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]
            # 判断是否启用MASSCAN
            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加上去更新。

    0x21:PullUpdate视图函数##

    0x22:checkupdate视图函数##

    0x23:installplugin视图函数##

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

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

    查看是否本地有安装。

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

    参考文章:一个还需要努力的人:巡风源码解读与分析

  • 相关阅读:
    6174问题
    阶乘的精确值
    小学生算术
    Primer回顾 数组和指针
    Primer回顾 标准库类型
    绪论
    字符串的存储
    条款39:明智而审慎的使用private继承
    条款34:区分接口继承和实现继承
    条款33:避免遮掩继承而来的名称
  • 原文地址:https://www.cnblogs.com/liangshian/p/11695161.html
Copyright © 2020-2023  润新知