Import upstream version 1.6.2
Kali Janitor
2 years ago
0 | support cve,cwe,cvss and metadata |
0 | Jan 13th, 2022 |
0 | Add packaging to requierments in setup.py |
0 | Add severity to shodan's plugins using cvss⏎ |
0 | Feb 3rd, 2022 |
0 | check if cve exist on cve-id field |
0 | Fix Fortify's plugin |
0 | Change qualysguard's plugin severity_dict to refer level 2 severities as low |
0 | Add references tu burp plugin |
0 | Mar 18th, 2022 |
0 | Move item.detail from data to desc |
0 | update open status |
0 | Now Appscan plugin saves line and highlight of the vulns in desc and data |
0 | Apr 4th, 2022 |
0 | 1.6.2 [Apr 4th, 2022]: | |
1 | --- | |
2 | * Now Appscan plugin saves line and highlight of the vulns in desc and data | |
3 | ||
4 | 1.6.1 [Mar 18th, 2022]: | |
5 | --- | |
6 | * Add references tu burp plugin | |
7 | * Move item.detail from data to desc | |
8 | * update open status | |
9 | ||
10 | 1.6.0 [Feb 3rd, 2022]: | |
11 | --- | |
12 | * Add packaging to requierments in setup.py | |
13 | * Add severity to shodan's plugins using cvss | |
14 | * check if cve exist on cve-id field | |
15 | * Fix Fortify's plugin | |
16 | * Change qualysguard's plugin severity_dict to refer level 2 severities as low | |
17 | ||
18 | 1.5.10 [Jan 13th, 2022]: | |
19 | --- | |
20 | * support cve,cwe,cvss and metadata | |
21 | ||
0 | 22 | 1.5.9 [Dec 27th, 2021]: |
1 | 23 | --- |
2 | * ADD cve in faraday_csv plugin | |
24 | * Add cve in faraday_csv plugin | |
3 | 25 | * ADD Grype plugin |
4 | 26 | |
5 | 27 | 1.5.8 [Dec 13th, 2021]: |
278 | 278 | command that it's going to be executed. |
279 | 279 | """ |
280 | 280 | self._current_path = current_path |
281 | if command_string.startswith(("sudo","python","python3")): | |
281 | if command_string.startswith(("sudo", "python", "python3")): | |
282 | 282 | params = " ".join(command_string.split()[2:]) |
283 | 283 | else: |
284 | 284 | params = " ".join(command_string.split()[1:]) |
392 | 392 | if ref is None: |
393 | 393 | ref = [] |
394 | 394 | if status == "": |
395 | status = "opened" | |
395 | status = "open" | |
396 | 396 | if impact is None: |
397 | 397 | impact = {} |
398 | 398 | if policyviolations is None: |
426 | 426 | if ref is None: |
427 | 427 | ref = [] |
428 | 428 | if status == "": |
429 | status = "opened" | |
429 | status = "open" | |
430 | 430 | if impact is None: |
431 | 431 | impact = {} |
432 | 432 | if policyviolations is None: |
484 | 484 | if ref is None: |
485 | 485 | ref = [] |
486 | 486 | if status == "": |
487 | status = "opened" | |
487 | status = "open" | |
488 | 488 | if impact is None: |
489 | 489 | impact = {} |
490 | 490 | if policyviolations is None: |
34 | 34 | try: |
35 | 35 | tree = ET.fromstring(xml_output) |
36 | 36 | except SyntaxError as err: |
37 | print('SyntaxError In xml: %s. %s' % (err, xml_output)) | |
37 | print(f'SyntaxError In xml: {err}. {xml_output}') | |
38 | 38 | return None |
39 | 39 | return tree |
40 | 40 | |
181 | 181 | sast_issues = [] |
182 | 182 | for item in tree: |
183 | 183 | name = self.issue_types[item.find("issue-type/ref").text] |
184 | source_file = item.attrib["filename"].replace('\\','/') | |
184 | source_file = item.attrib["filename"].replace('\\', '/') | |
185 | 185 | severity = 0 if item.find("severity-id") is None else int(item.find("severity-id").text) |
186 | 186 | description = item.find("fix/item/general/text").text |
187 | 187 | resolution = "" if item.find("variant-group/item/issue-information/fix-resolution-text") is None \ |
239 | 239 | data.append(f"Method: {item.find('variant-group/item/issue-information/method-signature').text}") |
240 | 240 | if item.find("variant-group/item/issue-information/method-signature2") is not None: |
241 | 241 | data.append(f"Location: {item.find('variant-group/item/issue-information/method-signature2').text}") |
242 | line = item.find("location") | |
243 | highlight = item.find("variant-group/item/issue-information/call-trace/call-invocation/context/highlight") | |
244 | if highlight is not None: | |
245 | data.append(f" {highlight.text}") | |
246 | issue_data["desc"] += "\n" + highlight.text | |
247 | if line is not None and len(line.text.split(':')) > 1 and line.text.split(':')[-1].isdigit(): | |
248 | data.append(f"line {line.text.split(':')[-1]}") | |
249 | issue_data["desc"] += f"line {line.text.split(':')[-1]}" | |
242 | 250 | issue_data['data'] = "\n".join(data) |
243 | 251 | sast_issues.append(issue_data) |
244 | 252 | return sast_issues |
59 | 59 | try: |
60 | 60 | tree = ET.fromstring(xml_output) |
61 | 61 | except SyntaxError as err: |
62 | print("SyntaxError: %s. %s" % (err, xml_output)) | |
62 | print(f"SyntaxError: {err}. {xml_output}") | |
63 | 63 | return None |
64 | 64 | |
65 | 65 | return tree |
104 | 104 | external_id = item_node.findall('type')[0] |
105 | 105 | request = self.decode_binary_node('./requestresponse/request') |
106 | 106 | response = self.decode_binary_node('./requestresponse/response') |
107 | ||
108 | 107 | detail = self.do_clean(item_node.findall('issueDetail')) |
109 | 108 | remediation = self.do_clean(item_node.findall('remediationBackground')) |
110 | 109 | background = self.do_clean(item_node.findall('issueBackground')) |
110 | self.references = self.do_clean(item_node.findall('references')) | |
111 | self.vulnClass = self.do_clean(item_node.findall('vulnerabilityClassifications')) | |
111 | 112 | self.cve = [] |
112 | 113 | if background: |
113 | 114 | cve = CVE_regex.search(background) |
143 | 144 | def do_clean(value): |
144 | 145 | |
145 | 146 | myreturn = "" |
146 | if value is not None: | |
147 | if len(value) > 0: | |
148 | myreturn = value[0].text | |
147 | if value is not None and len(value) > 0: | |
148 | myreturn = value[0].text | |
149 | 149 | return myreturn |
150 | 150 | |
151 | 151 | def decode_binary_node(self, path): |
209 | 209 | ports=[str(item.port)], |
210 | 210 | status="open") |
211 | 211 | |
212 | desc = "" | |
212 | 213 | if item.background: |
213 | desc = item.background | |
214 | else: | |
215 | desc = "" | |
214 | desc += item.background | |
216 | 215 | desc = self.removeHtml(desc) |
216 | data = "" | |
217 | 217 | if item.detail: |
218 | data = item.detail | |
219 | else: | |
220 | data = "" | |
221 | data = self.removeHtml(data) | |
218 | desc += self.removeHtml(item.detail) | |
219 | data = self.removeHtml(item.detail) | |
220 | ref = [] | |
221 | if item.references: | |
222 | ref += self.get_url(item.references) | |
223 | if item.vulnClass: | |
224 | ref += self.get_ref(item.vulnClass) | |
225 | ||
222 | 226 | resolution = self.removeHtml(item.remediation) if item.remediation else "" |
223 | 227 | |
224 | 228 | self.createAndAddVulnWebToService( |
233 | 237 | request=item.request, |
234 | 238 | response=item.response, |
235 | 239 | resolution=resolution, |
240 | ref=ref, | |
236 | 241 | external_id=item.external_id, |
237 | 242 | cve=item.cve |
238 | 243 | ) |
266 | 271 | |
267 | 272 | return str(soup) |
268 | 273 | |
274 | def get_ref(self, markup): | |
275 | soup = BeautifulSoup(markup, "html.parser") | |
276 | ||
277 | for tag in soup.find_all("ul"): | |
278 | for item in tag.find_all("li"): | |
279 | for a in item.find_all("a"): | |
280 | a.unwrap() | |
281 | item.unwrap() | |
282 | tag.unwrap() | |
283 | ref = str(soup).strip().split("\n") | |
284 | return ref | |
285 | ||
286 | def get_url(self, markup): | |
287 | soup = BeautifulSoup(markup, "html.parser") | |
288 | ref = [] | |
289 | for tag in soup.find_all("ul"): | |
290 | for item in tag.find_all("li"): | |
291 | for a in item.find_all("a"): | |
292 | ref += [a['href'].strip()] | |
293 | return ref | |
269 | 294 | |
270 | 295 | def createPlugin(ignore_info=False): |
271 | 296 | return BurpPlugin(ignore_info=ignore_info) |
57 | 57 | service_name, |
58 | 58 | protocol=protocol_name, |
59 | 59 | ports=[vuln_data['service']['port']]) |
60 | ||
61 | 60 | self.createAndAddVulnWebToService( |
62 | 61 | host_id, service_id, |
63 | 62 | vuln_data['name'], |
84 | 83 | |
85 | 84 | |
86 | 85 | class FortifyParser: |
87 | """ | |
86 | """ | |
88 | 87 | Parser for fortify on demand |
89 | 88 | """ |
90 | 89 | |
221 | 220 | references.append(classification.text) |
222 | 221 | |
223 | 222 | # Build description |
224 | description = u'' | |
223 | description = '' | |
225 | 224 | for report_section in issue_data.findall('./ReportSection'): |
226 | description += u'{} \n'.format(report_section.Name.text) | |
227 | description += u'{} \n'.format(report_section.SectionText.text) | |
228 | description += u'{} \n'.format(issue_data.get('id')) | |
225 | description += f'{report_section.Name.text} \n' | |
226 | description += f'{report_section.SectionText.text} \n' | |
227 | description += f'{issue_data.get("id")} \n' | |
229 | 228 | |
230 | 229 | h = html2text.HTML2Text() |
231 | 230 | description = h.handle(description) |
232 | 231 | |
233 | 232 | for repro_step in issue_data.findall('./ReproSteps'): |
234 | 233 | step = repro_step.ReproStep |
235 | ||
234 | ||
236 | 235 | if step is not None: |
237 | 236 | try: |
238 | 237 | params = step.PostParams.text |
258 | 257 | "method": method, |
259 | 258 | "query": query, |
260 | 259 | "response": response, |
261 | "request": request, | |
260 | "request": request.decode('utf-8'), | |
262 | 261 | "path": path, |
263 | 262 | "params": params, |
264 | 263 | "status_code": status_code, |
371 | 370 | idx = match.group(1) |
372 | 371 | if match.group(3): |
373 | 372 | idx = match.group(3) |
374 | _filekey = "{}.file".format(idx) | |
375 | _linekey = "{}.line".format(idx) | |
373 | _filekey = f"{idx}.file" | |
374 | _linekey = f"{idx}.line" | |
376 | 375 | text = text.replace(placeholder, "").replace( |
377 | 376 | torepl.format(_filekey), replacements[_filekey]).replace( |
378 | 377 | torepl.format(_linekey), replacements[_linekey]) |
386 | 385 | |
387 | 386 | text = text.replace(placeholder, replace_with) |
388 | 387 | |
389 | text += '{}\n Instance ID: {} \n'.format(text, vulnID) | |
388 | text += f'{text}\n Instance ID: {vulnID} \n' | |
390 | 389 | h = html2text.HTML2Text() |
391 | 390 | return text |
392 | 391 | |
393 | 392 | |
394 | 393 | def createPlugin(ignore_info=False): |
395 | 394 | return FortifyPlugin(ignore_info=ignore_info) |
396 |
32 | 32 | super().__init__(*arg, **kwargs) |
33 | 33 | self.id = "nuclei" |
34 | 34 | self.name = "Nuclei" |
35 | self.plugin_version = "1.0.2" | |
36 | self.version = "2.5.3" | |
35 | self.plugin_version = "1.0.3" | |
36 | self.version = "2.5.5" | |
37 | 37 | self.json_keys = {"matched-at", "template-id", "host"} |
38 | 38 | self._command_regex = re.compile(r'^(sudo nuclei|nuclei|\.\/nuclei|^.*?nuclei)\s+.*?') |
39 | 39 | self.xml_arg_re = re.compile(r"^.*(-o\s*[^\s]+).*$") |
87 | 87 | references = [references] |
88 | 88 | else: |
89 | 89 | references = [] |
90 | cwe = vuln_dict['info'].get('cwe', []) | |
91 | capec = vuln_dict['info'].get('capec', []) | |
92 | refs = sorted(list(set(reference + references + cwe + capec))) | |
90 | ||
91 | cve = vuln_dict['info'].get('classification', {}).get('cve-id', []) | |
92 | if cve: | |
93 | cve = [x.upper() for x in cve] | |
94 | ||
95 | # TODO CVSSv2, CVSSv3, CWE and CAPEC | |
96 | #cvssv2 = vuln_dict['info'].get('classification', {}).get('cvss-score') | |
97 | #cvssv3 = vuln_dict['info'].get('classification', {}).get('cvss-metrics') | |
98 | #cwe = vuln_dict['info'].get('classification', {}).get('cwe-id', []) | |
99 | #cwe = [x.upper() for x in cwe] | |
100 | #capec = vuln_dict['info'].get('metadata', {}).get('capec', []) | |
101 | #if isinstance(capec, str): | |
102 | # capec = capec.upper().split(',') | |
103 | ||
104 | refs = sorted(list(set(reference + references))) | |
105 | refs = list(filter(None, refs)) | |
106 | ||
93 | 107 | tags = vuln_dict['info'].get('tags', []) |
94 | 108 | if isinstance(tags, str): |
95 | 109 | tags = tags.split(',') |
96 | impact = vuln_dict['info'].get('impact') | |
97 | resolution = vuln_dict['info'].get('resolution', '') | |
98 | easeofresolution = vuln_dict['info'].get('easeofresolution') | |
110 | ||
111 | impact = {} | |
112 | impacted = vuln_dict['info'].get('metadata', {}).get('impact') | |
113 | if isinstance(impacted, str): | |
114 | for x in impacted.split(','): | |
115 | impact[x] = True | |
116 | ||
117 | resolution = vuln_dict['info'].get('metadata', {}).get('resolution', '') | |
118 | easeofresolution = vuln_dict['info'].get('metadata', {}).get('easeofresolution', None) | |
119 | ||
99 | 120 | request = vuln_dict.get('request', '') |
100 | 121 | if request: |
101 | 122 | method = request.split(" ")[0] |
121 | 142 | impact=impact, |
122 | 143 | resolution=resolution, |
123 | 144 | easeofresolution=easeofresolution, |
145 | cve=cve, | |
146 | # TODO CVSSv2, CVSSv3, CWE and CAPEC | |
147 | #cvssv2=cvssv2, | |
148 | #cvssv3=cvssv3, | |
149 | #cwe=cwe, | |
150 | #capec=capec, | |
124 | 151 | website=host, |
125 | 152 | request=request, |
126 | 153 | response=vuln_dict.get('response', ''), |
145 | 145 | |
146 | 146 | self.severity_dict = { |
147 | 147 | '1': 'info', |
148 | '2': 'info', | |
148 | '2': 'low', | |
149 | 149 | '3': 'med', |
150 | 150 | '4': 'high', |
151 | 151 | '5': 'critical'} |
179 | 179 | self.cve.append(cve_id) |
180 | 180 | |
181 | 181 | if self.cvss: |
182 | self.ref.append('CVSS SCORE: {}'.format(self.cvss)) | |
182 | self.ref.append(f'CVSS SCORE: {self.cvss}') | |
183 | 183 | |
184 | 184 | if self.pci: |
185 | self.ref.append('PCI: {}'.format(self.pci)) | |
185 | self.ref.append(f'PCI: {self.pci}') | |
186 | 186 | |
187 | 187 | def get_text_from_glossary(self, tag): |
188 | 188 | """ |
285 | 285 | |
286 | 286 | self.severity_dict = { |
287 | 287 | '1': 'info', |
288 | '2': 'info', | |
288 | '2': 'low', | |
289 | 289 | '3': 'med', |
290 | 290 | '4': 'high', |
291 | 291 | '5': 'critical'} |
12 | 12 | import shutil |
13 | 13 | |
14 | 14 | from faraday_plugins.plugins.plugin import PluginMultiLineJsonFormat |
15 | ||
15 | from faraday_plugins.plugins.plugins_utils import get_severity_from_cvss | |
16 | 16 | __author__ = "Valentin Vila" |
17 | 17 | __copyright__ = "Copyright (c) 2021, Faraday" |
18 | 18 | __credits__ = ["Valentin Vila"] |
71 | 71 | for name, vuln_info in vulns.items(): |
72 | 72 | description = vuln_info.get('summary') |
73 | 73 | references = vuln_info.get('references') |
74 | self.createAndAddVulnToService(h_id, s_id, name, desc=description, severity=0, ref=references, cve=name) | |
74 | cvss = vuln_info.get('cvss') | |
75 | severity = get_severity_from_cvss(cvss) if cvss else "info" | |
76 | self.createAndAddVulnToService(h_id, s_id, name, desc=description, severity=severity, ref=references, cve=name) | |
75 | 77 | |
76 | 78 | def processCommandString(self, username, current_path, command_string): |
77 | 79 | """ |
21 | 21 | } |
22 | 22 | STATUSES = { |
23 | 23 | 'OPEN': 'open', |
24 | 'CONFIRMED': 'opened', | |
24 | 'CONFIRMED': 'open', | |
25 | 25 | 'REOPENED': 're-opened', |
26 | 26 | 'CLOSED': 'closed', |
27 | 27 | 'RESOLVED': 'closed' |
0 | 0 | from setuptools import setup, find_packages |
1 | 1 | from re import search |
2 | 2 | |
3 | with open('faraday_plugins/__init__.py', 'rt', encoding='utf8') as f: | |
3 | with open('faraday_plugins/__init__.py', encoding='utf8') as f: | |
4 | 4 | version = search(r'__version__ = \'(.*?)\'', f.read()).group(1) |
5 | 5 | |
6 | 6 | |
14 | 14 | 'pytz', |
15 | 15 | 'python-dateutil', |
16 | 16 | 'colorama', |
17 | 'tabulate' | |
17 | 'tabulate', | |
18 | 'packaging' | |
18 | 19 | ] |
19 | 20 | |
20 | 21 |