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

Commit

Permalink
Merge pull request #580 from wufeifei/develop
Browse files Browse the repository at this point in the history
Released v2.0.0-alpha.5
  • Loading branch information
FeeiCN authored Sep 15, 2017
2 parents 0ba8a0b + 5a4fcea commit c39845a
Show file tree
Hide file tree
Showing 19 changed files with 1,778 additions and 77 deletions.
11 changes: 11 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,17 @@ Cobra Changelog

Here you can see the full list of changes between each Cobra release.

Version 2.0.0-alpha.5
---------------------

Released on Sep 15 2017

- 增加漏洞搜索在报告页 #475
- 优化Log输出 #570
- 增加yacc依赖帮助 #569
- 更改默认使用方法及参数配置
- 其它细节优化和Bug修复

Version 2.0.0-alpha.4
---------------------

Expand Down
4 changes: 2 additions & 2 deletions cobra/__version__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
__issue_page__ = 'https://github.com/wufeifei/cobra/issues/new'
__python_version__ = sys.version.split()[0]
__platform__ = platform.platform()
__version__ = '2.0.0-alpha.4'
__version__ = '2.0.0-alpha.5'
__author__ = 'Feei'
__author_email__ = '[email protected]'
__license__ = 'MIT License'
Expand All @@ -27,5 +27,5 @@
python {m} -t {td} -f json -o /tmp/report.json
python {m} -t {tg} -f json -o [email protected]
python {m} -t {tg} -f json -o http://push.to.com/api
sudo python {m} -H 127.0.0.1 -P 80
python {m} -H 127.0.0.1 -P 8888
""".format(m='cobra.py', td='tests/vulnerabilities', tg='https://github.com/ethicalhack3r/DVWA')
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)
cvi_count = list(search_result.values())
if int(cvi_count[0]) > 0:
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/cast.py
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ def is_controllable_param(self):
logger.debug("[AST] Not Java/PHP, can't parse ({l})".format(l=self.language))
return False, self.data
else:
logger.warning("[AST] Can't get `param`, check built-in rule")
logger.debug("[AST] Can't get `param`, check built-in rule")
return False, self.data

def match(self, rule, block_id):
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
6 changes: 4 additions & 2 deletions cobra/engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,9 +175,11 @@ def store(result):
return False
logger.info('[PUSH] {rc} Rules'.format(rc=len(rules)))
push_rules = []
off_rules = 0
for idx, single_rule in enumerate(rules):
if single_rule['status'] is False:
logger.info('[CVI-{cvi}] [STATUS] OFF, CONTINUE...'.format(cvi=single_rule['id']))
off_rules += 1
logger.debug('[CVI-{cvi}] [STATUS] OFF, CONTINUE...'.format(cvi=single_rule['id']))
continue
# SR(Single Rule)
logger.debug("""[PUSH] [CVI-{cvi}] {idx}.{name}({language})""".format(
Expand Down Expand Up @@ -227,7 +229,7 @@ def store(result):
if vn == 0:
logger.info('[SCAN] Not found vulnerability!')
else:
logger.info("[SCAN] Trigger Rules: {tr} Vulnerabilities ({vn})\r\n{table}".format(tr=len(trigger_rules), vn=len(find_vulnerabilities), table=table))
logger.info("[SCAN] Trigger Rules/Not Trigger Rules/Off Rules: {tr}/{ntr}/{fr} Vulnerabilities ({vn})\r\n{table}".format(tr=len(trigger_rules), ntr=len(diff_rules), fr=off_rules, vn=len(find_vulnerabilities), table=table))
if len(diff_rules) > 0:
logger.info('[SCAN] Not Trigger Rules ({l}): {r}'.format(l=len(diff_rules), r=','.join(diff_rules)))

Expand Down
2 changes: 1 addition & 1 deletion cobra/export.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ def write_to_file(target, sid, output_format='', filename=None):
:return:
"""
if not filename:
logger.info('[EXPORT] No filename given, nothing exported.')
logger.debug('[EXPORT] No filename given, nothing exported.')
return False

scan_data_file = os.path.join(running_path, '{sid}_data'.format(sid=sid))
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

0 comments on commit c39845a

Please sign in to comment.