def create_group(group_id=None): name = request.values.get('name') cname = request.values.get('cname') selectors = request.values.get('selectors') if request.method == 'POST': try: group = Group(name, cname, selectors=selectors) db.session.add(group) db.session.commit() except Exception as e: logger.error(e) return jsonify(dict(status=False, desc='添加失败')) else: return jsonify(dict(status=True, desc='添加成功')) else: group = db.session.query(Group).filter(Group.id == group_id).first() if not group: return jsonify(dict(status=False, desc='用户组不存在')) try: group.name = name group.cname = cname group.selectors = selectors db.session.add(group) db.session.commit() except Exception as e: logger.error(e) return jsonify(dict(status=False, desc='更新失败')) else: return jsonify(dict(status=True, desc='更新成功'))
def add_job_cron(func, **kwargs): scheduler.add_job(func, 'cron', **kwargs) try: scheduler.start() except Exception as e: logger.error(e)
def create_selector(selector_id=None): name = request.values.get('name') cname = request.values.get('cname') kind = request.values.get('kind') if request.method == 'POST': try: selector = Selector(name, cname, kind=kind) db.session.add(selector) db.session.commit() except Exception as e: logger.error(e) return jsonify(dict(status=False, desc='添加失败')) else: return jsonify(dict(status=True, desc='添加成功')) else: selector = db.session.query(Selector).filter( Selector.id == selector_id).first() if not selector: return jsonify(dict(status=False, desc='权限不存在')) try: selector.name = name selector.cname = cname selector.kind = kind db.session.add(selector) db.session.commit() except Exception as e: logger.error(e) return jsonify(dict(status=False, desc='更新失败')) else: return jsonify(dict(status=True, desc='更新成功'))
def report_model_delete(): model_id = request.values.get('model_id') scan_key = request.values.get('scan_key') if scan_key: user_id = verify_scan_key(scan_key).id else: user_id = current_user.id user = db.session.query(User).filter(User.id == user_id).first() admin_id = db.session.query(Group).filter(Group.name == 'ADMIN').first().id if str(admin_id) in user.groups.split(','): model = db.session.query(ReportModel).filter(ReportModel.model_id == model_id).first() else: model = db.session.query(ReportModel).filter(ReportModel.user_id == user_id & ReportModel.model_id == model_id).first() if not model: logger.error(model_id) abort(403) old_filename = model.logo_filename file_path1 = '%s%s' % (basedir, PDF_LOGO_PATH1) file_path2 = '%s%s' % (basedir, PDF_LOGO_PATH2) try: if os.path.exists(os.path.join(file_path1, old_filename)): os.remove(os.path.join(file_path1, old_filename)) if os.path.exists(os.path.join(file_path2, old_filename)): os.remove(os.path.join(file_path2, old_filename)) except Exception, e: return jsonify(dict(status=False, desc='logo文件删除失败' + str(e)))
def add_vul_report(task_id, site_id, vul_id, url, detail='', request_content='', response_content=''): try: # 存入web_result表 vul = db.session.query(WebVulList).filter( WebVulList.id == vul_id).first() level = vul.level res = WebResult(task_id=task_id, site_id=site_id, url=url, level=level, detail=detail, output='', vul_id=vul_id, asset_task_id=0) db.session.add(res) db.session.flush() web_result_id = res.id db.session.commit() except Exception, e: logger.error('Insert data to table: web_result failed: %s' % str(e)) return False
def delete_group(group_id): try: db.session.query(Group).filter(Group.id == group_id).delete() db.session.commit() except Exception as e: logger.error(e) return jsonify(dict(status=False, desc='删除失败')) else: return jsonify(dict(status=True, desc='删除成功'))
def delete_selector(selector_id): try: db.session.query(Selector).filter(Selector.id == selector_id).delete() db.session.commit() except Exception as e: logger.error(e) return jsonify(dict(status=False, desc='删除失败')) else: return jsonify(dict(status=True, desc='删除成功'))
def delete_user(user_id): try: user = db.session.query(User).filter(User.id == user_id).first() user.status = False db.session.commit() except Exception as e: logger.error(e) return jsonify(dict(status=False, desc='删除失败')) else: return jsonify(dict(status=True, desc='删除成功'))
def del_job(job_id): try: job_task_ref = db.session.query(ApJobsTaskRef).filter(ApJobsTaskRef.job_id == job_id).first() if job_task_ref.job_status == 1: scheduler.remove_job(job_id) db.session.query(ApJobsTaskRef).filter(ApJobsTaskRef.job_id == job_id).delete() db.session.commit() return True except Exception, e: print e logger.error(e) return False
def del_job_db(job_id): try: db.session.query(ApJobsTaskRef).filter( ApJobsTaskRef.parent_id == job_id).delete() db.session.query(ApJobsTaskRef).filter( ApJobsTaskRef.job_id == job_id).delete() db.session.commit() return True except Exception, e: print e logger.error(e) return False
def pause_job(job_id): try: job_task_ref = db.session.query(ApJobsTaskRef).filter(ApJobsTaskRef.job_id == job_id).first() if job_task_ref.job_status == 2: scheduler.pause_job(job_id, jobstore=jobstores) job_task_ref.job_status = 4 db.session.add(job_task_ref) db.session.commit() return True except Exception, e: print e logger.error(e) return False
def tsgz_loophole_count(): try: patch_no = request.values.get('patch_no') patch_rep = db.session.query(PatchReport.data_rep_json).filter( PatchReport.patch_no == patch_no).first() data_rep_json = patch_rep.data_rep_json if not data_rep_json: raise Exception data_rep_dict = json.loads(data_rep_json) data_rep_dict['status'] = True except Exception, e: logger.error(e) data_rep_dict = dict(status=False, desc=str(e))
def revoke_job(job_id): # job = run_spider.AsyncResult(job_id) # job.revoke() try: celery.control.revoke(job_id) job_child_list = db.session.query(ApJobsTaskRef).filter( ApJobsTaskRef.parent_id == job_id).all() if len(job_child_list) > 0: for job_child in job_child_list: celery.control.revoke(job_child.job_id) return True except Exception, e: print e logger.error(e) return False
def tsgz_loophole_detail(): try: patch_no = request.values.get('patch_no') job_id = request.values.get('job_id') job_task = db.session.query(ApJobsTaskRef).filter( ApJobsTaskRef.job_id == job_id).first() task_id = job_task.task_id patch_task = db.session.query(PatchTask.data_rep_json).filter( PatchTask.patch_no == patch_no, PatchTask.task_id == task_id).first() data_rep_json = patch_task.data_rep_json if not data_rep_json: raise Exception data_rep_dict = json.loads(data_rep_json) data_rep_dict['status'] = True except Exception, e: logger.error(e) data_rep_dict = dict(status=False, desc=str(e))
def formatResult2(self, taskid=0, jobid=''): scanData = { "task_id": taskid, "job_id": jobid, "domain": "", "name": "", "stats": { "high": 0, "med": 0, "info": 0, "low": 0 }, "start_time": "", "end_time": "", "high": [], "med": [], "low": [], "info": [], "task_state": "", "port": "", "scheme": "", "scan_time": "", "test_count": 0, "url_count": 0, "score": 0 } task = db.session.query(Task).filter(Task.id == taskid).first() if not task: return scanData job = db.session.query(ApJobsTaskRef).filter( ApJobsTaskRef.job_id == jobid).first() target = json.loads(task.target) scanData['task_id'] = taskid scanData['job_id'] = jobid scanData['domain'] = target[0]['domain'] scanData['name'] = task.name scanData['start_time'] = task.start_time.strftime( '%Y-%m-%d %H:%M:%S') if task.start_time else '' scanData['end_time'] = task.end_time.strftime( '%Y-%m-%d %H:%M:%S') if task.end_time else '' scanData['task_state'] = task.explainState() scanData['high'] = [] scanData['med'] = [] scanData['low'] = [] scanData['info'] = [] scanData['stats'] = {"high": 0, "med": 0, "low": 0, "info": 0} vulResults = {} webFormatResult = {} webResults = db.session.query( WebResult.task_id, WebResult.url, WebResult.level, WebResult.detail, WebResult.output, WebResult.asset_task_id, WebResult.vul_id, WebResultData.request, WebResultData.response).filter( WebResultData.web_result_id == WebResult.id, WebResult.task_id == taskid).all() if not webResults: return scanData for row in webResults: vulid = row.vul_id level = row.level.lower() if not vulResults.has_key(vulid): vulResults[vulid] = [] record = { "url": row.url, "detail": row.detail, "output": row.output, "asset_task_id": row.asset_task_id, "request": row.request, "response": row.response.split("\n\n")[0] } vulResults[vulid].append(record) webVuls = db.session.query( WebVulList.vul_id, WebVulList.vul_name, WebVulList.family_id, WebVulList.family, WebVulList.module_id, WebVulList.module, WebVulList.tag, WebVulList.level, WebVulList.effect, WebVulList.reference, WebVulList.solu, WebVulList.desc, WebVulFamilyRef.family.label('family_id')).filter( WebVulList.vul_id.in_(vulResults.keys()), WebVulList.vul_id == WebVulFamilyRef.vul_id).all() if not webVuls: return False data = {} for row in webVuls: vulid = row.vul_id level = row.level.lower() familyid = row.family_id if not data.has_key(level): data[level] = [] tag = json.dumps(row.tag) # 同一个漏洞最多显示五条记录 data[level].append({ "vul_id": row.vul_id, "vul_name": row.vul_name, "family_id": row.family_id, "family": row.family, "module_id": row.module_id, "module": row.module, "level": level, "effect": row.effect, "reference": row.reference, "desc": row.desc, "solu": row.solu, "tag": tag, "list": vulResults[vulid] }) # 统计漏洞数量 for level, rowlist in data.iteritems(): scanData['stats'][level] = len(rowlist) # --------增加安全评分、扫描url数等内容;by lichao -------------- # 格式化扫描对象: 域名、端口、协议 try: target_dict = json.loads(task.target)[0] scheme = target_dict.get('scheme', '') full_domain = target_dict.get('domain', '') if ':' in full_domain: sub_domain, port = full_domain.split(':', 1) else: sub_domain = full_domain if scheme == 'http': port = '80' elif scheme == 'https': port = '443' else: port = '' scanData['domain'] = sub_domain scanData['port'] = port scanData['scheme'] = scheme # 计算、格式化扫描耗时 start_time = scanData.get('start_time') end_time = scanData.get('end_time') scan_time_str = '' if start_time and end_time: t1 = datetime.strptime(start_time, '%Y-%m-%d %H:%M:%S') t2 = datetime.strptime(end_time, '%Y-%m-%d %H:%M:%S') scan_time = str(t2 - t1) days = (t2 - t1).days if days > 0: scan_time_str += u'%d 天 ' % days if ',' in scan_time: scan_time = scan_time.split(',', 1)[1] hours, minutes, seconds = scan_time.split(':', 2) scan_time_str += u'%s 小时 %s 分 %s 秒' % (hours, minutes, seconds) scanData['scan_time'] = scan_time_str # 扫描策略 scan_policy_id = task.web_scan_policy scan_policy = db.session.query(WebVulPolicy).filter( WebVulPolicy.id == scan_policy_id).first() if scan_policy: scanData['scan_policy'] = scan_policy.name else: scanData['scan_policy'] = '' # 统计扫描url数 url_count = db.session.query(SpiderUrl).filter( SpiderUrl.task_id == taskid).count() scanData['url_count'] = url_count # 扫描请求数,测试数 run_domain_count = db.session.query(WebVulList).filter( WebVulList.scan_type == 2).count() run_url_count = db.session.query(WebVulList).filter( WebVulList.scan_type == 1).count() # BakFileCheckScript_yd CompressFileCheckScript_yd ConfigFileCheckScript_yd SqlFileCheckScript # 以上四个文件都要遍历目录,payload总数 run_dir_payload_count = 484 if re.search(u'快速扫描', scan_policy.name): run_dir_payload_count = 0 domain_file_count = 108 # WebShellCheckScript_yd payload总数 dir_count = 1 test_count = run_domain_count + \ run_url_count * url_count + \ run_dir_payload_count * run_url_count * min(10, dir_count) + \ domain_file_count + \ random.randint(100, 200) scanData['test_count'] = test_count # scanData['stats'] = {"high": 0, "med": 0, "low": 0, "info": 0} # 安全|风险评分 high_count = scanData['stats']['high'] med_count = scanData['stats']['med'] low_count = scanData['stats']['low'] info_count = scanData['stats']['low'] if high_count > 0: score = 40 - 7 * ( high_count - 1) - 4 * med_count - 3 * low_count - 2 * info_count elif med_count > 0: score = 60 - 4 * (med_count - 1) - 3 * low_count - 2 * info_count elif low_count > 0: score = 80 - 3 * (low_count - 1) - 2 * info_count elif info_count > 0: score = 95 - 2 * (info_count - 1) else: score = 100 scanData['score'] = score except Exception, e: logger.error('web.utils.report Report.formatResult2 ERROR %s' % str(e))
try: # 文件上传失败,则删除已上传的部分文件 if os.path.exists(os.path.join(file_path1, new_filename)): os.remove(os.path.join(file_path1, new_filename)) if os.path.exists(os.path.join(file_path2, new_filename)): os.remove(os.path.join(file_path2, new_filename)) except Exception, e: logger.error("文件删除失败, error:%s" % str(e)) return jsonify(dict(status=False, desc='提交失败')) model = ReportModel(model_name=model_name, title=title, company=company, logo_filename=new_filename, footer=footer, user_id=user_id) db.session.add(model) db.session.commit() return jsonify(dict(status=True, desc='提交成功')) except Exception, e: logger.error(str(e)) return jsonify(dict(status=False, desc='提交失败')) # 进入修改WEB扫描报告PDF模板页面 @web.route('/report/edit_model') @web.route('/report/edit_model/<int:model_id>', methods=['GET', 'POST']) @login_required @permission_required('report_audit') def report_model_edit(model_id): ''' 供内部工作人员调用,自定义PDF报告模板 ''' scan_key = request.values.get('scan_key') if scan_key: user_id = verify_scan_key(scan_key).id
def report_model_create(): scan_key = request.values.get('scan_key') if scan_key: user_id = verify_scan_key(scan_key).id else: user_id = current_user.id model_name = request.values.get('model_name') title = request.values.get('title') company = request.values.get('company') footer = request.values.get('footer') logo_file = request.files.get('logo_file') if not model_name or not title or not company or not footer: return jsonify(dict(status=False, desc='必选字段不能为空')) if len(model_name) > 100: return jsonify(dict(status=False, desc='模板名称太长')) if len(title) > 100: return jsonify(dict(status=False, desc='模板标题太长')) if len(company) > 100: return jsonify(dict(status=False, desc='单位名称太长')) if len(footer) > 200: return jsonify(dict(status=False, desc='页脚太长')) if len(logo_file.read()) > 2 * 1024 * 1024: return jsonify(dict(status=False, desc='Logo文件太大,仅支持2MB以下')) # 对异常字符进行HTML编码,防XSS攻击 model_name = escape(model_name.decode('utf-8')) title = escape(title.decode('utf-8')) company = escape(company.decode('utf-8')) footer = escape(footer.decode('utf-8')) try: if not logo_file: new_filename = '' model = ReportModel(model_name=model_name, title=title, company=company, logo_filename=new_filename, footer=footer, user_id=user_id) db.session.add(model) db.session.commit() return jsonify(dict(status=True, desc='提交成功')) else: filename = secure_filename(logo_file.filename) if not re.match('^.{1,50}\.(?:png|jpg)$', filename, re.I): return jsonify(dict(status=False, desc='图片文件只支持.jpg或.png格式')) time_stamp = time() salt = '18f7fc1b0a37c7f023462249c1c1fc36' m = md5() m.update('%s%s%f' % (salt, filename, time_stamp)) postfix = filename.rsplit('.', 1)[1].lower() if postfix == 'jpg': new_filename = m.hexdigest() + '.jpg' elif postfix == 'png': new_filename = m.hexdigest() + '.png' else: return jsonify(dict(status=False, desc='图片文件只支持.jpg或.png格式')) file_path1 = '%s%s' % (basedir, PDF_LOGO_PATH1) file_path2 = '%s%s' % (basedir, PDF_LOGO_PATH2) try: im = Image.open(logo_file) im.save(os.path.join(file_path1, new_filename), quality=99) # 压缩后质量为原图的99%, 高保真 if os.path.exists(file_path2): im.save(os.path.join(file_path2, new_filename), quality=99) else: logger.debug("路径%s不存在,文件仅保存一份;如果在本地或测试环境,属于正常情况" % file_path2) except Exception, e: logger.error("文件保存失败, error:%s" % str(e)) try: # 文件上传失败,则删除已上传的部分文件 if os.path.exists(os.path.join(file_path1, new_filename)): os.remove(os.path.join(file_path1, new_filename)) if os.path.exists(os.path.join(file_path2, new_filename)): os.remove(os.path.join(file_path2, new_filename)) except Exception, e: logger.error("文件删除失败, error:%s" % str(e)) return jsonify(dict(status=False, desc='提交失败')) model = ReportModel(model_name=model_name, title=title, company=company, logo_filename=new_filename, footer=footer, user_id=user_id) db.session.add(model) db.session.commit() return jsonify(dict(status=True, desc='提交成功'))
def report_model_modify(model_id): scan_key = request.values.get('scan_key') if scan_key: user_id = verify_scan_key(scan_key).id else: user_id = current_user.id user = db.session.query(User).filter(User.id == user_id).first() admin_id = db.session.query(Group).filter(Group.name == 'ADMIN').first().id if str(admin_id) in user.groups.split(','): model = db.session.query(ReportModel).filter(ReportModel.model_id == model_id).first() else: model = db.session.query(ReportModel).filter(ReportModel.user_id == user_id & ReportModel.model_id == model_id).first() if not model: logger.error(model_id) abort(403) model_name = request.values.get('model_name') title = request.values.get('title') company = request.values.get('company') footer = request.values.get('footer') logo_file = request.files.get('logo_file') if not model_name or not title or not company or not footer: return jsonify(dict(status=False, desc='必选字段不能为空')) if len(model_name) > 100: return jsonify(dict(status=False, desc='模板名称太长')) if len(title) > 100: return jsonify(dict(status=False, desc='模板标题太长')) if len(company) > 100: return jsonify(dict(status=False, desc='单位名称太长')) if len(footer) > 200: return jsonify(dict(status=False, desc='页脚太长')) if len(logo_file.read()) > 2 * 1024 * 1024: return jsonify(dict(status=False, desc='Logo文件太大,仅支持2MB以下')) # 对异常字符进行HTML编码,防XSS攻击 new_model_name = escape(model_name.decode('utf-8')) new_title = escape(title.decode('utf-8')) new_company = escape(company.decode('utf-8')) new_footer = escape(footer.decode('utf-8')) try: model.model_name = new_model_name model.title = new_title model.company = new_company model.footer = new_footer if not logo_file: # 不更新logo db.session.commit() else: # 更新logo filename = secure_filename(logo_file.filename) if not re.match('^.{1,50}\.(?:png|jpg)$', filename, re.I): return jsonify(dict(status=False, desc='图片文件只支持.jpg或.png格式')) time_stamp = time() salt = '18f7fc1b0a37c7f023462249c1c1fc36' m = md5() m.update('%s%s%f' % (salt, filename, time_stamp)) postfix = filename.rsplit('.', 1)[1].lower() if postfix == 'jpg': new_filename = m.hexdigest() + '.jpg' elif postfix == 'png': new_filename = m.hexdigest() + '.png' else: return jsonify(dict(status=False, desc='图片文件只支持.jpg或.png格式')) file_path1 = '%s%s' % (basedir, PDF_LOGO_PATH1) file_path2 = '%s%s' % (basedir, PDF_LOGO_PATH2) try: im = Image.open(logo_file) im.save(os.path.join(file_path1, new_filename), quality=99) # 压缩后质量为原图的99%, 高保真 if os.path.exists(file_path2): im.save(os.path.join(file_path2, new_filename), quality=99) else: logger.debug("路径%s不存在,文件仅保存一份;如果在本地或测试环境,属于正常情况" % file_path2) except Exception, e: logger.error("文件保存失败, error:%s" % str(e)) return jsonify(dict(status=False, desc='提交失败')) old_filename = model.logo_filename model.logo_filename = new_filename db.session.commit() # 移除旧文件 try: if os.path.exists(os.path.join(file_path1, old_filename)): os.remove(os.path.join(file_path1, old_filename)) if os.path.exists(os.path.join(file_path2, old_filename)): os.remove(os.path.join(file_path2, old_filename)) except Exception, e: logger.error("文件删除失败, error:%s" % str(e)) return jsonify(dict(status=True, desc='新logo提交成功,旧logo删除失败'))
def create_user(user_id=None): name = request.values.get('name') cname = request.values.get('cname') email = request.values.get('email') mobile = request.values.get('mobile') company = request.values.get('company') password = request.values.get('password') repassword = request.values.get('repassword') department = request.values.get('department') role_name = request.values.get('user_role') status = True if request.values.get('user_status') else False groups = request.values.get('groups') if request.method == 'POST': user = db.session.query(User).filter(User.name == name).first() if user: return jsonify(dict(status=False, desc='账号已存在')) if password != repassword: return jsonify(dict(status=False, desc='两次输入密码不一致')) try: user = User(name, cname, email, mobile, department, company, rid=2, groups=groups) db.session.add(user) db.session.commit() # 设置密码及scan_key user.password = user.gen_password_hash(password) user.scan_key = user.generate_auth_uuid() db.session.add(user) db.session.commit() except Exception as e: logger.error(e) return jsonify(dict(status=False, desc='添加失败')) else: return jsonify(dict(status=True, desc='添加成功')) else: user = db.session.query(User).filter(User.id == user_id).first() if not user: return jsonify(dict(status=False, desc='账号不存在')) try: # user.name = name user.cname = cname user.email = email user.mobile = mobile user.company = company user.department = department role = db.session.query(Role).filter( Role.cname == role_name).first() user.rid = role.id user.status = status user.groups = groups db.session.add(user) db.session.commit() except Exception as e: logger.error(e) return jsonify(dict(status=False, desc='更新失败')) else: return jsonify(dict(status=True, desc='更新成功'))
except Exception, e: logger.error('Insert data to table: web_result failed: %s' % str(e)) return False try: # 存入web_result_data表 res_data = WebResultData(web_result_id=web_result_id, request=request_content, response=response_content, task_id=task_id, asset_task_id=0, site_id=site_id) db.session.add(res_data) db.session.commit() except Exception, e: logger.error('Insert data to table: web_result_data failed: %s' % str(e)) return False return True # 列出WEB扫描报告PDF模板, 供adminv5平台调用 @api.route('/report/list_model', methods=['POST']) @permission_required_inter('report_read') def report_model_list(): rep_models = db.session.query(ReportModel).all() rep_model_list = [] for rep_model in rep_models: rep_model_dict = rep_model.to_dict() preview_path = '/report2/pdf/cover/?model_id=%s' % rep_model.model_id preview_url = urljoin(url_for('web.index', _external=True), preview_path)