Skip to content
This repository was archived by the owner on Nov 28, 2023. It is now read-only.

Commit 32d4a33

Browse files
authored
Merge pull request #578 from 40huo/develop
add search page fix #475
2 parents 6cf80dc + 6d05c1a commit 32d4a33

11 files changed

+1747
-64
lines changed

cobra/api.py

+87-21
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
from .config import Config, running_path, package_path
3232
from .engine import Running
3333
from .log import logger
34-
from .utils import allowed_file, secure_filename, PY2
34+
from .utils import allowed_file, secure_filename, PY2, split_branch
3535

3636
try:
3737
# Python 3
@@ -299,8 +299,57 @@ def post():
299299
else:
300300
return {'code': 1002, 'msg': 'No such file.'}
301301

302-
return {'code': 1001, 'result': {'file_content': file_content,
303-
'extension': extension}}
302+
return {'code': 1001, 'result': {'file_content': file_content, 'extension': extension}}
303+
304+
305+
class Search(Resource):
306+
@staticmethod
307+
def post():
308+
"""
309+
Search specific rule.
310+
:return:
311+
"""
312+
data = request.json
313+
if not data or data == "":
314+
return {'code': 1003, 'msg': 'Only support json, please post json data.'}
315+
316+
sid = data.get('sid')
317+
if not sid or sid == '':
318+
return {'code': 1002, 'msg': 'sid is required.'}
319+
320+
rule_id = data.get('rule_id')
321+
if not rule_id or rule_id == '':
322+
return {'code': 1002, 'msg': 'rule_id is required.'}
323+
324+
scan_list_file = os.path.join(running_path, '{sid}_list'.format(sid=sid))
325+
if not os.path.exists(scan_list_file):
326+
return {'code': 1002, 'msg': 'No such sid.'}
327+
328+
with open(scan_list_file, 'r') as f:
329+
scan_list = json.load(f)
330+
331+
if not isinstance(rule_id, list):
332+
rule_id = [rule_id]
333+
334+
search_data = list()
335+
for s_sid in scan_list.get('sids').keys():
336+
target, branch = split_branch(scan_list.get('sids').get(s_sid))
337+
search_result = search_rule(s_sid, rule_id)
338+
if list(search_result.items()).count(0) == len(rule_id):
339+
continue
340+
search_data.append({
341+
'target_info': {
342+
'sid': s_sid,
343+
'target': target,
344+
'branch': branch,
345+
},
346+
'search_result': search_result,
347+
})
348+
349+
return {
350+
'code': 1001,
351+
'result': search_data,
352+
}
304353

305354

306355
@app.route('/', methods=['GET', 'POST'])
@@ -333,13 +382,7 @@ def summary():
333382
if scan_status.get('result').get('status') == 'running':
334383
still_running = scan_status.get('result').get('still_running')
335384
for s_sid, target_str in still_running.items():
336-
split_target = target_str.split(':')
337-
if len(split_target) == 3:
338-
target, branch = '{p}:{u}'.format(p=split_target[0], u=split_target[1]), split_target[-1]
339-
elif len(split_target) == 2:
340-
target, branch = target_str, 'master'
341-
else:
342-
target, branch = target_str, 'master'
385+
target, branch = split_branch(target_str)
343386
still_running[s_sid] = {'target': target,
344387
'branch': branch}
345388
else:
@@ -357,21 +400,16 @@ def summary():
357400
not_finished_number = scan_status.get('result').get('not_finished')
358401

359402
total_vul_number, critical_vul_number, high_vul_number, medium_vul_number, low_vul_number = 0, 0, 0, 0, 0
360-
rule_filter = dict()
403+
rule_num = dict()
404+
rules = dict()
361405
targets = list()
362406

363407
for s_sid, target_str in scan_list.get('sids').items():
364408
if s_sid not in still_running:
365409
target_info = dict()
366410

367411
# 分割项目地址与分支,默认 master
368-
split_target = target_str.split(':')
369-
if len(split_target) == 3:
370-
target, branch = '{p}:{u}'.format(p=split_target[0], u=split_target[1]), split_target[-1]
371-
elif len(split_target) == 2:
372-
target, branch = target_str, 'master'
373-
else:
374-
target, branch = target_str, 'master'
412+
target, branch = split_branch(target_str)
375413

