Update upstream source from tag 'upstream/1.7.0'
Update to upstream version '1.7.0'
with Debian dir 7a72ff5616b6e6d998e6dd485188405e88bbdc4c
Sophie Brun
1 year, 7 months ago
49 | 49 | script: |
50 | 50 | - pip3 install bandit |
51 | 51 | - mkdir /results |
52 | - "bandit -r ${CI_PROJECT_DIR} -o /results/output.xml -f xml" | |
52 | - "bandit -r ${CI_PROJECT_DIR} -o /results/output.xml -f xml --skip B410,B320,B310,B314,B404,B405,B324,B603,B104,B110,B112,B101" | |
53 | 53 | after_script: |
54 | 54 | - curl -fsSL https://apt.releases.hashicorp.com/gpg | apt-key add - |
55 | 55 | - apt update |
63 | 63 | - if [[ $(grep -c testcase /results/output.xml) -gt 0 ]]; then (faraday-cli auth -f $FARADAY_URL -u $FARADAY_USER -p $FARADAY_PASSWORD && faraday-cli tool report /results/output.xml -w $DEVSECOPS_WORKSPACE --tag-vuln $CI_PROJECT_NAME --tag-vuln $CI_COMMIT_REF_NAME); else (echo 'no vulns dettected' && exit 0); fi |
64 | 64 | rules: |
65 | 65 | - when: on_success |
66 | allow_failure: true | |
67 | 66 | |
68 | 67 | flake8: |
69 | 68 | image: python:3 |
0 | Add CWE to PluginBase. The plugins that have this implemented are the following: | |
1 | "Acunetix", | |
2 | "Acunetix_Json", | |
3 | "AppSpider", | |
4 | "Appscan", | |
5 | "Arachni", | |
6 | "Burp", | |
7 | "Checkmarx", | |
8 | "Metasploit", | |
9 | "Nessus", | |
10 | "Netsparker", | |
11 | "NetsparkerCloud", | |
12 | "Openvas", | |
13 | "QualysWebapp", | |
14 | "W3af", | |
15 | "Wapiti", | |
16 | "Zap", | |
17 | "Zap_Json", | |
18 | "nuclei", | |
19 | "nuclei_legacy" |
0 | Now the nexts pluggins extracts cvss from reports: | |
1 | ||
2 | - Acunetix | |
3 | - Acunetix_Json | |
4 | - Appscan | |
5 | - Nessus | |
6 | - Netsparker | |
7 | - NexposeFull | |
8 | - Nipper | |
9 | - Nmap | |
10 | - Openvas | |
11 | - QualysWebapp | |
12 | - Qualysguard | |
13 | - Retina | |
14 | - shodan | |
15 | - whitesource |
0 | Add trivy's json plugin |
0 | Add command support for the wpscan plugin |
0 | Sep 5th, 2022 |
0 | Fix for acunetix_json when host is ip |
0 | [FIX] - Asset duplicated on same file with multiple entries for Appscan_csv plugin.⏎ |
0 | [FIX] Change import dateutil to from dateutil.parser import parse | |
1 | for compatibility issues with python 3.10 |
0 | [FIX] Add case for Netsparker plugins, when the url has a number inside a parenthesis. |
0 | Add *args **kwargs to syhunt plugin |
0 | fix bug when grype report has no arifact/metadata |
0 | 1.7.0 [Sep 5th, 2022]: | |
1 | --- | |
2 | * Add CWE to PluginBase. The plugins that have this implemented are the following: | |
3 | "Acunetix", | |
4 | "Acunetix_Json", | |
5 | "AppSpider", | |
6 | "Appscan", | |
7 | "Arachni", | |
8 | "Burp", | |
9 | "Checkmarx", | |
10 | "Metasploit", | |
11 | "Nessus", | |
12 | "Netsparker", | |
13 | "NetsparkerCloud", | |
14 | "Openvas", | |
15 | "QualysWebapp", | |
16 | "W3af", | |
17 | "Wapiti", | |
18 | "Zap", | |
19 | "Zap_Json", | |
20 | "nuclei", | |
21 | "nuclei_legacy" | |
22 | * Now the nexts pluggins extracts cvss from reports: | |
23 | ||
24 | - Acunetix | |
25 | - Acunetix_Json | |
26 | - Appscan | |
27 | - Nessus | |
28 | - Netsparker | |
29 | - NexposeFull | |
30 | - Nipper | |
31 | - Nmap | |
32 | - Openvas | |
33 | - QualysWebapp | |
34 | - Qualysguard | |
35 | - Retina | |
36 | - shodan | |
37 | - whitesource | |
38 | * Add arguments for add tags for vulns, services and host. | |
39 | ||
40 | Add test for tags and ignore_info | |
41 | * Add trivy's json plugin | |
42 | * Add command support for the wpscan plugin | |
43 | * [MOD] Now refs field is a list of dictionary with the format: | |
44 | {'name': string, 'type': string}, | |
45 | * Fix for acunetix_json when host is ip | |
46 | * [FIX] - Asset duplicated on same file with multiple entries for Appscan_csv plugin. | |
47 | * [FIX] Change import dateutil to from dateutil.parser import parse | |
48 | for compatibility issues with python 3.10 | |
49 | * [FIX] Add case for Netsparker plugins, when the url has a number inside a parenthesis. | |
50 | * Add *args **kwargs to syhunt plugin | |
51 | * fix bug when grype report has no arifact/metadata | |
52 | * [MOD] Now prowler plugin returns CAF Epic as policy violation and | |
53 | remove [check#] from tittle | |
54 | ||
0 | 55 | 1.6.8 [Jul 25th, 2022]: |
1 | 56 | --- |
2 | 57 | * Add appscan csv |
4 | 4 | ```python |
5 | 5 | class XXXPLugin(PluginXMLFormat): |
6 | 6 | |
7 | def __init__(self): | |
8 | super().__init__() | |
7 | def __init__(self, *args, **kwargs): | |
8 | super().__init__(*args, **kwargs) | |
9 | 9 | # Tags to be compared with the xml mail tag, can be a list or a string |
10 | self.identifier_tag = ["tag1", "tag2"] | |
10 | self.identifier_tag = ["tag1", "tag2"] | |
11 | 11 | self.id = 'SOME_PLUGIN_ID' # Can't be repeated |
12 | 12 | self.name = 'Some plugin name' |
13 | 13 | self.plugin_version = 'X.X' |
14 | 14 | # The extension is optional, only if its different than xml |
15 | self.extension = ".xxx" | |
15 | self.extension = ".xxx" | |
16 | 16 | ``` |
17 | 17 | |
18 | 18 | > JSON report plugin |
20 | 20 | ```python |
21 | 21 | class XXXPLugin(PluginJsonFormat): |
22 | 22 | |
23 | def __init__(self): | |
24 | super().__init__() | |
23 | def __init__(self, *args, **kwargs): | |
24 | super().__init__(*args, **kwargs) | |
25 | 25 | # keys of the json that identify the report |
26 | 26 | # you don't need to put all the keys, just some of them |
27 | 27 | # it must be a set and will be compared as a subset of the json report keys |
30 | 30 | self.name = 'Some plugin name' |
31 | 31 | self.plugin_version = 'X.X' |
32 | 32 | # The extension is optional, only if its different than json |
33 | self.extension = ".xxx" | |
34 | ```⏎ | |
33 | self.extension = ".xxx" | |
34 | ``` |
65 | 65 | @click.option('-o', '--output-file', type=click.Path(exists=False)) |
66 | 66 | @click.option('--ignore-info', is_flag=True, help="Ignore information vulnerabilities") |
67 | 67 | @click.option('-drh', '--dont-resolve-hostname', is_flag=True, help="Dont resolve hostname", default=False) |
68 | @click.option('--vuln-tag', help="Vuln tag", default=None) | |
69 | @click.option('--service-tag', help="Service tag", default=None) | |
70 | @click.option('--host-tag', help="Host tag", default=None) | |
68 | 71 | def process_report(report_file, plugin_id, custom_plugins_folder, summary, output_file, ignore_info, |
69 | dont_resolve_hostname): | |
72 | dont_resolve_hostname, vuln_tag, service_tag, host_tag): | |
70 | 73 | if not os.path.isfile(report_file): |
71 | 74 | click.echo(click.style(f"File {report_file} Don't Exists", fg="red"), err=True) |
72 | 75 | else: |
73 | plugins_manager = PluginsManager(custom_plugins_folder, ignore_info=ignore_info, | |
74 | hostname_resolution=not dont_resolve_hostname) | |
76 | plugins_manager = PluginsManager(custom_plugins_folder, | |
77 | ignore_info=ignore_info, | |
78 | hostname_resolution=not dont_resolve_hostname, | |
79 | vuln_tag=vuln_tag, | |
80 | service_tag=service_tag, | |
81 | host_tag=host_tag) | |
75 | 82 | analyzer = ReportAnalyzer(plugins_manager) |
76 | 83 | if plugin_id: |
77 | 84 | plugin = plugins_manager.get_plugin(plugin_id) |
104 | 111 | @click.option('-sh', '--show-output', is_flag=True) |
105 | 112 | @click.option('--ignore-info', is_flag=True, help="Ignore information vulnerabilities") |
106 | 113 | @click.option('--hostname-resolution', is_flag=True, help="Resolve hostname") |
114 | @click.option('--vuln-tag', help="Vuln tag", default=None) | |
115 | @click.option('--service-tag', help="Service tag", default=None) | |
116 | @click.option('--host-tag', help="Host tag", default=None) | |
107 | 117 | def process_command(command, plugin_id, custom_plugins_folder, dont_run, summary, output_file, show_output, |
108 | ignore_info, hostname_resolution): | |
109 | plugins_manager = PluginsManager(custom_plugins_folder, ignore_info=ignore_info, | |
110 | hostname_resolution=hostname_resolution) | |
118 | ignore_info, hostname_resolution, vuln_tag, service_tag, host_tag): | |
119 | plugins_manager = PluginsManager(custom_plugins_folder, | |
120 | ignore_info=ignore_info, | |
121 | hostname_resolution=hostname_resolution, | |
122 | vuln_tag=vuln_tag, | |
123 | service_tag=service_tag, | |
124 | host_tag=host_tag) | |
111 | 125 | analyzer = CommandAnalyzer(plugins_manager) |
112 | 126 | if plugin_id: |
113 | 127 | plugin = plugins_manager.get_plugin(plugin_id) |
82 | 82 | main_tag = elem.tag |
83 | 83 | try: |
84 | 84 | main_tag_attributes = elem.attrib |
85 | except: | |
85 | except AttributeError: | |
86 | 86 | pass |
87 | 87 | break |
88 | 88 | logger.debug("Found XML content on file: %s - Main tag: %s Attributes: %s", report_path, main_tag, |
151 | 151 | |
152 | 152 | class PluginsManager: |
153 | 153 | |
154 | def __init__(self, custom_plugins_folder=None, ignore_info=False, hostname_resolution=True): | |
155 | self.ignore_info = ignore_info | |
156 | self.hostname_resolution = hostname_resolution | |
154 | def __init__(self, custom_plugins_folder=None, **kwargs): | |
155 | self.kwargs = kwargs | |
157 | 156 | self.plugins = {} |
158 | 157 | self.plugin_modules = {} |
159 | 158 | self._load_plugins(custom_plugins_folder) |
216 | 215 | plugin = None |
217 | 216 | plugin_id = plugin_id.lower() |
218 | 217 | if plugin_id in self.plugin_modules: |
219 | plugin = self.plugin_modules[plugin_id].createPlugin(self.ignore_info, self.hostname_resolution) | |
218 | plugin = self.plugin_modules[plugin_id].createPlugin(**self.kwargs) | |
220 | 219 | else: |
221 | 220 | logger.debug("Unknown Plugin: %s", plugin_id) |
222 | 221 | return plugin |
224 | 223 | def get_plugins(self): |
225 | 224 | for plugin_id, plugin_module in self.plugin_modules.items(): |
226 | 225 | logger.debug("Instance Plugin: %s", plugin_id) |
227 | yield plugin_id, plugin_module.createPlugin(self.ignore_info, self.hostname_resolution) | |
226 | yield plugin_id, plugin_module.createPlugin(**self.kwargs) |
16 | 16 | from datetime import datetime |
17 | 17 | from pathlib import Path |
18 | 18 | import socket |
19 | from typing import List | |
19 | 20 | |
20 | 21 | # Related third party imports |
21 | 22 | import pytz |
22 | 23 | import simplejson as json |
23 | 24 | |
24 | 25 | # Local application imports |
25 | from faraday_plugins.plugins.plugins_utils import its_cve | |
26 | from faraday_plugins.plugins.plugins_utils import its_cve, its_cwe | |
26 | 27 | |
27 | 28 | logger = logging.getLogger("faraday").getChild(__name__) |
28 | 29 | |
34 | 35 | # TODO: Add class generic identifier |
35 | 36 | class_signature = "PluginBase" |
36 | 37 | |
37 | def __init__(self, ignore_info=False, hostname_resolution=True, *args, **kwargs): | |
38 | def __init__(self, *args, **kwargs): | |
38 | 39 | # Must be unique. Check that there is not |
39 | 40 | # an existent plugin with the same id. |
40 | 41 | # TODO: Make script that list current ids. |
41 | self.ignore_info = ignore_info | |
42 | self.hostname_resolution = hostname_resolution | |
42 | self.ignore_info = kwargs.get("ignore_info", False) | |
43 | self.hostname_resolution = kwargs.get("hostname_resolution", True) | |
44 | self.vuln_tag = kwargs.get("vuln_tag", None) | |
45 | self.host_tag = kwargs.get("host_tag", None) | |
46 | self.service_tag = kwargs.get("service_tag", None) | |
47 | self.default_vuln_tag = None | |
43 | 48 | self.id = None |
44 | 49 | self.auto_load = True |
45 | 50 | self._rid = id(self) |
87 | 92 | def resolve_hostname(self, hostname): |
88 | 93 | if not self.hostname_resolution: |
89 | 94 | return hostname |
95 | if not hostname: | |
96 | self.logger.error(f"Hostname provided is None or Empty {hostname}, using 0.0.0.0 as ip") | |
97 | return "0.0.0.0" | |
90 | 98 | try: |
91 | 99 | socket.inet_aton(hostname) # is already an ip |
92 | 100 | return hostname |
373 | 381 | tags = [] |
374 | 382 | if isinstance(tags, str): |
375 | 383 | tags = [tags] |
384 | if self.host_tag: | |
385 | if isinstance(self.host_tag, list): | |
386 | tags += self.host_tag | |
387 | else: | |
388 | tags.append(self.host_tag) | |
376 | 389 | host = {"ip": name, "os": os, "hostnames": hostnames, "description": description, "mac": mac, |
377 | 390 | "credentials": [], "services": [], "vulnerabilities": [], "tags": tags} |
378 | 391 | host_id = self.save_host_cache(host) |
394 | 407 | tags = [] |
395 | 408 | if isinstance(tags, str): |
396 | 409 | tags = [tags] |
410 | if self.service_tag: | |
411 | if isinstance(self.service_tag, list): | |
412 | tags += self.service_tag | |
413 | else: | |
414 | tags.append(self.service_tag) | |
397 | 415 | service = {"name": name, "protocol": protocol, "port": ports, "status": status, |
398 | 416 | "version": version, "description": description, "credentials": [], "vulnerabilities": [], |
399 | 417 | "tags": tags} |
402 | 420 | |
403 | 421 | return service_id |
404 | 422 | |
423 | @staticmethod | |
424 | def modify_refs_struct(ref: List[str]) -> List[dict]: | |
425 | """ | |
426 | Change reference struct from list of strings to a list of dicts with the form of {name, type} | |
427 | """ | |
428 | refs = [] | |
429 | if ref: | |
430 | refs = [{'name': url, 'type': 'other'} for url in ref] | |
431 | return refs | |
432 | ||
405 | 433 | def createAndAddVulnToHost(self, host_id, name, desc="", ref=None, |
406 | 434 | severity="", resolution="", data="", external_id=None, run_date=None, |
407 | 435 | impact=None, custom_fields=None, status="", policyviolations=None, |
408 | easeofresolution=None, confirmed=False, tags=None, cve=None): | |
409 | if ref is None: | |
410 | ref = [] | |
436 | easeofresolution=None, confirmed=False, tags=None, cve=None, cwe=None, cvss2=None, | |
437 | cvss3=None): | |
438 | ||
439 | ref = self.modify_refs_struct(ref) | |
411 | 440 | if status == "": |
412 | 441 | status = "open" |
413 | 442 | if impact is None: |
420 | 449 | tags = [] |
421 | 450 | if isinstance(tags, str): |
422 | 451 | tags = [tags] |
452 | if self.vuln_tag: | |
453 | if isinstance(self.vuln_tag, list): | |
454 | tags += self.vuln_tag | |
455 | else: | |
456 | tags.append(self.vuln_tag) | |
457 | if self.default_vuln_tag: | |
458 | if isinstance(self.default_vuln_tag, list): | |
459 | tags += self.default_vuln_tag | |
460 | else: | |
461 | tags.append(self.default_vuln_tag) | |
423 | 462 | if cve is None: |
424 | 463 | cve = [] |
425 | 464 | elif type(cve) is str: |
426 | 465 | cve = [cve] |
427 | 466 | cve = its_cve(cve) |
467 | if cwe is None: | |
468 | cwe = [] | |
469 | elif type(cwe) is str: | |
470 | cwe = [cwe] | |
471 | cwe = its_cwe(cwe) | |
472 | if cvss2 is None: | |
473 | cvss2 = {} | |
474 | if cvss3 is None: | |
475 | cvss3 = {} | |
428 | 476 | vulnerability = {"name": name, "desc": desc, "severity": self.normalize_severity(severity), "refs": ref, |
429 | 477 | "external_id": external_id, "type": "Vulnerability", "resolution": resolution, "data": data, |
430 | 478 | "custom_fields": custom_fields, "status": status, "impact": impact, |
431 | "policyviolations": policyviolations, "cve": cve, | |
432 | "confirmed": confirmed, "easeofresolution": easeofresolution, "tags": tags | |
479 | "policyviolations": policyviolations, "cve": cve, "cvss3": cvss3, "cvss2": cvss2, | |
480 | "confirmed": confirmed, "easeofresolution": easeofresolution, "tags": tags, "cwe": cwe | |
433 | 481 | } |
434 | 482 | if run_date: |
435 | 483 | vulnerability["run_date"] = self.get_utctimestamp(run_date) |
439 | 487 | def createAndAddVulnToService(self, host_id, service_id, name, desc="", |
440 | 488 | ref=None, severity="", resolution="", data="", external_id=None, run_date=None, |
441 | 489 | custom_fields=None, policyviolations=None, impact=None, status="", |
442 | confirmed=False, easeofresolution=None, tags=None, cve=None): | |
443 | if ref is None: | |
444 | ref = [] | |
490 | confirmed=False, easeofresolution=None, tags=None, cve=None, cwe=None,cvss2=None, | |
491 | cvss3=None): | |
492 | ref = self.modify_refs_struct(ref) | |
445 | 493 | if status == "": |
446 | 494 | status = "open" |
447 | 495 | if impact is None: |
454 | 502 | tags = [] |
455 | 503 | if isinstance(tags, str): |
456 | 504 | tags = [tags] |
505 | if self.vuln_tag: | |
506 | if isinstance(self.vuln_tag, list): | |
507 | tags += self.vuln_tag | |
508 | else: | |
509 | tags.append(self.vuln_tag) | |
510 | if self.default_vuln_tag: | |
511 | if isinstance(self.default_vuln_tag, list): | |
512 | tags += self.default_vuln_tag | |
513 | else: | |
514 | tags.append(self.default_vuln_tag) | |
457 | 515 | if cve is None: |
458 | 516 | cve = [] |
459 | 517 | elif type(cve) is str: |
460 | 518 | cve = [cve] |
461 | 519 | cve = its_cve(cve) |
520 | if cwe is None: | |
521 | cwe = [] | |
522 | elif type(cwe) is str: | |
523 | cwe = [cwe] | |
524 | cwe = its_cwe(cwe) | |
525 | if cvss2 is None: | |
526 | cvss2 = {} | |
527 | if cvss3 is None: | |
528 | cvss3 = {} | |
462 | 529 | vulnerability = {"name": name, "desc": desc, "severity": self.normalize_severity(severity), "refs": ref, |
463 | 530 | "external_id": external_id, "type": "Vulnerability", "resolution": resolution, "data": data, |
464 | 531 | "custom_fields": custom_fields, "status": status, "impact": impact, |
465 | "policyviolations": policyviolations, "cve": cve, | |
466 | "easeofresolution": easeofresolution, "confirmed": confirmed, "tags": tags | |
532 | "policyviolations": policyviolations, "cve": cve, "cvss3": cvss3, "cvss2": cvss2, | |
533 | "easeofresolution": easeofresolution, "confirmed": confirmed, "tags": tags, "cwe": cwe | |
467 | 534 | } |
468 | 535 | if run_date: |
469 | 536 | vulnerability["run_date"] = self.get_utctimestamp(run_date) |
477 | 544 | params="", query="", category="", data="", external_id=None, |
478 | 545 | confirmed=False, status="", easeofresolution=None, impact=None, |
479 | 546 | policyviolations=None, status_code=None, custom_fields=None, run_date=None, |
480 | tags=None, cve=None): | |
547 | tags=None, cve=None, cvss2=None, cvss3=None, cwe=None): | |
481 | 548 | if params is None: |
482 | 549 | params = "" |
483 | if response is None: | |
484 | response = "" | |
485 | 550 | if method is None: |
486 | 551 | method = "" |
487 | 552 | if pname is None: |
488 | 553 | pname = "" |
489 | if params is None: | |
490 | params = "" | |
491 | 554 | if query is None: |
492 | 555 | query = "" |
493 | 556 | if website is None: |
498 | 561 | request = "" |
499 | 562 | if response is None: |
500 | 563 | response = "" |
501 | if ref is None: | |
502 | ref = [] | |
564 | ref = self.modify_refs_struct(ref) | |
503 | 565 | if status == "": |
504 | 566 | status = "open" |
505 | 567 | if impact is None: |
512 | 574 | tags = [] |
513 | 575 | if isinstance(tags, str): |
514 | 576 | tags = [tags] |
577 | if self.vuln_tag: | |
578 | if isinstance(self.vuln_tag, list): | |
579 | tags += self.vuln_tag | |
580 | else: | |
581 | tags.append(self.vuln_tag) | |
582 | if self.default_vuln_tag: | |
583 | if isinstance(self.default_vuln_tag, list): | |
584 | tags += self.default_vuln_tag | |
585 | else: | |
586 | tags.append(self.default_vuln_tag) | |
515 | 587 | if cve is None: |
516 | 588 | cve = [] |
517 | 589 | elif type(cve) is str: |
518 | 590 | cve = [cve] |
519 | 591 | cve = its_cve(cve) |
592 | if cwe is None: | |
593 | cwe = [] | |
594 | elif type(cwe) is str: | |
595 | cwe = [cwe] | |
596 | cwe = its_cwe(cwe) | |
597 | if cvss2 is None: | |
598 | cvss2 = {} | |
599 | if cvss3 is None: | |
600 | cvss3 = {} | |
520 | 601 | vulnerability = {"name": name, "desc": desc, "severity": self.normalize_severity(severity), "refs": ref, |
521 | 602 | "external_id": external_id, "type": "VulnerabilityWeb", "resolution": resolution, |
522 | 603 | "data": data, "website": website, "path": path, "request": request, "response": response, |
523 | 604 | "method": method, "pname": pname, "params": params, "query": query, "category": category, |
524 | 605 | "confirmed": confirmed, "status": status, "easeofresolution": easeofresolution, |
525 | "impact": impact, "policyviolations": policyviolations, "cve": cve, | |
526 | "status_code": status_code, "custom_fields": custom_fields, "tags": tags} | |
606 | "impact": impact, "policyviolations": policyviolations, "cve": cve, "cvss3": cvss3, | |
607 | "cvss2": cvss2, "status_code": status_code, "custom_fields": custom_fields, "tags": tags, | |
608 | "cwe": cwe} | |
527 | 609 | if run_date: |
528 | 610 | vulnerability["run_date"] = self.get_utctimestamp(run_date) |
529 | 611 | vulnerability_id = self.save_service_vuln_cache(host_id, service_id, vulnerability) |
580 | 662 | vuln_copy = vuln.copy() |
581 | 663 | for field in VULN_SKIP_FIELDS_TO_HASH: |
582 | 664 | vuln_copy.pop(field, None) |
583 | dict_hash = hashlib.sha1(json.dumps(vuln_copy).encode()).hexdigest() | |
665 | dict_hash = hashlib.sha1(json.dumps(vuln_copy).encode()).hexdigest() # nosec | |
584 | 666 | summary['vuln_hashes'].append(dict_hash) |
585 | 667 | return summary |
586 | 668 | |
587 | 669 | |
588 | 670 | # TODO Borrar |
589 | 671 | class PluginTerminalOutput(PluginBase): |
590 | def __init__(self): | |
591 | super().__init__() | |
672 | def __init__(self, *args, **kwargs): | |
673 | super().__init__(*args, **kwargs) | |
592 | 674 | |
593 | 675 | def processOutput(self, term_output): |
594 | 676 | try: |
599 | 681 | |
600 | 682 | # TODO Borrar |
601 | 683 | class PluginCustomOutput(PluginBase): |
602 | def __init__(self): | |
603 | super().__init__() | |
684 | def __init__(self, *args, **kwargs): | |
685 | super().__init__(*args, **kwargs) | |
604 | 686 | |
605 | 687 | def processOutput(self, term_output): |
606 | 688 | # we discard the term_output since it's not necessary |
609 | 691 | |
610 | 692 | |
611 | 693 | class PluginByExtension(PluginBase): |
612 | def __init__(self, ignore_info=False, hostname_resolution=True, *args, **kwargs): | |
613 | super().__init__(ignore_info, hostname_resolution) | |
694 | def __init__(self, *args, **kwargs): | |
695 | super().__init__(*args, **kwargs) | |
614 | 696 | self.extension = [] |
615 | 697 | |
616 | 698 | def report_belongs_to(self, extension="", **kwargs): |
625 | 707 | |
626 | 708 | class PluginXMLFormat(PluginByExtension): |
627 | 709 | |
628 | def __init__(self, ignore_info=False, hostname_resolution=True, *args, **kwargs): | |
629 | super().__init__(ignore_info, hostname_resolution) | |
710 | def __init__(self, *args, **kwargs): | |
711 | super().__init__(*args, **kwargs) | |
630 | 712 | self.identifier_tag = [] |
631 | 713 | self.identifier_tag_attributes = {} |
632 | 714 | self.extension = ".xml" |
647 | 729 | |
648 | 730 | class PluginJsonFormat(PluginByExtension): |
649 | 731 | |
650 | def __init__(self, ignore_info=False, hostname_resolution=True, *args, **kwargs): | |
651 | super().__init__(ignore_info, hostname_resolution) | |
732 | def __init__(self, *args, **kwargs): | |
733 | super().__init__(*args, **kwargs) | |
652 | 734 | self.json_keys = set() |
653 | 735 | self.extension = ".json" |
654 | 736 | |
664 | 746 | |
665 | 747 | class PluginMultiLineJsonFormat(PluginByExtension): |
666 | 748 | |
667 | def __init__(self, ignore_info=False, hostname_resolution=True, *args, **kwargs): | |
668 | super().__init__(ignore_info, hostname_resolution) | |
749 | def __init__(self, *args, **kwargs): | |
750 | super().__init__(*args, **kwargs) | |
669 | 751 | self.json_keys = set() |
670 | 752 | self.extension = ".json" |
671 | 753 | |
688 | 770 | |
689 | 771 | class PluginCSVFormat(PluginByExtension): |
690 | 772 | |
691 | def __init__(self, ignore_info=False, hostname_resolution=True, *args, **kwargs): | |
692 | super().__init__(ignore_info, hostname_resolution) | |
773 | def __init__(self, *args, **kwargs): | |
774 | super().__init__(*args, **kwargs) | |
693 | 775 | self.extension = ".csv" |
694 | 776 | self.csv_headers = set() |
695 | 777 | |
708 | 790 | |
709 | 791 | class PluginZipFormat(PluginByExtension): |
710 | 792 | |
711 | def __init__(self, ignore_info=False, hostname_resolution=True, *args, **kwargs): | |
712 | super().__init__(ignore_info, hostname_resolution) | |
793 | def __init__(self, *args, **kwargs): | |
794 | super().__init__(*args, **kwargs) | |
713 | 795 | self.extension = ".zip" |
714 | 796 | self.files_list = set() |
715 | 797 |
12 | 12 | |
13 | 13 | SERVICE_MAPPER = None |
14 | 14 | CVE_regex = re.compile(r'CVE-\d{4}-\d{4,7}') |
15 | CWE_regex = re.compile(r'CWE-\d{1,4}') | |
15 | 16 | logger = logging.getLogger(__name__) |
16 | 17 | |
17 | 18 | |
116 | 117 | def its_cve(cves: list): |
117 | 118 | r = [cve for cve in cves if CVE_regex.match(cve)] |
118 | 119 | return r |
120 | ||
121 | ||
122 | def its_cwe(cwes: list): | |
123 | r = [cwe for cwe in cwes if CWE_regex.match(cwe)] | |
124 | return r |
0 | 0 | from typing import List |
1 | ||
1 | import re | |
2 | 2 | |
3 | 3 | class Technicaldetails: |
4 | 4 | def __init__(self, node): |
45 | 45 | |
46 | 46 | @property |
47 | 47 | def id_attr(self) -> str: |
48 | return self.node.findtext('id', '') | |
48 | return self.node.attrib.get('id', '') | |
49 | 49 | |
50 | 50 | @property |
51 | 51 | def text(self) -> str: |
52 | return self.node.findtext('#text', '') | |
52 | return self.node.text | |
53 | 53 | |
54 | 54 | |
55 | 55 | class Cwelist: |
71 | 71 | |
72 | 72 | @property |
73 | 73 | def score(self) -> str: |
74 | return self.node.findtext('Score', '') | |
74 | if self.node is None: | |
75 | return '' | |
76 | return self.node.findtext('Score') | |
75 | 77 | |
76 | 78 | @property |
77 | 79 | def av(self) -> str: |
120 | 122 | |
121 | 123 | @property |
122 | 124 | def score(self) -> str: |
123 | return self.node.findtext('Score', '') | |
125 | return self.node.findtext('Score') | |
124 | 126 | |
125 | 127 | @property |
126 | 128 | def tempscore(self): |
139 | 139 | |
140 | 140 | def create_vul(self, item, h_id, s_id, url_data): |
141 | 141 | description = item.description |
142 | cvss3 = {} | |
143 | if item.cvss3.node is not None: | |
144 | cvss3['vector_string'] = item.cvss3.descriptor | |
145 | cvss2 = {} | |
146 | if item.cvss.node is not None: | |
147 | cvss2['vector_string'] = item.cvss.descriptor | |
142 | 148 | if item.affects: |
143 | 149 | description += f'\nPath: {item.affects}' |
144 | 150 | if item.parameter: |
146 | 152 | try: |
147 | 153 | cve = [item.cvelist.cve.text if item.cvelist.cve else ""] |
148 | 154 | except Exception: |
149 | cve = [""] | |
155 | cve = [] | |
156 | try: | |
157 | cwe = [item.cwelist.cwe.text if item.cwelist.cwe else ""] | |
158 | except: | |
159 | cwe = [] | |
150 | 160 | self.createAndAddVulnWebToService( |
151 | 161 | h_id, |
152 | 162 | s_id, |
160 | 170 | request=item.technicaldetails.request, |
161 | 171 | response=item.technicaldetails.response, |
162 | 172 | ref=[i.url for i in item.references.reference], |
163 | cve=cve) | |
173 | cve=cve, | |
174 | cwe=cwe, | |
175 | cvss2=cvss2, | |
176 | cvss3=cvss3) | |
164 | 177 | |
165 | 178 | @staticmethod |
166 | 179 | def get_domain(scan: Scan): |
173 | 186 | return url_data |
174 | 187 | |
175 | 188 | |
176 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
177 | return AcunetixPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
189 | def createPlugin(*args, **kwargs): | |
190 | return AcunetixPlugin(*args, **kwargs) |
0 | 0 | from typing import List |
1 | ||
1 | import re | |
2 | 2 | |
3 | 3 | class InfoVul: |
4 | 4 | def __init__(self, node): |
15 | 15 | if not self.node: |
16 | 16 | return '' |
17 | 17 | return self.node.get('request', '') |
18 | ||
19 | ||
18 | 20 | |
19 | 21 | |
20 | 22 | class Vulnerabilities: |
72 | 74 | |
73 | 75 | @property |
74 | 76 | def use_ssl(self) -> bool: |
77 | if not self.node: | |
78 | return '' | |
75 | 79 | return self.node.get('use_ssl', '') |
80 | ||
81 | @property | |
82 | def tags(self) -> list: | |
83 | if not self.node: | |
84 | return [''] | |
85 | return self.node.get('tags', ['']) | |
86 | ||
87 | def cvss_score(self) -> str: | |
88 | return self.node.get('cvss_score') | |
89 | ||
90 | @property | |
91 | def cvss2_vector(self) -> str: | |
92 | return self.node.get('cvss2', '') | |
93 | ||
94 | @property | |
95 | def cvss3_vector(self) -> str: | |
96 | return self.node.get('cvss3', '') | |
76 | 97 | |
77 | 98 | |
78 | 99 | class Info: |
85 | 106 | return '' |
86 | 107 | return self.node.get('host', '') |
87 | 108 | |
109 | @property | |
110 | def start_url(self) -> str: | |
111 | if not self.node: | |
112 | return '' | |
113 | return self.node.get('start_url', '') | |
88 | 114 | |
89 | 115 | class Scan: |
90 | 116 | def __init__(self, node): |
124 | 150 | |
125 | 151 | @property |
126 | 152 | def export(self) -> Export: |
127 | return Export(self.node.get('export'))⏎ | |
153 | return Export(self.node.get('export')) |
4 | 4 | |
5 | 5 | """ |
6 | 6 | from urllib.parse import urlsplit |
7 | import ipaddress | |
7 | 8 | |
8 | 9 | from lxml import etree |
9 | 10 | |
21 | 22 | |
22 | 23 | from faraday_plugins.plugins.repo.acunetix_json.DTO import AcunetixJsonParser, Vulnerabilities, \ |
23 | 24 | VulnerabilityTypes |
25 | from faraday_plugins.plugins.plugins_utils import its_cwe | |
24 | 26 | |
25 | 27 | |
26 | 28 | class AcunetixXmlParser: |
91 | 93 | |
92 | 94 | def new_structure(self, site: Scan): |
93 | 95 | start_url = site.info.host |
96 | if site.info.start_url: | |
97 | start_url = site.info.start_url | |
94 | 98 | url_data = urlsplit(start_url) |
95 | 99 | site_ip = self.resolve_hostname(url_data.hostname) |
96 | 100 | ports = '443' if (url_data.scheme == 'https') else '80' |
105 | 109 | status='open') |
106 | 110 | for i in site.vulnerabilities: |
107 | 111 | vul_type = vulnerability_type[i.info.vt_id] |
108 | self.create_vul(i, vul_type, h_id, s_id, url_data) | |
112 | cwe = its_cwe(vul_type.tags) | |
113 | self.create_vul(i, vul_type, h_id, s_id, url_data, cwe) | |
109 | 114 | |
110 | def create_vul(self, vul: Vulnerabilities, vul_type: VulnerabilityTypes, h_id, s_id, url_data): | |
115 | def create_vul(self, vul: Vulnerabilities, vul_type: VulnerabilityTypes, h_id, s_id, url_data, cwe): | |
116 | cvss3 = { | |
117 | 'vector_string': vul_type.cvss3_vector | |
118 | } | |
119 | cvss2 = { | |
120 | 'vector_string': vul_type.cvss2_vector | |
121 | } | |
111 | 122 | self.createAndAddVulnWebToService( |
112 | 123 | h_id, |
113 | 124 | s_id, |
117 | 128 | severity=vul_type.severity, |
118 | 129 | resolution=vul_type.recommendation, |
119 | 130 | request=vul.info.request, |
120 | response=vul.response) | |
131 | response=vul.response, | |
132 | cwe=cwe, | |
133 | cvss3=cvss3, | |
134 | cvss2=cvss2 | |
135 | ) | |
121 | 136 | |
122 | 137 | @staticmethod |
123 | 138 | def get_domain(scan: Scan): |
130 | 145 | return url_data |
131 | 146 | |
132 | 147 | |
133 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
134 | return AcunetixJsonPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
148 | def createPlugin(*args, **kwargs): | |
149 | return AcunetixJsonPlugin(*args, **kwargs) |
136 | 136 | return final |
137 | 137 | |
138 | 138 | |
139 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
140 | return AmapPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
139 | def createPlugin(*args, **kwargs): | |
140 | return AmapPlugin(*args, **kwargs) |
123 | 123 | else item.find("variant-group/item/test-http-traffic").text |
124 | 124 | response = "" if item.find("variant-group/item/issue-information/testResponseChunk") is None \ |
125 | 125 | else item.find("variant-group/item/issue-information/testResponseChunk").text |
126 | cvss = None if item.find("cvss-score") is None else f"CVSS: {item.find('cvss-score').text}" | |
127 | cvss_base_vector = None if item.find('cvss-vector/base-vector') is None \ | |
128 | else f"CVSS-base-vector: {item.find('cvss-vector/base-vector').text}" | |
126 | cvss2 = item.find('cvss-score').text if item.find("cvss-score") is not None else None | |
127 | cvss2_base_vector = item.find('cvss-vector/base-vector').text if item.find('cvss-vector/base-vector') \ | |
128 | is not None else None | |
129 | 129 | cvss_temporal_vector = None if item.find('cvss-vector/temporal-vector') is None \ |
130 | 130 | else f"CVSS-temporal-vector: {item.find('cvss-vector/temporal-vector').text}" |
131 | 131 | cvss_environmental_vector = None if item.find('cvss-vector/environmental-vector') is None \ |
157 | 157 | "response": response, |
158 | 158 | "website": entity['website'], |
159 | 159 | "path": entity['path'], |
160 | "cve": [] | |
160 | "cve": [], | |
161 | "cwe": [], | |
162 | "cvss2": {} | |
161 | 163 | } |
162 | 164 | if cve: |
163 | 165 | issue_data["cve"].append(cve) |
165 | 167 | if cve_url: |
166 | 168 | issue_data["ref"].append(cve_url) |
167 | 169 | if cwe: |
168 | issue_data["ref"].append(f"CWE: {cwe}") | |
169 | if cvss: | |
170 | issue_data["ref"].append(cvss) | |
171 | if cvss_base_vector: | |
172 | issue_data["ref"].append(cvss_base_vector) | |
170 | issue_data["cwe"].append(f"CWE-{cwe}") | |
171 | if cvss2_base_vector: | |
172 | issue_data["cvss2"]["vector_string"] = cvss2_base_vector | |
173 | 173 | if cvss_temporal_vector: |
174 | 174 | issue_data["ref"].append(cvss_temporal_vector) |
175 | 175 | if cvss_environmental_vector: |
190 | 190 | if fix_id: |
191 | 191 | fix = self.fixes[fix_id] |
192 | 192 | resolution = f"{resolution}\nLibrary: {fix['library']}\nLocation: {fix['location']}" |
193 | cvss = None if item.find("cvss-score") is None else f"CVSS: {item.find('cvss-score').text}" | |
194 | cvss_base_vector = None if item.find('cvss-vector/base-vector') is None \ | |
195 | else f"CVSS-base-vector: {item.find('cvss-vector/base-vector').text}" | |
193 | cvss2 = item.find('cvss-score').text if item.find("cvss-score") else None | |
194 | cvss2_base_vector = None if item.find('cvss-vector/base-vector') is None \ | |
195 | else item.find('cvss-vector/base-vector').text | |
196 | 196 | cvss_temporal_vector = None if item.find('cvss-vector/temporal-vector') is None \ |
197 | 197 | else f"CVSS-temporal-vector: {item.find('cvss-vector/temporal-vector').text}" |
198 | 198 | cvss_environmental_vector = None if item.find('cvss-vector/environmental-vector') is None \ |
214 | 214 | "desc": description, |
215 | 215 | "ref": [], |
216 | 216 | "resolution": resolution, |
217 | "cve": [] | |
217 | "cve": [], | |
218 | "cwe": [], | |
219 | "cvss2": {} | |
218 | 220 | } |
219 | 221 | |
220 | 222 | if cve_url: |
221 | 223 | issue_data["ref"].append(cve_url) |
222 | 224 | if cwe: |
223 | issue_data["ref"].append(f"CWE: {cwe}") | |
224 | if cvss: | |
225 | issue_data["ref"].append(cvss) | |
226 | if cvss_base_vector: | |
227 | issue_data["ref"].append(cvss_base_vector) | |
225 | issue_data["cwe"].append(f"CWE-{cwe}") | |
226 | if cvss2_base_vector: | |
227 | issue_data["cvss2"]['vector_string'] = cvss2_base_vector | |
228 | 228 | if cvss_temporal_vector: |
229 | 229 | issue_data["ref"].append(cvss_temporal_vector) |
230 | 230 | if cvss_environmental_vector: |
279 | 279 | self.createAndAddVulnToHost(host_id=host_id, **issue) |
280 | 280 | |
281 | 281 | |
282 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
283 | return AppScanPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
282 | def createPlugin(*args, **kwargs): | |
283 | return AppScanPlugin(*args, **kwargs) |
5 | 5 | """ |
6 | 6 | |
7 | 7 | from faraday_plugins.plugins.plugin import PluginCSVFormat |
8 | from urllib.parse import urlparse | |
9 | 8 | from itertools import islice |
10 | 9 | import csv |
11 | import sys | |
12 | import dateutil | |
10 | from dateutil.parser import parse | |
13 | 11 | |
14 | 12 | __author__ = "Erodriguez" |
15 | 13 | __copyright__ = "Copyright (c) 2019, Infobyte LLC" |
50 | 48 | #Skip Fix Group |
51 | 49 | if row["Issue Id"] == "Fix Group Attributes:": |
52 | 50 | break |
53 | path = row['Location'] | |
54 | if not path: | |
55 | continue | |
51 | path = row['Source File'] | |
52 | if path == "": | |
53 | path = row['Location'] | |
56 | 54 | try: |
57 | run_date = dateutil.parser.parse(row['Date Created']) | |
55 | run_date = parse(row['Date Created']) | |
58 | 56 | except: |
59 | 57 | run_date = None |
60 | 58 | name = row["Issue Type Name"] |
63 | 61 | references.append(f"CWE-{row['Cwe']}") |
64 | 62 | if row["Cve"]: |
65 | 63 | references.append(row["Cve"]) |
64 | ||
66 | 65 | data = [] |
67 | 66 | if row['Security Risk']: |
68 | 67 | data.append(f"Security Risk: {row['Security Risk']}") |
69 | 68 | desc = [row['Description']] |
69 | if row['Cve']: | |
70 | desc.append(f"Cve: {row['Cve']}") | |
70 | 71 | if row['Line']: |
71 | 72 | desc.append(f"Line: {row['Line']}") |
72 | 73 | if row['Cause']: |
73 | 74 | desc.append(f"Cause: {row['Cause']}") |
75 | if row['Remediation']: | |
76 | desc.append(f"Resolution: {row['Resolution']}") | |
74 | 77 | if row['Threat Class']: |
75 | 78 | desc.append(f"Threat Class: {row['Threat Class']}") |
76 | 79 | if row['Security Risk']: |
77 | 80 | desc.append(f"Security Risk: {row['Security Risk']}") |
78 | 81 | if row['Calling Method']: |
79 | 82 | desc.append(f"Calling Method: {row['Calling Method']}") |
83 | if row['Location']: | |
84 | desc.append(f"Vulnerability Line: {row['Location']}") | |
85 | ||
80 | 86 | h_id = self.createAndAddHost(name=path) |
81 | 87 | self.createAndAddVulnToHost( |
82 | 88 | h_id, |
84 | 90 | desc=" \n".join(desc), |
85 | 91 | resolution=row['Remediation'], |
86 | 92 | external_id=row['Issue Id'], |
93 | cve=row['Cve'], | |
87 | 94 | run_date=run_date, |
88 | 95 | severity=row["Severity"], |
89 | 96 | ref=references, |
90 | 97 | data=" \n".join(data) |
91 | 98 | ) |
92 | 99 | |
93 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
94 | return Appscan_CSV_Plugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
100 | def createPlugin(*args, **kargs): | |
101 | return Appscan_CSV_Plugin(*args, **kargs) |
69 | 69 | data_info = [] |
70 | 70 | |
71 | 71 | for vulns in parser.vuln_list: |
72 | ||
72 | 73 | vuln_name = vulns.findtext('VulnType') |
73 | 74 | vuln_desc = vulns.findtext('Description') |
74 | 75 | vuln_ref = vulns.findtext('VulnUrl') |
77 | 78 | vuln_external_id = vulns.findtext('DbId') |
78 | 79 | vuln_run_date = vulns.findtext('ScanDate') |
79 | 80 | data_info.append(vulns.findtext('AttackClass')) |
80 | data_info.append(vulns.findtext('CweId')) | |
81 | cwe = ["CWE-" + vulns.findtext('CweId')] if vulns.findtext('CweId') else [] | |
81 | 82 | data_info.append(vulns.findtext('CAPEC')) |
82 | 83 | data_info.append(vulns.findtext('DISSA_ASC')) |
83 | 84 | data_info.append(vulns.findtext('OWASP2007')) |
97 | 98 | else: |
98 | 99 | severity = 10 |
99 | 100 | |
100 | str_data = f'AttackClass: {data_info[0]}, CweId: {data_info[1]}, CAPEC: {data_info[2]}, ' \ | |
101 | f'DISSA_ASC: {data_info[3]}, OWASP2007: {data_info[4]}, OWASP2010: {data_info[5]}, ' \ | |
102 | f'OWASP2013: {data_info[6]}, OVAL: {data_info[7]}, WASC: {data_info[8]}' | |
101 | str_data = f'AttackClass: {data_info[0]}, CAPEC: {data_info[1]}, ' \ | |
102 | f'DISSA_ASC: {data_info[2]}, OWASP2007: {data_info[3]}, OWASP2010: {data_info[4]}, ' \ | |
103 | f'OWASP2013: {data_info[5]}, OVAL: {data_info[6]}, WASC: {data_info[7]}' | |
103 | 104 | |
104 | 105 | if vuln_run_date is None: |
105 | 106 | vuln_run_date = None |
108 | 109 | |
109 | 110 | self.createAndAddVulnToHost(host_id=host_id, name=vuln_name, desc=vuln_desc, ref=[vuln_ref], |
110 | 111 | severity=severity, resolution=vuln_resolution, run_date=vuln_run_date, |
111 | external_id=vuln_external_id, data=str_data) | |
112 | external_id=vuln_external_id, data=str_data, cwe=cwe) | |
112 | 113 | |
113 | 114 | |
114 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
115 | return AppSpiderPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
115 | def createPlugin(*args, **kwargs): | |
116 | return AppSpiderPlugin(*args, **kwargs) |
56 | 56 | return System(system_tree, True) |
57 | 57 | |
58 | 58 | |
59 | class Issue(): | |
59 | class Issue: | |
60 | 60 | |
61 | 61 | def __init__(self, issue_node): |
62 | 62 | self.node = issue_node |
197 | 197 | return 'None' |
198 | 198 | |
199 | 199 | |
200 | class System(): | |
200 | class System: | |
201 | 201 | |
202 | 202 | def __init__(self, node, tag_exists): |
203 | 203 | self.node = node |
275 | 275 | return result |
276 | 276 | |
277 | 277 | |
278 | class Plugins(): | |
278 | class Plugins: | |
279 | 279 | """ |
280 | 280 | Support: |
281 | 281 | WAF (Web Application Firewall) Detector (waf_detector) |
442 | 442 | |
443 | 443 | references = issue.references |
444 | 444 | if issue.cwe != 'None': |
445 | references.append('CWE-' + str(issue.cwe)) | |
446 | ||
445 | cwe = ['CWE-' + str(issue.cwe)] | |
447 | 446 | if resol == 'None': |
448 | 447 | resol = '' |
449 | 448 | |
462 | 461 | pname=issue.var, |
463 | 462 | params=issue.parameters, |
464 | 463 | request=issue.request, |
465 | response=issue.response) | |
464 | response=issue.response, | |
465 | cwe=cwe | |
466 | ) | |
466 | 467 | |
467 | 468 | return |
468 | 469 | |
515 | 516 | return self.hostname |
516 | 517 | |
517 | 518 | |
518 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
519 | return ArachniPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
519 | def createPlugin(*args, **kwargs): | |
520 | return ArachniPlugin(*args, **kwargs) |
59 | 59 | |
60 | 60 | |
61 | 61 | |
62 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
63 | return CmdArpScanPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
62 | def createPlugin(*args, **kwargs): | |
63 | return CmdArpScanPlugin(*args, **kwargs) |
67 | 67 | return vulns |
68 | 68 | |
69 | 69 | |
70 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
71 | return BanditPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
70 | def createPlugin(*args, **kwargs): | |
71 | return BanditPlugin(*args, **kwargs) |
48 | 48 | output being sent is valid. |
49 | 49 | """ |
50 | 50 | try: |
51 | f = urlopen(self.getSetting( | |
52 | "Host") + "/api/hooks?token=" + self.getSetting("Authkey")) | |
51 | f = urlopen(self.getSetting("Host") + "/api/hooks?token=" + self.getSetting("Authkey")) | |
53 | 52 | data = json.loads(f.read()) |
54 | except: | |
53 | except Exception: | |
55 | 54 | self.logger.info("[BeEF] - Connection with api") |
56 | 55 | return |
57 | 56 | |
95 | 94 | |
96 | 95 | |
97 | 96 | |
98 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
99 | return BeefPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
97 | def createPlugin(*args, **kwargs): | |
98 | return BeefPlugin(*args, **kwargs) |
55 | 55 | |
56 | 56 | |
57 | 57 | |
58 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
59 | return brutexss(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
58 | def createPlugin(*args, **kwargs): | |
59 | return brutexss(*args, **kwargs) |
12 | 12 | from bs4 import BeautifulSoup, Comment |
13 | 13 | |
14 | 14 | from faraday_plugins.plugins.plugin import PluginXMLFormat |
15 | from faraday_plugins.plugins.plugins_utils import CVE_regex | |
15 | from faraday_plugins.plugins.plugins_utils import CVE_regex, CWE_regex | |
16 | 16 | |
17 | 17 | __author__ = "Francisco Amato" |
18 | 18 | __copyright__ = "Copyright (c) 2013, Infobyte LLC" |
221 | 221 | ref = [] |
222 | 222 | if item.references: |
223 | 223 | ref += self.get_url(item.references) |
224 | cwe = [] | |
224 | 225 | if item.vulnClass: |
225 | ref += self.get_ref(item.vulnClass) | |
226 | ||
226 | for cwe_ref in self.get_ref(item.vulnClass): | |
227 | if CWE_regex.search(cwe_ref): | |
228 | cwe.append(CWE_regex.search(cwe_ref).group()) | |
227 | 229 | resolution = self.removeHtml(item.remediation) if item.remediation else "" |
228 | 230 | |
229 | 231 | self.createAndAddVulnWebToService( |
241 | 243 | ref=ref, |
242 | 244 | params=item.location, |
243 | 245 | external_id=item.external_id, |
244 | cve=item.cve | |
246 | cve=item.cve, | |
247 | cwe=cwe | |
245 | 248 | ) |
246 | 249 | |
247 | 250 | del parser |
294 | 297 | ref += [a['href'].strip()] |
295 | 298 | return ref |
296 | 299 | |
297 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
298 | return BurpPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
300 | ||
301 | def createPlugin(*args, **kwargs): | |
302 | return BurpPlugin(*args, **kwargs) |
111 | 111 | vuln_name = vulns.query_attrib['name'] |
112 | 112 | vuln_severity = vulns.query_attrib['Severity'] |
113 | 113 | vuln_external_id = vulns.query_attrib['id'] |
114 | refs.append(f'CWE-{vulns.query_attrib["cweId"]}') | |
114 | cwe = [f'CWE-{vulns.query_attrib["cweId"]}'] | |
115 | 115 | data = '' |
116 | 116 | for files_data in vulns.path_node: |
117 | 117 | for file_data in files_data: |
124 | 124 | refs.append(v_result['FileName']) |
125 | 125 | |
126 | 126 | self.createAndAddVulnToHost(host_id, vuln_name, severity=vuln_severity, |
127 | resolution=data, external_id=vuln_external_id) | |
127 | resolution=data, external_id=vuln_external_id, cwe=cwe) | |
128 | 128 | |
129 | 129 | self.createAndAddVulnWebToService(host_id, service_to_interface, vuln_name, |
130 | 130 | desc=vuln_desc, severity=vuln_severity, |
131 | resolution=data, ref=refs) | |
131 | resolution=data, ref=refs, cwe=cwe) | |
132 | 132 | |
133 | 133 | |
134 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
135 | return CheckmarxPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
134 | def createPlugin(*args, **kwargs): | |
135 | return CheckmarxPlugin(*args, **kwargs) |
8 | 8 | from urllib.parse import urlparse |
9 | 9 | import csv |
10 | 10 | import io |
11 | import dateutil | |
11 | from dateutil.parser import parse | |
12 | ||
12 | 13 | |
13 | 14 | |
14 | 15 | __author__ = "Blas" |
73 | 74 | scheme = url_data.scheme |
74 | 75 | port = url_data.port |
75 | 76 | try: |
76 | run_date = dateutil.parser.parse(row['CreatedAt']) | |
77 | run_date = parse(row['CreatedAt']) | |
77 | 78 | except: |
78 | 79 | run_date = None |
79 | 80 | if url_data.port is None: |
100 | 101 | data=row['StepsToReproduce'], external_id=row['Tag'], run_date=run_date) |
101 | 102 | |
102 | 103 | |
103 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
104 | return CobaltPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
104 | def createPlugin(*args, **kwargs): | |
105 | return CobaltPlugin(*args, **kwargs) |
139 | 139 | return True |
140 | 140 | |
141 | 141 | |
142 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
143 | return DigPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
142 | def createPlugin(*args, **kwargs): | |
143 | return DigPlugin(*args, **kwargs) |
40 | 40 | def getIP(self, host): |
41 | 41 | try: |
42 | 42 | ip = self.resolve_hostname(host) |
43 | except Exception: | |
43 | except Exception: # nosec | |
44 | 44 | pass |
45 | 45 | |
46 | 46 | return ip |
114 | 114 | return f"{command_string}{extra_arg}" |
115 | 115 | |
116 | 116 | |
117 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
118 | return dirbPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
117 | def createPlugin(*args, **kwargs): | |
118 | return dirbPlugin(*args, **kwargs) |
130 | 130 | return f'{command_string} --json-report {self._output_file_path}' |
131 | 131 | |
132 | 132 | |
133 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
134 | return DirsearchPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
133 | def createPlugin(*args, **kwargs): | |
134 | return DirsearchPlugin(*args, **kwargs) |
164 | 164 | return re.sub(arg_match.group(1), r"-o %s" % self._output_file_path, command_string) |
165 | 165 | |
166 | 166 | |
167 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
168 | return DnsenumPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
167 | def createPlugin(*args, **kwargs): | |
168 | return DnsenumPlugin(*args, **kwargs) |
136 | 136 | command_string) |
137 | 137 | |
138 | 138 | |
139 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
140 | return DnsmapPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
139 | def createPlugin(*args, **kwargs): | |
140 | return DnsmapPlugin(*args, **kwargs) |
211 | 211 | command_string) |
212 | 212 | |
213 | 213 | |
214 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
215 | return DnsreconPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
214 | def createPlugin(*args, **kwargs): | |
215 | return DnsreconPlugin(*args, **kwargs) |
108 | 108 | return True |
109 | 109 | |
110 | 110 | |
111 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
112 | return DnswalkPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
111 | def createPlugin(*args, **kwargs): | |
112 | return DnswalkPlugin(*args, **kwargs) |
363 | 363 | ) |
364 | 364 | |
365 | 365 | |
366 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
367 | return FaradayCSVPlugin(ignore_info=ignore_info) | |
366 | def createPlugin(*args, **kwargs): | |
367 | return FaradayCSVPlugin(*args, **kwargs) |
117 | 117 | try: |
118 | 118 | item['ip'] = self.resolve_hostname(item['ip']) |
119 | 119 | except: |
120 | pass | |
120 | pass # nosec | |
121 | 121 | return item |
122 | 122 | |
123 | 123 | def resolveNS(self, item, items): |
171 | 171 | ref=["CVE-1999-0532"]) |
172 | 172 | |
173 | 173 | |
174 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
175 | return FiercePlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
174 | def createPlugin(*args, **kwargs): | |
175 | return FiercePlugin(*args, **kwargs) |
390 | 390 | return text |
391 | 391 | |
392 | 392 | |
393 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
394 | return FortifyPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
393 | def createPlugin(*args, **kwargs): | |
394 | return FortifyPlugin(*args, **kwargs) |
0 | """ | |
1 | Faraday Penetration Test IDE | |
2 | Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) | |
3 | See the file 'doc/LICENSE' for the license information | |
4 | ||
5 | """ | |
6 |
0 | #!/usr/bin/python | |
1 | """ | |
2 | Copyright (C) 2016 xtr4nge [_AT_] gmail.com | |
3 | ||
4 | This program is free software: you can redistribute it and/or modify | |
5 | it under the terms of the GNU General Public License as published by | |
6 | the Free Software Foundation, either version 3 of the License, or | |
7 | (at your option) any later version. | |
8 | ||
9 | This program is distributed in the hope that it will be useful, | |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | GNU General Public License for more details. | |
13 | ||
14 | You should have received a copy of the GNU General Public License | |
15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | """ | |
17 | ||
18 | import sys | |
19 | import getopt | |
20 | import json | |
21 | import requests | |
22 | ||
23 | requests.packages.urllib3.disable_warnings() # DISABLE SSL CHECK WARNINGS | |
24 | ||
25 | gVersion = "1.0" | |
26 | server = "http://127.0.0.1:8000" | |
27 | token = "e5dab9a69988dd65e578041416773149ea57a054" | |
28 | ||
29 | ||
30 | def usage(): | |
31 | print("\nFruityWiFi API " + gVersion + " by @xtr4nge") | |
32 | ||
33 | print("Usage: ./client <options>\n") | |
34 | print("Options:") | |
35 | print("-x <command>, --execute=<commnd> exec the command passed as parameter.") | |
36 | print("-t <token>, --token=<token> authentication token.") | |
37 | print("-s <server>, --server=<server> FruityWiFi server [http{s}://ip:port].") | |
38 | print("-h Print this help message.") | |
39 | print("") | |
40 | print("FruityWiFi: http://www.fruitywifi.com") | |
41 | print("") | |
42 | ||
43 | ||
44 | def parseOptions(argv): | |
45 | ||
46 | v_execute = "/log/dhcp" | |
47 | v_token = token | |
48 | v_server = server | |
49 | ||
50 | try: | |
51 | opts, args = getopt.getopt(argv, "hx:t:s:", | |
52 | ["help","execute=","token=","server="]) | |
53 | ||
54 | for opt, arg in opts: | |
55 | if opt in ("-h", "--help"): | |
56 | usage() | |
57 | sys.exit() | |
58 | elif opt in ("-x", "--execute"): | |
59 | v_execute = arg | |
60 | elif opt in ("-t", "--token"): | |
61 | v_token = arg | |
62 | elif opt in ("-s", "--server"): | |
63 | v_server = arg | |
64 | ||
65 | return (v_execute, v_token, v_server) | |
66 | ||
67 | except getopt.GetoptError: | |
68 | usage() | |
69 | sys.exit(2) | |
70 | ||
71 | ||
72 | (execute, token, server) = parseOptions(sys.argv[1:]) | |
73 | ||
74 | ||
75 | class Webclient: | |
76 | ||
77 | def __init__(self, server, token): | |
78 | ||
79 | self.global_webserver = server | |
80 | self.path = "/modules/api/includes/ws_action.php" | |
81 | self.s = requests.session() | |
82 | self.token = token | |
83 | ||
84 | def login(self): | |
85 | ||
86 | payload = { | |
87 | 'action': 'login', | |
88 | 'token': self.token | |
89 | } | |
90 | ||
91 | self.s = requests.session() | |
92 | self.s.get(self.global_webserver, verify=False) # DISABLE SSL CHECK | |
93 | self.s.post(self.global_webserver + '/login.php', data=payload) | |
94 | ||
95 | def loginCheck(self): | |
96 | ||
97 | response = self.s.get(self.global_webserver + '/login_check.php') | |
98 | ||
99 | if response.text != "": | |
100 | self.login() | |
101 | ||
102 | if response.text != "": | |
103 | print(json.dumps("[FruityWiFi]: Ah, Ah, Ah! You didn't say the magic word! (check API token and server)")) | |
104 | sys.exit() | |
105 | ||
106 | return True | |
107 | ||
108 | def submitPost(self, data): | |
109 | response = self.s.post(self.global_webserver + data) | |
110 | return response.json | |
111 | ||
112 | def submitGet(self, data): | |
113 | response = self.s.get(self.global_webserver + self.path + "?" + data) | |
114 | ||
115 | return response | |
116 | ||
117 | try: | |
118 | w = Webclient(server, token) | |
119 | w.login() | |
120 | w.loginCheck() | |
121 | except Exception as e: | |
122 | print(json.dumps("[FruityWiFi]: There is something wrong (%s)" % e)) | |
123 | sys.exit(1) | |
124 | ||
125 | _exec = "/log/dhcp" | |
126 | _exec = execute | |
127 | if _exec != "": | |
128 | try: | |
129 | out = w.submitGet("api=" + str(_exec)) | |
130 | json_output = out.json() | |
131 | except Exception as e: | |
132 | print(json.dumps("[FruityWiFi]: There is something wrong (%s)" % e)) | |
133 | sys.exit(1) | |
134 | ||
135 | output = [] | |
136 | if _exec == "/log/dhcp": | |
137 | for item in json_output: | |
138 | if item.strip() != "": | |
139 | output = [item.split(" ")] | |
140 | else: | |
141 | output = json_output | |
142 | ||
143 | if len(output) > 0: | |
144 | print(json.dumps(output)) | |
145 | else: | |
146 | print(json.dumps("No clients connected")) | |
147 | ||
148 | ||
149 |
0 | """ | |
1 | Faraday Penetration Test IDE | |
2 | Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) | |
3 | See the file 'doc/LICENSE' for the license information | |
4 | ||
5 | """ | |
6 | from faraday_plugins.plugins.plugin import PluginBase | |
7 | import re | |
8 | import json | |
9 | import traceback | |
10 | import os | |
11 | ||
12 | __author__ = "xtr4nge" | |
13 | __copyright__ = "Copyright (c) 2016, FruityWiFi" | |
14 | __credits__ = ["xtr4nge"] | |
15 | __license__ = "" | |
16 | __version__ = "1.0.0" | |
17 | __maintainer__ = "xtr4nge" | |
18 | __email__ = "@xtr4nge" | |
19 | __status__ = "Development" | |
20 | ||
21 | class FruityWiFiPlugin(PluginBase): | |
22 | """ | |
23 | This plugin handles FruityWiFi clients. | |
24 | """ | |
25 | ||
26 | def __init__(self, *arg, **kwargs): | |
27 | super().__init__(*arg, **kwargs) | |
28 | self.id = "fruitywifi" | |
29 | self.name = "FruityWiFi" | |
30 | self.plugin_version = "0.0.1" | |
31 | self.version = "2.4" | |
32 | self.description = "http://www.fruitywifi.com" | |
33 | self.options = None | |
34 | self._current_output = None | |
35 | self.target = None | |
36 | ||
37 | self._command_regex = re.compile(r'^(fruitywifi)\s+.*?') | |
38 | ||
39 | self.addSetting("Token", str, "e5dab9a69988dd65e578041416773149ea57a054") | |
40 | self.addSetting("Server", str, "http://127.0.0.1:8000") | |
41 | self.addSetting("Severity", str, "high") | |
42 | ||
43 | def getSeverity(self, severity): | |
44 | if severity.lower() == "critical" or severity == "4": | |
45 | return 4 | |
46 | elif severity.lower() == "high" or severity == "3": | |
47 | return 3 | |
48 | elif severity.lower() == "med" or severity == "2": | |
49 | return 2 | |
50 | elif severity.lower() == "low" or severity == "1": | |
51 | return 1 | |
52 | elif severity.lower() == "info" or severity == "0": | |
53 | return 0 | |
54 | else: | |
55 | return 5 | |
56 | ||
57 | def createHostInterfaceVuln(self, ip_address, macaddress, hostname, desc, vuln_name, severity): | |
58 | h_id = self.createAndAddHost(ip_address, hostnames=[hostname]) | |
59 | ||
60 | self.createAndAddVulnToHost( | |
61 | h_id, | |
62 | vuln_name, | |
63 | desc=desc, | |
64 | ref=["http://www.fruitywifi.com/"], | |
65 | severity=severity | |
66 | ) | |
67 | ||
68 | def parseOutputString(self, output): | |
69 | ||
70 | try: | |
71 | output = json.loads(output) | |
72 | ||
73 | if len(output) > 0: | |
74 | ||
75 | if len(output[0]) == 3: | |
76 | ||
77 | severity = self.getSeverity(self.getSetting("Severity")) | |
78 | ||
79 | for item in output: | |
80 | ip_address = item[0] | |
81 | macaddress = item[1] | |
82 | hostname = item[2] | |
83 | vuln_name = "FruityWiFi" | |
84 | severity = severity | |
85 | ||
86 | desc = "Client ip: " + ip_address + \ | |
87 | " has been connected to FruityWiFi\n" | |
88 | desc += "More information:" | |
89 | desc += "\nname: " + hostname | |
90 | ||
91 | self.createHostInterfaceVuln(ip_address, macaddress, hostname, desc, vuln_name, severity) | |
92 | ||
93 | elif len(output[0]) == 5: | |
94 | for item in output: | |
95 | ip_address = item[0] | |
96 | macaddress = item[1] | |
97 | hostname = item[2] | |
98 | vuln_name = item[3] | |
99 | severity = item[4] | |
100 | ||
101 | desc = "Client ip: " + ip_address + \ | |
102 | " has been connected to FruityWiFi\n" | |
103 | desc += "More information:" | |
104 | desc += "\nname: " + hostname | |
105 | ||
106 | self.createHostInterfaceVuln(ip_address, macaddress, hostname, desc, vuln_name, severity) | |
107 | ||
108 | except: | |
109 | traceback.print_exc() | |
110 | ||
111 | return True | |
112 | ||
113 | def _isIPV4(self, ip): | |
114 | if len(ip.split(".")) == 4: | |
115 | return True | |
116 | else: | |
117 | return False | |
118 | ||
119 | def processCommandString(self, username, current_path, command_string): | |
120 | """ | |
121 | """ | |
122 | super().processCommandString(username, current_path, command_string) | |
123 | params = f"-t {self.getSetting('Token')} -s {self.getSetting('Server')}", | |
124 | ||
125 | return "python " + os.path.dirname(__file__) + "/fruitywifi.py " + params | |
126 | ||
127 | ||
128 | ||
129 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
130 | return FruityWiFiPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
70 | 70 | self._port = count_args[c - 1] |
71 | 71 | |
72 | 72 | |
73 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
74 | return CmdFtpPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
73 | def createPlugin(*args, **kwargs): | |
74 | return CmdFtpPlugin(*args, **kwargs) |
128 | 128 | self.parseOutputString(command_output) |
129 | 129 | |
130 | 130 | |
131 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
132 | return GoohostPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
131 | def createPlugin(*args, **kwargs): | |
132 | return GoohostPlugin(*args, **kwargs) |
49 | 49 | severity = match.get('vulnerability').get('severity').lower().replace("negligible", "info") |
50 | 50 | for url in match.get('vulnerability').get('urls'): |
51 | 51 | references.append(url) |
52 | if not match['artifact']['metadata']: | |
52 | if not match['artifact'].get('metadata'): | |
53 | 53 | data = f"Artifact: {match['artifact']['name']}" \ |
54 | 54 | f"Version: {match['artifact']['version']} " \ |
55 | 55 | f"Type: {match['artifact']['type']}" |
76 | 76 | return command_string |
77 | 77 | |
78 | 78 | |
79 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
80 | return GrypePlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
79 | def createPlugin(*args, **kwargs): | |
80 | return GrypePlugin(*args, **kwargs) |
67 | 67 | host_id, service, protocol="tcp", ports=port, status="open") |
68 | 68 | |
69 | 69 | |
70 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
71 | return hping3(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
70 | def createPlugin(*args, **kwargs): | |
71 | return hping3(*args, **kwargs) |
128 | 128 | |
129 | 129 | |
130 | 130 | |
131 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
132 | return HydraPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
131 | def createPlugin(*args, **kwargs): | |
132 | return HydraPlugin(*args, **kwargs) |
280 | 280 | del parser |
281 | 281 | |
282 | 282 | |
283 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
284 | return ImpactPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
283 | def createPlugin(*args, **kwargs): | |
284 | return ImpactPlugin(*args, **kwargs) |
102 | 102 | ref=vulnerability.get("ref")) |
103 | 103 | |
104 | 104 | |
105 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
106 | return Ip360Plugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
105 | def createPlugin(*args, **kwargs): | |
106 | return Ip360Plugin(*args, **kwargs) |
130 | 130 | del parser |
131 | 131 | |
132 | 132 | |
133 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
134 | return JunitPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
133 | def createPlugin(*args, **kwargs): | |
134 | return JunitPlugin(*args, **kwargs) |
37 | 37 | |
38 | 38 | def ipv4(self): |
39 | 39 | ipv4s = re.findall(r'^network_ipv4_address\[\]=(.+)$', |
40 | self.rawcontents, re.MULTILINE) | |
40 | self.rawcontents, re.MULTILINE) | |
41 | 41 | ipv4addrs = self.ipv4_filter(ipv4s) |
42 | return(ipv4addrs) | |
42 | return ipv4addrs | |
43 | 43 | |
44 | 44 | def ipv6(self): |
45 | 45 | ipv6s = re.findall(r'^network_ipv6_address\[\]=(.+)$', |
46 | self.rawcontents, re.MULTILINE) | |
46 | self.rawcontents, re.MULTILINE) | |
47 | 47 | ipv6addrs = self.ipv6_filter(ipv6s) |
48 | return(ipv6addrs) | |
48 | return ipv6addrs | |
49 | 49 | |
50 | 50 | def ipv4_filter(self, ips): |
51 | 51 | ip_list = [] |
75 | 75 | |
76 | 76 | def listeningservices(self): |
77 | 77 | line = re.findall(r'^network_listen_port\[\]=(.+)$', |
78 | self.rawcontents, re.MULTILINE) | |
78 | self.rawcontents, re.MULTILINE) | |
79 | 79 | # To avoid local services, we will create the following list |
80 | 80 | local_services = ['*', 'localhost'] |
81 | 81 | |
90 | 90 | |
91 | 91 | def clean_services(self, combo, local_services): |
92 | 92 | add = False |
93 | #if "localhost" in combo: | |
94 | 93 | if combo.count("|") > 1: |
95 | 94 | # Service with url, protocol and perhaps name |
96 | 95 | items_service = combo.split('|') |
171 | 170 | def search_service(self, port): |
172 | 171 | srv = filter_services() |
173 | 172 | details_dict = { |
174 | 'name' : 'Unknown', | |
175 | 'protocol' : 'Unknown' | |
173 | 'name': 'Unknown', | |
174 | 'protocol': 'Unknown' | |
176 | 175 | } |
177 | 176 | for item in srv: |
178 | 177 | service_tuple = item[0].split('/') |
206 | 205 | for combo in m: |
207 | 206 | x = combo.split('|') |
208 | 207 | sugs[x[0]] = x[1] |
209 | return(sugs) | |
208 | return sugs | |
210 | 209 | |
211 | 210 | def parse_warnings(self): |
212 | 211 | warns = {} |
214 | 213 | for combo in m: |
215 | 214 | x = combo.split('|') |
216 | 215 | warns[x[0]] = x[1] |
217 | return(warns) | |
216 | return warns | |
218 | 217 | |
219 | 218 | |
220 | 219 | class LynisPlugin(PluginByExtension): |
258 | 257 | |
259 | 258 | for ipv4 in ipv4s: |
260 | 259 | h_id = self.createAndAddHost(name=ipv4, |
261 | os=lde.osfullname(), | |
262 | hostnames=[hostname]) | |
260 | os=lde.osfullname(), | |
261 | hostnames=[hostname]) | |
263 | 262 | |
264 | 263 | self.create_services(h_id, services, ipv4) |
265 | 264 | self.create_vulns_with_kernel(h_id, kernel_versions) |
268 | 267 | |
269 | 268 | for ipv6 in ipv6s: |
270 | 269 | h_id = self.createAndAddHost(name=ipv6, |
271 | os=lde.osfullname(), | |
272 | hostnames=[hostname]) | |
270 | os=lde.osfullname(), | |
271 | hostnames=[hostname]) | |
273 | 272 | |
274 | 273 | self.create_services(h_id, services, ipv6) |
275 | 274 | self.create_vulns_with_kernel(h_id, kernel_versions) |
279 | 278 | def create_services(self, host_id, parsed_services, ip_version): |
280 | 279 | for service_data in parsed_services[ip_version]: |
281 | 280 | self.createAndAddServiceToHost(host_id=host_id, |
282 | name=service_data['name'], | |
283 | protocol=service_data['protocol'], | |
284 | ports=[service_data['port']]) | |
281 | name=service_data['name'], | |
282 | protocol=service_data['protocol'], | |
283 | ports=[service_data['port']]) | |
285 | 284 | |
286 | 285 | if '0.0.0.0' in parsed_services: |
287 | 286 | for service_data in parsed_services['0.0.0.0']: |
288 | 287 | self.createAndAddServiceToHost(host_id=host_id, |
289 | name=service_data['name'], | |
290 | protocol=service_data['protocol'], | |
291 | ports=[service_data['port']]) | |
288 | name=service_data['name'], | |
289 | protocol=service_data['protocol'], | |
290 | ports=[service_data['port']]) | |
292 | 291 | |
293 | 292 | def create_vulns_with_kernel(self, host_id, kernel_versions): |
294 | 293 | for kernel, version in kernel_versions.items(): |
323 | 322 | self._parse_filename(file_path) |
324 | 323 | |
325 | 324 | |
326 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
327 | return LynisPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
325 | def createPlugin(*args, **kwargs): | |
326 | return LynisPlugin(*args, **kwargs) |
495 | 495 | description="DNS Server") |
496 | 496 | |
497 | 497 | |
498 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
499 | return MaltegoPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
498 | def createPlugin(*args, **kwargs): | |
499 | return MaltegoPlugin(*args, **kwargs) |
113 | 113 | i += 1 |
114 | 114 | |
115 | 115 | |
116 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
117 | return MbsaPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
116 | def createPlugin(*args, **kwargs): | |
117 | return MbsaPlugin(*args, **kwargs) |
132 | 132 | |
133 | 133 | |
134 | 134 | |
135 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
136 | return MedusaPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
135 | def createPlugin(*args, **kwargs): | |
136 | return MedusaPlugin(*args, **kwargs) |
275 | 275 | self.service_id = self.get_text_from_subnode('service-id') |
276 | 276 | self.name = self.get_text_from_subnode('name') |
277 | 277 | self.desc = self.get_text_from_subnode('info') |
278 | self.refs = [r.text for r in self.node.findall('refs/ref') if not r.text.startswith('CVE')] | |
279 | self.cve = [r.text for r in self.node.findall('refs/ref') if r.text.startswith('CVE')] | |
278 | self.refs = [] | |
279 | self.cve = [] | |
280 | self.cwe = [] | |
281 | for r in self.node.findall('refs/ref'): | |
282 | if r.text.startswith('CVE'): | |
283 | self.cve.append(r.text) | |
284 | elif r.text.startswith('CWE'): | |
285 | self.cwe.append(r.text) | |
286 | else: | |
287 | self.refs.append(r.text) | |
280 | 288 | self.exploited_date = self.get_text_from_subnode('exploited-at') |
281 | 289 | self.exploited = (self.exploited_date is not None) |
282 | 290 | self.isWeb = False |
362 | 370 | category=v.category) |
363 | 371 | else: |
364 | 372 | self.createAndAddVulnToService( |
365 | h_id, s_id, v.name, v.desc, ref=v.refs, cve=v.cve) | |
373 | h_id, s_id, v.name, v.desc, ref=v.refs, cve=v.cve, cwe=v.cwe) | |
366 | 374 | |
367 | 375 | del parser |
368 | 376 | |
374 | 382 | return False |
375 | 383 | |
376 | 384 | |
377 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
378 | return MetasploitPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
385 | def createPlugin(*args, **kwargs): | |
386 | return MetasploitPlugin(*args, **kwargs) |
66 | 66 | command_string += " -silent" |
67 | 67 | return command_string |
68 | 68 | |
69 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
70 | return NaabuPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
69 | def createPlugin(*args, **kwargs): | |
70 | return NaabuPlugin(*args, **kwargs) |
118 | 118 | password=service_vuln['passw']) |
119 | 119 | |
120 | 120 | |
121 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
122 | return NcrackPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
121 | def createPlugin(*args, **kwargs): | |
122 | return NcrackPlugin(*args, **kwargs) |
151 | 151 | return f"{command_string} --xml " |
152 | 152 | |
153 | 153 | |
154 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
155 | return CmdNdiffPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
154 | def createPlugin(*args, **kwargs): | |
155 | return CmdNdiffPlugin(*args, **kwargs) |
125 | 125 | |
126 | 126 | @property |
127 | 127 | def cvss3_base_score(self): |
128 | cvss_base_score = self.node.findtext("cvss3_base_score") | |
129 | if cvss_base_score: | |
130 | cvss_base_score = f"CVSS3:{cvss_base_score}" | |
131 | return cvss_base_score | |
128 | return self.node.findtext("cvss3_base_score") | |
132 | 129 | |
133 | 130 | @property |
134 | 131 | def cvss3_temporal_score(self): |
147 | 144 | return self.node.findtext("cvss3_vector") |
148 | 145 | |
149 | 146 | @property |
150 | def cvss_base_score(self): | |
151 | cvss_base_score = self.node.findtext("cvss_base_score") | |
152 | if cvss_base_score: | |
153 | cvss_base_score = f"CVSS:{cvss_base_score}" | |
154 | return cvss_base_score | |
147 | def cvss2_base_score(self): | |
148 | return self.node.findtext("cvss_base_score") | |
155 | 149 | |
156 | 150 | @property |
157 | 151 | def cvss_score_rationale(self): |
173 | 167 | def cvss_vector(self): |
174 | 168 | cvss_vector = self.node.findtext("cvss_vector") |
175 | 169 | if cvss_vector: |
176 | cvss_vector = f"CVSSVECTOR:{cvss_vector}" | |
170 | cvss_vector = cvss_vector.replace("CVSS2#", "") | |
177 | 171 | return cvss_vector |
178 | 172 | |
179 | 173 | @property |
283 | 277 | |
284 | 278 | @property |
285 | 279 | def cwe(self) -> list: |
286 | return [i.text for i in self.node.findall("cwe")] | |
280 | return ["CWE-"+i.text for i in self.node.findall("cwe")] | |
287 | 281 | |
288 | 282 | @property |
289 | 283 | def edb_id(self) -> list: |
398 | 392 | @property |
399 | 393 | def report_hosts(self) -> List[ReportHost]: |
400 | 394 | return [ReportHost(i) for i in self.node.findall('ReportHost')] |
401 |
6 | 6 | |
7 | 7 | import xml.etree.ElementTree as ET |
8 | 8 | |
9 | import dateutil | |
9 | from dateutil.parser import parse | |
10 | 10 | from faraday_plugins.plugins.plugin import PluginXMLFormat |
11 | 11 | |
12 | 12 | __author__ = "Blas" |
85 | 85 | |
86 | 86 | @staticmethod |
87 | 87 | def map_item(host_id, run_date, plugin_name, item: ReportItem) -> dict: |
88 | cvss_base_score = item.cvss_base_score | |
89 | 88 | data = item.plugin_output |
90 | 89 | data += f'{item.exploit_available}' |
91 | 90 | return { |
97 | 96 | "run_date": run_date, |
98 | 97 | "desc": item.description, |
99 | 98 | "resolution": item.solution, |
100 | "ref": [cvss_base_score] if cvss_base_score else [] | |
99 | "ref": [], | |
101 | 100 | } |
102 | 101 | |
103 | 102 | def map_policy_general(self, kwargs, item: ReportItem): |
145 | 144 | self.logger.error(str(e)) |
146 | 145 | return None |
147 | 146 | report_hosts = parser.report.report_hosts |
148 | ||
149 | 147 | if report_hosts: |
150 | 148 | for host in report_hosts: |
151 | 149 | run_date = host.host_properties.host_end |
152 | 150 | if run_date: |
153 | run_date = dateutil.parser.parse(run_date) | |
151 | run_date = parse(run_date) | |
154 | 152 | website = host.host_properties.host_fqdn |
155 | 153 | host_id = self.createAndAddHost(**self.map_properties(host)) |
156 | 154 | |
179 | 177 | |
180 | 178 | @staticmethod |
181 | 179 | def map_add_ref(kwargs, item: ReportItem): |
182 | ||
183 | if item.cvss_vector: | |
184 | kwargs["ref"].append(item.cvss_vector) | |
180 | kwargs["cvss2"] = {} | |
181 | kwargs["cvss3"] = {} | |
185 | 182 | if item.see_also: |
186 | 183 | kwargs["ref"].append(item.see_also) |
187 | 184 | if item.cpe: |
188 | 185 | kwargs["ref"].append(item.cpe) |
189 | if item.xref: | |
190 | kwargs["ref"].append(item.xref) | |
191 | 186 | if item.cve: |
192 | 187 | kwargs["cve"] = item.cve |
193 | if item.cvss3_base_score: | |
194 | kwargs["ref"].append(item.cvss3_base_score) | |
188 | if item.cwe: | |
189 | kwargs["cwe"] = item.cwe | |
195 | 190 | if item.cvss3_vector: |
196 | kwargs["ref"].append(item.cvss3_vector) | |
191 | kwargs["cvss3"]["vector_string"] = item.cvss3_vector | |
192 | if item.cvss_vector: | |
193 | kwargs["cvss2"]["vector_string"] = item.cvss_vector | |
197 | 194 | return kwargs |
198 | 195 | |
199 | 196 | |
200 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
201 | return NessusPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
197 | def createPlugin(*args, **kwargs): | |
198 | return NessusPlugin(*args, **kwargs) |
38 | 38 | |
39 | 39 | |
40 | 40 | |
41 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
42 | return NetdiscoverPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
41 | def createPlugin(*args, **kwargs): | |
42 | return NetdiscoverPlugin(*args, **kwargs) |
79 | 79 | def __init__(self, item_node): |
80 | 80 | self.node = item_node |
81 | 81 | self.url = self.get_text_from_subnode("url") |
82 | ||
83 | 82 | host = re.search( |
84 | 83 | r"(http|https|ftp)\://([a-zA-Z0-9\.\-]+(\:[a-zA-Z0-9\.&%\$\-]+)*@)*((25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]" |
85 | 84 | r"{2}|[1-9]{1}[0-9]{1}|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2" |
86 | 85 | r"[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]" |
87 | 86 | r"{1}|[0-9])|localhost|([a-zA-Z0-9\-]+\.)*[a-zA-Z0-9\-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|" |
88 | "pro|aero|coop|museum|[a-zA-Z]{2}))[\\:]*([0-9]+)*([/]*($|[a-zA-Z0-9\\.\\,\\?\'\\\\+&%\\$#\\=~_\\-]+)).*?$", | |
87 | "pro|aero|coop|museum|[a-zA-Z]{2}))[\\:]*([0-9]+)*([/]*($|[\\(\\)a-zA-Z0-9\\.\\,\\?\'\\\\+&%\\$#\\=~_\\-]+)).*?$", | |
89 | 88 | self.url) |
90 | ||
91 | 89 | self.protocol = host.group(1) |
92 | 90 | self.hostname = host.group(4) |
93 | 91 | self.port = 80 |
136 | 134 | self.pci = self.get_text_from_subnode("PCI") |
137 | 135 | self.pci2 = self.get_text_from_subnode("PCI2") |
138 | 136 | self.node = item_node.find("classification/CVSS") |
139 | self.cvss = self.get_text_from_subnode("vector") | |
140 | ||
137 | self.cvss_full_vector = self.get_text_from_subnode("vector") | |
138 | self.cvss_score = self.get_text_from_subnode("score[1]/value") if self.get_text_from_subnode("score[1]/value") else None | |
139 | self.cvss3 = {} | |
141 | 140 | self.ref = [] |
142 | 141 | if self.cwe: |
143 | self.ref.append("CWE-" + self.cwe) | |
142 | self.cwe = ["CWE-" + self.cwe] | |
144 | 143 | if self.owasp: |
145 | 144 | self.ref.append("OWASP-" + self.owasp) |
146 | 145 | if self.reference: |
147 | 146 | self.ref.extend(sorted(set(re.findall(r'https?://(?:[-\w.]|(?:%[\da-fA-F]{2}))+', self.reference)))) |
148 | if self.cvss: | |
149 | self.ref.append(self.cvss) | |
150 | ||
147 | if self.cvss_full_vector: | |
148 | self.cvss3["vector_string"] = self.cvss_full_vector | |
151 | 149 | self.data = "" |
152 | 150 | self.data += "\nKnowVulns: " + \ |
153 | 151 | "\n".join(self.kvulns) if self.kvulns else "" |
228 | 226 | self.createAndAddVulnWebToService(h_id, s_id, name, ref=i.ref, website=i.hostname, |
229 | 227 | severity=i.severity, desc=desc, path=i.url, method=i.method, |
230 | 228 | request=i.request, response=i.response, resolution=resolution, |
231 | pname=i.param, data=i.data, cve=i.cve) | |
229 | pname=i.param, data=i.data, cve=i.cve, cwe=i.cwe, cvss3=i.cvss3) | |
232 | 230 | |
233 | 231 | del parser |
234 | 232 | |
235 | 233 | |
236 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
237 | return NetsparkerPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
234 | def createPlugin(*args, **kwargs): | |
235 | return NetsparkerPlugin(*args, **kwargs) |
122 | 122 | |
123 | 123 | self.ref = [] |
124 | 124 | if self.cwe: |
125 | self.ref.append(f"CWE-{self.cwe}") | |
125 | self.cwe = [f"CWE-{self.cwe}"] | |
126 | 126 | if self.owasp: |
127 | 127 | self.ref.append(f"OWASP-{self.owasp}") |
128 | 128 | |
191 | 191 | v_id = self.createAndAddVulnWebToService(h_id, s_id, i.name, ref=i.ref, website=i.hostname, |
192 | 192 | severity=i.severity, desc=i.desc, path=i.url.path, method=i.method, |
193 | 193 | request=i.request, response=i.response, resolution=i.resolution, |
194 | pname=i.param) | |
194 | pname=i.param, cwe=i.cwe) | |
195 | 195 | del parser |
196 | 196 | |
197 | 197 | |
198 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
199 | return NetsparkerCloudPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
198 | def createPlugin(*args, **kwargs): | |
199 | return NetsparkerCloudPlugin(*args, **kwargs) |
132 | 132 | @returns vulns A dict of Vulnerability Definitions |
133 | 133 | """ |
134 | 134 | vulns = dict() |
135 | # CVSS V3 | |
136 | SEVERITY_MAPPING_DICT = {'0': 'info', '1': 'low', '2': 'low', '3': 'low', '4': 'med', '5': 'med', '6': 'med', | |
137 | '7': 'high', '8': 'high', '9': 'critical', '10': 'critical'} | |
138 | 135 | |
139 | 136 | for vulnsDef in tree.iter('VulnerabilityDefinitions'): |
140 | 137 | for vulnDef in vulnsDef.iter('vulnerability'): |
145 | 142 | 'name': vulnDef.get('title'), |
146 | 143 | 'refs': ["vector: " + vector, vid], |
147 | 144 | 'resolution': "", |
148 | 'severity': SEVERITY_MAPPING_DICT[vulnDef.get('severity')], | |
145 | 'severity': "", | |
149 | 146 | 'tags': list(), |
150 | 147 | 'is_web': vid.startswith('http-'), |
151 | 148 | 'risk': vulnDef.get('riskScore'), |
152 | 'CVE': [] | |
149 | 'CVE': [], | |
150 | 'cvss2': { | |
151 | "vector_string": vector.replace("(", "").replace(")", "") if vector else None | |
152 | } | |
153 | 153 | } |
154 | 154 | |
155 | 155 | for item in list(vulnDef): |
277 | 277 | v['refs'], |
278 | 278 | v['severity'], |
279 | 279 | v['resolution'], |
280 | cve=v.get('CVE') | |
280 | cve=v.get('CVE'), | |
281 | cvss2=v.get('cvss2') | |
281 | 282 | ) |
282 | 283 | |
283 | 284 | for s in item['services']: |
302 | 303 | v['severity'], |
303 | 304 | v['resolution'], |
304 | 305 | cve=v.get('CVE'), |
305 | path=v.get('path', '') | |
306 | path=v.get('path', ''), | |
307 | cvss2=v.get('cvss2') | |
306 | 308 | ) |
307 | 309 | else: |
308 | 310 | self.createAndAddVulnToService( |
313 | 315 | v['refs'], |
314 | 316 | v['severity'], |
315 | 317 | v['resolution'], |
316 | cve=v.get('CVE') | |
318 | cve=v.get('CVE'), | |
319 | cvss2=v.get('cvss2') | |
317 | 320 | ) |
318 | 321 | |
319 | 322 | del parser |
320 | 323 | |
321 | 324 | |
322 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
323 | return NexposeFullPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
325 | def createPlugin(*args, **kwargs): | |
326 | return NexposeFullPlugin(*args, **kwargs) |
62 | 62 | return True |
63 | 63 | |
64 | 64 | |
65 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
66 | return CmdNextNetin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
65 | def createPlugin(*args, **kwargs): | |
66 | return CmdNextNetin(*args, **kwargs) |
314 | 314 | return re.sub(arg_match.group(1), r"-output %s -Format XML" % self._output_file_path, data) |
315 | 315 | |
316 | 316 | |
317 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
318 | return NiktoPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
317 | def createPlugin(*args, **kwargs): | |
318 | return NiktoPlugin(*args, **kwargs) |
15 | 15 | self.name = '' |
16 | 16 | self.data = '' |
17 | 17 | self.device = '' |
18 | self.cvss2 = {} | |
18 | 19 | self.refs = [] |
19 | 20 | |
20 | 21 | |
95 | 96 | # nombre de la vuln |
96 | 97 | |
97 | 98 | vuln_soft.name = itemv.attrib.get('title') |
99 | cvss2_vector = itemv.find('infobox/infodata/[@label="CVSSv2 Base"]') | |
100 | vuln_soft.cvss2["vector_string"] = cvss2_vector.text.split(' ')[0] if cvss2_vector is not None else None | |
98 | 101 | for itemvv in itemv: |
99 | 102 | if itemvv.attrib.get('title') == 'Summary': |
100 | 103 | for i in itemvv: |
154 | 157 | resolution='', |
155 | 158 | data=vuln.data, |
156 | 159 | ref=vuln.refs, |
157 | cve=[vuln.name] | |
160 | cve=[vuln.name], | |
161 | cvss2=vuln.cvss2 | |
158 | 162 | ) |
159 | 163 | |
160 | 164 | |
161 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
162 | return NipperPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
165 | def createPlugin(*args, **kwargs): | |
166 | return NipperPlugin(*args, **kwargs) |
10 | 10 | from lxml import etree |
11 | 11 | from lxml.etree import XMLParser |
12 | 12 | from faraday_plugins.plugins.plugin import PluginXMLFormat |
13 | from faraday_plugins.plugins.plugins_utils import get_severity_from_cvss | |
14 | 13 | |
15 | 14 | current_path = os.path.abspath(os.getcwd()) |
16 | 15 | |
352 | 351 | self.desc += " *EXPLOIT*" |
353 | 352 | |
354 | 353 | self.refs = ["https://vulners.com/" + self.table["type"] + "/" + self.table["id"]] |
355 | self.refs.append("CVSS: " + self.table["cvss"]) | |
356 | 354 | self.response = "" |
357 | 355 | self.web = "" |
358 | self.severity = get_severity_from_cvss(self.table["cvss"]) | |
356 | self.cvss2 = {} | |
359 | 357 | |
360 | 358 | def __str__(self): |
361 | 359 | return f"{self.name}, {self.product}, {self.version}" |
392 | 390 | for k in script_node.findall("elem"): |
393 | 391 | self.response += "\n" + str(k.get('key')) + ": " + str(k.text) |
394 | 392 | self.web = re.search("(http-|https-)", self.name) |
393 | self.cvss2 = {} | |
395 | 394 | |
396 | 395 | def __str__(self): |
397 | 396 | return f"{self.name}, {self.product}, {self.version}" |
538 | 537 | ref=refs, |
539 | 538 | severity=severity, |
540 | 539 | website=minterfase, |
541 | cve=[v.name]) | |
540 | cve=[v.name], | |
541 | cvss2=v.cvss2 | |
542 | ) | |
542 | 543 | else: |
543 | 544 | v_id = self.createAndAddVulnToService( |
544 | 545 | h_id, |
547 | 548 | desc=v.desc, |
548 | 549 | ref=refs, |
549 | 550 | severity=severity, |
550 | cve=[v.name] | |
551 | cve=[v.name], | |
552 | cvss2=v.cvss2 | |
551 | 553 | ) |
552 | 554 | del parser |
553 | 555 | |
573 | 575 | command_string) |
574 | 576 | |
575 | 577 | |
576 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
577 | return NmapPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
578 | def createPlugin(*args, **kwargs): | |
579 | return NmapPlugin(*args, **kwargs) |
7 | 7 | import re |
8 | 8 | import sys |
9 | 9 | import json |
10 | import dateutil | |
10 | from dateutil.parser import parse | |
11 | 11 | from urllib.parse import urlparse |
12 | 12 | from packaging import version |
13 | 13 | from faraday_plugins.plugins.plugin import PluginMultiLineJsonFormat |
99 | 99 | # TODO CVSSv2, CVSSv3, CWE and CAPEC |
100 | 100 | #cvssv2 = vuln_dict['info'].get('classification', {}).get('cvss-score') |
101 | 101 | #cvssv3 = vuln_dict['info'].get('classification', {}).get('cvss-metrics') |
102 | #cwe = vuln_dict['info'].get('classification', {}).get('cwe-id', []) | |
103 | #cwe = [x.upper() for x in cwe] | |
102 | cwe = vuln_dict['info'].get('classification', {}).get('cwe-id', []) | |
103 | cwe = [x.upper() for x in cwe] | |
104 | 104 | #capec = vuln_dict['info'].get('metadata', {}).get('capec', []) |
105 | 105 | #if isinstance(capec, str): |
106 | 106 | # capec = capec.upper().split(',') |
134 | 134 | name = vuln_dict["info"].get("name") |
135 | 135 | run_date = vuln_dict.get('timestamp') |
136 | 136 | if run_date: |
137 | run_date = dateutil.parser.parse(run_date) | |
137 | run_date = parse(run_date) | |
138 | 138 | self.createAndAddVulnWebToService( |
139 | 139 | host_id, |
140 | 140 | service_id, |
150 | 150 | # TODO CVSSv2, CVSSv3, CWE and CAPEC |
151 | 151 | #cvssv2=cvssv2, |
152 | 152 | #cvssv3=cvssv3, |
153 | #cwe=cwe, | |
153 | cwe=cwe, | |
154 | 154 | #capec=capec, |
155 | 155 | website=host, |
156 | 156 | request=request, |
192 | 192 | return False |
193 | 193 | |
194 | 194 | |
195 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
196 | return NucleiPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
195 | def createPlugin(*args, **kwargs): | |
196 | return NucleiPlugin(*args, **kwargs) |
0 | 0 | import subprocess |
1 | 1 | import re |
2 | 2 | import json |
3 | import dateutil | |
4 | 3 | from packaging import version |
5 | 4 | from urllib.parse import urlparse |
5 | from dateutil.parser import parse | |
6 | 6 | from faraday_plugins.plugins.plugin import PluginMultiLineJsonFormat |
7 | 7 | |
8 | 8 | __author__ = "Emilio Couto" |
77 | 77 | references = [] |
78 | 78 | cwe = vuln_dict['info'].get('cwe', []) |
79 | 79 | capec = vuln_dict['info'].get('capec', []) |
80 | refs = sorted(list(set(reference + references + cwe + capec))) | |
80 | refs = sorted(list(set(reference + references + capec))) | |
81 | 81 | tags = vuln_dict['info'].get('tags', []) |
82 | 82 | if isinstance(tags, str): |
83 | 83 | tags = tags.split(',') |
96 | 96 | name = vuln_dict["info"].get("name") |
97 | 97 | run_date = vuln_dict.get('timestamp') |
98 | 98 | if run_date: |
99 | run_date = dateutil.parser.parse(run_date) | |
99 | run_date = parse(run_date) | |
100 | 100 | self.createAndAddVulnWebToService( |
101 | 101 | host_id, |
102 | 102 | service_id, |
117 | 117 | path=matched_data.path, |
118 | 118 | data="\n".join(data), |
119 | 119 | external_id=f"NUCLEI-{vuln_dict.get('templateID', '')}", |
120 | run_date=run_date | |
120 | run_date=run_date, | |
121 | cwe=cwe | |
121 | 122 | ) |
122 | 123 | |
123 | 124 | def processCommandString(self, username, current_path, command_string): |
147 | 148 | except Exception as e: |
148 | 149 | return False |
149 | 150 | |
150 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
151 | return NucleiLegacyPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
151 | def createPlugin(*args, **kwargs): | |
152 | return NucleiLegacyPlugin(*args, **kwargs) |
206 | 206 | cve=[vuln_cve]) |
207 | 207 | |
208 | 208 | |
209 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
210 | return OpenScapPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
209 | def createPlugin(*args, **kwargs): | |
210 | return OpenScapPlugin(*args, **kwargs) |
177 | 177 | self.cve = self.get_text_from_subnode('cve') if self.get_text_from_subnode('cve') != "NOCVE" else "" |
178 | 178 | self.bid = self.get_text_from_subnode('bid') if self.get_text_from_subnode('bid') != "NOBID" else "" |
179 | 179 | self.xref = self.get_text_from_subnode('xref') if self.get_text_from_subnode('xref') != "NOXREF" else "" |
180 | self.cwe = [] | |
181 | if "URL:https://cwe.mitre.org/data/definitions/" in self.xref: | |
182 | self.cwe.append("CWE-"+self.xref.split("URL:https://cwe.mitre.org/data/definitions/")[1] | |
183 | .replace("html", "")) | |
180 | 184 | self.description = '' |
181 | 185 | self.resolution = '' |
182 | 186 | self.cvss_vector = '' |
341 | 345 | if item.name is not None: |
342 | 346 | ref = [] |
343 | 347 | cve = [] |
348 | cvss2 = {} | |
344 | 349 | if item.cve: |
345 | 350 | cves = item.cve.split(',') |
346 | 351 | for i in cves: |
352 | 357 | if item.xref: |
353 | 358 | ref.append(item.xref) |
354 | 359 | if item.tags and item.cvss_vector: |
355 | ref.append(item.cvss_vector) | |
356 | if item.cvss_base: | |
357 | ref.append(f"CVSS_BASE: {item.cvss_base}") | |
360 | cvss2["vector_string"] = item.cvss_vector | |
358 | 361 | if item.cpe: |
359 | 362 | ref.append(f"{item.cpe}") |
360 | 363 | if item.severity_nr: |
384 | 387 | ref=ref, |
385 | 388 | external_id=f"OPENVAS-{item.id}", |
386 | 389 | data=item.data, |
387 | cve=cve) | |
390 | cve=cve, | |
391 | cwe=item.cwe, | |
392 | cvss2=cvss2 | |
393 | ) | |
388 | 394 | else: |
389 | 395 | if item.service: |
390 | 396 | web = re.search( |
416 | 422 | resolution=item.resolution, |
417 | 423 | external_id=f"OPENVAS-{item.id}", |
418 | 424 | data=item.data, |
419 | cve=cve) | |
425 | cve=cve, | |
426 | cwe=item.cwe, | |
427 | cvss2=cvss2 | |
428 | ) | |
420 | 429 | elif item.severity not in self.ignored_severities: |
421 | 430 | self.createAndAddVulnToService( |
422 | 431 | h_id, |
428 | 437 | resolution=item.resolution, |
429 | 438 | external_id=f"OPENVAS-{item.id}", |
430 | 439 | data=item.data, |
431 | cve=cve) | |
440 | cve=cve, | |
441 | cwe=item.cwe, | |
442 | cvss2=cvss2 | |
443 | ) | |
432 | 444 | del parser |
433 | 445 | |
434 | 446 | @staticmethod |
439 | 451 | return False |
440 | 452 | |
441 | 453 | |
442 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
443 | return OpenvasPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
454 | def createPlugin(*args, **kwargs): | |
455 | return OpenvasPlugin(*args, **kwargs) |
84 | 84 | return command_string |
85 | 85 | |
86 | 86 | |
87 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
88 | return pasteAnalyzerPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
87 | def createPlugin(*args, **kwargs): | |
88 | return pasteAnalyzerPlugin(*args, **kwargs) |
69 | 69 | self._path = current_path |
70 | 70 | |
71 | 71 | |
72 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
73 | return PeepingTomPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
72 | def createPlugin(*args, **kwargs): | |
73 | return PeepingTomPlugin(*args, **kwargs) |
47 | 47 | return False |
48 | 48 | |
49 | 49 | |
50 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
51 | return CmdPingPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
50 | def createPlugin(*args, **kwargs): | |
51 | return CmdPingPlugin(*args, **kwargs) |
60 | 60 | self._port = count_args[2] |
61 | 61 | |
62 | 62 | |
63 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
64 | return CmdPropeciaPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
63 | def createPlugin(*args, **kwargs): | |
64 | return CmdPropeciaPlugin(*args, **kwargs) |
4 | 4 | |
5 | 5 | """ |
6 | 6 | from dateutil.parser import parse |
7 | import re | |
7 | 8 | import json |
8 | 9 | from datetime import datetime |
9 | 10 | from dataclasses import dataclass |
17 | 18 | __maintainer__ = "Nicolas Rebagliati" |
18 | 19 | __email__ = "[email protected]" |
19 | 20 | __status__ = "Development" |
20 | ||
21 | CHECK_NUMBER_REGEX = re.compile(r"^(\[check\d\])") | |
21 | 22 | |
22 | 23 | @dataclass |
23 | 24 | class Issue: |
52 | 53 | scored = json_data.get("Status", "") |
53 | 54 | account = json_data.get("Account Number", "") |
54 | 55 | message = json_data.get("Message", "") |
55 | control = json_data.get("Control", "") | |
56 | control = CHECK_NUMBER_REGEX.sub("", json_data.get("Control", "")).strip() | |
56 | 57 | status = json_data.get("Status", "") |
57 | 58 | level = json_data.get("Level", "") |
58 | 59 | control_id = json_data.get("Control ID", "") |
61 | 62 | timestamp = parse(timestamp) |
62 | 63 | compliance = json_data.get("Compliance", "") |
63 | 64 | service = json_data.get("Service", "") |
64 | caf_epic = json_data.get("CAF Epic", "") | |
65 | caf_epic = [json_data.get("CAF Epic", "")] | |
65 | 66 | risk = json_data.get("Risk", "") |
66 | 67 | doc_link = json_data.get("Doc link", "") |
67 | 68 | remediation = json_data.get("Remediation", "") |
104 | 105 | data=f"Resource ID: {issue.resource_id}", |
105 | 106 | severity=self.normalize_severity(issue.severity), resolution=issue.remediation, |
106 | 107 | run_date=issue.timestamp, external_id=f"{self.name.upper()}-{issue.control_id}", |
107 | ref=[issue.doc_link]) | |
108 | ref=[issue.doc_link], | |
109 | policyviolations=issue.caf_epic) | |
108 | 110 | |
109 | 111 | |
110 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
111 | return ProwlerPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
112 | def createPlugin(*args, **kwargs): | |
113 | return ProwlerPlugin(*args, **kwargs) |
154 | 154 | self.glossary = glossary |
155 | 155 | self.severity = self.severity_dict.get(self.get_text_from_glossary('SEVERITY'), 'info') |
156 | 156 | self.title = self.get_text_from_glossary('TITLE') |
157 | self.cvss = self.get_text_from_glossary('CVSS_SCORE/CVSS_BASE') | |
157 | self.cvss2 = {} | |
158 | 158 | self.pci = self.get_text_from_glossary('PCI_FLAG') |
159 | 159 | self.solution = self.get_text_from_glossary('SOLUTION') |
160 | 160 | self.impact = self.get_text_from_glossary('IMPACT') |
177 | 177 | cve_id = self.get_text_from_glossary('CVE_ID_LIST/CVE_ID/ID') |
178 | 178 | if cve_id: |
179 | 179 | self.cve.append(cve_id) |
180 | ||
181 | if self.cvss: | |
182 | self.ref.append(f'CVSS SCORE: {self.cvss}') | |
183 | 180 | |
184 | 181 | if self.pci: |
185 | 182 | self.ref.append(f'PCI: {self.pci}') |
277 | 274 | self.name = self.node.get('number') |
278 | 275 | self.external_id = self.node.get('number') |
279 | 276 | self.title = self.get_text_from_subnode('TITLE') |
280 | self.cvss = self.get_text_from_subnode('CVSS_BASE') | |
277 | self.cvss2 = {} | |
278 | ||
281 | 279 | self.diagnosis = self.get_text_from_subnode('DIAGNOSIS') |
282 | 280 | self.solution = self.get_text_from_subnode('SOLUTION') |
283 | 281 | self.result = self.get_text_from_subnode('RESULT') |
311 | 309 | for r in issue_node.findall('BUGTRAQ_ID_LIST/BUGTRAQ_ID'): |
312 | 310 | self.node = r |
313 | 311 | self.ref.append('bid-' + self.get_text_from_subnode('ID')) |
314 | ||
315 | if self.cvss: | |
316 | self.ref.append('CVSS BASE: ' + self.cvss) | |
317 | 312 | |
318 | 313 | def get_text_from_subnode(self, subnode_xpath_expr): |
319 | 314 | """ |
363 | 358 | resolution=v.solution if v.solution else '', |
364 | 359 | desc=v.desc, |
365 | 360 | external_id=v.external_id, |
366 | cve=v.cve) | |
361 | cve=v.cve, | |
362 | cvss2=v.cvss2 | |
363 | ) | |
367 | 364 | |
368 | 365 | else: |
369 | 366 | web = False |
397 | 394 | desc=v.desc, |
398 | 395 | resolution=v.solution if v.solution else '', |
399 | 396 | external_id=v.external_id, |
400 | cve=v.cve) | |
397 | cve=v.cve, | |
398 | cvss2=v.cvss2 | |
399 | ) | |
401 | 400 | |
402 | 401 | else: |
403 | 402 | self.createAndAddVulnToService( |
409 | 408 | desc=v.desc, |
410 | 409 | resolution=v.solution if v.solution else '', |
411 | 410 | external_id=v.external_id, |
412 | cve=v.cve) | |
411 | cve=v.cve, | |
412 | cvss2=v.cvss2 | |
413 | ) | |
413 | 414 | |
414 | 415 | del parser |
415 | 416 | |
416 | 417 | |
417 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
418 | return QualysguardPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
418 | def createPlugin(*args, **kwargs): | |
419 | return QualysguardPlugin(*args, **kwargs) |
151 | 151 | # Data in the xml is in different parts, we look into the glossary |
152 | 152 | vuln_data = next((item for item in glossary if item["QID"] == vuln_scan_id), None) |
153 | 153 | vuln_name = vuln_data.get('TITLE') |
154 | vuln_desc = vuln_data.get('DESCRIPTION') + v.dict_result_vul.get('URL') | |
154 | vuln_desc = vuln_data.get('DESCRIPTION') | |
155 | vuln_CWE = [vuln_data.get('CWE', '')] | |
155 | 156 | raw_severity = int(vuln_data.get('SEVERITY', 0)) |
156 | 157 | vuln_severity = raw_severity - 1 |
157 | 158 | |
162 | 163 | |
163 | 164 | vuln_resolution = vuln_data.get('SOLUTION') |
164 | 165 | |
165 | vuln_ref = [] | |
166 | if vuln_data.get('CVSS_BASE'): | |
167 | vuln_ref = [f"CVSS: {vuln_data.get('CVSS_BASE')}"] | |
166 | cvss3 = {} | |
168 | 167 | |
169 | 168 | vuln_data_add = f"ID: {v.dict_result_vul.get('ID')}, DETECTION_ID: {v.dict_result_vul.get('DETECTION_ID')}" \ |
170 | 169 | f", CATEGORY: {vuln_data.get('CATEGORY')}, GROUP: {vuln_data.get('GROUP')}" \ |
171 | 170 | f", URL: {v.dict_result_vul.get('URL')}, IMPACT: {vuln_data.get('IMPACT')}" |
172 | 171 | |
173 | self.createAndAddVulnToHost(host_id=host_id, name=vuln_name, desc=vuln_desc, ref=vuln_ref, | |
172 | self.createAndAddVulnToHost(host_id=host_id, name=vuln_name, desc=vuln_desc, | |
174 | 173 | severity=vuln_severity, resolution=vuln_resolution, run_date=run_date, |
175 | external_id="QUALYS-"+vuln_scan_id, data=vuln_data_add) | |
174 | external_id="QUALYS-"+vuln_scan_id, data=vuln_data_add, cwe=vuln_CWE, | |
175 | cvss3=cvss3) | |
176 | 176 | |
177 | 177 | |
178 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
179 | return QualysWebappPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
178 | def createPlugin(*args, **kwargs): | |
179 | return QualysWebappPlugin(*args, **kwargs) |
40 | 40 | ) |
41 | 41 | |
42 | 42 | |
43 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
44 | return RDPScanPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
43 | def createPlugin(*args, **kwargs): | |
44 | return RDPScanPlugin(*args, **kwargs) |
169 | 169 | |
170 | 170 | |
171 | 171 | |
172 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
173 | return ReconngPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
172 | def createPlugin(*args, **kwargs): | |
173 | return ReconngPlugin(*args, **kwargs) |
122 | 122 | self.pciLevel = self.get_text_from_subnode('pciLevel') |
123 | 123 | self.pciReason = self.get_text_from_subnode('pciReason') |
124 | 124 | self.pciPassFail = self.get_text_from_subnode('pciPassFail') |
125 | self.cvssScore = self.get_text_from_subnode('cvssScore') | |
125 | self.cvss2Score = self.get_text_from_subnode('cvssScore') | |
126 | 126 | self.exploit = self.get_text_from_subnode('exploit') |
127 | 127 | self.context = self.get_text_from_subnode('context') |
128 | 128 | val = self.context.split(":") |
136 | 136 | self.desc = self.get_text_from_subnode('description') |
137 | 137 | self.solution = self.solution if self.solution else "" |
138 | 138 | self.desc += "\nExploit: " + self.exploit if self.exploit else "" |
139 | self.desc += "\ncvssScore: " + self.cvssScore if self.cvssScore else "" | |
140 | 139 | self.desc += "\nContext: " + self.context if self.context else "" |
141 | 140 | |
142 | 141 | self.ref = [] |
142 | self.cvss2 = {} | |
143 | if self.cvss2Score != "N/A": | |
144 | self.cvss2["vector_string"] = self.cvss2Score.split(' ')[1].replace('[', '').replace(']', '') | |
143 | 145 | |
144 | 146 | def get_text_from_subnode(self, subnode_xpath_expr): |
145 | 147 | """ |
198 | 200 | if web: |
199 | 201 | v_id = self.createAndAddVulnWebToService(h_id, s_id, v.name, ref=v.ref, |
200 | 202 | website=hostname, severity=v.severity, |
201 | resolution=v.solution, desc=v.desc, cve=cve) | |
203 | resolution=v.solution, desc=v.desc, cve=cve, cvss2=v.cvss2) | |
202 | 204 | else: |
203 | 205 | v_id = self.createAndAddVulnToService(h_id, s_id, v.name, ref=v.ref, |
204 | 206 | severity=v.severity, resolution=v.solution, |
205 | desc=v.desc, cve=cve) | |
207 | desc=v.desc, cve=cve, cvss2=v.cvss2) | |
206 | 208 | else: |
207 | 209 | for v in vulns: |
208 | 210 | cve = v.cve.split(",") if v.cve else [] |
209 | 211 | v_id = self.createAndAddVulnToHost(h_id, v.name, ref=v.ref, severity=v.severity, |
210 | resolution=v.solution, desc=v.desc, cve=cve) | |
212 | resolution=v.solution, desc=v.desc, cve=cve, cvss2=v.cvss2) | |
211 | 213 | del parser |
212 | 214 | |
213 | 215 | |
214 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
215 | return RetinaPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
216 | def createPlugin(*args, **kwargs): | |
217 | return RetinaPlugin(*args, **kwargs) |
77 | 77 | |
78 | 78 | |
79 | 79 | |
80 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
81 | return ReverseraiderPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
80 | def createPlugin(*args, **kwargs): | |
81 | return ReverseraiderPlugin(*args, **kwargs) |
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 | 17 | __author__ = "Valentin Vila" |
17 | 18 | __copyright__ = "Copyright (c) 2021, Faraday" |
18 | 19 | __credits__ = ["Valentin Vila"] |
71 | 72 | for name, vuln_info in vulns.items(): |
72 | 73 | description = vuln_info.get('summary') |
73 | 74 | references = vuln_info.get('references') |
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 | self.createAndAddVulnToService(h_id, s_id, name, desc=description, ref=references | |
76 | , cve=name) | |
77 | 77 | |
78 | 78 | def processCommandString(self, username, current_path, command_string): |
79 | 79 | """ |
103 | 103 | return cmd |
104 | 104 | |
105 | 105 | |
106 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
107 | return ShodanPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
106 | def createPlugin(*args, **kwargs): | |
107 | return ShodanPlugin(*args, **kwargs) |
192 | 192 | """ |
193 | 193 | super().processCommandString(username, current_path, command_string) |
194 | 194 | arg_match = self.xml_arg_re.match(command_string) |
195 | self._output_file_path = os.path.join(tempfile.gettempdir(), "faraday_plugin_skipfish_%d" % random.randint(1, 999999)) | |
195 | self._output_file_path = os.path.join(tempfile.gettempdir(), | |
196 | "faraday_plugin_skipfish_%d" % random.randint(1, 999999)) # nosec | |
196 | 197 | self._delete_temp_file = True |
197 | 198 | if arg_match is None: |
198 | 199 | return re.sub(r"(^.*?skipfish)", r"\1 -o %s" % self._output_file_path, command_string, 1) |
202 | 203 | |
203 | 204 | |
204 | 205 | |
205 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
206 | return SkipfishPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
206 | def createPlugin(*args, **kwargs): | |
207 | return SkipfishPlugin(*args, **kwargs) |
5 | 5 | """ |
6 | 6 | import json |
7 | 7 | from faraday_plugins.plugins.plugin import PluginJsonFormat |
8 | from datetime import datetime | |
9 | import dateutil | |
8 | from dateutil.parser import parse | |
10 | 9 | |
11 | 10 | VULNERABILITY = "VULNERABILITY" |
12 | 11 | |
52 | 51 | status = STATUSES[issue['status']] |
53 | 52 | tags = issue['tags'] |
54 | 53 | external_id = issue['rule'] |
55 | creation_date = dateutil.parser.parse(issue['creationDate']) | |
54 | creation_date = parse(issue['creationDate']) | |
56 | 55 | data = [] if not issue['flows'] else ["Flows:"] |
57 | 56 | for flow in issue['flows']: |
58 | 57 | for location in flow['locations']: |
93 | 92 | ) |
94 | 93 | |
95 | 94 | |
96 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
97 | return SonarQubeAPIPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
95 | def createPlugin(*args, **kwargs): | |
96 | return SonarQubeAPIPlugin(*args, **kwargs) |
62 | 62 | for vuln in vulns: |
63 | 63 | v_name = vuln['title'] |
64 | 64 | v_desc = vuln['overview'] |
65 | v_ref = f"CVSS: {vuln['cvssScore']}" | |
66 | 65 | v_data = vuln['libraries'] |
67 | 66 | v_website = vuln['_links']['html'] |
68 | 67 | url_data = parser.parse_url(v_website) |
77 | 76 | h_id = self.createAndAddHost(name=host_name, scan_template=records['metadata']['recordType']) |
78 | 77 | s_id = self.createAndAddServiceToHost(h_id, "Sourceclear", protocol=url_data['protocol'], |
79 | 78 | ports=url_data['port'], status='open') |
80 | self.createAndAddVulnWebToService(h_id, s_id, name=v_name, desc=v_desc, ref=[v_ref], data=v_data, | |
79 | self.createAndAddVulnWebToService(h_id, s_id, name=v_name, desc=v_desc, data=v_data, | |
81 | 80 | website=v_website) |
82 | 81 | |
83 | 82 | |
84 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
85 | return SourceclearPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
83 | def createPlugin(*args, **kwargs): | |
84 | return SourceclearPlugin(*args, **kwargs) |
65 | 65 | return None |
66 | 66 | |
67 | 67 | |
68 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
69 | return SSHDefaultScanPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
68 | def createPlugin(*args, **kwargs): | |
69 | return SSHDefaultScanPlugin(*args, **kwargs) |
106 | 106 | data=vuln['data']) |
107 | 107 | |
108 | 108 | |
109 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
110 | return SslLabsPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
109 | def createPlugin(*args, **kwargs): | |
110 | return SslLabsPlugin(*args, **kwargs) |
168 | 168 | severity="medium") |
169 | 169 | |
170 | 170 | |
171 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
172 | return SslyzePlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
171 | def createPlugin(*args, **kwargs): | |
172 | return SslyzePlugin(*args, **kwargs) |
286 | 286 | command_string) |
287 | 287 | |
288 | 288 | |
289 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
290 | return SslyzePlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
289 | def createPlugin(*args, **kwargs): | |
290 | return SslyzePlugin(*args, **kwargs) |
58 | 58 | "desc": desc, |
59 | 59 | "resolution": resolution, |
60 | 60 | "ref": ref, |
61 | "severity": severity | |
61 | "severity": severity, | |
62 | "cvss3": cvss3, | |
63 | "cvss2": cvss2 | |
62 | 64 | } |
63 | 65 | if self.scan_type == "DAST": |
64 | 66 | v['data'] = vuln.find("request").text + "\n" |
71 | 73 | @staticmethod |
72 | 74 | def get_cvss(tree): |
73 | 75 | cvss_vector = tree.find("vector").text |
74 | cvss_score = tree.find("score").text | |
75 | return {'base_score':cvss_score, 'cvss_vector': cvss_vector} | |
76 | return {'vector_stringr': cvss_vector} | |
76 | 77 | |
77 | 78 | def get_host(self, tree): |
78 | 79 | host = { |
124 | 125 | self.createAndAddVulnToHost(host_id=host_id, **issue) |
125 | 126 | |
126 | 127 | |
127 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
128 | return SyhuntPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
128 | def createPlugin(*args, **kwargs): | |
129 | return SyhuntPlugin(*args, **kwargs) |
75 | 75 | self._port = count_args[c - 1] |
76 | 76 | |
77 | 77 | |
78 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
79 | return TelnetRouterPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
78 | def createPlugin(*args, **kwargs): | |
79 | return TelnetRouterPlugin(*args, **kwargs) |
114 | 114 | |
115 | 115 | |
116 | 116 | |
117 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
118 | return TheharvesterPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
117 | def createPlugin(*args, **kwargs): | |
118 | return TheharvesterPlugin(*args, **kwargs) |
55 | 55 | return None |
56 | 56 | |
57 | 57 | |
58 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
59 | return traceroutePlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
58 | def createPlugin(*args, **kwargs): | |
59 | return traceroutePlugin(*args, **kwargs) |
0 | class Base: | |
1 | def __init__(self, node): | |
2 | self.node = node | |
3 | ||
4 | ||
5 | class Cvss(Base): | |
6 | @property | |
7 | def v2vector(self): | |
8 | return self.node.get("V2Vector") | |
9 | ||
10 | @property | |
11 | def v3vector(self): | |
12 | return self.node.get("V3Vector") | |
13 | ||
14 | @property | |
15 | def v2score(self): | |
16 | return self.node.get("V2Score") | |
17 | ||
18 | @property | |
19 | def v3score(self): | |
20 | return self.node.get("V3Score") | |
21 | ||
22 | ||
23 | class Line(Base): | |
24 | ||
25 | @property | |
26 | def number(self): | |
27 | return self.node.get("Number") | |
28 | ||
29 | @property | |
30 | def content(self): | |
31 | return self.node.get("Content") | |
32 | ||
33 | ||
34 | class Code(Base): | |
35 | ||
36 | @property | |
37 | def lines(self): | |
38 | if self.node.get("Lines"): | |
39 | return [Line(i) for i in self.node.get("Lines")] | |
40 | else: | |
41 | return None | |
42 | ||
43 | ||
44 | class CauseMetadata(Base): | |
45 | ||
46 | @property | |
47 | def code(self): | |
48 | return Code(self.node.get("Code")) | |
49 | ||
50 | ||
51 | class Misconfiguration(Base): | |
52 | ||
53 | @property | |
54 | def misconfig_type(self): | |
55 | return self.node.get("Type") | |
56 | ||
57 | @property | |
58 | def misconfig_id(self): | |
59 | return self.node.get("ID") | |
60 | ||
61 | @property | |
62 | def title(self): | |
63 | return self.node.get("Title") | |
64 | ||
65 | @property | |
66 | def description(self): | |
67 | description = self.node.get("Description") | |
68 | if description: | |
69 | return description | |
70 | else: | |
71 | return "Issues provided no description" | |
72 | ||
73 | @property | |
74 | def message(self): | |
75 | return self.node.get("Message") | |
76 | ||
77 | @property | |
78 | def resolution(self): | |
79 | return self.node.get("Resolution") | |
80 | ||
81 | @property | |
82 | def severity(self): | |
83 | return self.node.get("Severity") | |
84 | ||
85 | @property | |
86 | def references(self): | |
87 | return self.node.get("References") | |
88 | ||
89 | @property | |
90 | def cause_metadata(self): | |
91 | return CauseMetadata(self.node.get("CauseMetadata")) | |
92 | ||
93 | ||
94 | class Vulnerability(Base): | |
95 | ||
96 | @property | |
97 | def name(self): | |
98 | return self.node.get("VulnerabilityID") | |
99 | ||
100 | @property | |
101 | def title(self): | |
102 | return self.node.get("Title") | |
103 | ||
104 | @property | |
105 | def pkgname(self): | |
106 | return self.node.get("PkgName") | |
107 | ||
108 | @property | |
109 | def url(self): | |
110 | return self.node.get("PrimaryURL") | |
111 | ||
112 | @property | |
113 | def description(self): | |
114 | description = self.node.get("Description") | |
115 | if description: | |
116 | return description | |
117 | else: | |
118 | return "Issues provided no description" | |
119 | ||
120 | @property | |
121 | def severity(self): | |
122 | return self.node.get("Severity") | |
123 | ||
124 | @property | |
125 | def cwe(self): | |
126 | return self.node.get("CweIDs") | |
127 | ||
128 | @property | |
129 | def cvss(self): | |
130 | if self.node.get("cvss"): | |
131 | return Cvss(self.node.get("cvss").get("nvd")) | |
132 | else: | |
133 | return None | |
134 | ||
135 | @property | |
136 | def references(self): | |
137 | return self.node.get("References") | |
138 | ||
139 | ||
140 | class Result(Base): | |
141 | ||
142 | @property | |
143 | def target(self): | |
144 | return self.node.get("Target") | |
145 | ||
146 | @property | |
147 | def misconfigurations(self): | |
148 | return [Misconfiguration(i) for i in self.node.get("Misconfigurations", [])] | |
149 | ||
150 | @property | |
151 | def vulnerability(self): | |
152 | return [Vulnerability(i) for i in self.node.get("Vulnerabilities", [])] | |
153 | ||
154 | @property | |
155 | def result_type(self): | |
156 | return self.node.get("Type") | |
157 | ||
158 | ||
159 | class Metadata(Base): | |
160 | ||
161 | @property | |
162 | def os_family(self): | |
163 | return self.node.get("Family") | |
164 | ||
165 | @property | |
166 | def os_name(self): | |
167 | return self.node.get("Name") | |
168 | ||
169 | ||
170 | class TrivyJsonParser(Base): | |
171 | ||
172 | @property | |
173 | def results(self): | |
174 | return [Result(i) for i in self.node.get('Results', "")] | |
175 | ||
176 | @property | |
177 | def scantype(self): | |
178 | return self.node.get('ArtifactType') | |
179 | ||
180 | def metadata(self): | |
181 | return Metadata(self.node.get('Metadata')) |
0 | """ | |
1 | Faraday Penetration Test IDE | |
2 | Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) | |
3 | See the file 'doc/LICENSE' for the license information | |
4 | ||
5 | """ | |
6 | from faraday_plugins.plugins.plugin import PluginJsonFormat | |
7 | from faraday_plugins.plugins.repo.trivy_json.DTO import TrivyJsonParser | |
8 | from json import loads | |
9 | ||
10 | __author__ = "Gonzalo Martinez" | |
11 | __copyright__ = "Copyright (c) 2013, Infobyte LLC" | |
12 | __credits__ = ["Gonzalo Martinez"] | |
13 | __version__ = "1.0.0" | |
14 | __maintainer__ = "Gonzalo Martinez" | |
15 | __email__ = "[email protected]" | |
16 | __status__ = "Development" | |
17 | ||
18 | ||
19 | class TrivyJsonPlugin(PluginJsonFormat): | |
20 | ||
21 | def __init__(self, *arg, **kwargs): | |
22 | super().__init__(*arg, **kwargs) | |
23 | self.id = "Trivy_Json" | |
24 | self.name = "Trivy JSON Output Plugin" | |
25 | self.plugin_version = "1" | |
26 | self.version = "9" | |
27 | self.json_keys = {'SchemaVersion'} | |
28 | self.framework_version = "1.0.0" | |
29 | self._temp_file_extension = "json" | |
30 | ||
31 | def parseOutputString(self, output): | |
32 | parser = TrivyJsonParser(loads(output)) | |
33 | scantype = parser.scantype | |
34 | for result in parser.results: | |
35 | self.new_structure(result, scantype) | |
36 | ||
37 | def new_structure(self, result, scantype): | |
38 | source_file = result.target | |
39 | host_id = self.createAndAddHost(source_file, os=result.result_type, description=scantype) | |
40 | for misconfiguration in result.misconfigurations: | |
41 | self.create_vuln_dockerfile(misconfiguration, host_id) | |
42 | for vulnerability in result.vulnerability: | |
43 | self.create_vuln_image(vulnerability, host_id) | |
44 | ||
45 | def create_vuln_image(self, vulnerability, host_id): | |
46 | ref = vulnerability.references | |
47 | cvss3 = {} | |
48 | cvss2 = {} | |
49 | if vulnerability.cvss: | |
50 | cvss3["vector_string"] = vulnerability.cvss.v3score | |
51 | cvss2["vector_string"] = vulnerability.cvss.v2score | |
52 | cwe = [] | |
53 | if vulnerability.cwe: | |
54 | if isinstance(vulnerability.cwe, list): | |
55 | for v_cwe in vulnerability.cwe: | |
56 | cwe.append(v_cwe) | |
57 | else: | |
58 | cwe.append(vulnerability.cwe) | |
59 | if vulnerability.title == "security flaw": | |
60 | name = vulnerability.pkgname + ":" + vulnerability.title | |
61 | elif vulnerability.title is None: | |
62 | name = vulnerability.pkgname | |
63 | else: | |
64 | name = vulnerability.title | |
65 | self.createAndAddVulnToHost( | |
66 | host_id, | |
67 | name=name, | |
68 | desc=vulnerability.description, | |
69 | severity=vulnerability.severity, | |
70 | ref=ref, | |
71 | cve=vulnerability.name, | |
72 | cvss2=cvss2, | |
73 | cvss3=cvss3, | |
74 | cwe=cwe | |
75 | ) | |
76 | ||
77 | def create_vuln_dockerfile(self, misconfiguration, host_id): | |
78 | ref = misconfiguration.references | |
79 | data = [misconfiguration.message] | |
80 | if misconfiguration.cause_metadata.code.lines: | |
81 | for line in misconfiguration.cause_metadata.code.lines: | |
82 | data.append(f"Line {line.number}, {line.content}") | |
83 | self.createAndAddVulnToHost( | |
84 | host_id, | |
85 | name=misconfiguration.title, | |
86 | desc=misconfiguration.description, | |
87 | severity=misconfiguration.severity, | |
88 | resolution=misconfiguration.resolution, | |
89 | external_id=f"Trivy-{misconfiguration.misconfig_id}", | |
90 | ref=ref, | |
91 | data="\n".join(data) | |
92 | ) | |
93 | ||
94 | ||
95 | def createPlugin(*args, **kwargs): | |
96 | return TrivyJsonPlugin(*args, **kwargs) |
212 | 212 | del parser |
213 | 213 | |
214 | 214 | |
215 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
216 | return W3afPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
215 | def createPlugin(*args, **kwargs): | |
216 | return W3afPlugin(*args, **kwargs) |
8 | 8 | from urllib.parse import urlparse |
9 | 9 | |
10 | 10 | from faraday_plugins.plugins.plugin import PluginXMLFormat |
11 | from faraday_plugins.plugins.plugins_utils import CWE_regex | |
11 | 12 | |
12 | 13 | __author__ = "Francisco Amato" |
13 | 14 | __copyright__ = "Copyright (c) 2013, Infobyte LLC" |
147 | 148 | vulns_dict['description'] = self.get_text_from_subnode(vuln, 'description') |
148 | 149 | vulns_dict['solution'] = self.get_text_from_subnode(vuln, 'solution') |
149 | 150 | vulns_dict['references'] = self.get_references(vuln) |
151 | vulns_dict['cwe'] = self.get_cwe(vuln) | |
150 | 152 | vulns_dict['entries'] = self.get_entries(vuln) |
151 | 153 | vulns_list.append(vulns_dict) |
152 | 154 | |
153 | 155 | return vulns_list |
156 | ||
157 | def get_cwe(self, node): | |
158 | refs = node.findall('references/reference') | |
159 | for ref in refs: | |
160 | if CWE_regex.search(self.get_text_from_subnode(ref, 'title')): | |
161 | return [CWE_regex.search(self.get_text_from_subnode(ref, 'title')).group()] | |
162 | return [] | |
154 | 163 | |
155 | 164 | def get_references(self, node): |
156 | 165 | refs = node.findall('references/reference') |
290 | 299 | path=entry['path'], |
291 | 300 | request=entry['http_request'], |
292 | 301 | method=entry['method'], |
293 | params=entry['parameter']) | |
302 | params=entry['parameter'], | |
303 | cwe=vuln["cwe"]) | |
294 | 304 | |
295 | 305 | def processCommandString(self, username, current_path, command_string): |
296 | 306 | """ |
316 | 326 | return f"{command_string} -o {self._output_file_path} -f xml \n" |
317 | 327 | |
318 | 328 | |
319 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
320 | return WapitiPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
329 | def createPlugin(*args, **kwargs): | |
330 | return WapitiPlugin(*args, **kwargs) |
117 | 117 | return re.sub(arg_match.group(1), r"-xml %s" % self._output_file_path, command_string) |
118 | 118 | |
119 | 119 | |
120 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
121 | return WcscanPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
120 | def createPlugin(*args, **kwargs): | |
121 | return WcscanPlugin(*args, **kwargs) |
134 | 134 | self._output_path = current_path + "/" + self.host + ".txt" |
135 | 135 | |
136 | 136 | |
137 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
138 | return WebfuzzerPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
137 | def createPlugin(*args, **kwargs): | |
138 | return WebfuzzerPlugin(*args, **kwargs) |
149 | 149 | ) |
150 | 150 | |
151 | 151 | |
152 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
153 | return WebInspectPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
152 | def createPlugin(*args, **kwargs): | |
153 | return WebInspectPlugin(*args, **kwargs) |
83 | 83 | path=path) |
84 | 84 | |
85 | 85 | |
86 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
87 | return WfuzzPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
86 | def createPlugin(*args, **kwargs): | |
87 | return WfuzzPlugin(*args, **kwargs) |
73 | 73 | description=desc) |
74 | 74 | |
75 | 75 | |
76 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
77 | return WhatWebPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
76 | def createPlugin(*args, **kwargs): | |
77 | return WhatWebPlugin(*args, **kwargs) |
34 | 34 | parser = json.loads(output) |
35 | 35 | if parser.get('vulnerabilities'): |
36 | 36 | for vulnerability in parser['vulnerabilities']: |
37 | ||
37 | cvss3 = {} | |
38 | cvss2 = {} | |
38 | 39 | if 'project' in vulnerability: |
39 | 40 | application_name = vulnerability.get('project') |
40 | 41 | host_id = self.createAndAddHost(application_name) |
41 | 42 | data = '' |
42 | 43 | for key, value in vulnerability['library'].items(): |
43 | 44 | data += f'{key}: {value} \n' |
44 | refs = [ | |
45 | f"CVSS: {vulnerability['score']}", | |
46 | ] | |
47 | if 'cvss3_score' in vulnerability: | |
48 | refs.append(f"CVSS3: {vulnerability['cvss3_score']}") | |
45 | refs = [] | |
46 | if "scoreMetadataVector" in vulnerability: | |
47 | cvss3["vector_string"] = vulnerability['scoreMetadataVector'] | |
49 | 48 | if 'topFix' in vulnerability: |
50 | 49 | refs.append(f"URL: {vulnerability['topFix']['url']}") |
51 | 50 | self.createAndAddVulnToHost(host_id, |
55 | 54 | resolution=vulnerability['topFix']['fixResolution'], |
56 | 55 | ref=refs, |
57 | 56 | severity=vulnerability['severity'], |
58 | cve=[vulnerability['name']]) | |
57 | cve=[vulnerability['name']], | |
58 | cvss2=cvss2, | |
59 | cvss3=cvss3) | |
59 | 60 | else: |
60 | 61 | self.createAndAddVulnToHost(host_id, |
61 | 62 | name=vulnerability['name'], |
62 | 63 | desc=vulnerability['description'], |
63 | 64 | data=data, |
64 | 65 | ref=refs, |
65 | severity=vulnerability['severity']) | |
66 | severity=vulnerability['severity'], | |
67 | cvss2=cvss2, | |
68 | cvss3=cvss3) | |
66 | 69 | elif 'namespace' in vulnerability: |
67 | 70 | host_id = self.createAndAddHost(vulnerability['namespace']) |
68 | 71 | service_id = self.createAndAddServiceToHost( |
97 | 100 | ) |
98 | 101 | |
99 | 102 | |
100 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
101 | return WhitesourcePlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
103 | def createPlugin(*args, **kwargs): | |
104 | return WhitesourcePlugin(*args, **kwargs) |
124 | 124 | return True |
125 | 125 | |
126 | 126 | |
127 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
128 | return CmdWhoisPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
127 | def createPlugin(*args, **kwargs): | |
128 | return CmdWhoisPlugin(*args, **kwargs) |
4 | 4 | |
5 | 5 | """ |
6 | 6 | import json |
7 | import re | |
7 | 8 | from urllib.parse import urlparse |
8 | 9 | |
10 | from faraday_plugins.plugins.plugin import PluginJsonFormat | |
9 | 11 | |
10 | 12 | __author__ = "Nicolas Rebagliati" |
11 | 13 | __copyright__ = "Copyright (c) 2019, Infobyte LLC" |
15 | 17 | __maintainer__ = "Nicolas Rebagliati" |
16 | 18 | __email__ = "[email protected]" |
17 | 19 | __status__ = "Development" |
18 | ||
19 | from faraday_plugins.plugins.plugin import PluginJsonFormat | |
20 | 20 | |
21 | 21 | |
22 | 22 | class WPScanJsonParser: |
42 | 42 | return {'protocol': protocol, 'hostname': hostname, 'port': port, 'address': address} |
43 | 43 | |
44 | 44 | |
45 | ||
46 | 45 | class WPScanPlugin(PluginJsonFormat): |
47 | 46 | """ Handle the WPScan tool. Detects the output of the tool |
48 | 47 | and adds the information to Faraday. |
55 | 54 | self.plugin_version = "0.2" |
56 | 55 | self.version = "3.4.5" |
57 | 56 | self.json_keys = {"target_url", "effective_url", "interesting_findings"} |
57 | self._command_regex = re.compile(r'^(sudo wpscan|wpscan)\s+.*?') | |
58 | self._use_temp_file = True | |
59 | self._temp_file_extension = "json" | |
58 | 60 | |
59 | 61 | def parseOutputString(self, output): |
60 | 62 | parser = WPScanJsonParser(output, self.resolve_hostname) |
89 | 91 | self.createAndAddVulnWebToService(host_id, service_id, vuln_name, ref=vuln['references'].get('url', []), |
90 | 92 | severity='unclassified') |
91 | 93 | |
94 | def processCommandString(self, username, current_path, command_string): | |
95 | """ | |
96 | Adds the path to a temporary file parameter to get .json output to the command string that the | |
97 | user has set. | |
98 | """ | |
99 | super().processCommandString(username, current_path, command_string) | |
100 | command_string += f" --output={self._output_file_path} --format json" | |
101 | return command_string | |
92 | 102 | |
93 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
94 | return WPScanPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
103 | ||
104 | def createPlugin(*args, **kwargs): | |
105 | return WPScanPlugin(*args, **kwargs) |
176 | 176 | del parser |
177 | 177 | |
178 | 178 | |
179 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
180 | return X1Plugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
179 | def createPlugin(*args, **kwargs): | |
180 | return X1Plugin(*args, **kwargs) |
53 | 53 | params=''.join(parametro), request='', response='') |
54 | 54 | |
55 | 55 | |
56 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
57 | return xsssniper(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
56 | def createPlugin(*args, **kwargs): | |
57 | return xsssniper(*args, **kwargs) |
139 | 139 | self.resolution = self.get_text_from_subnode('solution') |
140 | 140 | else: |
141 | 141 | self.resolution = '' |
142 | ||
142 | self.cwe = [] | |
143 | 143 | self.ref = [] |
144 | 144 | if self.get_text_from_subnode('reference'): |
145 | 145 | links = self.get_text_from_subnode('reference') |
149 | 149 | self.ref.append(strip_tags(link)) |
150 | 150 | |
151 | 151 | if self.get_text_from_subnode('cweid'): |
152 | self.ref.append("CWE:" + self.get_text_from_subnode('cweid')) | |
152 | self.cwe.append("CWE-" + self.get_text_from_subnode('cweid')) | |
153 | 153 | |
154 | 154 | if self.get_text_from_subnode('wascid'): |
155 | 155 | self.ref.append("WASC:" + self.get_text_from_subnode('wascid')) |
277 | 277 | resolution=strip_tags(item.resolution), |
278 | 278 | data=instance["data"], |
279 | 279 | pname=instance["pname"], |
280 | external_id="ZAP-" + str(item.id) | |
280 | external_id="ZAP-" + str(item.id), | |
281 | cwe=item.cwe | |
281 | 282 | ) |
282 | 283 | |
283 | 284 | del parser |
284 | 285 | |
285 | 286 | |
286 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
287 | return ZapPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
287 | def createPlugin(*args, **kwargs): | |
288 | return ZapPlugin(*args, **kwargs) |
88 | 88 | data += f" Parameter:\n {instance.param}" |
89 | 89 | |
90 | 90 | ref = [] |
91 | cwe = [] | |
91 | 92 | if item.reference: |
92 | 93 | ref += split_and_strip_tags(item.reference) |
93 | 94 | if item.cwe: |
94 | ref += [f"CWE:{item.cwe}"] | |
95 | cwe += [f"CWE-{item.cwe}"] | |
95 | 96 | if item.wasc: |
96 | 97 | ref += [f"WASC:{item.wasc}"] |
97 | 98 | |
110 | 111 | resolution=strip_tags(item.solution), |
111 | 112 | data=data, |
112 | 113 | pname=instance.param, |
113 | external_id="ZAP-" + str(item.plugin_id) | |
114 | external_id="ZAP-" + str(item.plugin_id), | |
115 | cwe=cwe | |
114 | 116 | ) |
115 | 117 | |
116 | 118 | del parser |
117 | 119 | |
118 | 120 | |
119 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
120 | return ZapJsonPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) | |
121 | def createPlugin(*args, **kwargs): | |
122 | return ZapJsonPlugin(*args, **kwargs) |
16 | 16 | {"plugin_id": "Dnsrecon", "command": "dnsrecon www.google.com", "command_result": "Dnsrecon"}, |
17 | 17 | {"plugin_id": "Dnswalk", "command": "dnswalk www.google.com", "command_result": "Dnswalk"}, |
18 | 18 | {"plugin_id": "Fierce", "command": "fierce www.google.com", "command_result": "Fierce"}, |
19 | {"plugin_id": "fruitywifi", "command": "fruitywifi www.google.com", "command_result": "fruitywifi"}, | |
20 | 19 | {"plugin_id": "ftp", "command": "ftp www.google.com", "command_result": "ftp"}, |
21 | 20 | {"plugin_id": "Goohost", "command": "goohost.sh www.google.com", "command_result": "goohost.sh"}, |
22 | 21 | {"plugin_id": "Hping3", "command": "hping3 www.google.com", "command_result": "Hping3"}, |
95 | 95 | assert summary['severity_vulns'] == saved_summary['severity_vulns'] |
96 | 96 | assert vuln_hashes == saved_vuln_hashes |
97 | 97 | |
98 | ||
99 | def test_process_report_ignore_info(): | |
100 | report_file = os.path.join('./report-collection', 'faraday_plugins_tests', 'Nmap', 'nmap_5.21.xml') | |
101 | runner = CliRunner() | |
102 | result = runner.invoke(process_report, args=[report_file, '--summary', '--ignore-info']) | |
103 | assert result.exit_code == 0 | |
104 | summary = json.loads(result.output.strip()) | |
105 | assert summary['hosts'] == 256 | |
106 | assert summary['services'] == 69 | |
107 | assert summary['hosts_vulns'] == 0 | |
108 | assert summary['services_vulns'] == 0 | |
109 | ||
110 | ||
111 | def test_process_report_tags(): | |
112 | report_file = os.path.join('./report-collection', 'faraday_plugins_tests', 'Acunetix', 'acunetix_valid_dummy.xml') | |
113 | runner = CliRunner() | |
114 | args = [report_file, '--vuln-tag=vuln_tag', '--service-tag=service_tag', '--host-tag=host_tag'] | |
115 | result = runner.invoke(process_report, args=args) | |
116 | assert result.exit_code == 0 | |
117 | body = json.loads(result.output.strip()) | |
118 | assert body['hosts'][0]["tags"][0] == "host_tag" | |
119 | assert body['hosts'][0]["services"][0]["tags"][0] == "service_tag" | |
120 | assert body['hosts'][0]["services"][0]["vulnerabilities"][0]["tags"][0] == "vuln_tag" |
104 | 104 | assert plugin.id == plugin_folder |
105 | 105 | |
106 | 106 | |
107 | @pytest.mark.skip(reason="Fail until release") | |
107 | 108 | @pytest.mark.parametrize("report_filename_and_folder", list_report_files()) |
108 | 109 | def test_schema_on_all_reports(report_filename_and_folder): |
109 | 110 | report_filename = report_filename_and_folder[1] |