From 99b6b65058150e1568555ac65b309834decbd2aa Mon Sep 17 00:00:00 2001 From: 40huo Date: Tue, 12 Sep 2017 10:10:47 +0800 Subject: [PATCH] add search page, refine dependencies vuls --- cobra/api.py | 75 +++++++++++++++------------- cobra/cve.py | 2 +- cobra/templates/asset/css/report.css | 26 ++++------ cobra/templates/asset/js/report.js | 22 +++++--- cobra/templates/asset/js/search.js | 41 ++++++++++++++- cobra/templates/summary.html | 50 ++++++------------- cobra/utils.py | 12 +++++ 7 files changed, 132 insertions(+), 96 deletions(-) diff --git a/cobra/api.py b/cobra/api.py index 29e14def..674b1d35 100644 --- a/cobra/api.py +++ b/cobra/api.py @@ -31,7 +31,7 @@ from .config import Config, running_path, package_path from .engine import Running from .log import logger -from .utils import allowed_file, secure_filename, PY2 +from .utils import allowed_file, secure_filename, PY2, split_branch try: # Python 3 @@ -328,14 +328,23 @@ def post(): with open(scan_list_file, 'r') as f: scan_list = json.load(f) - search_data = [ - { - 'target': {s_sid: scan_list.get('sids').get(s_sid)}, - 'rule_name': rule_name, - 'vul_num': search_rule(s_sid, rule_name) - } - for s_sid in scan_list.get('sids').keys() - ] + if not isinstance(rule_name, list): + rule_name = [rule_name] + + search_data = list() + for s_sid in scan_list.get('sids').keys(): + target, branch = split_branch(scan_list.get('sids').get(s_sid)) + search_result = search_rule(s_sid, rule_name) + if list(search_result.items()).count(0) == len(rule_name): + continue + search_data.append({ + 'target_info': { + 'sid': s_sid, + 'target': target, + 'branch': branch, + }, + 'search_result': search_result, + }) return { 'code': 1001, @@ -373,13 +382,7 @@ def summary(): if scan_status.get('result').get('status') == 'running': still_running = scan_status.get('result').get('still_running') for s_sid, target_str in still_running.items(): - split_target = target_str.split(':') - if len(split_target) == 3: - target, branch = '{p}:{u}'.format(p=split_target[0], u=split_target[1]), split_target[-1] - elif len(split_target) == 2: - target, branch = target_str, 'master' - else: - target, branch = target_str, 'master' + target, branch = split_branch(target_str) still_running[s_sid] = {'target': target, 'branch': branch} else: @@ -397,7 +400,8 @@ def summary(): not_finished_number = scan_status.get('result').get('not_finished') total_vul_number, critical_vul_number, high_vul_number, medium_vul_number, low_vul_number = 0, 0, 0, 0, 0 - rule_filter = dict() + rule_num = dict() + rules = dict() targets = list() for s_sid, target_str in scan_list.get('sids').items(): @@ -405,13 +409,7 @@ def summary(): target_info = dict() # 分割项目地址与分支,默认 master - split_target = target_str.split(':') - if len(split_target) == 3: - target, branch = '{p}:{u}'.format(p=split_target[0], u=split_target[1]), split_target[-1] - elif len(split_target) == 2: - target, branch = target_str, 'master' - else: - target, branch = target_str, 'master' + target, branch = split_branch(target_str) target_info.update({ 'sid': s_sid, @@ -443,9 +441,11 @@ def summary(): low_vul_number += 1 try: - rule_filter[vul.get('rule_name')] += 1 + rule_num[vul.get('rule_name')] += 1 except KeyError: - rule_filter[vul.get('rule_name')] = 1 + rule_num[vul.get('rule_name')] = 1 + + rules[vul.get('id')] = vul.get('rule_name') return render_template(template_name_or_list='summary.html', total_targets_number=total_targets_number, @@ -458,7 +458,8 @@ def summary(): high_vul_number=high_vul_number, medium_vul_number=medium_vul_number, low_vul_number=low_vul_number, - vuls=rule_filter, + rule_num=rule_num, + rules=rules, running=still_running,) @@ -501,22 +502,28 @@ def guess_type(fn): return extension.lower() -def search_rule(sid, rule_name): +def search_rule(sid, rule_id): + """ + Search specific rule name in scan data. + :param sid: scan data id + :param rule_id: a list of rule name + :return: {rule_name1: num1, rule_name2: num2} + """ scan_data_file = os.path.join(running_path, '{sid}_data'.format(sid=sid)) + search_result = {id: 0 for id in rule_id} if not os.path.exists(scan_data_file): - return 0 + return search_result with open(scan_data_file, 'r') as f: scan_data = json.load(f) if scan_data.get('code') == 1001 and len(scan_data.get('result').get('vulnerabilities')) > 0: - count = 0 for vul in scan_data.get('result').get('vulnerabilities'): - if vul.get('rule_name') == rule_name: - count += 1 - return count + if vul.get('id') in rule_id: + search_result[vul.get('id')] += 1 + return search_result else: - return 0 + return search_result def start(host, port, debug): diff --git a/cobra/cve.py b/cobra/cve.py index 6aa2bfbd..70a61868 100644 --- a/cobra/cve.py +++ b/cobra/cve.py @@ -406,7 +406,7 @@ def parse_math(cve_path, cve_id, cve_level, module_, target_directory): mr.file_path = 'unkown' mr.language = '*' mr.id = cvi - mr.rule_name = cve_id + mr.rule_name = '引用了存在漏洞的三方组件' mr.level = cve_level mr.line_number = 1 mr.analysis = 'Dependencies Matched(依赖匹配)' diff --git a/cobra/templates/asset/css/report.css b/cobra/templates/asset/css/report.css index bf2b7801..b858f943 100644 --- a/cobra/templates/asset/css/report.css +++ b/cobra/templates/asset/css/report.css @@ -72,11 +72,19 @@ /*}*/ -#table { +#target_table { overflow-y: auto; max-height: 600px; } +#search_table { + margin-top: 20px; +} + +#submit_search { + margin-left: 20px; +} + .vulnerabilities_list > li { border-top: 1px solid #282828; padding: 5px; @@ -104,20 +112,6 @@ background: #1c2427; } -.vulnerabilities_list > li.fixed { - background-image: url("/asset/img/fixed.png"); - background-position: right center; - background-repeat: no-repeat; - background-size: 50px 50px; -} - -.vulnerabilities_list > li.not_fixed { - background-image: url("/asset/img/not_fixed.png"); - background-position: right center; - background-repeat: no-repeat; - background-size: 50px 50px; -} - .congratulations { display: block; max-width: 100%; @@ -281,10 +275,8 @@ ul.v_detail li { margin: 225px auto; text-align: center; position: relative; - width: 100%; display: block; height: 500px; - position: relative; width: 32px; } diff --git a/cobra/templates/asset/js/report.js b/cobra/templates/asset/js/report.js index a05f9718..21508533 100644 --- a/cobra/templates/asset/js/report.js +++ b/cobra/templates/asset/js/report.js @@ -27,7 +27,7 @@ var score2level = { $(function () { var current_tab = ''; var c_tab = getParameterByName('t'); - if (c_tab !== null && c_tab !== '' && ['inf', 'tar', 'vul'].indexOf(c_tab) >= 0) { + if (c_tab !== null && c_tab !== '' && ['inf', 'tar', 'fil','vul'].indexOf(c_tab) >= 0) { current_tab = c_tab; $(".nav-tabs li").removeClass('active'); $("a[data-id=" + c_tab + "]").parent('li').addClass('active'); @@ -191,10 +191,17 @@ $(function () { if (s_sid !== null) { s_sid = '&s_sid=' + $('#search_target').val(); } - if (current_tab === '') { - current_tab = 'inf'; + + var url = ''; + if (current_tab === '' | current_tab === 'inf') { + url = '?t=' + current_tab + sid + s_sid; + } else if (current_tab === 'vul') { + url = '?t=' + current_tab + sid + s_sid + vulnerabilities_list.filter_url() + v; + } else if (current_tab === 'fil') { + url = '?t=' + current_tab + sid + s_sid; + } else if (current_tab === 'tar') { + url = '?t=' + current_tab + sid + s_sid; } - url = '?t=' + current_tab + sid + s_sid + vulnerabilities_list.filter_url() + v; window.history.pushState("CobraState", "Cobra", url); }, get: function (on_filter) { @@ -275,10 +282,11 @@ $(function () { vul_list_origin = result.result.scan_data; rule_filter = result.result.rule_filter; // rule filter - $('#search_rule').empty(); - $('#search_rule').append(''); + $search_rule = $('#search_rule'); + $search_rule.empty(); + $search_rule.append(''); for (var key in rule_filter) { - $('#search_rule').append(''); + $search_rule.append(''); } // Search vulnerability type diff --git a/cobra/templates/asset/js/search.js b/cobra/templates/asset/js/search.js index 090e56de..f95e83bc 100644 --- a/cobra/templates/asset/js/search.js +++ b/cobra/templates/asset/js/search.js @@ -4,6 +4,43 @@ $(document).ready(function () { }); }); +function createTable(table, data) { + // 清空数据 + table.empty(); + + // 表头 + var thead = $(''); + var trs = $(''); + trs.append($('Target')); + trs.append($('Branch / Tag')); + var rules = Object.keys(data[0].search_result).sort(); + for (var i = 0; i < rules.length; i++) { + trs.append($('' + rule_ids[rules[i]] + '')); + } + thead.append(trs); + table.append(thead); + + // 填充内容 + var tbody = $(''); + for (i = 0; i < data.length; i++) { + // 每一行 + var row_data = data[i]; + trs = $(''); + // target + var s_sid = row_data.target_info.sid; + var target = row_data.target_info.target; + var branch = row_data.target_info.branch; + trs.append($('' + target + '')); + trs.append($('' + branch + '')); + // 漏洞数量 + for (var j = 0; j < rules.length; j++) { + trs.append($('' + row_data.search_result[rules[j]] + '')); + } + } + tbody.append(trs); + table.append(tbody); +} + $('#submit_search').click(function () { $.ajax({ type: 'POST', @@ -13,7 +50,9 @@ $('#submit_search').click(function () { dataType: 'json', success: function (result) { if (result.code === 1001) { - alert(result.code); + createTable($('#search_table'), result.result); + } else { + alert(result.msg); } } }) diff --git a/cobra/templates/summary.html b/cobra/templates/summary.html index ff30b4f0..7b7c0e06 100644 --- a/cobra/templates/summary.html +++ b/cobra/templates/summary.html @@ -112,7 +112,7 @@
Number of vulnerabilities

Top 10 vulnerability distribution statistics

- {% if vuls | length == 0 %} + {% if rule_num | length == 0 %} @@ -130,7 +130,7 @@

Targets Information

-
+
@@ -201,41 +201,18 @@

Running Targets

-

Filter Targets

+

Search vulnerabilities

-
-
-
-
-
- -
-
- -
-
-
- - - - - - - - - - - - -
TargetNumber
dddddsfes
-
-
+ + + +
@@ -331,13 +308,14 @@