376414
target_info.update({
377415
'sid': s_sid,
@@ -403,9 +441,11 @@ def summary():
403441
low_vul_number += 1
404442

405443
try:
406-
rule_filter[vul.get('rule_name')] += 1
444+
rule_num[vul.get('rule_name')] += 1
407445
except KeyError:
408-
rule_filter[vul.get('rule_name')] = 1
446+
rule_num[vul.get('rule_name')] = 1
447+
448+
rules[vul.get('id')] = vul.get('rule_name')
409449

410450
return render_template(template_name_or_list='summary.html',
411451
total_targets_number=total_targets_number,
@@ -418,7 +458,8 @@ def summary():
418458
high_vul_number=high_vul_number,
419459
medium_vul_number=medium_vul_number,
420460
low_vul_number=low_vul_number,
421-
vuls=rule_filter,
461+
rule_num=rule_num,
462+
rules=rules,
422463
running=still_running,)
423464

424465

@@ -461,6 +502,30 @@ def guess_type(fn):
461502
return extension.lower()
462503

463504

505+
def search_rule(sid, rule_id):
506+
"""
507+
Search specific rule name in scan data.
508+
:param sid: scan data id
509+
:param rule_id: a list of rule name
510+
:return: {rule_name1: num1, rule_name2: num2}
511+
"""
512+
scan_data_file = os.path.join(running_path, '{sid}_data'.format(sid=sid))
513+
search_result = dict.fromkeys(rule_id, 0)
514+
if not os.path.exists(scan_data_file):
515+
return search_result
516+
517+
with open(scan_data_file, 'r') as f:
518+
scan_data = json.load(f)
519+
520+
if scan_data.get('code') == 1001 and len(scan_data.get('result').get('vulnerabilities')) > 0:
521+
for vul in scan_data.get('result').get('vulnerabilities'):
522+
if vul.get('id') in rule_id:
523+
search_result[vul.get('id')] += 1
524+
return search_result
525+
else:
526+
return search_result
527+
528+
464529
def start(host, port, debug):
465530
logger.info('Start {host}:{port}'.format(host=host, port=port))
466531
api = Api(app)
@@ -470,6 +535,7 @@ def start(host, port, debug):
470535
api.add_resource(FileUpload, '/api/upload')
471536
api.add_resource(ResultData, '/api/list')
472537
api.add_resource(ResultDetail, '/api/detail')
538+
api.add_resource(Search, '/api/search')
473539

474540
# consumer
475541
threads = []

cobra/cve.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,7 @@ def parse_math(cve_path, cve_id, cve_level, module_, target_directory):
406406
mr.file_path = 'unkown'
407407
mr.language = '*'
408408
mr.id = cvi
409-
mr.rule_name = cve_id
409+
mr.rule_name = '引用了存在漏洞的三方组件'
410410
mr.level = cve_level
411411
mr.line_number = 1
412412
mr.analysis = 'Dependencies Matched(依赖匹配)'

cobra/templates/asset/css/bootstrap-multiselect.css

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cobra/templates/asset/css/report.css

+25-29
Original file line numberDiff line numberDiff line change
@@ -52,31 +52,43 @@
5252

5353
/* Let's get this party started */
5454
/*::-webkit-scrollbar {*/
55-
/*width: 10px;*/
55+
/*width: 10px;*/
5656
/*}*/
5757

5858
/*!* Track *!*/
5959
/*::-webkit-scrollbar-track {*/
60-
/*background: #343f44;*/
60+
/*background: #343f44;*/
6161
/*}*/
6262

6363
/*!* Handle *!*/
6464
/*::-webkit-scrollbar-thumb {*/
65-
/*background: #525b5f !important;*/
66-
/*border-radius: 5px !important;*/
67-
/*border: 1px solid #383e40 !important;*/
65+
/*background: #525b5f !important;*/
66+
/*border-radius: 5px !important;*/
67+
/*border: 1px solid #383e40 !important;*/
6868
/*}*/
6969

7070
/*::-webkit-scrollbar-thumb:window-inactive {*/
71-
/*background: rgba(255, 0, 0, 0.4);*/
71+
/*background: rgba(255, 0, 0, 0.4);*/
7272
/*}*/
7373

74+
#target_table {
75+
overflow: auto;
76+
max-height: 600px;
77+
}
78+
79+
#search_table {
80+
margin-top: 20px;
81+
}
7482

75-
#table {
76-
overflow-y: auto;
83+
#search_table_div {
84+
overflow: auto;
7785
max-height: 600px;
7886
}
7987

88+
#submit_search {
89+
margin-left: 20px;
90+
}
91+
8092
.vulnerabilities_list > li {
8193
border-top: 1px solid #282828;
8294
padding: 5px;
@@ -104,20 +116,6 @@
104116
background: #1c2427;
105117
}
106118

107-
.vulnerabilities_list > li.fixed {
108-
background-image: url("/asset/img/fixed.png");
109-
background-position: right center;
110-
background-repeat: no-repeat;
111-
background-size: 50px 50px;
112-
}
113-
114-
.vulnerabilities_list > li.not_fixed {
115-
background-image: url("/asset/img/not_fixed.png");
116-
background-position: right center;
117-
background-repeat: no-repeat;
118-
background-size: 50px 50px;
119-
}
120-
121119
.congratulations {
122120
display: block;
123121
max-width: 100%;
@@ -158,19 +156,19 @@ ul.v_detail li {
158156
border-radius: 6px;
159157
}
160158

161-
.n-o-v tr:nth-child(1) td:nth-child(2){
159+
.n-o-v tr:nth-child(1) td:nth-child(2) {
162160
color: red;
163161
}
164162

165-
.n-o-v tr:nth-child(2) td:nth-child(2){
166-
color: gold;
163+
.n-o-v tr:nth-child(2) td:nth-child(2) {
164+
color: gold;
167165
}
168166

169-
.n-o-v tr:nth-child(3) td:nth-child(2){
167+
.n-o-v tr:nth-child(3) td:nth-child(2) {
170168
color: green;
171169
}
172170

173-
.n-o-v tr:nth-child(4) td:nth-child(2){
171+
.n-o-v tr:nth-child(4) td:nth-child(2) {
174172
color: #357abd;
175173
}
176174

@@ -281,10 +279,8 @@ ul.v_detail li {
281279
margin: 225px auto;
282280
text-align: center;
283281
position: relative;
284-
width: 100%;
285282
display: block;
286283
height: 500px;
287-
position: relative;
288284
width: 32px;
289285
}
290286

0 commit comments

Comments
 (0)