misp-modules 2.4.196__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (194) hide show
  1. misp_modules/__init__.py +379 -0
  2. misp_modules/helpers/__init__.py +1 -0
  3. misp_modules/helpers/cache.py +84 -0
  4. misp_modules/lib/__init__.py +4 -0
  5. misp_modules/lib/_vmray/__init__.py +0 -0
  6. misp_modules/lib/_vmray/parser.py +1417 -0
  7. misp_modules/lib/_vmray/rest_api.py +148 -0
  8. misp_modules/lib/cof2misp/LICENSE-2.0.txt +202 -0
  9. misp_modules/lib/cof2misp/__init__.py +0 -0
  10. misp_modules/lib/cof2misp/cof.py +165 -0
  11. misp_modules/lib/joe_mapping.py +114 -0
  12. misp_modules/lib/joe_parser.py +573 -0
  13. misp_modules/lib/lastline_api.py +841 -0
  14. misp_modules/lib/qintel_helper.py +263 -0
  15. misp_modules/lib/stix2misp.py +2080 -0
  16. misp_modules/lib/stix2misp_mapping.py +460 -0
  17. misp_modules/lib/synonymsToTagNames.json +1 -0
  18. misp_modules/lib/vt_graph_parser/__init__.py +8 -0
  19. misp_modules/lib/vt_graph_parser/errors.py +20 -0
  20. misp_modules/lib/vt_graph_parser/helpers/__init__.py +7 -0
  21. misp_modules/lib/vt_graph_parser/helpers/parsers.py +88 -0
  22. misp_modules/lib/vt_graph_parser/helpers/rules.py +304 -0
  23. misp_modules/lib/vt_graph_parser/helpers/wrappers.py +58 -0
  24. misp_modules/lib/vt_graph_parser/importers/__init__.py +7 -0
  25. misp_modules/lib/vt_graph_parser/importers/base.py +98 -0
  26. misp_modules/lib/vt_graph_parser/importers/pymisp_response.py +73 -0
  27. misp_modules/modules/__init__.py +4 -0
  28. misp_modules/modules/action_mod/__init__.py +1 -0
  29. misp_modules/modules/action_mod/_utils/__init__.py +1 -0
  30. misp_modules/modules/action_mod/_utils/utils.py +70 -0
  31. misp_modules/modules/action_mod/mattermost.py +113 -0
  32. misp_modules/modules/action_mod/slack.py +96 -0
  33. misp_modules/modules/action_mod/testaction.py +68 -0
  34. misp_modules/modules/expansion/__init__.py +36 -0
  35. misp_modules/modules/expansion/_dnsdb_query/COPYRIGHT +27 -0
  36. misp_modules/modules/expansion/_dnsdb_query/LICENSE +202 -0
  37. misp_modules/modules/expansion/_dnsdb_query/README.md +162 -0
  38. misp_modules/modules/expansion/_dnsdb_query/__init__.py +0 -0
  39. misp_modules/modules/expansion/_dnsdb_query/dnsdb_query.py +327 -0
  40. misp_modules/modules/expansion/_ransomcoindb/__init__.py +0 -0
  41. misp_modules/modules/expansion/_ransomcoindb/ransomcoindb.py +96 -0
  42. misp_modules/modules/expansion/_vulnerability_parser/__init__.py +0 -0
  43. misp_modules/modules/expansion/_vulnerability_parser/vulnerability_parser.py +118 -0
  44. misp_modules/modules/expansion/abuseipdb.py +146 -0
  45. misp_modules/modules/expansion/apiosintds.py +365 -0
  46. misp_modules/modules/expansion/apivoid.py +133 -0
  47. misp_modules/modules/expansion/assemblyline_query.py +179 -0
  48. misp_modules/modules/expansion/assemblyline_submit.py +100 -0
  49. misp_modules/modules/expansion/backscatter_io.py +84 -0
  50. misp_modules/modules/expansion/btc_scam_check.py +54 -0
  51. misp_modules/modules/expansion/btc_steroids.py +238 -0
  52. misp_modules/modules/expansion/censys_enrich.py +287 -0
  53. misp_modules/modules/expansion/circl_passivedns.py +85 -0
  54. misp_modules/modules/expansion/circl_passivessl.py +113 -0
  55. misp_modules/modules/expansion/clamav.py +129 -0
  56. misp_modules/modules/expansion/cluster25_expand.py +239 -0
  57. misp_modules/modules/expansion/countrycode.py +69 -0
  58. misp_modules/modules/expansion/cpe.py +140 -0
  59. misp_modules/modules/expansion/crowdsec.py +235 -0
  60. misp_modules/modules/expansion/crowdstrike_falcon.py +148 -0
  61. misp_modules/modules/expansion/cuckoo_submit.py +161 -0
  62. misp_modules/modules/expansion/cve.py +57 -0
  63. misp_modules/modules/expansion/cve_advanced.py +185 -0
  64. misp_modules/modules/expansion/cytomic_orion.py +196 -0
  65. misp_modules/modules/expansion/dbl_spamhaus.py +78 -0
  66. misp_modules/modules/expansion/dns.py +71 -0
  67. misp_modules/modules/expansion/docx_enrich.py +71 -0
  68. misp_modules/modules/expansion/domaintools.py +290 -0
  69. misp_modules/modules/expansion/eql.py +91 -0
  70. misp_modules/modules/expansion/eupi.py +86 -0
  71. misp_modules/modules/expansion/extract_url_components.py +83 -0
  72. misp_modules/modules/expansion/farsight_passivedns.py +243 -0
  73. misp_modules/modules/expansion/geoip_asn.py +75 -0
  74. misp_modules/modules/expansion/geoip_city.py +75 -0
  75. misp_modules/modules/expansion/geoip_country.py +73 -0
  76. misp_modules/modules/expansion/google_safe_browsing.py +86 -0
  77. misp_modules/modules/expansion/google_search.py +57 -0
  78. misp_modules/modules/expansion/google_threat_intelligence.py +453 -0
  79. misp_modules/modules/expansion/greynoise.py +346 -0
  80. misp_modules/modules/expansion/hashdd.py +53 -0
  81. misp_modules/modules/expansion/hashlookup.py +118 -0
  82. misp_modules/modules/expansion/hibp.py +62 -0
  83. misp_modules/modules/expansion/html_to_markdown.py +63 -0
  84. misp_modules/modules/expansion/hyasinsight.py +881 -0
  85. misp_modules/modules/expansion/intel471.py +73 -0
  86. misp_modules/modules/expansion/intelmq_eventdb.py.experimental +67 -0
  87. misp_modules/modules/expansion/ip2locationio.py +90 -0
  88. misp_modules/modules/expansion/ipasn.py +70 -0
  89. misp_modules/modules/expansion/ipinfo.py +112 -0
  90. misp_modules/modules/expansion/ipqs_fraud_and_risk_scoring.py +633 -0
  91. misp_modules/modules/expansion/iprep.py +98 -0
  92. misp_modules/modules/expansion/jinja_template_rendering.py +54 -0
  93. misp_modules/modules/expansion/joesandbox_query.py +91 -0
  94. misp_modules/modules/expansion/joesandbox_submit.py +147 -0
  95. misp_modules/modules/expansion/lastline_query.py +148 -0
  96. misp_modules/modules/expansion/lastline_submit.py +180 -0
  97. misp_modules/modules/expansion/macaddress_io.py +130 -0
  98. misp_modules/modules/expansion/macvendors.py +55 -0
  99. misp_modules/modules/expansion/malshare_upload.py +107 -0
  100. misp_modules/modules/expansion/malwarebazaar.py +67 -0
  101. misp_modules/modules/expansion/mcafee_insights_enrich.py +249 -0
  102. misp_modules/modules/expansion/mmdb_lookup.py +138 -0
  103. misp_modules/modules/expansion/module.py.skeleton +44 -0
  104. misp_modules/modules/expansion/mwdb.py +152 -0
  105. misp_modules/modules/expansion/ocr_enrich.py +74 -0
  106. misp_modules/modules/expansion/ods_enrich.py +71 -0
  107. misp_modules/modules/expansion/odt_enrich.py +61 -0
  108. misp_modules/modules/expansion/onyphe.py +243 -0
  109. misp_modules/modules/expansion/onyphe_full.py +387 -0
  110. misp_modules/modules/expansion/otx.py +167 -0
  111. misp_modules/modules/expansion/passive_ssh.py +150 -0
  112. misp_modules/modules/expansion/passivetotal.py +358 -0
  113. misp_modules/modules/expansion/pdf_enrich.py +58 -0
  114. misp_modules/modules/expansion/pptx_enrich.py +65 -0
  115. misp_modules/modules/expansion/qintel_qsentry.py +229 -0
  116. misp_modules/modules/expansion/qrcode.py +99 -0
  117. misp_modules/modules/expansion/ransomcoindb.py +82 -0
  118. misp_modules/modules/expansion/rbl.py +126 -0
  119. misp_modules/modules/expansion/recordedfuture.py +544 -0
  120. misp_modules/modules/expansion/reversedns.py +77 -0
  121. misp_modules/modules/expansion/securitytrails.py +571 -0
  122. misp_modules/modules/expansion/shodan.py +244 -0
  123. misp_modules/modules/expansion/sigma_queries.py +61 -0
  124. misp_modules/modules/expansion/sigma_syntax_validator.py +49 -0
  125. misp_modules/modules/expansion/sigmf_expand.py +303 -0
  126. misp_modules/modules/expansion/socialscan.py +108 -0
  127. misp_modules/modules/expansion/sophoslabs_intelix.py +146 -0
  128. misp_modules/modules/expansion/sourcecache.py +57 -0
  129. misp_modules/modules/expansion/stairwell.py +156 -0
  130. misp_modules/modules/expansion/stix2_pattern_syntax_validator.py +56 -0
  131. misp_modules/modules/expansion/threatcrowd.py +170 -0
  132. misp_modules/modules/expansion/threatfox.py +75 -0
  133. misp_modules/modules/expansion/threatminer.py +152 -0
  134. misp_modules/modules/expansion/triage_submit.py +119 -0
  135. misp_modules/modules/expansion/trustar_enrich.py +235 -0
  136. misp_modules/modules/expansion/urlhaus.py +164 -0
  137. misp_modules/modules/expansion/urlscan.py +269 -0
  138. misp_modules/modules/expansion/variotdbs.py +133 -0
  139. misp_modules/modules/expansion/virustotal.py +311 -0
  140. misp_modules/modules/expansion/virustotal_public.py +272 -0
  141. misp_modules/modules/expansion/virustotal_upload.py +91 -0
  142. misp_modules/modules/expansion/vmray_submit.py +161 -0
  143. misp_modules/modules/expansion/vmware_nsx.py +628 -0
  144. misp_modules/modules/expansion/vulndb.py +292 -0
  145. misp_modules/modules/expansion/vulnerability_lookup.py +324 -0
  146. misp_modules/modules/expansion/vulners.py +81 -0
  147. misp_modules/modules/expansion/vysion.py +221 -0
  148. misp_modules/modules/expansion/whois.py +72 -0
  149. misp_modules/modules/expansion/whoisfreaks.py +232 -0
  150. misp_modules/modules/expansion/wiki.py +58 -0
  151. misp_modules/modules/expansion/xforceexchange.py +189 -0
  152. misp_modules/modules/expansion/xlsx_enrich.py +63 -0
  153. misp_modules/modules/expansion/yara_query.py +70 -0
  154. misp_modules/modules/expansion/yara_syntax_validator.py +49 -0
  155. misp_modules/modules/expansion/yeti.py +196 -0
  156. misp_modules/modules/export_mod/__init__.py +3 -0
  157. misp_modules/modules/export_mod/cef_export.py +93 -0
  158. misp_modules/modules/export_mod/cisco_firesight_manager_ACL_rule_export.py +150 -0
  159. misp_modules/modules/export_mod/defender_endpoint_export.py +141 -0
  160. misp_modules/modules/export_mod/goamlexport.py +255 -0
  161. misp_modules/modules/export_mod/liteexport.py +97 -0
  162. misp_modules/modules/export_mod/mass_eql_export.py +106 -0
  163. misp_modules/modules/export_mod/nexthinkexport.py +131 -0
  164. misp_modules/modules/export_mod/osqueryexport.py +125 -0
  165. misp_modules/modules/export_mod/pdfexport.py +107 -0
  166. misp_modules/modules/export_mod/testexport.py +73 -0
  167. misp_modules/modules/export_mod/threatStream_misp_export.py +114 -0
  168. misp_modules/modules/export_mod/threat_connect_export.py +125 -0
  169. misp_modules/modules/export_mod/virustotal_collections.py +141 -0
  170. misp_modules/modules/export_mod/vt_graph.py +120 -0
  171. misp_modules/modules/export_mod/yara_export.py +290 -0
  172. misp_modules/modules/import_mod/__init__.py +22 -0
  173. misp_modules/modules/import_mod/cof2misp.py +264 -0
  174. misp_modules/modules/import_mod/csvimport.py +319 -0
  175. misp_modules/modules/import_mod/cuckooimport.py +749 -0
  176. misp_modules/modules/import_mod/email_import.py +294 -0
  177. misp_modules/modules/import_mod/goamlimport.py +188 -0
  178. misp_modules/modules/import_mod/import_blueprint.py +93 -0
  179. misp_modules/modules/import_mod/joe_import.py +74 -0
  180. misp_modules/modules/import_mod/lastline_import.py +160 -0
  181. misp_modules/modules/import_mod/mispjson.py +73 -0
  182. misp_modules/modules/import_mod/ocr.py +122 -0
  183. misp_modules/modules/import_mod/openiocimport.py +99 -0
  184. misp_modules/modules/import_mod/taxii21.py +383 -0
  185. misp_modules/modules/import_mod/testimport.py +73 -0
  186. misp_modules/modules/import_mod/threatanalyzer_import.py +552 -0
  187. misp_modules/modules/import_mod/url_import.py +97 -0
  188. misp_modules/modules/import_mod/vmray_import.py +96 -0
  189. misp_modules/modules/import_mod/vmray_summary_json_import.py +87 -0
  190. misp_modules-2.4.196.dist-info/LICENSE +661 -0
  191. misp_modules-2.4.196.dist-info/METADATA +281 -0
  192. misp_modules-2.4.196.dist-info/RECORD +194 -0
  193. misp_modules-2.4.196.dist-info/WHEEL +4 -0
  194. misp_modules-2.4.196.dist-info/entry_points.txt +3 -0
