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

add search page fix #578

Merged
merged 12 commits into from
Sep 15, 2017
Merged
108 changes: 87 additions & 21 deletions cobra/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -299,8 +299,57 @@ def post():
else:
return {'code': 1002, 'msg': 'No such file.'}

return {'code': 1001, 'result': {'file_content': file_content,
'extension': extension}}
return {'code': 1001, 'result': {'file_content': file_content, 'extension': extension}}


class Search(Resource):
@staticmethod
def post():
"""
Search specific rule.
:return:
"""
data = request.json
if not data or data == "":
return {'code': 1003, 'msg': 'Only support json, please post json data.'}

sid = data.get('sid')
if not sid or sid == '':
return {'code': 1002, 'msg': 'sid is required.'}

rule_id = data.get('rule_id')
if not rule_id or rule_id == '':
return {'code': 1002, 'msg': 'rule_id is required.'}

scan_list_file = os.path.join(running_path, '{sid}_list'.format(sid=sid))
if not os.path.exists(scan_list_file):
return {'code': 1002, 'msg': 'No such sid.'}

with open(scan_list_file, 'r') as f:
scan_list = json.load(f)

if not isinstance(rule_id, list):
rule_id = [rule_id]

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_id)
if list(search_result.items()).count(0) == len(rule_id):
continue
search_data.append({
'target_info': {
'sid': s_sid,
'target': target,
'branch': branch,
},
'search_result': search_result,
})

return {
'code': 1001,
'result': search_data,
}


@app.route('/', methods=['GET', 'POST'])
Expand Down Expand Up @@ -333,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:
Expand All @@ -357,21 +400,16 @@ 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():
if s_sid not in still_running:
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,
Expand Down Expand Up @@ -403,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,
Expand All @@ -418,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,)


Expand Down Expand Up @@ -461,6 +502,30 @@ def guess_type(fn):
return extension.lower()


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 = dict.fromkeys(rule_id, 0)
if not os.path.exists(scan_data_file):
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:
for vul in scan_data.get('result').get('vulnerabilities'):
if vul.get('id') in rule_id:
search_result[vul.get('id')] += 1
return search_result
else:
return search_result


def start(host, port, debug):
logger.info('Start {host}:{port}'.format(host=host, port=port))
api = Api(app)
Expand All @@ -470,6 +535,7 @@ def start(host, port, debug):
api.add_resource(FileUpload, '/api/upload')
api.add_resource(ResultData, '/api/list')
api.add_resource(ResultDetail, '/api/detail')
api.add_resource(Search, '/api/search')

# consumer
threads = []
Expand Down
2 changes: 1 addition & 1 deletion cobra/cve.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(依赖匹配)'
Expand Down
1 change: 1 addition & 0 deletions cobra/templates/asset/css/bootstrap-multiselect.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

54 changes: 25 additions & 29 deletions cobra/templates/asset/css/report.css
Original file line number Diff line number Diff line change
Expand Up @@ -52,31 +52,43 @@

/* Let's get this party started */
/*::-webkit-scrollbar {*/
/*width: 10px;*/
/*width: 10px;*/
/*}*/

/*!* Track *!*/
/*::-webkit-scrollbar-track {*/
/*background: #343f44;*/
/*background: #343f44;*/
/*}*/

/*!* Handle *!*/
/*::-webkit-scrollbar-thumb {*/
/*background: #525b5f !important;*/
/*border-radius: 5px !important;*/
/*border: 1px solid #383e40 !important;*/
/*background: #525b5f !important;*/
/*border-radius: 5px !important;*/
/*border: 1px solid #383e40 !important;*/
/*}*/

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

#target_table {
overflow: auto;
max-height: 600px;
}

#search_table {
margin-top: 20px;
}

#table {
overflow-y: auto;
#search_table_div {
overflow: auto;
max-height: 600px;
}

#submit_search {
margin-left: 20px;
}

.vulnerabilities_list > li {
border-top: 1px solid #282828;
padding: 5px;
Expand Down Expand Up @@ -104,20 +116,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%;
Expand Down Expand Up @@ -158,19 +156,19 @@ ul.v_detail li {
border-radius: 6px;
}

.n-o-v tr:nth-child(1) td:nth-child(2){
.n-o-v tr:nth-child(1) td:nth-child(2) {
color: red;
}

.n-o-v tr:nth-child(2) td:nth-child(2){
color: gold;
.n-o-v tr:nth-child(2) td:nth-child(2) {
color: gold;
}

.n-o-v tr:nth-child(3) td:nth-child(2){
.n-o-v tr:nth-child(3) td:nth-child(2) {
color: green;
}

.n-o-v tr:nth-child(4) td:nth-child(2){
.n-o-v tr:nth-child(4) td:nth-child(2) {
color: #357abd;
}

Expand Down Expand Up @@ -281,10 +279,8 @@ ul.v_detail li {
margin: 225px auto;
text-align: center;
position: relative;
width: 100%;
display: block;
height: 500px;
position: relative;
width: 32px;
}

Expand Down
Loading