Esempio n. 1
0
def modify_plugin():
    """
    禁用指定的插件,
    服务端:1.从CHECKER_INSTANCE_DICT指定插件设置disable 2.并向MQ中发送一条消息
    引擎端:1.等到引擎消费到指令从CHECKER_INSTANCE_DICT,也将该插件的disable设置为True
    :return: 
    """
    from plugins.base.vuln_enum import PluginSwith
    from common.plugins_util import modify_default_checkers
    post_data = request.get_json(force=True)
    param_list = ["name", "switch"]
    if has_dict_value_blank(post_data, param_list):
        return jsonify(
            status=400,
            message="更新失败",
            data={"extra_info": "请保证%s任一参数值不为空" % ','.join(param_list)})
    try:
        post_checker_name = post_data.get("name")
        post_switch = post_data.get("switch")
        plugin_switch = PluginSwith.ON if post_switch else PluginSwith.OFF
        checkers = load_default_checkers()
        if post_checker_name not in checkers:
            return jsonify(
                status=400,
                message="更新失败",
                data={"extra_info": "不存在名为%s的插件" % post_checker_name})

        PluginInfoService.update(
            fields=({
                PluginInfo.useable: plugin_switch
            }),
            where=(PluginInfo.plugin_name == post_checker_name))

        RedisService.modify_plugin_switch(checkers[post_checker_name],
                                          plugin_switch)

        system_notice_celery.delay(
            broadcast={
                "type": BroadCastType.PLUGIN,
                "action": BroadCastAction.MODIFY_PLUGIN,
                "data": {
                    "name": post_checker_name,
                    "switch": plugin_switch
                }
            })
        modify_default_checkers()
        return jsonify(status=200,
                       message="更新成功",
                       data={
                           "extra_info":
                           "{}插件{}".format("启用" if plugin_switch else "禁用",
                                           post_checker_name)
                       })
    except Exception as e:
        logger.exception("modify_plugin raise error")
        return jsonify(status=500,
                       message="未知异常",
                       data={"extra_info": "修改插件信息时出现未知异常,请联系管理员查看异常日志"})
Esempio n. 2
0
def insert_plugin():
    """
    新增插件,
    服务端:1.保存插件到本地,先上传到tmp目录,然后解析插件是否满足格式出tag并移动到tag目录,刷新插件列表 2.向MQ发送一条消息包含插件
    引擎端:2.消费到MQ发送消息,并下载最新插件并新增到CHECKER_INSTANCE_DICT
    :return: 
    """
    import shutil
    from common.system_util import mkdir
    from common.path import PLUGIN_PATH
    from common.plugins_util import load_default_checkers

    def allowed_file(filename):
        """
        检测是否为python文件
        :param filename: 
        :return: 
        """
        return '.' in filename and filename.rsplit('.', 1)[1] in ["py"]

    def parse_plugin_file(plugin_file_path):
        """
        warnning: 插件文件路径,这里会存在安全隐患,请按照实际需求考虑是否用imp.load_source
        :param plugin_file_path: 
        :return: 
        """
        import imp
        from exception.hunter_web_exception import BaseHunterException

        # 解析插件并且分类
        base_checker = imp.load_source('BaseChecker', plugin_file_path)
        checker_instance = base_checker.Checker()
        checker_instance.check_plugin_info()
        # 检测插件是否重名
        checker_name = checker_instance.info["name"]
        if checker_name in load_default_checkers():
            raise BaseHunterException("插件%s已经存在,请重新命名" % checker_name)
        return checker_instance

    def move_plugin(tmp_plugin_file_path, checker_instance, filename):
        """
        :param checker_instance: 
        :return: 
        """
        # 移动插件到指定目录
        tag = checker_instance.info["tag"]
        mkdir(PLUGIN_PATH + tag)
        formal_plugin_file_path = os.path.join(PLUGIN_PATH + tag, filename)
        shutil.move(tmp_plugin_file_path, formal_plugin_file_path)

    def save_plugin_info(checker_instance):
        if PluginInfoService.count(where=(
                PluginInfo.plugin_name == checker_instance.info["name"])) == 0:
            PluginInfoService.save(
                author=checker_instance.info["author"],
                plugin_name=checker_instance.info["name"],
                plugin_tag=checker_instance.info["tag"],
                imp_version=checker_instance.info["imp_version"],
                description=checker_instance.info["description"],
                repair=checker_instance.info["repair"],
                type=checker_instance.info["type"]["fullname"],
                chinese_type=checker_instance.info["type"]["fullchinesename"],
                level=checker_instance.info["type"]["level"],
            )

    try:
        file = request.files['file']
        if file and allowed_file(file.filename):
            filename = file.filename
            tmp_plugin_file_path = os.path.join(PLUGIN_PATH + "tmp/", filename)
            file.save(tmp_plugin_file_path)
            # 解析插件
            checker_instance = parse_plugin_file(tmp_plugin_file_path)
            move_plugin(tmp_plugin_file_path, checker_instance, filename)
            # 保存到数据
            save_plugin_info(checker_instance)
            load_default_checkers(True)
            RedisService.modify_plugin_switch(checker_instance, PluginSwith.ON)
            system_notice_celery.delay(
                broadcast={
                    "type": BroadCastType.PLUGIN,
                    "action": BroadCastAction.INSERT_PLUGIN,
                    "data": {
                        "name": checker_instance.info["name"]
                    }
                })
            return jsonify(status=200,
                           message="上传成功",
                           data={"extra_info": "您可以刷新网页后使用新插件"})
        return jsonify(status=500,
                       message="上传失败",
                       data={"extra_info": "您上传的插件不是py文件"})
    except Exception as e:
        logger.exception("create_plugin raise error")
        # 解析插件是否满足格式
        return jsonify(status=500, message="上传失败", data={"extra_info": str(e)})