@@ -0,0 +1,292 @@
1
+ #!/usr/bin/env python3
2
+
3
+ '''
4
+ Import VulnDB
5
+ https://vulndb.cyberriskanalytics.com/
6
+ https://www.riskbasedsecurity.com/
7
+ '''
8
+
9
+ import oauth2 as oauth
10
+ import json
11
+
12
+ import logging
13
+ import sys
14
+
15
+
16
+ log = logging.getLogger('vulndb')
17
+ log.setLevel(logging.DEBUG)
18
+ ch = logging.StreamHandler(sys.stdout)
19
+ ch.setLevel(logging.DEBUG)
20
+ formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
21
+ ch.setFormatter(formatter)
22
+ log.addHandler(ch)
23
+
24
+
25
+ misperrors = {'error': 'Error'}
26
+ mispattributes = {
27
+ 'input': ['vulnerability'],
28
+ 'output': ['text', 'link', 'cpe']}
29
+ moduleinfo = {
30
+ 'version': '0.1',
31
+ 'author': 'Koen Van Impe',
32
+ 'description': 'Module to query VulnDB (RiskBasedSecurity.com).',
33
+ 'module-type': ['expansion', 'hover'],
34
+ 'name': 'VulnDB Lookup',
35
+ 'logo': 'vulndb.png',
36
+ 'requirements': ['An access to the VulnDB API (apikey, apisecret)'],
37
+ 'features': 'This module takes a vulnerability attribute as input and queries VulnDB in order to get some additional data about it.\n\nThe API gives the result of the query which can be displayed in the screen, and/or mapped into MISP attributes to add in the event.',
38
+ 'references': ['https://vulndb.cyberriskanalytics.com/'],
39
+ 'input': 'A vulnerability attribute.',
40
+ 'output': 'Additional data enriching the CVE input, fetched from VulnDB.',
41
+ }
42
+
43
+ moduleconfig = ['apikey', 'apisecret', 'discard_dates', 'discard_external_references', 'discard_cvss', 'discard_productinformation', 'discard_classification', 'discard_cpe']
44
+
45
+
46
+ def handler(q=False):
47
+ # Base URL for VulnDB
48
+ VULNDB_URL = "https://vulndb.cyberriskanalytics.com"
49
+
50
+ if q is False:
51
+ return False
52
+ request = json.loads(q)
53
+
54
+ # Only continue if we have a vulnerability attribute
55
+ if not request.get('vulnerability'):
56
+ misperrors['error'] = 'Vulnerability ID missing for VulnDB.'
57
+ return misperrors
58
+ vulnerability = request.get('vulnerability')
59
+
60
+ if request["config"].get("apikey") is None or request["config"].get("apisecret") is None:
61
+ misperrors["error"] = "Missing API key or secret value for VulnDB."
62
+ return misperrors
63
+ apikey = request["config"].get("apikey")
64
+ apisecret = request["config"].get("apisecret")
65
+
66
+ # This has to be done the 'inverse' way, MISP-server settings are set to False by default
67
+ add_cvss = True
68
+ add_products = True
69
+ add_classifications = True
70
+ add_cpe = True
71
+ add_dates = True
72
+ add_ext_references = True
73
+
74
+ if request["config"].get("discard_dates") is not None and request["config"].get("discard_dates").lower() == "true":
75
+ add_dates = False
76
+ if request["config"].get("discard_external_references") is not None and request["config"].get("discard_external_references").lower() == "true":
77
+ add_ext_references = False
78
+ if request["config"].get("discard_cvss") is not None and request["config"].get("discard_cvss").lower() == "true":
79
+ add_cvss = False
80
+ if request["config"].get("discard_productinformation") is not None and request["config"].get("discard_productinformation").lower() == "true":
81
+ add_products = False
82
+ if request["config"].get("discard_classification") is not None and request["config"].get("discard_classification").lower() == "true":
83
+ add_classifications = False
84
+ if request["config"].get("discard_cpe") is not None and request["config"].get("discard_cpe").lower() == "true":
85
+ add_cpe = False
86
+
87
+ cpu_vulndb = ""
88
+ if add_cpe:
89
+ cpu_vulndb = "?show_cpe=true"
90
+
91
+ find_by_cve_url = "%s/api/v1/vulnerabilities/%s/find_by_cve_id%s" % (VULNDB_URL, vulnerability, cpu_vulndb)
92
+ log.debug(find_by_cve_url)
93
+
94
+ try:
95
+
96
+ consumer = oauth.Consumer(key=apikey, secret=apisecret)
97
+ client = oauth.Client(consumer)
98
+ resp, content = client.request(find_by_cve_url, "GET")
99
+ content_json = json.loads(content.decode())
100
+
101
+ if content_json:
102
+ if 'error' in content_json:
103
+ misperrors["error"] = "No CVE information found."
104
+ return misperrors
105
+ else:
106
+ output = {'results': list()}
107
+ values_text = list()
108
+ values_links = list()
109
+ values_cpe = list()
110
+
111
+ results = content_json["results"][0]
112
+
113
+ # Include the VulnDB title and ID
114
+ values_text.append(results["title"])
115
+ vulndb_id_link = "%s/vulnerabilities/%s" % (VULNDB_URL, results["vulndb_id"])
116
+ values_links.append(vulndb_id_link)
117
+
118
+ # Descriptive part of the VulnDB item
119
+ description = results.get('description', '') or ''
120
+ keywords = results.get('keywords', '') or ''
121
+ solution = results.get('solution', '') or ''
122
+ manual_notes = results.get('manual_notes', '') or ''
123
+ t_description = results.get('t_description', '') or ''
124
+ if description:
125
+ values_text.append(description)
126
+ if t_description:
127
+ values_text.append(t_description)
128
+ if manual_notes:
129
+ values_text.append("Notes: " + manual_notes)
130
+ if keywords:
131
+ values_text.append("Keywords: " + keywords)
132
+ if solution:
133
+ values_text.append("Solution: " + solution)
134
+
135
+ # VulnDB items contain a number of dates, do we include them?
136
+ if add_dates:
137
+ log.debug("Include dates")
138
+ solution_date = results.get('solution_date', '') or ''
139
+ if solution_date:
140
+ values_text.append("Solution date: " + solution_date)
141
+ disclosure_date = results.get('disclosure_date', '') or ''
142
+ if disclosure_date:
143
+ values_text.append("Disclosure date: " + disclosure_date)
144
+ discovery_date = results.get('discovery_date', '') or ''
145
+ if discovery_date:
146
+ values_text.append("Discovery date: " + discovery_date)
147
+ exploit_publish_date = results.get('exploit_publish_date', '') or ''
148
+ if exploit_publish_date:
149
+ values_text.append("Exploit published date: " + exploit_publish_date)
150
+ vendor_informed_date = results.get('vendor_informed_date', '') or ''
151
+ if vendor_informed_date:
152
+ values_text.append("Vendor informed date: " + vendor_informed_date)
153
+ vendor_ack_date = results.get('vendor_ack_date', '') or ''
154
+ if vendor_ack_date:
155
+ values_text.append("Vendor acknowledgement date: " + vendor_ack_date)
156
+ third_party_solution_date = results.get('third_party_solution_date', '') or ''
157
+ if third_party_solution_date:
158
+ values_text.append("Third party solution date: " + third_party_solution_date)
159
+
160
+ # External references
161
+ if add_ext_references:
162
+ ext_references = results.get('ext_references')
163
+ if ext_references:
164
+ log.debug("Include external references")
165
+ for reference in ext_references:
166
+ reference_type = reference["type"]
167
+ if reference_type == "Other Advisory URL":
168
+ values_links.append(reference["value"])
169
+ elif reference_type == "News Article":
170
+ values_links.append(reference["value"])
171
+ elif reference_type == "Generic Informational URL":
172
+ values_links.append(reference["value"])
173
+ elif reference_type == "Vendor Specific Advisory URL":
174
+ values_links.append(reference["value"])
175
+ elif reference_type == "Vendor URL":
176
+ values_links.append(reference["value"])
177
+ elif reference_type == "Mail List Post":
178
+ values_links.append(reference["value"])
179
+ elif reference_type == "Metasploit URL":
180
+ values_links.append(reference["value"])
181
+ elif reference_type == "Packet Storm":
182
+ values_links.append(reference["value"])
183
+ elif reference_type == "Generic Exploit URL":
184
+ values_links.append(reference["value"])
185
+ elif reference_type == "CERT VU":
186
+ reference_link = "http://www.kb.cert.org/vuls/id/%s" % reference["value"]
187
+ values_links.append(reference_link)
188
+ elif reference_type == "CVE ID":
189
+ reference_link = "https://nvd.nist.gov/vuln/detail/%s" % reference["value"]
190
+ values_links.append(reference_link)
191
+ elif reference_type == "Microsoft Knowledge Base Article":
192
+ reference_link = "https://support.microsoft.com/en-us/help/%s" % reference["value"]
193
+ values_links.append(reference_link)
194
+ elif reference_type == "Exploit Database":
195
+ reference_link = "https://www.exploit-db.com/exploits/%s" % reference["value"]
196
+ values_links.append(reference_link)
197
+ elif reference_type == "Generic Informational URL":
198
+ values_links.append(reference["value"])
199
+ elif reference_type == "Generic Informational URL":
200
+ values_links.append(reference["value"])
201
+ elif reference_type == "Generic Informational URL":
202
+ values_links.append(reference["value"])
203
+ elif reference_type == "Generic Informational URL":
204
+ values_links.append(reference["value"])
205
+ elif reference_type == "Generic Informational URL":
206
+ values_links.append(reference["value"])
207
+
208
+ # CVSS Scoring
209
+ if add_cvss:
210
+ cvss = results.get('cvss_metrics')
211
+ if cvss:
212
+ log.debug("Include CVSS")
213
+ for cvss_metric in cvss:
214
+ score = cvss_metric.get("score")
215
+ if score:
216
+ values_text.append("CVSS %s (base: %s) (source: %s)" % (score, cvss_metric.get("calculated_cvss_base_score"), cvss_metric.get("source")))
217
+
218
+ # Add products
219
+ if add_products:
220
+ products = results.get('products')
221
+ if products and len(products) > 0:
222
+
223
+ # Get the vendors
224
+ vendors = results.get('vendors')
225
+ vendors_name = ""
226
+ log.debug("Include product information")
227
+ if vendors:
228
+ for vendor in vendors:
229
+ vendor_detail = vendor.get("vendor")
230
+ if vendor_detail:
231
+ vendor_name = vendor_detail.get("name")
232
+ if vendor_name:
233
+ vendors_name += vendor_name + " "
234
+
235
+ # Walk through all vendors
236
+ for product in products:
237
+ vulnerable_product = vendors_name
238
+ name = product.get("name")
239
+ if name:
240
+ vulnerable_product += "%s " % name
241
+ versions = product.get("versions")
242
+ if versions:
243
+ vulnerable_product += "("
244
+ for version in versions:
245
+ affected = version.get("affected")
246
+
247
+ if affected and affected == "true":
248
+ vulnerable_product += " %s " % version.get("name")
249
+ if add_cpe:
250
+ version_cpe = version.get("cpe")
251
+ if version_cpe:
252
+ cpe = version_cpe[0].get("cpe")
253
+ if cpe:
254
+ values_cpe.append(cpe)
255
+
256
+ vulnerable_product += ")"
257
+ # Add vulnerable products
258
+ values_text.append(vulnerable_product)
259
+
260
+ # Add vulnerability classifications
261
+ if add_classifications:
262
+ classifications = results.get("classifications")
263
+ if classifications and len(classifications) > 0:
264
+ vulnerability_classification = ""
265
+ log.debug("Include classifications")
266
+ for classification in classifications:
267
+ longname = classification.get("longname")
268
+ description = classification.get("description")
269
+ vulnerability_classification += " \"%s\" " % longname
270
+ values_text.append(vulnerability_classification)
271
+
272
+ # Finished processing the VulnDB reply; set the result for MISP
273
+ output['results'] += [{'types': 'text', 'values': values_text}]
274
+ output['results'] += [{'types': 'link', 'values': values_links}]
275
+ if add_cpe:
276
+ output['results'] += [{'types': 'cpe', 'values': values_cpe}]
277
+ return output
278
+ else:
279
+ misperrors["error"] = "No information retrieved from VulnDB."
280
+ return misperrors
281
+ except Exception:
282
+ misperrors["error"] = "Error while fetching information from VulnDB, wrong API keys?"
283
+ return misperrors
284
+
285
+
286
+ def introspection():
287
+ return mispattributes
288
+
289
+
290
+ def version():
291
+ moduleinfo['config'] = moduleconfig
292
+ return moduleinfo
@@ -0,0 +1,324 @@
1
+ import json
2
+ import requests
3
+ from . import check_input_attribute, standard_error_message
4
+ from ._vulnerability_parser.vulnerability_parser import (
5
+ VulnerabilityMapping, VulnerabilityParser)
6
+ from pymisp import MISPObject
7
+ from typing import Iterator
8
+
9
+ misperrors = {'error': 'Error'}
10
+ mispattributes = {'input': ['vulnerability'], 'format': 'misp_standard'}
11
+ moduleinfo = {
12
+ 'version': '1',
13
+ 'author': 'Christian Studer',
14
+ 'description': 'An expansion module to query Vulnerability Lookup',
15
+ 'module-type': ['expansion', 'hover'],
16
+ 'name': 'Vulnerability Lookup',
17
+ 'logo': '',
18
+ 'requirements': [],
19
+ 'features': '',
20
+ 'references': [],
21
+ 'input': '',
22
+ 'output': '',
23
+ }
24
+ api_url = 'https://vulnerability.circl.lu'
25
+
26
+
27
+ class VulnerabilityLookupMapping(VulnerabilityMapping):
28
+ __csaf_mapping = {
29
+ 'id': 'id',
30
+ 'initial_release_date': 'published',
31
+ 'current_release_date': 'modified'
32
+ }
33
+ __cve_mapping = {
34
+ 'cveId': 'id',
35
+ 'datePublished': 'published',
36
+ 'dateUpdated': 'modified',
37
+ 'state': 'state'
38
+ }
39
+ __gsd_mapping = {
40
+ 'id': 'id',
41
+ 'details': 'description',
42
+ 'modified': 'modified'
43
+ }
44
+ __nvd_mapping = {
45
+ 'id': 'id',
46
+ 'published': 'published',
47
+ 'lastModified': 'modified'
48
+ }
49
+ __ossf_mapping = {
50
+ 'id': 'id',
51
+ 'summary': 'summary',
52
+ 'details': 'description',
53
+ 'published': 'published',
54
+ 'modified': 'modified'
55
+ }
56
+ __related_vuln_mapping = {
57
+ 'cve': 'id',
58
+ 'title': 'summary',
59
+ 'discovery_date': 'published'
60
+ }
61
+ __source_mapping = {
62
+ 'cve': '_parse_cve_description',
63
+ 'ghsa': '_parse_standard_description',
64
+ 'gsd': '_parse_gsd_description',
65
+ 'mal': '_parse_ossf_description',
66
+ 'pysec': '_parse_standard_description',
67
+ 'var': '_parse_variot_description'
68
+ }
69
+ __source_mapping.update(
70
+ dict.fromkeys(
71
+ (
72
+ 'cisco', 'icsa', 'icsma', 'nn', 'oxas',
73
+ 'rhba', 'rhea', 'rhsa', 'sca', 'ssa', 'wid'
74
+ ),
75
+ '_parse_csaf_description'
76
+ )
77
+ )
78
+ __standard_mapping = {
79
+ 'id': 'id',
80
+ 'details': 'description',
81
+ 'published': 'published',
82
+ 'modified': 'modified'
83
+ }
84
+
85
+ @classmethod
86
+ def csaf_mapping(cls) -> dict:
87
+ return cls.__csaf_mapping
88
+
89
+ @classmethod
90
+ def cve_mapping(cls) -> dict:
91
+ return cls.__cve_mapping
92
+
93
+ @classmethod
94
+ def gsd_mapping(cls) -> dict:
95
+ return cls.__gsd_mapping
96
+
97
+ @classmethod
98
+ def nvd_mapping(cls) -> dict:
99
+ return cls.__nvd_mapping
100
+
101
+ @classmethod
102
+ def ossf_mapping(cls) -> dict:
103
+ return cls.__ossf_mapping
104
+
105
+ @classmethod
106
+ def related_vuln_mapping(cls) -> dict:
107
+ return cls.__related_vuln_mapping
108
+
109
+ @classmethod
110
+ def source_mapping(cls, field: str) -> str:
111
+ return cls.__source_mapping.get(field)
112
+
113
+ @classmethod
114
+ def standard_mapping(cls) -> dict:
115
+ return cls.__standard_mapping
116
+
117
+
118
+ class VulnerabilityLookupParser(VulnerabilityParser):
119
+ def __init__(self, attribute: dict):
120
+ super().__init__(attribute)
121
+ self.__mapping = VulnerabilityLookupMapping
122
+ self.__errors = []
123
+
124
+ @property
125
+ def errors(self) -> list:
126
+ return self.__errors
127
+
128
+ @property
129
+ def mapping(self) -> VulnerabilityLookupMapping:
130
+ return self.__mapping
131
+
132
+ def parse_lookup_result(self, lookup_result: dict):
133
+ feature = self.mapping.source_mapping(
134
+ self.misp_attribute.value.split('-')[0].lower()
135
+ )
136
+ getattr(self, feature)(lookup_result)
137
+
138
+ def _parse_aliases(self, aliases: list) -> Iterator[str]:
139
+ for alias in aliases:
140
+ query = requests.get(f"{api_url}/vulnerability/{alias}")
141
+ if query.status_code != 200:
142
+ self.errors.append(
143
+ f'Unable to query related vulnerability id {alias}'
144
+ )
145
+ continue
146
+ vulnerability = query.json()
147
+ if not vulnerability:
148
+ self.errors.append(
149
+ f'No results for related vulnerability id{alias}'
150
+ )
151
+ continue
152
+ feature = self.mapping.source_mapping(alias.split('-')[0].lower())
153
+ yield getattr(self, feature)(vulnerability)
154
+
155
+ def _parse_csaf_description(self, lookup_result: dict) -> str:
156
+ description = lookup_result['document']
157
+
158
+ tracking = description['tracking']
159
+ misp_object = MISPObject('vulnerability')
160
+ for field, relation in self.mapping.csaf_mapping().items():
161
+ misp_object.add_attribute(relation, tracking[field])
162
+ misp_object.add_attribute('summary', description['title'])
163
+ for reference in description.get('references', []):
164
+ misp_object.add_attribute('references', reference['url'])
165
+ misp_object.add_attribute('credit', description['publisher']['name'])
166
+ misp_object.add_reference(self.misp_attribute.uuid, 'describes')
167
+ vulnerability_object = self.misp_event.add_object(misp_object)
168
+
169
+ for vulnerability in lookup_result['vulnerabilities']:
170
+ related = MISPObject('vulnerability')
171
+ for field, relation in self.mapping.related_vuln_mapping().items():
172
+ if vulnerability.get(field):
173
+ related.add_attribute(relation, vulnerability[field])
174
+ for score in vulnerability.get('scores', []):
175
+ cvss_v3 = score['cvss_v3']
176
+ related.add_attribute('cvss-score', cvss_v3['baseScore'])
177
+ related.add_attribute('cvss-string', cvss_v3['vectorString'])
178
+ for reference in vulnerability.get('references', []):
179
+ related.add_attribute('references', reference['url'])
180
+ related.add_reference(vulnerability_object.uuid, 'related-to')
181
+ related_vulnerability = self.misp_event.add_object(related)
182
+ if vulnerability.get('cwe'):
183
+ cwe = vulnerability['cwe']
184
+ weakness = MISPObject('weakness')
185
+ for field, value in cwe.items():
186
+ weakness.add_attribute(field, value)
187
+ weakness.add_reference(related_vulnerability.uuid, 'leads-to')
188
+ self.misp_event.add_object(weakness)
189
+
190
+ return vulnerability_object.uuid
191
+
192
+ def _parse_cve_description(self, lookup_result: dict) -> str:
193
+ misp_object = MISPObject('vulnerability')
194
+ cveMetaData = lookup_result['cveMetadata']
195
+ for field, relation in self.mapping.cve_mapping().items():
196
+ misp_object.add_attribute(relation, cveMetaData[field])
197
+ for reference in lookup_result['containers']['cna']['references']:
198
+ misp_object.add_attribute('references', reference['url'])
199
+ misp_object.add_reference(self.misp_attribute.uuid, 'related-to')
200
+ vulnerability_object = self.misp_event.add_object(misp_object)
201
+ return vulnerability_object.uuid
202
+
203
+ def _parse_cve_related_description(self, cve_description: dict) -> str:
204
+ misp_object = MISPObject('vulnerability')
205
+ misp_object.add_attribute(
206
+ 'id', cve_description['CVE_data_meta']['ID']
207
+ )
208
+ misp_object.add_attribute(
209
+ 'description',
210
+ cve_description['description']['description_data'][0]['value']
211
+ )
212
+ for cvss in cve_description.get('impact', {}).get('cvss', []):
213
+ misp_object.add_attribute('cvss-score', cvss['baseScore'])
214
+ misp_object.add_attribute('cvss-string', cvss['vectorString'])
215
+ for reference in misp_object.get('references', {}).get('reference_data', []):
216
+ misp_object.add_attribute('references', reference['url'])
217
+ return self.misp_event.add_object(misp_object).uuid
218
+
219
+ def _parse_gsd_description(self, lookup_result: dict) -> str:
220
+ misp_object = MISPObject('vulnerability')
221
+ gsd_details = lookup_result['gsd']['osvSchema']
222
+ for field, relation in self.mapping.gsd_mapping().items():
223
+ misp_object.add_attribute(relation, gsd_details[field])
224
+ misp_object.add_reference(self.misp_attribute.uuid, 'related-to')
225
+ vulnerability_object = self.misp_event.add_object(misp_object)
226
+
227
+ for field, values in lookup_result['namespaces'].items():
228
+ if field == 'cve.org':
229
+ vulnerability_object.add_reference(
230
+ self._parse_cve_related_description(values), 'related-to'
231
+ )
232
+ continue
233
+ if field == 'nvd.nist.gov' and values.get('cve'):
234
+ vulnerability_object.add_reference(
235
+ self._parse_nvd_related_description(values['cve']),
236
+ 'related-to'
237
+ )
238
+
239
+ return vulnerability_object.uuid
240
+
241
+ def _parse_nvd_related_description(self, nvd_description: dict) -> str:
242
+ misp_object = MISPObject('vulnerability')
243
+ for field, relation in self.mapping.nvd_mapping().items():
244
+ misp_object.add_attribute(relation, nvd_description[field])
245
+ misp_object.add_attribute(
246
+ 'description', nvd_description['descriptions'][0]['value']
247
+ )
248
+ for cvss in nvd_description.get('metrics', {}).get('cvssMetricV31', []):
249
+ misp_object.add_attribute(
250
+ 'cvss-score', cvss['cvssData']['baseScore']
251
+ )
252
+ misp_object.add_attribute(
253
+ 'cvss-string', cvss['cvssData']['vectorString']
254
+ )
255
+ for reference in nvd_description.get('references', []):
256
+ misp_object.add_attribute('references', reference['url'])
257
+ return self.misp_event.add_object(misp_object).uuid
258
+
259
+ def _parse_ossf_description(self, lookup_result: dict) -> str:
260
+ misp_object = MISPObject('vulnerability')
261
+ for field, relation in self.mapping.ossf_mapping().items():
262
+ misp_object.add_attribute(relation, lookup_result[field])
263
+ for reference in lookup_result['references']:
264
+ misp_object.add_attribute('references', reference['url'])
265
+ misp_object.add_reference(self.misp_attribute.uuid, 'related-to')
266
+ vulnerability_object = self.misp_event.add_object(misp_object)
267
+
268
+ if lookup_result.get('aliases'):
269
+ for vuln_uuid in self._parse_aliases(lookup_result['aliases']):
270
+ vulnerability_object.add_reference(vuln_uuid, 'related-to')
271
+
272
+ return vulnerability_object.uuid
273
+
274
+ def _parse_standard_description(self, lookup_result: dict) -> str:
275
+ misp_object = MISPObject('vulnerability')
276
+ for field, relation in self.mapping.standard_mapping().items():
277
+ misp_object.add_attribute(relation, lookup_result[field])
278
+ for cvss in lookup_result.get('severity', []):
279
+ misp_object.add_attribute('cvss-string', cvss['score'])
280
+ for reference in lookup_result['references']:
281
+ misp_object.add_attribute('references', reference['url'])
282
+ misp_object.add_reference(self.misp_attribute.uuid, 'related-to')
283
+ vulnerability_object = self.misp_event.add_object(misp_object)
284
+
285
+ if lookup_result.get('aliases'):
286
+ for vuln_uuid in self._parse_aliases(lookup_result['aliases']):
287
+ vulnerability_object.add_reference(vuln_uuid, 'related-to')
288
+
289
+ return vulnerability_object.uuid
290
+
291
+
292
+ def handler(q=False):
293
+ if q is False:
294
+ return q
295
+ request = json.loads(q)
296
+ if not check_input_attribute(request.get('attribute', {})):
297
+ return {
298
+ 'error': f'{standard_error_message}, which should contain '
299
+ 'at least a type, a value and an UUID.'
300
+ }
301
+ attribute = request['attribute']
302
+ if attribute.get('type') != 'vulnerability':
303
+ misperrors['error'] = 'Vulnerability ID missing'
304
+ return misperrors
305
+ lookup = requests.get(f"{api_url}/vulnerability/{attribute['value']}")
306
+ if lookup.status_code == 200:
307
+ vulnerability = lookup.json()
308
+ if not vulnerability:
309
+ misperrors['error'] = 'Non existing Vulnerability ID.'
310
+ return misperrors
311
+ else:
312
+ misperrors['error'] = 'Vulnerability Lookup API not accessible.'
313
+ return misperrors
314
+ parser = VulnerabilityLookupParser(attribute)
315
+ parser.parse_lookup_result(vulnerability)
316
+ return parser.get_results()
317
+
318
+
319
+ def introspection():
320
+ return mispattributes
321
+
322
+
323
+ def version():
324
+ return moduleinfo