diff --git a/.travis.yml b/.travis.yml index 1f561654..70a8136a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,5 @@ language: python python: - - "3.5" - "3.6" - "3.7" - "nightly" diff --git a/README.md b/README.md index b8714fad..34a3196c 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ -**写在最前,Cobra-W仍然处于测试开发阶段,未发布正式版本,谨慎应用...** +**写在最前,Cobra-W就像手中的一把剑,这把剑好不好用是Cobra-W的事,如何使用是你的事,希望能有更多的人参与到Cobra-W的变化中来...** -**请使用python3运行该工具,已停止维护python2.7环境** +**请使用python3.6+运行该工具,已停止维护python2.7环境** # Cobra-W [![GitHub (pre-)release](https://img.shields.io/github/release/LoRexxar/Cobra-W/all.svg)](https://github.com/LoRexxar/Cobra-W/releases) [![license](https://img.shields.io/github/license/mashape/apistatus.svg?maxAge=2592000)](https://github.com/wufeifei/cobra/blob/master/LICENSE) [![Build Status](https://travis-ci.org/LoRexxar/Cobra-W.svg?branch=master)](https://travis-ci.org/LoRexxar/Cobra-W) -[![Coverage Status](https://coveralls.io/repos/github/LoRexxar/Cobra-W/badge.svg?branch=master)](https://coveralls.io/github/LoRexxar/Cobra-W?branch=master) +![](https://img.shields.io/badge/language-python3.7-orange.svg) ## Introduction Cobra是一款**源代码安全审计**工具,支持检测多种开发语言源代码中的**大部分显著**的安全问题和漏洞。 diff --git a/cobra/__version__.py b/cobra/__version__.py index abf4c611..9621888b 100644 --- a/cobra/__version__.py +++ b/cobra/__version__.py @@ -7,7 +7,7 @@ __issue_page__ = 'https://github.com/LoRexxar/Cobra-W/issues/new' __python_version__ = sys.version.split()[0] __platform__ = platform.platform() -__version__ = '1.8.2' +__version__ = '1.9.0' __author__ = 'LoRexxar' __author_email__ = 'LoRexxar@gmail.com' __license__ = 'MIT License' diff --git a/cobra/cli.py b/cobra/cli.py index ec789bc8..4a3a0ca7 100644 --- a/cobra/cli.py +++ b/cobra/cli.py @@ -96,7 +96,7 @@ def start(target, formatter, output, special_rules, a_sid=None, language=None, s # Pretreatment ast object ast_object.init_pre(target_directory, files) - ast_object.pre_ast(main_language) + ast_object.pre_ast_all(main_language) # scan scan(target_directory=target_directory, a_sid=a_sid, s_sid=s_sid, special_rules=pa.special_rules, diff --git a/cobra/engine.py b/cobra/engine.py index a5cdc314..a06c3e79 100644 --- a/cobra/engine.py +++ b/cobra/engine.py @@ -14,7 +14,9 @@ import json import os import re +import asyncio import traceback +import functools import portalocker from phply import phpast as php @@ -167,11 +169,20 @@ def store(result): else: logger.debug('[SCAN] [STORE] Not found vulnerabilities on this rule!') + async def start_scan(target_directory, rule, files, language, secret_name): + + result = scan_single(target_directory, rule, files, language, secret_name) + store(result) + if len(rules) == 0: logger.critical('no rules!') return False logger.info('[PUSH] {rc} Rules'.format(rc=len(rules))) push_rules = [] + scan_list = [] + + # async start task + loop = asyncio.get_event_loop() for idx, single_rule in enumerate(sorted(rules.keys())): @@ -189,8 +200,12 @@ def store(result): vulnerability=rule.vulnerability, language=rule.language )) - result = scan_single(target_directory, rule, files, language, secret_name) - store(result) + # result = scan_single(target_directory, rule, files, language, secret_name) + scan_list.append(start_scan(target_directory, rule, files, language, secret_name)) + # store(result) + + loop.run_until_complete(asyncio.gather(*scan_list)) + loop.close() # print data = [] diff --git a/cobra/pretreatment.py b/cobra/pretreatment.py index 26cbb107..dc89bf69 100644 --- a/cobra/pretreatment.py +++ b/cobra/pretreatment.py @@ -22,6 +22,8 @@ import codecs import traceback import zipfile +import queue +import asyncio could_ast_pase_lans = ["php", "chromeext", "javascript"] @@ -76,12 +78,13 @@ class Pretreatment: def __init__(self): self.file_list = [] + self.target_queue = queue.Queue() self.target_directory = "" self.pre_result = {} self.define_dict = {} - self.pre_ast() + self.pre_ast_all() def init_pre(self, target_directory, files): self.file_list = files @@ -99,7 +102,7 @@ def get_path(self, filepath): else: return os.path.join(self.target_directory, filepath) - def pre_ast(self, lan=None): + def pre_ast_all(self, lan=None): if lan is not None: # 检查是否在可ast pasre列表中 @@ -109,6 +112,17 @@ def pre_ast(self, lan=None): return True for fileext in self.file_list: + self.target_queue.put(fileext) + + loop = asyncio.get_event_loop() + scan_list = (self.pre_ast() for i in range(20)) + loop.run_until_complete(asyncio.gather(*scan_list)) + + async def pre_ast(self): + + while not self.target_queue.empty(): + + fileext = self.target_queue.get() if fileext[0] in ext_dict['php']: # 下面是对于php文件的处理逻辑 @@ -145,7 +159,8 @@ def pre_ast(self, lan=None): for node in all_nodes: if isinstance(node, php.FunctionCall) and node.name == "define": define_params = node.params - logger.debug("[AST][Pretreatment] new define {}={}".format(define_params[0].node, define_params[1].node)) + logger.debug( + "[AST][Pretreatment] new define {}={}".format(define_params[0].node, define_params[1].node)) self.define_dict[define_params[0].node] = define_params[1].node @@ -168,7 +183,7 @@ def pre_ast(self, lan=None): # target可能是单个文件,这里需要专门处理 if not self.target_directory.endswith("/") and not self.target_directory.endswith("\\"): - relative_path = os.path.join(re.split(r'[\\|/]', self.target_directory)[-1]+"_files") + relative_path = os.path.join(re.split(r'[\\|/]', self.target_directory)[-1] + "_files") else: relative_path = target_files_path.split(self.target_directory)[-1] @@ -212,7 +227,6 @@ def pre_ast(self, lan=None): new_filepath = filepath + ".pretty" if not os.path.isfile(new_filepath): - fi2 = codecs.open(new_filepath, "w", encoding='utf-8', errors='ignore') code_content = jsbeautifier.beautify(code_content) fi2.write(code_content) @@ -235,6 +249,9 @@ def pre_ast(self, lan=None): except: logger.warning('[AST] something error, {}'.format(traceback.format_exc())) + return True + + def get_nodes(self, filepath, vul_lineno=None, lan=None): filepath = os.path.normpath(filepath) diff --git a/docs/changelog.md b/docs/changelog.md index 0c6ff042..d62b9f4e 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -142,4 +142,9 @@ - 2019-10-23 - Cobra-W 1.8.2 - 修复了针对chrome 插件扫描时无法扫描js的bug - - 添加了js美化代码模块以便于更好的扫描以及人工确认 \ No newline at end of file + - 添加了js美化代码模块以便于更好的扫描以及人工确认 +- 2019-11-04 + - Cobra-W 1.9.0 + - 将Python版本限制升级到3.6并添加多处异步优化 + - 现在工具整体扫描效率优化了3倍左右 + \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index e5f8e0fb..015e4b3e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,6 +5,6 @@ portalocker==1.1.0 prettytable==0.7.2 rarfile==2.7 requests>=2.20.0 -Werkzeug==0.11.9 +Werkzeug==0.16.0 esprima==4.0.1 jsbeautifier==1.10.2 \ No newline at end of file diff --git a/tests/test_parser.py b/tests/test_parser.py index e700facf..14dfccce 100644 --- a/tests/test_parser.py +++ b/tests/test_parser.py @@ -19,7 +19,7 @@ files = [('.php', {'list': ["v_parser.php", "v.php"]})] ast_object.init_pre(project_directory + '/tests/vulnerabilities/', files) -ast_object.pre_ast() +ast_object.pre_ast_all() target_projects = project_directory + '/tests/vulnerabilities/v_parser.php'