-
Notifications
You must be signed in to change notification settings - Fork 25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Updates to API calls for CSAF output #19
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -1,6 +1,11 @@ | ||||||
#!/usr/bin/python3 | ||||||
|
||||||
import requests,json,sys,getpass,argparse | ||||||
import requests | ||||||
import json | ||||||
import sys | ||||||
import getpass | ||||||
import argparse | ||||||
import uuid | ||||||
|
||||||
################################################################################### | ||||||
###################### Python Script to collect VINCE API ######################## | ||||||
|
@@ -9,7 +14,7 @@ | |||||
### Usage ### | ||||||
|
||||||
# To run this script you must have the following: | ||||||
# Python 2.7 or Python 3 (Preferred) | ||||||
# use Python 3 | ||||||
# Python modules requests,json,sys,getpass,argparse | ||||||
|
||||||
# Simply run following command in terminal to validate json file against schema: | ||||||
|
@@ -24,6 +29,17 @@ | |||||
################################################################################### | ||||||
################################################################################### | ||||||
|
||||||
def deepcheck(obj,dir): | ||||||
x = obj | ||||||
for s in dir.split("."): | ||||||
if isinstance(x,dict) and s in x: | ||||||
x = x[s] | ||||||
elif isinstance(x,list) and int(s) < len(x): | ||||||
x = x[int(s)] | ||||||
else: | ||||||
return None | ||||||
return x | ||||||
|
||||||
|
||||||
def error_exit(reason): | ||||||
print(json.dumps({"error":reason})) | ||||||
|
@@ -33,7 +49,7 @@ def fatal_exit(ex_cls, ex, tb): | |||||
#Send all locals into a error array back to exit | ||||||
#errors = map(str,locals()) | ||||||
errors = {"ex_cls":str(ex_cls),"ex":str(ex),"tb":str(tb)} | ||||||
print(json.dumps({"errors":"Program error","info":errors})) | ||||||
print(json.dumps({"error":"Program error","info":errors})) | ||||||
sys.exit(2) | ||||||
|
||||||
|
||||||
|
@@ -51,11 +67,12 @@ def create_response(key,turl): | |||||
result[key] = json.loads(str(r.text)) | ||||||
|
||||||
def vince_to_cvrf(vince): | ||||||
case_id = vince["get_case"]["vuid"] | ||||||
cvrf = { "document": { | ||||||
"acknowledgments": [ | ||||||
{ | ||||||
"urls": [ | ||||||
"https://kb.cert.org/vuls/id/"+vince["get_case"]["vuid"] | ||||||
"https://kb.cert.org/vuls/id/"+case_id | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should include at least the anchor to acknowledgments section (as extracting the single values is not supported yet). The anchor must be supported by the website as well.
Suggested change
|
||||||
] | ||||||
} | ||||||
], | ||||||
|
@@ -67,11 +84,6 @@ def vince_to_cvrf(vince): | |||||
"text": vince["get_case"]["summary"], | ||||||
"title": "Summary" | ||||||
}, | ||||||
{ | ||||||
"category": "faq", | ||||||
"text": "Please visit https://vuls.cert.org/confluence/display/Wiki/Vulnerability+Disclosure+Policy for full disclosure policy document", | ||||||
"title": "Vulnerability Policy" | ||||||
}, | ||||||
{ | ||||||
"category": "legal_disclaimer", | ||||||
"text": "THIS DOCUMENT IS PROVIDED ON AN \"AS IS\" BASIS AND DOES NOT IMPLY ANY KIND OF GUARANTEE OR WARRANTY, INCLUDING THE WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. YOUR USE OF THE INFORMATION ON THE DOCUMENT OR MATERIALS LINKED FROM THE DOCUMENT IS AT YOUR OWN RISK.", | ||||||
|
@@ -86,9 +98,15 @@ def vince_to_cvrf(vince): | |||||
"namespace": "https://kb.cert.org/" | ||||||
}, | ||||||
"references": [ | ||||||
{ | ||||||
"url": "https://vuls.cert.org/confluence/display/Wiki/Vulnerability+Disclosure+Policy", | ||||||
"summary": "CERT/CC vulnerability disclosure policy" | ||||||
}, | ||||||
|
||||||
{ | ||||||
"summary": "CERT/CC document released", | ||||||
"url": "https://kb.cert.org/vuls/id/"+vince["get_case"]["vuid"] | ||||||
"category": "self", | ||||||
"url": "https://kb.cert.org/vuls/id/"+case_id | ||||||
} | ||||||
], | ||||||
"title": vince["get_case"]["title"], | ||||||
|
@@ -100,8 +118,8 @@ def vince_to_cvrf(vince): | |||||
"version": "1.30.0" | ||||||
} | ||||||
}, | ||||||
"id": vince["get_case"]["vuid"], | ||||||
"initial_release_date": vince["get_case"]["created"], | ||||||
"id": "VU#"+case_id, | ||||||
"initial_release_date": vince["get_case"]["due_date"], | ||||||
"revision_history": [ | ||||||
{ | ||||||
"date": vince["get_case"]["due_date"], | ||||||
|
@@ -114,21 +132,74 @@ def vince_to_cvrf(vince): | |||||
} | ||||||
}} | ||||||
cvrf["vulnerabilities"] = [] | ||||||
#map vulnerabilities to cvrf | ||||||
#map vulnerabilities to csaf | ||||||
#for now assume a singe product vendor id | ||||||
product_csafid = "CSAFPID-"+str(uuid.uuid1()) | ||||||
for k in vince["get_vuls"]: | ||||||
cve = k["name"].upper() | ||||||
#We dont have a CVE title in VINCE, so get the first sentence | ||||||
#to mimic a title per vulnerability. | ||||||
# @tschmidtb51 also suggested something similar. | ||||||
#https://github.com/CERTCC/VINCE/issues/17 | ||||||
short_title = k["description"].split(".")[0]+"." | ||||||
cvrf["vulnerabilities"].append({ | ||||||
"title":k["description"], | ||||||
"cve":k["name"]}) | ||||||
"title":short_title, | ||||||
"notes":[{ | ||||||
"category": "summary", | ||||||
"text": k["description"] | ||||||
}], | ||||||
"cve": cve, | ||||||
"product_status": { | ||||||
"known_affected": [ | ||||||
product_csafid | ||||||
] | ||||||
} | ||||||
}) | ||||||
if cve.find("CVE-") > -1: | ||||||
try: | ||||||
cve_url = "https://olbat.github.io/nvdcve/"+cve+".json" | ||||||
resp = requests.get(url=cve_url) | ||||||
data = resp.json() | ||||||
cvss_v3_data = deepcheck(data,"impact.baseMetricV3.cvssV3") | ||||||
cvss_v2_data = deepcheck(data,"impact.baseMetricV2.cvssV2") | ||||||
cve_title = deepcheck(data,"cve.description.description_data.0.value") | ||||||
if cve_title: | ||||||
#replace the title with CVE information | ||||||
cvrf["vulnerabilities"][-1]["title"] = cve_title | ||||||
#Add cvss_v3 or cvss_v2 data is available | ||||||
if cvss_v3_data: | ||||||
cvrf["vulnerabilities"][-1]["scores"] = [{"cvss_v3": cvss_v3_data, | ||||||
"products": [product_csafid]}] | ||||||
elif cvss_v2_data: | ||||||
cvrf["vulnerabilities"][-1]["scores"] = [{"cvss_v2": cvss_v2_data, | ||||||
"products": [product_csafid]}] | ||||||
except: | ||||||
pass | ||||||
vendor_name = "Unknown" | ||||||
if vince["get_original_report"]["vendor_name"]: | ||||||
vendor_name = vince["get_original_report"]["vendor_name"] | ||||||
product_name = "Unknown" | ||||||
if vince["get_original_report"]["product_name"]: | ||||||
product_name = vince["get_original_report"]["product_name"] | ||||||
product_version = "1.0.0" | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If the product version is not present, it should not be specified. |
||||||
if vince["get_original_report"]["product_version"]: | ||||||
product_version = vince["get_original_report"]["product_version"] | ||||||
product_fullname = vendor_name + " " + product_name + " " + product_version | ||||||
cvrf["product_tree"] = {"branches": [{ | ||||||
"category": "product_version", | ||||||
"name": vince["get_original_report"]["product_name"] | ||||||
if vince["get_original_report"]["product_name"] else "Unspecified", | ||||||
"product": { | ||||||
"name": vince["get_original_report"]["product_name"] | ||||||
if vince["get_original_report"]["product_name"] else "Unspecified", | ||||||
"product_id": vince["get_original_report"]["product_version"] | ||||||
if vince["get_original_report"]["product_version"] else "Unknown" | ||||||
} | ||||||
"category": "vendor", | ||||||
"name": vendor_name, | ||||||
"branches": [{ | ||||||
"category": "product_name", | ||||||
"name": product_name, | ||||||
"branches": [{ | ||||||
"category": "product_version", | ||||||
"name": product_version, | ||||||
"product": { | ||||||
"product_id": product_csafid, | ||||||
"name": product_fullname | ||||||
} | ||||||
}] | ||||||
}] | ||||||
}]} | ||||||
return cvrf | ||||||
|
||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.