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

Commit 9fb4197

Browse files
authored
Merge pull request #999 from BlBana/master
优化了git_projects脚本,支持参数传入扫描单个/多个目标,单条/多条指定规则,输出格式,输出方式,扫描完后是否删除项目
2 parents df11d17 + a961418 commit 9fb4197

File tree

4 files changed

+189
-35
lines changed

4 files changed

+189
-35
lines changed

cobra/__version__.py

+21
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,24 @@
2929
python {m} -t {tg} -f json -o http://push.to.com/api
3030
python {m} -H 127.0.0.1 -P 8888
3131
""".format(m='cobra.py', td='tests/vulnerabilities', tg='https://github.com/ethicalhack3r/DVWA')
32+
33+
__introduction_git__ = """
34+
This script can push your target to the api
35+
Please write cobra_ip, secret_key in config when you want to scan the specified git address
36+
Please write gitlab_url, private_token, cobra_ip, secret_key when you want to scan all gitlab's projects
37+
"""
38+
39+
__epilog_git__ = """Usage:
40+
python {m} -a
41+
python {m} -a -r cvi-190001,cvi-190002
42+
python {m} -a -f json -o /tmp/report.json
43+
44+
python {m} -t {td}
45+
python {m} -t {td},{td1}
46+
python {m} -t {td},{td1} -d
47+
python {m} -t {td} -r cvi-190001,cvi-190002
48+
python {m} -t {td} -f json -o /tmp/report.json
49+
python {m} -t {tg} -f json -o [email protected]
50+
python {m} -t {tg} -f json -o http://push.to.com/api
51+
""".format(m='git_projcets.py', td='tests/vulnerabilities', td1='tests/dvwa',
52+
tg='https://github.com/ethicalhack3r/DVWA')

cobra/cve.py

+30-5
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import gzip
1919
import xml.etree.cElementTree as eT
2020
import multiprocessing
21+
import subprocess
2122
from .config import project_directory, Config, config_path
2223
from .log import logger
2324
from .dependencies import Dependencies
@@ -283,6 +284,24 @@ def download_rule_gz():
283284
for t in threads:
284285
t.join()
285286
end_time = datetime.datetime.now()
287+
for afile in files:
288+
param = ['file', afile]
289+
p = subprocess.Popen(param, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
290+
res_out, res_err = p.communicate()
291+
292+
res_out = res_out.decode('utf-8')
293+
res_err = res_err.decode('utf-8')
294+
295+
if 'HTML' in res_out:
296+
os.remove(afile)
297+
afile_name = os.path.split(afile)[1]
298+
year = afile_name.split('.')[0]
299+
url = "https://static.nvd.nist.gov/feeds/xml/cve/2.0/nvdcve-2.0-" + str(year) + ".xml.gz"
300+
try:
301+
urlretrieve(url, afile)
302+
except IOError:
303+
logger.warning('[CVE] The {} download fail'.format(afile))
304+
286305
logger.info("All CVE xml file already download success, use time:%ds" % (end_time - start_time).seconds)
287306
return files
288307

@@ -292,11 +311,17 @@ def un_gz(gz_files):
292311
start_time = datetime.datetime.now()
293312
logger.info("Start decompress rule files, Please wait a moment....")
294313
for gz_file in gz_files:
295-
f_name = gz_file.replace(".gz", "")
296-
g_file = gzip.GzipFile(gz_file)
297-
open(f_name, "wb+").write(g_file.read())
298-
g_file.close()
299-
os.remove(gz_file)
314+
if os.path.exists(gz_file):
315+
f_name = gz_file.replace(".gz", "")
316+
317+
try:
318+
g_file = gzip.GzipFile(gz_file, "rb")
319+
open(f_name, "wb+").write(g_file.read())
320+
g_file.close()
321+
except IOError:
322+
logger.warning('[CVE] The {} download fail'.format(gz_file))
323+
324+
os.remove(gz_file)
300325
end_time = datetime.datetime.now()
301326
logger.info("Decompress success, use time:%ds" % (end_time - start_time).seconds)
302327
return True

git_projects.py

+134-28
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@
1515
import requests
1616
import re
1717
import threading
18+
import argparse
1819
from cobra.log import logger
1920
from cobra.config import code_path, Config
21+
from cobra.__version__ import __epilog_git__, __introduction_git__
2022

2123
try:
2224
# Python 3
@@ -25,40 +27,77 @@
2527
# Python 2
2628
import Queue as queue
2729

28-
2930
git_urls = []
3031

3132

32-
def start():
33+
def start(target, format, output, rules, dels, all):
34+
"""
35+
start push target to api
36+
:param target:
37+
:param format:
38+
:param output:
39+
:param rules:
40+
:param dels:
41+
:param all:
42+
:return:
43+
"""
3344
url = Config('git', 'gitlab_url').value
3445
private_token = Config('git', 'private_token').value
3546
cobra_ip = Config('git', 'cobra_ip').value
3647
key = Config('cobra', 'secret_key').value
3748
threads = []
38-
pages = get_pages(url, private_token)
39-
q_pages = queue.Queue(pages)
4049
result_path = code_path + '/result_sid'
41-
fi = open(result_path, 'w+')
42-
for i in range(int(pages)):
43-
q_pages.put(i + 1)
50+
fi = open(result_path, 'a+')
4451

45-
for i in range(10):
46-
thread = threading.Thread(target=get_git_urls, args=(url, private_token, q_pages, fi))
47-
thread.start()
48-
threads.append(thread)
52+
try:
53+
if all is False and target is not '':
54+
if isinstance(target, list):
55+
for tar in target:
56+
fi.write(tar + '\n')
57+
else:
58+
fi.write(target + '\n')
4959

50-
for thread in threads:
51-
thread.join()
60+
res = push_to_api(target, cobra_ip, key, fi, format, output, rules, dels)
5261

53-
res = push_to_api(git_urls, cobra_ip, key, fi)
62+
elif all is True and target is '':
63+
pages = get_pages(url, private_token)
64+
q_pages = queue.Queue(pages)
5465

55-
if res:
56-
logger.info("Git push success: {}".format(len(git_urls)))
57-
else:
58-
logger.info("Git push fail")
66+
for i in range(int(pages)):
67+
q_pages.put(i + 1)
68+
69+
for i in range(10):
70+
thread = threading.Thread(target=get_git_urls, args=(url, private_token, q_pages, fi))
71+
thread.start()
72+
threads.append(thread)
73+
74+
for thread in threads:
75+
thread.join()
76+
77+
res = push_to_api(git_urls, cobra_ip, key, fi, format, output, rules, dels)
78+
79+
else:
80+
res = False
81+
82+
if res:
83+
logger.info("[GIT-PRO] Git push success")
84+
logger.info("[GIT-PRO] All projects have been pushed")
85+
else:
86+
logger.warning("[GIT-PRO] Git push fail")
87+
88+
fi.close()
89+
90+
except requests.exceptions.MissingSchema:
91+
logger.warning('[GIT-PRO] Please write gitlab_url and private_token in config file')
5992

60-
fi.close()
61-
logger.info("All projects have been pushed")
93+
except requests.exceptions.ConnectionError:
94+
logger.warning('[GIT-PRO] Please check the cobra_ip or gitlab_url is right')
95+
96+
except requests.exceptions.InvalidSchema:
97+
logger.warning('[GIT-PRO] Please add http:// before the cobra_ip or gitlab_url')
98+
99+
except Exception as e:
100+
logger.warning('[GIT-PRO] {}'.format(e.message))
62101

63102

64103
def get_git_urls(url, private_token, q_pages, fi):
@@ -90,39 +129,69 @@ def get_git_urls(url, private_token, q_pages, fi):
90129
git_urls.append(request_url)
91130

92131
elif r.status_code == 404:
93-
logger.warning("page %d 404" % page)
132+
logger.warning("[GIT-PRO] page %d 404" % page)
94133

95134
else:
96-
logger.warning("page %d is %d" % page, r.status_code)
135+
logger.warning("[GIT-PRO] page %d is %d" % page, r.status_code)
97136
q_pages.task_done()
98137

99138

100139
def request_target(target_url, params=None, header=None, method="get"):
140+
"""
141+
start request
142+
:param target_url:
143+
:param params:
144+
:param header:
145+
:param method:
146+
:return:
147+
"""
101148
if method == "get":
102149
response = requests.get(url=target_url, params=params, headers=header)
103150
return response
151+
104152
if method == "post":
105153
response = requests.post(url=target_url, data=json.dumps(params), headers=header)
106154
return response
107155

108156

109-
def push_to_api(urls, cobra_ip, key, fi):
157+
def push_to_api(urls, cobra_ip, key, fi, format, output, rules, dels):
158+
"""
159+
:param urls:
160+
:param cobra_ip:
161+
:param key:
162+
:param fi:
163+
:param format:
164+
:param output:
165+
:param rules:
166+
:param dels:
167+
:return:
168+
"""
110169
headers = {"Content-Type": "application/json"}
111170
url = cobra_ip + "/api/add"
112-
payload = {"key": key, "target": urls, "dels": True, "rule": "cvi-190009"}
171+
payload = {"key": key, "target": urls, "dels": dels, "formatter": format, "output": output,
172+
"rule": rules}
113173
r = request_target(url, payload, headers, method="post")
174+
114175
if r.status_code == 200:
115176
fi.write(str(r.json()) + '\n')
116-
logger.info(r.json())
177+
logger.info('[GIT-PRO] ' + str(r.json()))
117178
return True
179+
118180
elif r.status_code == 404:
119-
logger.info("The page is 404")
181+
logger.info("[GIT-PRO] The page is 404")
182+
120183
else:
121-
logger.info(r.json())
184+
logger.info('[GIT-PRO] ' + str(r.json()))
122185
return False
123186

124187

125188
def get_pages(url, private_token):
189+
"""
190+
get the pages num
191+
:param url:
192+
:param private_token:
193+
:return:
194+
"""
126195
params = {"private_token": private_token}
127196
response = request_target(url, params)
128197
res = response.headers['link'].split(",")
@@ -132,5 +201,42 @@ def get_pages(url, private_token):
132201
return pages
133202

134203

204+
def _check_rule_name(name):
205+
return re.match(r'^(cvi|CVI)-\d{6}(\.xml)?', name.strip()) is not None
206+
207+
135208
if __name__ == '__main__':
136-
start()
209+
special_rules = []
210+
211+
parser = argparse.ArgumentParser(prog='git_projects', epilog=__epilog_git__, description=__introduction_git__, formatter_class=argparse.RawDescriptionHelpFormatter)
212+
parser.add_argument('-t', '--target', dest='target', action='store', default='', metavar='<target>', help='The git address or git list, e.g: test/vul/v.php,test/vul/v.java')
213+
parser.add_argument('-f', '--format', dest='format', action='store', default='json', metavar='<format>', choices=['json', 'csv', 'xml'], help='report output format')
214+
parser.add_argument('-o', '--output', dest='output', action='store', default='', metavar='<output>', help='report output STREAM, FILE, HTTP API URL, MAIL')
215+
parser.add_argument('-r', '--rule', dest='rules', action='store', default=None, metavar='<rule_id>', help='specifies rules e.g: CVI-100001,cvi-190001')
216+
parser.add_argument('-d', '--dels', dest='dels', action='store_true', default=False, help='del target directory True or False')
217+
parser.add_argument('-a', '--all', dest='all', action='store_true', default=False, help='Git push all git-projects from gitlab')
218+
args = parser.parse_args()
219+
220+
if args.target == '' and args.all is False:
221+
parser.print_help()
222+
exit()
223+
224+
if ',' in args.target:
225+
targets = args.target.split(',')
226+
else:
227+
targets = args.target
228+
229+
try:
230+
if ',' in args.rules:
231+
rules = args.rules.split(',')
232+
for rule in rules:
233+
if _check_rule_name(rule) is False:
234+
logger.critical('[GIT-PRO] Exception special rule name(e.g: CVI-110001): {sr}'.format(sr=rule))
235+
else:
236+
if _check_rule_name(args.rules) is False:
237+
logger.critical('[GIT-PRO] Exception special rule name(e.g: CVI-110001): {sr}'.format(sr=args.rules))
238+
239+
except TypeError:
240+
logger.info('[GIT-PRO] The rules is None, Cobra will use all rules to scan')
241+
242+
start(targets, args.format, args.output, args.rules, args.dels, args.all)

tests/test_cve_parse.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -112,15 +112,17 @@ def test_download_rule_gz():
112112
files = download_rule_gz()
113113
assert isinstance(files, list)
114114
for file_ in files:
115-
os.remove(file_)
115+
if os.path.exists(file_):
116+
os.remove(file_)
116117

117118

118119
def test_un_gz():
119120
files = download_rule_gz()
120121
res = un_gz(files)
121122
assert res is True
122123
for year in range(2002, datetime.datetime.now().year+1):
123-
os.remove(project_directory+"/rules/%d.xml" % year)
124+
if os.path.exists(project_directory+"/rules/%d.xml" % year):
125+
os.remove(project_directory+"/rules/%d.xml" % year)
124126

125127

126128
def test_rule_single():

0 commit comments

Comments
 (0)