Update upstream source from tag 'upstream/1.6.8'
Update to upstream version '1.6.8'
with Debian dir 44f86894e98b0f6b303385c18c0cafb68550139e
Sophie Brun
1 year, 9 months ago
0 | .get_secrets: | |
1 | script: | |
2 | - export VAULT_TOKEN="$(vault write -field=token auth/jwt/login role=python-sast-readonly jwt=$CI_JOB_JWT)"; if [ -z "$VAULT_TOKEN" ]; then exit 1; fi | |
3 | - if [ -z "$DEVSECOPS_WORKSPACE" ]; then export DEVSECOPS_WORKSPACE="$(vault kv get -field=DEVSECOPS_WORKSPACE secrets/gitlab/SAST)"; fi; if [ -z "$DEVSECOPS_WORKSPACE" ]; then exit 1; fi | |
4 | - if [ -z "$FARADAY_PASSWORD" ]; then export FARADAY_PASSWORD="$(vault kv get -field=FARADAY_PASSWORD secrets/gitlab/SAST)"; fi; if [ -z "$FARADAY_PASSWORD" ]; then exit 1; fi | |
5 | - if [ -z "$FARADAY_URL" ]; then export FARADAY_URL="$(vault kv get -field=FARADAY_URL secrets/gitlab/SAST)"; fi; if [ -z "$FARADAY_URL" ]; then exit 1; fi | |
6 | - if [ -z "$FARADAY_USER" ]; then export FARADAY_USER="$(vault kv get -field=FARADAY_USER secrets/gitlab/SAST)"; fi; if [ -z "$FARADAY_USER" ]; then exit 1; fi |
0 | variables: | |
1 | VAULT_ROLE: 'python-sast-readonly' | |
2 | VAULT_ADDR: 'https://tluav-lb.faradaysec.com' | |
3 | VAULT_SECRET_PATH: 'gitlab/SAST' | |
4 | ||
5 | ||
6 | include: | |
7 | - local: .gitlab/ci/fetch-secrets.yml | |
8 | ||
0 | 9 | stages: |
10 | - SAST | |
1 | 11 | - pre_testing |
2 | 12 | - testing |
3 | 13 | - post_testing |
31 | 41 | - git checkout $REPORT_REF |
32 | 42 | - cd .. |
33 | 43 | |
44 | bandit: | |
45 | stage: SAST | |
46 | image: python:3 | |
47 | tags: | |
48 | - faradaytests | |
49 | script: | |
50 | - pip3 install bandit | |
51 | - mkdir /results | |
52 | - "bandit -r ${CI_PROJECT_DIR} -o /results/output.xml -f xml" | |
53 | after_script: | |
54 | - curl -fsSL https://apt.releases.hashicorp.com/gpg | apt-key add - | |
55 | - apt update | |
56 | - apt-get install software-properties-common -y | |
57 | - apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com focal main" | |
58 | - apt update | |
59 | - apt install vault -y | |
60 | - setcap cap_ipc_lock= /usr/bin/vault | |
61 | - !reference [ .get_secrets, script ] | |
62 | - pip3 install faraday-cli | |
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 | rules: | |
65 | - when: on_success | |
66 | allow_failure: true | |
34 | 67 | |
35 | 68 | flake8: |
36 | 69 | image: python:3 |
0 | support cve,cwe,cvss and metadata |
0 | Jan 13th, 2022 |
0 | Add packaging to requierments in setup.py |
0 | Add severity to shodan's plugins using cvss⏎ |
0 | Feb 3rd, 2022 |
0 | check if cve exist on cve-id field |
0 | Fix Fortify's plugin |
0 | Change qualysguard's plugin severity_dict to refer level 2 severities as low |
0 | Add references tu burp plugin |
0 | Mar 18th, 2022 |
0 | Move item.detail from data to desc |
0 | update open status |
0 | Now Appscan plugin saves line and highlight of the vulns in desc and data |
0 | Apr 4th, 2022 |
0 | Add Zap Json plugin. |
0 | Apr 19th, 2022 |
0 | Add location as params in burp's plugin |
0 | Apr 21th, 2022 |
0 | Now the faraday_csv custom_fields regex match any no whitespace character. |
0 | Apr 28th, 2022 |
0 | Now Openvas's plugin set severity to Critical when cvss >= 9.0 |
0 | Add hostname_resolution parameter within plugins |
0 | May 20th, 2022 |
0 | Fix openvas external ID |
0 | Change hostname_restolution to dont_resolve_hostname for process-report and now test dosent resovle hostname |
0 | Jun 2nd, 2022 |
0 | Now QualysWebApp's plugin will diferenciate vulns from differents urlpaths |
0 | Add appscan csv |
0 | Now faraday_csv's plugin uses ignore_info parameter |
0 | Add syhunt plugin |
0 | Jul 25th, 2022 |
0 | Add cve and data fields to desc for avoid duplications |
0 | Now nuclei resolve hostname if the field ip is None |
0 | 1.6.8 [Jul 25th, 2022]: | |
1 | --- | |
2 | * Add appscan csv | |
3 | * Now faraday_csv's plugin uses ignore_info parameter | |
4 | * Add syhunt plugin | |
5 | * Add cve and data fields to desc for avoid duplications | |
6 | * Now nuclei resolve hostname if the field ip is None | |
7 | ||
8 | 1.6.7 [Jun 2nd, 2022]: | |
9 | --- | |
10 | * Change hostname_restolution to dont_resolve_hostname for process-report and now test dosent resovle hostname | |
11 | * Now QualysWebApp's plugin will diferenciate vulns from differents urlpaths | |
12 | ||
13 | 1.6.6 [May 20th, 2022]: | |
14 | --- | |
15 | * Add hostname_resolution parameter within plugins | |
16 | * Fix openvas external ID | |
17 | ||
18 | 1.6.5 [Apr 28th, 2022]: | |
19 | --- | |
20 | * Now Openvas's plugin set severity to Critical when cvss >= 9.0 | |
21 | ||
22 | 1.6.4 [Apr 21th, 2022]: | |
23 | --- | |
24 | * Add location as params in burp's plugin | |
25 | * Now the faraday_csv custom_fields regex match any no whitespace character. | |
26 | ||
27 | 1.6.3 [Apr 19th, 2022]: | |
28 | --- | |
29 | * Add Zap Json plugin. | |
30 | ||
31 | 1.6.2 [Apr 4th, 2022]: | |
32 | --- | |
33 | * Now Appscan plugin saves line and highlight of the vulns in desc and data | |
34 | ||
35 | 1.6.1 [Mar 18th, 2022]: | |
36 | --- | |
37 | * Add references tu burp plugin | |
38 | * Move item.detail from data to desc | |
39 | * update open status | |
40 | ||
41 | 1.6.0 [Feb 3rd, 2022]: | |
42 | --- | |
43 | * Add packaging to requierments in setup.py | |
44 | * Add severity to shodan's plugins using cvss | |
45 | * check if cve exist on cve-id field | |
46 | * Fix Fortify's plugin | |
47 | * Change qualysguard's plugin severity_dict to refer level 2 severities as low | |
48 | ||
49 | 1.5.10 [Jan 13th, 2022]: | |
50 | --- | |
51 | * support cve,cwe,cvss and metadata | |
52 | ||
0 | 53 | 1.5.9 [Dec 27th, 2021]: |
1 | 54 | --- |
2 | * ADD cve in faraday_csv plugin | |
55 | * Add cve in faraday_csv plugin | |
3 | 56 | * ADD Grype plugin |
4 | 57 | |
5 | 58 | 1.5.8 [Dec 13th, 2021]: |
64 | 64 | @click.option('--summary', is_flag=True) |
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 | def process_report(report_file, plugin_id, custom_plugins_folder, summary, output_file, ignore_info): | |
67 | @click.option('-drh', '--dont-resolve-hostname', is_flag=True, help="Dont resolve hostname", default=False) | |
68 | def process_report(report_file, plugin_id, custom_plugins_folder, summary, output_file, ignore_info, | |
69 | dont_resolve_hostname): | |
68 | 70 | if not os.path.isfile(report_file): |
69 | 71 | click.echo(click.style(f"File {report_file} Don't Exists", fg="red"), err=True) |
70 | 72 | else: |
71 | plugins_manager = PluginsManager(custom_plugins_folder, ignore_info=ignore_info) | |
73 | plugins_manager = PluginsManager(custom_plugins_folder, ignore_info=ignore_info, | |
74 | hostname_resolution=not dont_resolve_hostname) | |
72 | 75 | analyzer = ReportAnalyzer(plugins_manager) |
73 | 76 | if plugin_id: |
74 | 77 | plugin = plugins_manager.get_plugin(plugin_id) |
100 | 103 | @click.option('-o', '--output-file', type=click.Path(exists=False)) |
101 | 104 | @click.option('-sh', '--show-output', is_flag=True) |
102 | 105 | @click.option('--ignore-info', is_flag=True, help="Ignore information vulnerabilities") |
106 | @click.option('--hostname-resolution', is_flag=True, help="Resolve hostname") | |
103 | 107 | def process_command(command, plugin_id, custom_plugins_folder, dont_run, summary, output_file, show_output, |
104 | ignore_info): | |
105 | plugins_manager = PluginsManager(custom_plugins_folder, ignore_info=ignore_info) | |
108 | ignore_info, hostname_resolution): | |
109 | plugins_manager = PluginsManager(custom_plugins_folder, ignore_info=ignore_info, | |
110 | hostname_resolution=hostname_resolution) | |
106 | 111 | analyzer = CommandAnalyzer(plugins_manager) |
107 | 112 | if plugin_id: |
108 | 113 | plugin = plugins_manager.get_plugin(plugin_id) |
151 | 151 | |
152 | 152 | class PluginsManager: |
153 | 153 | |
154 | def __init__(self, custom_plugins_folder=None, ignore_info=False): | |
154 | def __init__(self, custom_plugins_folder=None, ignore_info=False, hostname_resolution=True): | |
155 | 155 | self.ignore_info = ignore_info |
156 | self.hostname_resolution = hostname_resolution | |
156 | 157 | self.plugins = {} |
157 | 158 | self.plugin_modules = {} |
158 | 159 | self._load_plugins(custom_plugins_folder) |
215 | 216 | plugin = None |
216 | 217 | plugin_id = plugin_id.lower() |
217 | 218 | if plugin_id in self.plugin_modules: |
218 | plugin = self.plugin_modules[plugin_id].createPlugin(self.ignore_info) | |
219 | plugin = self.plugin_modules[plugin_id].createPlugin(self.ignore_info, self.hostname_resolution) | |
219 | 220 | else: |
220 | 221 | logger.debug("Unknown Plugin: %s", plugin_id) |
221 | 222 | return plugin |
223 | 224 | def get_plugins(self): |
224 | 225 | for plugin_id, plugin_module in self.plugin_modules.items(): |
225 | 226 | logger.debug("Instance Plugin: %s", plugin_id) |
226 | yield plugin_id, plugin_module.createPlugin(self.ignore_info) | |
227 | yield plugin_id, plugin_module.createPlugin(self.ignore_info, self.hostname_resolution) |
15 | 15 | from collections import defaultdict |
16 | 16 | from datetime import datetime |
17 | 17 | from pathlib import Path |
18 | import socket | |
18 | 19 | |
19 | 20 | # Related third party imports |
20 | 21 | import pytz |
33 | 34 | # TODO: Add class generic identifier |
34 | 35 | class_signature = "PluginBase" |
35 | 36 | |
36 | def __init__(self, ignore_info=False): | |
37 | def __init__(self, ignore_info=False, hostname_resolution=True, *args, **kwargs): | |
37 | 38 | # Must be unique. Check that there is not |
38 | 39 | # an existent plugin with the same id. |
39 | 40 | # TODO: Make script that list current ids. |
40 | 41 | self.ignore_info = ignore_info |
42 | self.hostname_resolution = hostname_resolution | |
41 | 43 | self.id = None |
42 | 44 | self.auto_load = True |
43 | 45 | self._rid = id(self) |
82 | 84 | temp_file_path = os.path.join(temp_dir, temp_filename) |
83 | 85 | return temp_file_path |
84 | 86 | |
87 | def resolve_hostname(self, hostname): | |
88 | if not self.hostname_resolution: | |
89 | return hostname | |
90 | try: | |
91 | socket.inet_aton(hostname) # is already an ip | |
92 | return hostname | |
93 | except OSError: | |
94 | pass | |
95 | try: | |
96 | ip_address = socket.gethostbyname(hostname) | |
97 | except Exception as e: | |
98 | return hostname | |
99 | else: | |
100 | return ip_address | |
101 | ||
85 | 102 | @staticmethod |
86 | 103 | def get_utctimestamp(date): |
87 | 104 | if date is not None: |
278 | 295 | command that it's going to be executed. |
279 | 296 | """ |
280 | 297 | self._current_path = current_path |
281 | if command_string.startswith(("sudo","python","python3")): | |
298 | if command_string.startswith(("sudo", "python", "python3")): | |
282 | 299 | params = " ".join(command_string.split()[2:]) |
283 | 300 | else: |
284 | 301 | params = " ".join(command_string.split()[1:]) |
392 | 409 | if ref is None: |
393 | 410 | ref = [] |
394 | 411 | if status == "": |
395 | status = "opened" | |
412 | status = "open" | |
396 | 413 | if impact is None: |
397 | 414 | impact = {} |
398 | 415 | if policyviolations is None: |
426 | 443 | if ref is None: |
427 | 444 | ref = [] |
428 | 445 | if status == "": |
429 | status = "opened" | |
446 | status = "open" | |
430 | 447 | if impact is None: |
431 | 448 | impact = {} |
432 | 449 | if policyviolations is None: |
484 | 501 | if ref is None: |
485 | 502 | ref = [] |
486 | 503 | if status == "": |
487 | status = "opened" | |
504 | status = "open" | |
488 | 505 | if impact is None: |
489 | 506 | impact = {} |
490 | 507 | if policyviolations is None: |
592 | 609 | |
593 | 610 | |
594 | 611 | class PluginByExtension(PluginBase): |
595 | def __init__(self, ignore_info=False): | |
596 | super().__init__(ignore_info) | |
612 | def __init__(self, ignore_info=False, hostname_resolution=True, *args, **kwargs): | |
613 | super().__init__(ignore_info, hostname_resolution) | |
597 | 614 | self.extension = [] |
598 | 615 | |
599 | 616 | def report_belongs_to(self, extension="", **kwargs): |
608 | 625 | |
609 | 626 | class PluginXMLFormat(PluginByExtension): |
610 | 627 | |
611 | def __init__(self, ignore_info=False): | |
612 | super().__init__(ignore_info) | |
628 | def __init__(self, ignore_info=False, hostname_resolution=True, *args, **kwargs): | |
629 | super().__init__(ignore_info, hostname_resolution) | |
613 | 630 | self.identifier_tag = [] |
614 | 631 | self.identifier_tag_attributes = {} |
615 | 632 | self.extension = ".xml" |
630 | 647 | |
631 | 648 | class PluginJsonFormat(PluginByExtension): |
632 | 649 | |
633 | def __init__(self, ignore_info=False): | |
634 | super().__init__(ignore_info) | |
650 | def __init__(self, ignore_info=False, hostname_resolution=True, *args, **kwargs): | |
651 | super().__init__(ignore_info, hostname_resolution) | |
635 | 652 | self.json_keys = set() |
636 | 653 | self.extension = ".json" |
637 | 654 | |
647 | 664 | |
648 | 665 | class PluginMultiLineJsonFormat(PluginByExtension): |
649 | 666 | |
650 | def __init__(self, ignore_info=False): | |
651 | super().__init__(ignore_info) | |
667 | def __init__(self, ignore_info=False, hostname_resolution=True, *args, **kwargs): | |
668 | super().__init__(ignore_info, hostname_resolution) | |
652 | 669 | self.json_keys = set() |
653 | 670 | self.extension = ".json" |
654 | 671 | |
671 | 688 | |
672 | 689 | class PluginCSVFormat(PluginByExtension): |
673 | 690 | |
674 | def __init__(self, ignore_info=False): | |
675 | super().__init__(ignore_info) | |
691 | def __init__(self, ignore_info=False, hostname_resolution=True, *args, **kwargs): | |
692 | super().__init__(ignore_info, hostname_resolution) | |
676 | 693 | self.extension = ".csv" |
677 | 694 | self.csv_headers = set() |
678 | 695 | |
691 | 708 | |
692 | 709 | class PluginZipFormat(PluginByExtension): |
693 | 710 | |
694 | def __init__(self, ignore_info=False): | |
695 | super().__init__(ignore_info) | |
711 | def __init__(self, ignore_info=False, hostname_resolution=True, *args, **kwargs): | |
712 | super().__init__(ignore_info, hostname_resolution) | |
696 | 713 | self.extension = ".zip" |
697 | 714 | self.files_list = set() |
698 | 715 |
19 | 19 | """Given a URL, return kwargs to pass to createAndAddVulnWebToService.""" |
20 | 20 | parse = urlsplit(url) |
21 | 21 | return { |
22 | "website": "{}://{}".format(parse.scheme, parse.netloc), | |
22 | "website": f"{parse.scheme}://{parse.netloc}", | |
23 | 23 | "path": parse.path, |
24 | 24 | "query": parse.query |
25 | 25 | } |
93 | 93 | 'mobility-header' |
94 | 94 | ] |
95 | 95 | |
96 | for item in protocols: | |
97 | yield item | |
98 | ||
99 | ||
100 | def resolve_hostname(hostname): | |
101 | try: | |
102 | socket.inet_aton(hostname) # is already an ip | |
103 | return hostname | |
104 | except socket.error: | |
105 | pass | |
106 | try: | |
107 | ip_address = socket.gethostbyname(hostname) | |
108 | except Exception as e: | |
109 | return hostname | |
110 | else: | |
111 | return ip_address | |
96 | yield from protocols | |
112 | 97 | |
113 | 98 | |
114 | 99 | def get_severity_from_cvss(cvss): |
9 | 9 | from lxml import etree |
10 | 10 | |
11 | 11 | from faraday_plugins.plugins.plugin import PluginXMLFormat |
12 | from faraday_plugins.plugins.plugins_utils import resolve_hostname | |
13 | 12 | from faraday_plugins.plugins.repo.acunetix.DTO import Acunetix, Scan |
14 | 13 | |
15 | 14 | __author__ = "Francisco Amato" |
106 | 105 | host = request_host[0] |
107 | 106 | url = f'http://{host}' |
108 | 107 | url_data = urlsplit(url) |
109 | site_ip = resolve_hostname(host) | |
108 | site_ip = self.resolve_hostname(host) | |
110 | 109 | h_id = self.createAndAddHost(site_ip, site.os, hostnames=[host]) |
111 | 110 | s_id = self.createAndAddServiceToHost( |
112 | 111 | h_id, |
120 | 119 | self.logger.warning("No host in request") |
121 | 120 | |
122 | 121 | def old_structure(self, url_data, site: Scan): |
123 | site_ip = resolve_hostname(url_data.hostname) | |
122 | site_ip = self.resolve_hostname(url_data.hostname) | |
124 | 123 | if url_data.hostname: |
125 | 124 | hostnames = [url_data.hostname] |
126 | 125 | else: |
174 | 173 | return url_data |
175 | 174 | |
176 | 175 | |
177 | def createPlugin(ignore_info=False): | |
178 | return AcunetixPlugin(ignore_info=ignore_info) | |
176 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
177 | return AcunetixPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
7 | 7 | |
8 | 8 | from lxml import etree |
9 | 9 | |
10 | from faraday_plugins.plugins.plugin import PluginXMLFormat, PluginJsonFormat | |
11 | from faraday_plugins.plugins.plugins_utils import resolve_hostname | |
10 | from faraday_plugins.plugins.plugin import PluginJsonFormat | |
12 | 11 | from faraday_plugins.plugins.repo.acunetix.DTO import Acunetix, Scan |
13 | 12 | from json import loads |
14 | 13 | |
93 | 92 | def new_structure(self, site: Scan): |
94 | 93 | start_url = site.info.host |
95 | 94 | url_data = urlsplit(start_url) |
96 | site_ip = resolve_hostname(url_data.hostname) | |
95 | site_ip = self.resolve_hostname(url_data.hostname) | |
97 | 96 | ports = '443' if (url_data.scheme == 'https') else '80' |
98 | 97 | vulnerability_type = {i.vt_id: i for i in site.vul_types} |
99 | 98 | h_id = self.createAndAddHost(site_ip, None, hostnames=[url_data.hostname]) |
131 | 130 | return url_data |
132 | 131 | |
133 | 132 | |
134 | def createPlugin(ignore_info=False): | |
135 | return AcunetixJsonPlugin(ignore_info=ignore_info) | |
133 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
134 | return AcunetixJsonPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
136 | 136 | return final |
137 | 137 | |
138 | 138 | |
139 | def createPlugin(ignore_info=False): | |
140 | return AmapPlugin(ignore_info=ignore_info) | |
139 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
140 | return AmapPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
0 | 0 | from urllib.parse import urlparse |
1 | 1 | |
2 | 2 | from faraday_plugins.plugins.plugin import PluginXMLFormat |
3 | from faraday_plugins.plugins.plugins_utils import resolve_hostname | |
4 | 3 | |
5 | 4 | import xml.etree.ElementTree as ET |
6 | 5 | |
34 | 33 | try: |
35 | 34 | tree = ET.fromstring(xml_output) |
36 | 35 | except SyntaxError as err: |
37 | print('SyntaxError In xml: %s. %s' % (err, xml_output)) | |
36 | print(f'SyntaxError In xml: {err}. {xml_output}') | |
38 | 37 | return None |
39 | 38 | return tree |
40 | 39 | |
162 | 161 | } |
163 | 162 | if cve: |
164 | 163 | issue_data["cve"].append(cve) |
164 | issue_data["desc"] += cve | |
165 | 165 | if cve_url: |
166 | 166 | issue_data["ref"].append(cve_url) |
167 | 167 | if cwe: |
181 | 181 | sast_issues = [] |
182 | 182 | for item in tree: |
183 | 183 | name = self.issue_types[item.find("issue-type/ref").text] |
184 | source_file = item.attrib["filename"].replace('\\','/') | |
184 | source_file = item.attrib["filename"].replace('\\', '/') | |
185 | 185 | severity = 0 if item.find("severity-id") is None else int(item.find("severity-id").text) |
186 | 186 | description = item.find("fix/item/general/text").text |
187 | 187 | resolution = "" if item.find("variant-group/item/issue-information/fix-resolution-text") is None \ |
217 | 217 | "cve": [] |
218 | 218 | } |
219 | 219 | |
220 | if cve: | |
221 | issue_data["cve"].append(cve) | |
222 | 220 | if cve_url: |
223 | 221 | issue_data["ref"].append(cve_url) |
224 | 222 | if cwe: |
231 | 229 | issue_data["ref"].append(cvss_temporal_vector) |
232 | 230 | if cvss_environmental_vector: |
233 | 231 | issue_data["ref"].append(cvss_environmental_vector) |
232 | if cve: | |
233 | issue_data["cve"].append(cve) | |
234 | issue_data["desc"] += f"\nCVE: {cve}" | |
234 | 235 | # Build data |
235 | 236 | data = [] |
236 | 237 | if item.attrib.get("caller"): |
240 | 241 | if item.find("variant-group/item/issue-information/method-signature2") is not None: |
241 | 242 | data.append(f"Location: {item.find('variant-group/item/issue-information/method-signature2').text}") |
242 | 243 | issue_data['data'] = "\n".join(data) |
244 | issue_data['desc'] += "\n".join(data) | |
243 | 245 | sast_issues.append(issue_data) |
244 | 246 | return sast_issues |
245 | 247 | |
264 | 266 | host = issue.pop("host") |
265 | 267 | port = issue.pop("port") |
266 | 268 | service_name = issue.pop("service_name") |
267 | ip = resolve_hostname(host) | |
269 | ip = self.resolve_hostname(host) | |
268 | 270 | host_os = issue.pop("os") |
269 | 271 | host_id = self.createAndAddHost(ip, hostnames=host, os=host_os) |
270 | 272 | service_id = self.createAndAddServiceToHost(host_id, service_name, ports=port) |
277 | 279 | self.createAndAddVulnToHost(host_id=host_id, **issue) |
278 | 280 | |
279 | 281 | |
280 | def createPlugin(ignore_info=False): | |
281 | return AppScanPlugin(ignore_info=ignore_info) | |
282 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
283 | return AppScanPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
0 | """ | |
1 | Faraday Penetration Test IDE | |
2 | Copyright (C) 2017 Infobyte LLC (http://www.infobytesec.com/) | |
3 | See the file 'doc/LICENSE' for the license information | |
4 | ||
5 | """ |
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 | ||
7 | from faraday_plugins.plugins.plugin import PluginCSVFormat | |
8 | from urllib.parse import urlparse | |
9 | from itertools import islice | |
10 | import csv | |
11 | import sys | |
12 | import dateutil | |
13 | ||
14 | __author__ = "Erodriguez" | |
15 | __copyright__ = "Copyright (c) 2019, Infobyte LLC" | |
16 | __credits__ = ["Erodriguez"] | |
17 | __license__ = "" | |
18 | __version__ = "1.0.0" | |
19 | __maintainer__ = "Erodriguez" | |
20 | __email__ = "[email protected]" | |
21 | __status__ = "Development" | |
22 | ||
23 | ||
24 | class Appscan_CSV_Plugin(PluginCSVFormat): | |
25 | """ | |
26 | Example plugin to parse Appscan output. | |
27 | """ | |
28 | ||
29 | def __init__(self, *arg, **kwargs): | |
30 | super().__init__(*arg, **kwargs) | |
31 | self.csv_headers = {'HCL AppScan on Cloud'} | |
32 | self.id = "Appscan_CSV" | |
33 | self.name = "Appscan CSV Output Plugin" | |
34 | self.plugin_version = "0.0.1" | |
35 | self.version = "0.0.1" | |
36 | self.framework_version = "1.0.1" | |
37 | ||
38 | def _parse_filename(self, filename): | |
39 | with open(filename) as output: | |
40 | self.parseOutputString(islice(output, 15, None)) | |
41 | ||
42 | def parseOutputString(self, output): | |
43 | try: | |
44 | reader = csv.DictReader(output) | |
45 | except: | |
46 | print("Error parser output") | |
47 | return None | |
48 | ||
49 | for row in reader: | |
50 | #Skip Fix Group | |
51 | if row["Issue Id"] == "Fix Group Attributes:": | |
52 | break | |
53 | path = row['Location'] | |
54 | if not path: | |
55 | continue | |
56 | try: | |
57 | run_date = dateutil.parser.parse(row['Date Created']) | |
58 | except: | |
59 | run_date = None | |
60 | name = row["Issue Type Name"] | |
61 | references = [] | |
62 | if row["Cwe"]: | |
63 | references.append(f"CWE-{row['Cwe']}") | |
64 | if row["Cve"]: | |
65 | references.append(row["Cve"]) | |
66 | data = [] | |
67 | if row['Security Risk']: | |
68 | data.append(f"Security Risk: {row['Security Risk']}") | |
69 | desc = [row['Description']] | |
70 | if row['Line']: | |
71 | desc.append(f"Line: {row['Line']}") | |
72 | if row['Cause']: | |
73 | desc.append(f"Cause: {row['Cause']}") | |
74 | if row['Threat Class']: | |
75 | desc.append(f"Threat Class: {row['Threat Class']}") | |
76 | if row['Security Risk']: | |
77 | desc.append(f"Security Risk: {row['Security Risk']}") | |
78 | if row['Calling Method']: | |
79 | desc.append(f"Calling Method: {row['Calling Method']}") | |
80 | h_id = self.createAndAddHost(name=path) | |
81 | self.createAndAddVulnToHost( | |
82 | h_id, | |
83 | name=name, | |
84 | desc=" \n".join(desc), | |
85 | resolution=row['Remediation'], | |
86 | external_id=row['Issue Id'], | |
87 | run_date=run_date, | |
88 | severity=row["Severity"], | |
89 | ref=references, | |
90 | data=" \n".join(data) | |
91 | ) | |
92 | ||
93 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
94 | return Appscan_CSV_Plugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
0 | 0 | #!/usr/bin/env python |
1 | # -*- coding: utf-8 -*- | |
2 | 1 | """ |
3 | 2 | Faraday Penetration Test IDE |
4 | 3 | Copyright (C) 2016 Infobyte LLC (http://www.infobytesec.com/) |
31 | 30 | try: |
32 | 31 | tree = ET.fromstring(xml_output) |
33 | 32 | except SyntaxError as err: |
34 | print('SyntaxError In xml: %s. %s' % (err, xml_output)) | |
33 | print(f'SyntaxError In xml: {err}. {xml_output}') | |
35 | 34 | return None |
36 | 35 | return tree |
37 | 36 | |
112 | 111 | external_id=vuln_external_id, data=str_data) |
113 | 112 | |
114 | 113 | |
115 | def createPlugin(ignore_info=False): | |
116 | return AppSpiderPlugin(ignore_info=ignore_info) | |
114 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
115 | return AppSpiderPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
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 resolve_hostname | |
12 | 11 | |
13 | 12 | __author__ = 'Ezequiel Tavella' |
14 | 13 | __copyright__ = 'Copyright 2016, Faraday Project' |
164 | 163 | data = request.findtext("method", "").upper() |
165 | 164 | data += f" {request.findtext('url', '')}" |
166 | 165 | for h in request.findall('headers/header'): |
167 | data += "\n%s: %s" % (h.get('name'), h.get('value')) | |
166 | data += f"\n{h.get('name')}: {h.get('value')}" | |
168 | 167 | if request.findtext('body',""): |
169 | data += "\n%s" % request.findtext('body',"") | |
168 | data += f"\n{request.findtext('body','')}" | |
170 | 169 | return data |
171 | 170 | |
172 | 171 | @staticmethod |
419 | 418 | |
420 | 419 | self.hostname = self.getHostname(parser.system.url) |
421 | 420 | if parser.plugins.ip: |
422 | self.address = resolve_hostname(parser.plugins.ip) | |
423 | else: | |
424 | self.address = resolve_hostname(self.hostname) | |
421 | self.address = self.resolve_hostname(parser.plugins.ip) | |
422 | else: | |
423 | self.address = self.resolve_hostname(self.hostname) | |
425 | 424 | |
426 | 425 | # Create host and interface |
427 | 426 | host_id = self.createAndAddHost(self.address, hostnames=[self.hostname]) |
494 | 493 | # add reporter |
495 | 494 | cmd_prefix_match = re.match(r"(^.*?)arachni ", command_string) |
496 | 495 | cmd_prefix = cmd_prefix_match.group(1) |
497 | reporter_cmd = "%s%s --reporter=\"xml:outfile=%s\" \"%s\"" % (cmd_prefix, "arachni_reporter", xml_file_path, | |
496 | reporter_cmd = "{}{} --reporter=\"xml:outfile={}\" \"{}\"".format(cmd_prefix, "arachni_reporter", xml_file_path, | |
498 | 497 | afr_file_path) |
499 | return "/usr/bin/env -- bash -c '%s 2>&1 && if [ -e \"%s\" ];then %s 2>&1;fi'" % (main_cmd, | |
498 | return "/usr/bin/env -- bash -c '{} 2>&1 && if [ -e \"{}\" ];then {} 2>&1;fi'".format(main_cmd, | |
500 | 499 | afr_file_path, |
501 | 500 | reporter_cmd) |
502 | 501 | |
516 | 515 | return self.hostname |
517 | 516 | |
518 | 517 | |
519 | def createPlugin(ignore_info=False): | |
520 | return ArachniPlugin(ignore_info=ignore_info) | |
518 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
519 | return ArachniPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
59 | 59 | |
60 | 60 | |
61 | 61 | |
62 | def createPlugin(ignore_info=False): | |
63 | return CmdArpScanPlugin(ignore_info=ignore_info) | |
64 | ||
62 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
63 | return CmdArpScanPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
67 | 67 | return vulns |
68 | 68 | |
69 | 69 | |
70 | def createPlugin(ignore_info=False): | |
71 | return BanditPlugin(ignore_info=ignore_info) | |
70 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
71 | return BanditPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
95 | 95 | |
96 | 96 | |
97 | 97 | |
98 | def createPlugin(ignore_info=False): | |
99 | return BeefPlugin(ignore_info=ignore_info) | |
100 | ||
98 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
99 | return BeefPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
11 | 11 | __version__ = "1.0.0" |
12 | 12 | |
13 | 13 | from faraday_plugins.plugins.plugin import PluginBase |
14 | from faraday_plugins.plugins.plugins_utils import resolve_hostname | |
15 | 14 | |
16 | 15 | |
17 | 16 | class brutexss (PluginBase): |
32 | 31 | found_vuln = False |
33 | 32 | for linea in lineas: |
34 | 33 | if linea.find("is available! Good!") > 0: |
35 | url = re.findall('(?:[-\w.]|(?:%[\da-fA-F]{2}))+', linea)[0] | |
34 | url = re.findall(r'(?:[-\w.]|(?:%[\da-fA-F]{2}))+', linea)[0] | |
36 | 35 | port = 80 |
37 | 36 | if urlparse(url).scheme == 'https': |
38 | 37 | port = 443 |
40 | 39 | if len(netloc_splitted) > 1: |
41 | 40 | port = netloc_splitted[1] |
42 | 41 | if linea.find("Vulnerable") > 0 and "No" not in linea: |
43 | vuln_list = re.findall("\w+", linea) | |
42 | vuln_list = re.findall(r"\w+", linea) | |
44 | 43 | if vuln_list[2] == "Vulnerable": |
45 | 44 | parametro.append(vuln_list[1]) |
46 | 45 | found_vuln = len(parametro) > 0 |
47 | address = resolve_hostname(url) | |
46 | address = self.resolve_hostname(url) | |
48 | 47 | host_id = self.createAndAddHost(url, hostnames=[url]) |
49 | 48 | service_id = self.createAndAddServiceToHost(host_id, self.protocol, 'tcp', |
50 | 49 | ports=[port], status='Open', version="", |
56 | 55 | |
57 | 56 | |
58 | 57 | |
59 | def createPlugin(ignore_info=False): | |
60 | return brutexss(ignore_info=ignore_info) | |
61 | ||
62 | ||
58 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
59 | return brutexss(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
59 | 59 | try: |
60 | 60 | tree = ET.fromstring(xml_output) |
61 | 61 | except SyntaxError as err: |
62 | print("SyntaxError: %s. %s" % (err, xml_output)) | |
62 | print(f"SyntaxError: {err}. {xml_output}") | |
63 | 63 | return None |
64 | 64 | |
65 | 65 | return tree |
104 | 104 | external_id = item_node.findall('type')[0] |
105 | 105 | request = self.decode_binary_node('./requestresponse/request') |
106 | 106 | response = self.decode_binary_node('./requestresponse/response') |
107 | ||
108 | 107 | detail = self.do_clean(item_node.findall('issueDetail')) |
109 | 108 | remediation = self.do_clean(item_node.findall('remediationBackground')) |
110 | 109 | background = self.do_clean(item_node.findall('issueBackground')) |
110 | self.references = self.do_clean(item_node.findall('references')) | |
111 | self.vulnClass = self.do_clean(item_node.findall('vulnerabilityClassifications')) | |
111 | 112 | self.cve = [] |
112 | 113 | if background: |
113 | 114 | cve = CVE_regex.search(background) |
126 | 127 | else 80) |
127 | 128 | |
128 | 129 | self.name = name.text |
129 | self.location = location.text | |
130 | 130 | self.path = path.text |
131 | loc = re.search(r"(?<=\[).+?(?=\])", location.text.replace(self.path, "")) | |
132 | self.location = loc.group().split(" ")[0] if loc else "" | |
131 | 133 | |
132 | 134 | self.ip = host_node.get('ip') |
133 | 135 | self.url = self.node.get('url') |
143 | 145 | def do_clean(value): |
144 | 146 | |
145 | 147 | myreturn = "" |
146 | if value is not None: | |
147 | if len(value) > 0: | |
148 | myreturn = value[0].text | |
148 | if value is not None and len(value) > 0: | |
149 | myreturn = value[0].text | |
149 | 150 | return myreturn |
150 | 151 | |
151 | 152 | def decode_binary_node(self, path): |
209 | 210 | ports=[str(item.port)], |
210 | 211 | status="open") |
211 | 212 | |
213 | desc = "" | |
212 | 214 | if item.background: |
213 | desc = item.background | |
214 | else: | |
215 | desc = "" | |
215 | desc += item.background | |
216 | 216 | desc = self.removeHtml(desc) |
217 | data = "" | |
217 | 218 | if item.detail: |
218 | data = item.detail | |
219 | else: | |
220 | data = "" | |
221 | data = self.removeHtml(data) | |
219 | desc += self.removeHtml(item.detail) | |
220 | data = self.removeHtml(item.detail) | |
221 | ref = [] | |
222 | if item.references: | |
223 | ref += self.get_url(item.references) | |
224 | if item.vulnClass: | |
225 | ref += self.get_ref(item.vulnClass) | |
226 | ||
222 | 227 | resolution = self.removeHtml(item.remediation) if item.remediation else "" |
223 | 228 | |
224 | 229 | self.createAndAddVulnWebToService( |
233 | 238 | request=item.request, |
234 | 239 | response=item.response, |
235 | 240 | resolution=resolution, |
241 | ref=ref, | |
242 | params=item.location, | |
236 | 243 | external_id=item.external_id, |
237 | 244 | cve=item.cve |
238 | 245 | ) |
266 | 273 | |
267 | 274 | return str(soup) |
268 | 275 | |
269 | ||
270 | def createPlugin(ignore_info=False): | |
271 | return BurpPlugin(ignore_info=ignore_info) | |
276 | def get_ref(self, markup): | |
277 | soup = BeautifulSoup(markup, "html.parser") | |
278 | ||
279 | for tag in soup.find_all("ul"): | |
280 | for item in tag.find_all("li"): | |
281 | for a in item.find_all("a"): | |
282 | a.unwrap() | |
283 | item.unwrap() | |
284 | tag.unwrap() | |
285 | ref = str(soup).strip().split("\n") | |
286 | return ref | |
287 | ||
288 | def get_url(self, markup): | |
289 | soup = BeautifulSoup(markup, "html.parser") | |
290 | ref = [] | |
291 | for tag in soup.find_all("ul"): | |
292 | for item in tag.find_all("li"): | |
293 | for a in item.find_all("a"): | |
294 | ref += [a['href'].strip()] | |
295 | return ref | |
296 | ||
297 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
298 | return BurpPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
28 | 28 | try: |
29 | 29 | tree = ET.fromstring(xml_output) |
30 | 30 | except SyntaxError as err: |
31 | print('SyntaxError In xml: %s. %s' % (err, xml_output)) | |
31 | print(f'SyntaxError In xml: {err}. {xml_output}') | |
32 | 32 | return None |
33 | 33 | return tree |
34 | 34 | |
131 | 131 | resolution=data, ref=refs) |
132 | 132 | |
133 | 133 | |
134 | def createPlugin(ignore_info=False): | |
135 | return CheckmarxPlugin(ignore_info=ignore_info) | |
134 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
135 | return CheckmarxPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
20 | 20 | __email__ = "[email protected]" |
21 | 21 | __status__ = "Development" |
22 | 22 | |
23 | from faraday_plugins.plugins.plugins_utils import resolve_hostname | |
24 | 23 | |
25 | 24 | |
26 | 25 | class CobaltParser: |
84 | 83 | port = 80 |
85 | 84 | else: |
86 | 85 | port = url_data.port |
87 | name = resolve_hostname(url_data.netloc) | |
86 | name = self.resolve_hostname(url_data.netloc) | |
88 | 87 | references = [] |
89 | 88 | if row['RefKey']: |
90 | 89 | references.append(row['RefKey']) |
101 | 100 | data=row['StepsToReproduce'], external_id=row['Tag'], run_date=run_date) |
102 | 101 | |
103 | 102 | |
104 | def createPlugin(ignore_info=False): | |
105 | return CobaltPlugin(ignore_info=ignore_info) | |
103 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
104 | return CobaltPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
6 | 6 | """ |
7 | 7 | import re |
8 | 8 | |
9 | __author__ = u"Andres Tarantini" | |
10 | __copyright__ = u"Copyright (c) 2015 Andres Tarantini" | |
11 | __credits__ = [u"Andres Tarantini"] | |
12 | __license__ = u"MIT" | |
13 | __version__ = u"0.0.1" | |
14 | __maintainer__ = u"Andres Tarantini" | |
15 | __email__ = u"[email protected]" | |
16 | __status__ = u"Development" | |
9 | __author__ = "Andres Tarantini" | |
10 | __copyright__ = "Copyright (c) 2015 Andres Tarantini" | |
11 | __credits__ = ["Andres Tarantini"] | |
12 | __license__ = "MIT" | |
13 | __version__ = "0.0.1" | |
14 | __maintainer__ = "Andres Tarantini" | |
15 | __email__ = "[email protected]" | |
16 | __status__ = "Development" | |
17 | 17 | |
18 | 18 | from faraday_plugins.plugins.plugin import PluginBase |
19 | from faraday_plugins.plugins.plugins_utils import resolve_hostname | |
20 | 19 | |
21 | 20 | |
22 | 21 | class DigPlugin(PluginBase): |
35 | 34 | def parseOutputString(self, output): |
36 | 35 | # Ignore all lines that start with ";" |
37 | 36 | parsed_output = [line for line in output.splitlines() if line and line[ |
38 | 0] != u";"] | |
37 | 0] != ";"] | |
39 | 38 | if not parsed_output: |
40 | 39 | return True |
41 | 40 | |
42 | 41 | # Parse results |
43 | 42 | results = [] |
44 | answer_section_columns = [u"domain", | |
45 | u"ttl", u"class", u"type", u"data"] | |
43 | answer_section_columns = ["domain", | |
44 | "ttl", "class", "type", "data"] | |
46 | 45 | for line in parsed_output: |
47 | 46 | line_split = line.split() # the first 4 elements are domain, ttl, class, type; everything else data |
48 | 47 | results.append(dict(zip(answer_section_columns, line_split[:4] + [line_split[4:]] ))) |
50 | 49 | # Create hosts is results information is relevant |
51 | 50 | try: |
52 | 51 | for result in results: |
53 | relevant_types = [u"A", u"AAAA", u"MX", u"NS", u"SOA", u"TXT"] | |
52 | relevant_types = ["A", "AAAA", "MX", "NS", "SOA", "TXT"] | |
54 | 53 | # TODO implement more types from https://en.wikipedia.org/wiki/List_of_DNS_record_types |
55 | 54 | |
56 | if result.get(u"type") in relevant_types: | |
55 | if result.get("type") in relevant_types: | |
57 | 56 | |
58 | 57 | # get domain |
59 | domain = result.get(u"domain") | |
58 | domain = result.get("domain") | |
60 | 59 | |
61 | 60 | |
62 | 61 | # get IP address (special if type "A") |
63 | if result.get(u"type") == u"A": # A = IPv4 address from dig | |
64 | ip_address = result.get(u"data")[0] | |
62 | if result.get("type") == "A": # A = IPv4 address from dig | |
63 | ip_address = result.get("data")[0] | |
65 | 64 | else: # if not, from socket |
66 | ip_address = resolve_hostname(domain) | |
65 | ip_address = self.resolve_hostname(domain) | |
67 | 66 | |
68 | 67 | # Create host |
69 | 68 | host_id = self.createAndAddHost(ip_address, hostnames=[domain]) |
70 | 69 | |
71 | 70 | |
72 | 71 | # all other TYPES that aren't 'A' and 'AAAA' are dealt here: |
73 | if result.get(u"type") == u"MX": # Mail exchange record | |
74 | mx_priority = result.get(u"data")[0] | |
75 | mx_record = result.get(u"data")[1] | |
72 | if result.get("type") == "MX": # Mail exchange record | |
73 | mx_priority = result.get("data")[0] | |
74 | mx_record = result.get("data")[1] | |
76 | 75 | |
77 | 76 | service_id = self.createAndAddServiceToHost( |
78 | 77 | host_id=host_id, |
88 | 87 | name="priority", |
89 | 88 | text=text.encode('ascii', 'ignore')) |
90 | 89 | |
91 | elif result.get(u"type") == u"NS": # Name server record | |
92 | ns_record = result.get(u"data")[0] | |
90 | elif result.get("type") == "NS": # Name server record | |
91 | ns_record = result.get("data")[0] | |
93 | 92 | self.createAndAddServiceToHost( |
94 | 93 | name=ns_record, |
95 | 94 | protocol="DNS", |
96 | 95 | ports=[53], |
97 | 96 | description="DNS Server") |
98 | 97 | |
99 | elif result.get(u"type") == u"SOA": # Start of Authority Record | |
100 | ns_record = result.get(u"data")[0] # primary namer server | |
101 | responsible_party = result.get(u"data")[1] # responsible party of domain | |
102 | timestamp = result.get(u"data")[2] | |
103 | refresh_zone_time = result.get(u"data")[3] | |
104 | retry_refresh_time = result.get(u"data")[4] | |
105 | upper_limit_time = result.get(u"data")[5] | |
106 | negative_result_ttl = result.get(u"data")[6] | |
98 | elif result.get("type") == "SOA": # Start of Authority Record | |
99 | ns_record = result.get("data")[0] # primary namer server | |
100 | responsible_party = result.get("data")[1] # responsible party of domain | |
101 | timestamp = result.get("data")[2] | |
102 | refresh_zone_time = result.get("data")[3] | |
103 | retry_refresh_time = result.get("data")[4] | |
104 | upper_limit_time = result.get("data")[5] | |
105 | negative_result_ttl = result.get("data")[6] | |
107 | 106 | |
108 | 107 | service_id = self.createAndAddServiceToHost( |
109 | 108 | host_id=host_id, |
126 | 125 | name="priority", |
127 | 126 | text=text.encode('ascii', 'ignore')) |
128 | 127 | |
129 | elif result.get(u"type") == u"TXT": # TXT record | |
130 | text = " ".join(result.get(u"data")[:]) | |
128 | elif result.get("type") == "TXT": # TXT record | |
129 | text = " ".join(result.get("data")[:]) | |
131 | 130 | self.createAndAddNoteToHost( |
132 | 131 | host_id=host_id, |
133 | 132 | name="TXT Information", |
140 | 139 | return True |
141 | 140 | |
142 | 141 | |
143 | def createPlugin(ignore_info=False): | |
144 | return DigPlugin(ignore_info=ignore_info) | |
145 | ||
146 | ||
142 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
143 | return DigPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
13 | 13 | __status__ = "Development" |
14 | 14 | |
15 | 15 | from faraday_plugins.plugins.plugin import PluginBase |
16 | from faraday_plugins.plugins.plugins_utils import resolve_hostname | |
17 | 16 | |
18 | 17 | |
19 | 18 | class dirbPlugin(PluginBase): |
40 | 39 | |
41 | 40 | def getIP(self, host): |
42 | 41 | try: |
43 | ip = resolve_hostname(host) | |
42 | ip = self.resolve_hostname(host) | |
44 | 43 | except Exception: |
45 | 44 | pass |
46 | 45 | |
112 | 111 | arg_search = re.search(silent_mode_re,command_string) |
113 | 112 | if arg_search is None: |
114 | 113 | extra_arg +=" -S" |
115 | return "%s%s" % (command_string, extra_arg) | |
114 | return f"{command_string}{extra_arg}" | |
116 | 115 | |
117 | 116 | |
118 | def createPlugin(ignore_info=False): | |
119 | return dirbPlugin(ignore_info=ignore_info) | |
120 | ||
121 | ||
117 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
118 | return dirbPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
8 | 8 | import argparse |
9 | 9 | import urllib.parse as urlparse |
10 | 10 | from faraday_plugins.plugins.plugin import PluginBase |
11 | from faraday_plugins.plugins.plugins_utils import get_vulnweb_url_fields, resolve_hostname | |
11 | from faraday_plugins.plugins.plugins_utils import get_vulnweb_url_fields | |
12 | 12 | |
13 | 13 | |
14 | 14 | __author__ = "Matías Lang" |
82 | 82 | return |
83 | 83 | for (base_url, items) in data.items(): |
84 | 84 | base_split = urlparse.urlsplit(base_url) |
85 | ip = resolve_hostname(base_split.hostname) | |
85 | ip = self.resolve_hostname(base_split.hostname) | |
86 | 86 | h_id = self.createAndAddHost(ip, hostnames=[base_split.hostname]) |
87 | 87 | s_id = self.createAndAddServiceToHost( |
88 | 88 | h_id, |
103 | 103 | item['content-length']) |
104 | 104 | redirect = item.get('redirect') |
105 | 105 | if redirect is not None: |
106 | response += '\nLocation: {}'.format(redirect) | |
106 | response += f'\nLocation: {redirect}' | |
107 | 107 | self.createAndAddVulnWebToService( |
108 | 108 | h_id, |
109 | 109 | s_id, |
110 | name='Path found: {} ({})'.format(item['path'], item['status']), | |
111 | desc="Dirsearch tool found the following URL: {}".format( | |
112 | url.geturl()), | |
110 | name=f'Path found: {item["path"]} ({item["status"]})', | |
111 | desc=f"Dirsearch tool found the following URL: {url.geturl()}", | |
113 | 112 | severity="info", |
114 | 113 | method='GET', |
115 | 114 | response=response, |
128 | 127 | return None |
129 | 128 | else: |
130 | 129 | super().processCommandString(username, current_path, command_string) |
131 | return '{} --json-report {}'.format(command_string, self._output_file_path) | |
130 | return f'{command_string} --json-report {self._output_file_path}' | |
132 | 131 | |
133 | 132 | |
134 | def createPlugin(ignore_info=False): | |
135 | return DirsearchPlugin(ignore_info=ignore_info) | |
136 | ||
133 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
134 | return DirsearchPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
49 | 49 | try: |
50 | 50 | tree = ET.fromstring(xml_output) |
51 | 51 | except SyntaxError as err: |
52 | print("SyntaxError: %s. %s" % (err, xml_output)) | |
52 | print(f"SyntaxError: {err}. {xml_output}") | |
53 | 53 | return None |
54 | 54 | |
55 | 55 | return tree |
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): | |
168 | return DnsenumPlugin(ignore_info=ignore_info) | |
167 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
168 | return DnsenumPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
129 | 129 | arg_match = self.xml_arg_re.match(command_string) |
130 | 130 | |
131 | 131 | if arg_match is None: |
132 | return "%s -r %s \\n" % (command_string, self._output_file_path) | |
132 | return f"{command_string} -r {self._output_file_path} \\n" | |
133 | 133 | else: |
134 | 134 | return re.sub(arg_match.group(1), |
135 | 135 | r"-r %s" % self._output_file_path, |
136 | 136 | command_string) |
137 | 137 | |
138 | 138 | |
139 | def createPlugin(ignore_info=False): | |
140 | return DnsmapPlugin(ignore_info=ignore_info) | |
139 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
140 | return DnsmapPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
49 | 49 | try: |
50 | 50 | tree = ET.fromstring(xml_output) |
51 | 51 | except SyntaxError as err: |
52 | print("SyntaxError: %s. %s" % (err, xml_output)) | |
52 | print(f"SyntaxError: {err}. {xml_output}") | |
53 | 53 | return None |
54 | 54 | |
55 | 55 | return tree |
211 | 211 | command_string) |
212 | 212 | |
213 | 213 | |
214 | def createPlugin(ignore_info=False): | |
215 | return DnsreconPlugin(ignore_info=ignore_info) | |
214 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
215 | return DnsreconPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
6 | 6 | import re |
7 | 7 | |
8 | 8 | from faraday_plugins.plugins.plugin import PluginBase |
9 | from faraday_plugins.plugins.plugins_utils import resolve_hostname | |
10 | 9 | |
11 | 10 | __author__ = "Francisco Amato" |
12 | 11 | __copyright__ = "Copyright (c) 2013, Infobyte LLC" |
31 | 30 | @param dnswalk_filepath A proper simple report generated by dnswalk |
32 | 31 | """ |
33 | 32 | |
34 | def __init__(self, output): | |
33 | def __init__(self, output, resolve_hostName): | |
35 | 34 | |
36 | 35 | lists = output.split("\n") |
37 | 36 | self.items = [] |
37 | self.resolve_hostName = resolve_hostName | |
38 | 38 | |
39 | 39 | for line in lists: |
40 | mregex = re.search("WARN: ([\w\.]+) ([\w]+) ([\w\.]+):", line) | |
40 | mregex = re.search(r"WARN: ([\w\.]+) ([\w]+) ([\w\.]+):", line) | |
41 | 41 | if mregex is not None: |
42 | 42 | item = { |
43 | 43 | 'host': mregex.group(1), |
47 | 47 | self.items.append(item) |
48 | 48 | |
49 | 49 | mregex = re.search( |
50 | "Getting zone transfer of ([\w\.]+) from ([\w\.]+)\.\.\.done\.", | |
50 | r"Getting zone transfer of ([\w\.]+) from ([\w\.]+)\.\.\.done\.", | |
51 | 51 | line) |
52 | 52 | |
53 | 53 | if mregex is not None: |
54 | ip = resolve_hostname(mregex.group(2)) | |
54 | ip = self.resolve_hostname(mregex.group(2)) | |
55 | 55 | item = { |
56 | 56 | 'host': mregex.group(1), |
57 | 57 | 'ip': ip, |
86 | 86 | """ |
87 | 87 | output is the shell output of command Dnswalk. |
88 | 88 | """ |
89 | parser = DnswalkParser(output) | |
89 | parser = DnswalkParser(output, self.resolve_hostname) | |
90 | 90 | |
91 | 91 | for item in parser.items: |
92 | 92 | if item['type'] == "A": |
108 | 108 | return True |
109 | 109 | |
110 | 110 | |
111 | def createPlugin(ignore_info=False): | |
112 | return DnswalkPlugin(ignore_info=ignore_info) | |
111 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
112 | return DnswalkPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
125 | 125 | |
126 | 126 | if (port and not protocol) or (protocol and not port): |
127 | 127 | self.logger.error( |
128 | ("Missing columns in CSV file. " | |
129 | "In order to import services, you need to add a column called port " | |
130 | " and a column called protocol.") | |
128 | "Missing columns in CSV file. " | |
129 | "In order to import services, you need to add a column called port " | |
130 | " and a column called protocol." | |
131 | 131 | ) |
132 | 132 | return None |
133 | 133 | else: |
139 | 139 | |
140 | 140 | if (vuln_name and not vuln_desc) or (vuln_desc and not vuln_name): |
141 | 141 | self.logger.error( |
142 | ("Missing columns in CSV file. " | |
143 | "In order to import vulnerabilities, you need to add a " | |
144 | "column called name and a column called desc.") | |
142 | "Missing columns in CSV file. " | |
143 | "In order to import vulnerabilities, you need to add a " | |
144 | "column called name and a column called desc." | |
145 | 145 | ) |
146 | 146 | return None |
147 | 147 | else: |
153 | 153 | def get_custom_fields_names(headers): |
154 | 154 | custom_fields_names = [] |
155 | 155 | for header in headers: |
156 | match = re.match(r"cf_(\w+)", header) | |
156 | match = re.match(r"cf_(\S+)", header) | |
157 | 157 | if match: |
158 | 158 | custom_fields_names.append(match.group(1)) |
159 | 159 | |
363 | 363 | ) |
364 | 364 | |
365 | 365 | |
366 | def createPlugin(ignore_info=False): | |
367 | return FaradayCSVPlugin(ignore_info=False) | |
366 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
367 | return FaradayCSVPlugin(ignore_info=ignore_info) |
4 | 4 | |
5 | 5 | """ |
6 | 6 | import re |
7 | import os | |
8 | import random | |
9 | 7 | |
10 | 8 | from faraday_plugins.plugins.plugin import PluginBase |
11 | from faraday_plugins.plugins.plugins_utils import resolve_hostname | |
12 | 9 | |
13 | 10 | |
14 | 11 | __author__ = "Francisco Amato" |
41 | 38 | self.items = [] |
42 | 39 | |
43 | 40 | regex = re.search( |
44 | "DNS Servers for ([\w\.-]+):\n([^$]+)Trying zone transfer first...", | |
41 | "DNS Servers for ([\\w\\.-]+):\n([^$]+)Trying zone transfer first...", | |
45 | 42 | output) |
46 | 43 | |
47 | 44 | if regex is not None: |
50 | 47 | self.dns = list(filter(None, mstr.splitlines())) |
51 | 48 | |
52 | 49 | regex = re.search( |
53 | "Now performing [\d]+ test\(s\)...\n([^$]+)\nSubnets found ", | |
50 | "Now performing [\\d]+ test\\(s\\)...\n([^$]+)\nSubnets found ", | |
54 | 51 | output) |
55 | 52 | if regex is not None: |
56 | 53 | hosts_list = regex.group(1).splitlines() |
118 | 115 | item['ip'] = i['ip'] |
119 | 116 | return item |
120 | 117 | try: |
121 | item['ip'] = resolve_hostname(item['ip']) | |
118 | item['ip'] = self.resolve_hostname(item['ip']) | |
122 | 119 | except: |
123 | 120 | pass |
124 | 121 | return item |
126 | 123 | def resolveNS(self, item, items): |
127 | 124 | try: |
128 | 125 | item['hosts'][0] = item['ip'] |
129 | item['ip'] = resolve_hostname(item['ip']) | |
126 | item['ip'] = self.resolve_hostname(item['ip']) | |
130 | 127 | except: |
131 | 128 | pass |
132 | 129 | return item |
138 | 135 | |
139 | 136 | item['isResolver'] = False |
140 | 137 | item['isZoneVuln'] = False |
141 | if (item['record'] == "CNAME"): | |
138 | if item['record'] == "CNAME": | |
142 | 139 | self.resolveCNAME(item, parser.items) |
143 | if (item['record'] == "NS"): | |
140 | if item['record'] == "NS": | |
144 | 141 | self.resolveNS(item, parser.items) |
145 | 142 | item['isResolver'] = True |
146 | 143 | item['isZoneVuln'] = parser.isZoneVuln |
174 | 171 | ref=["CVE-1999-0532"]) |
175 | 172 | |
176 | 173 | |
177 | ||
178 | def createPlugin(ignore_info=False): | |
179 | return FiercePlugin(ignore_info=ignore_info) | |
180 | ||
181 | ||
174 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
175 | return FiercePlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
57 | 57 | service_name, |
58 | 58 | protocol=protocol_name, |
59 | 59 | ports=[vuln_data['service']['port']]) |
60 | ||
61 | 60 | self.createAndAddVulnWebToService( |
62 | 61 | host_id, service_id, |
63 | 62 | vuln_data['name'], |
84 | 83 | |
85 | 84 | |
86 | 85 | class FortifyParser: |
87 | """ | |
86 | """ | |
88 | 87 | Parser for fortify on demand |
89 | 88 | """ |
90 | 89 | |
221 | 220 | references.append(classification.text) |
222 | 221 | |
223 | 222 | # Build description |
224 | description = u'' | |
223 | description = '' | |
225 | 224 | for report_section in issue_data.findall('./ReportSection'): |
226 | description += u'{} \n'.format(report_section.Name.text) | |
227 | description += u'{} \n'.format(report_section.SectionText.text) | |
228 | description += u'{} \n'.format(issue_data.get('id')) | |
225 | description += f'{report_section.Name.text} \n' | |
226 | description += f'{report_section.SectionText.text} \n' | |
227 | description += f'{issue_data.get("id")} \n' | |
229 | 228 | |
230 | 229 | h = html2text.HTML2Text() |
231 | 230 | description = h.handle(description) |
232 | 231 | |
233 | 232 | for repro_step in issue_data.findall('./ReproSteps'): |
234 | 233 | step = repro_step.ReproStep |
235 | ||
234 | ||
236 | 235 | if step is not None: |
237 | 236 | try: |
238 | 237 | params = step.PostParams.text |
258 | 257 | "method": method, |
259 | 258 | "query": query, |
260 | 259 | "response": response, |
261 | "request": request, | |
260 | "request": request.decode('utf-8'), | |
262 | 261 | "path": path, |
263 | 262 | "params": params, |
264 | 263 | "status_code": status_code, |
371 | 370 | idx = match.group(1) |
372 | 371 | if match.group(3): |
373 | 372 | idx = match.group(3) |
374 | _filekey = "{}.file".format(idx) | |
375 | _linekey = "{}.line".format(idx) | |
373 | _filekey = f"{idx}.file" | |
374 | _linekey = f"{idx}.line" | |
376 | 375 | text = text.replace(placeholder, "").replace( |
377 | 376 | torepl.format(_filekey), replacements[_filekey]).replace( |
378 | 377 | torepl.format(_linekey), replacements[_linekey]) |
386 | 385 | |
387 | 386 | text = text.replace(placeholder, replace_with) |
388 | 387 | |
389 | text += '{}\n Instance ID: {} \n'.format(text, vulnID) | |
388 | text += f'{text}\n Instance ID: {vulnID} \n' | |
390 | 389 | h = html2text.HTML2Text() |
391 | 390 | return text |
392 | 391 | |
393 | 392 | |
394 | def createPlugin(ignore_info=False): | |
395 | return FortifyPlugin(ignore_info=ignore_info) | |
396 | ||
393 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
394 | return FortifyPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
33 | 33 | self.options = None |
34 | 34 | self._current_output = None |
35 | 35 | self.target = None |
36 | ||
36 | ||
37 | 37 | self._command_regex = re.compile(r'^(fruitywifi)\s+.*?') |
38 | ||
38 | ||
39 | 39 | self.addSetting("Token", str, "e5dab9a69988dd65e578041416773149ea57a054") |
40 | 40 | self.addSetting("Server", str, "http://127.0.0.1:8000") |
41 | 41 | self.addSetting("Severity", str, "high") |
42 | ||
42 | ||
43 | 43 | def getSeverity(self, severity): |
44 | 44 | if severity.lower() == "critical" or severity == "4": |
45 | 45 | return 4 |
53 | 53 | return 0 |
54 | 54 | else: |
55 | 55 | return 5 |
56 | ||
56 | ||
57 | 57 | def createHostInterfaceVuln(self, ip_address, macaddress, hostname, desc, vuln_name, severity): |
58 | 58 | h_id = self.createAndAddHost(ip_address, hostnames=[hostname]) |
59 | 59 | |
64 | 64 | ref=["http://www.fruitywifi.com/"], |
65 | 65 | severity=severity |
66 | 66 | ) |
67 | ||
67 | ||
68 | 68 | def parseOutputString(self, output): |
69 | ||
69 | ||
70 | 70 | try: |
71 | 71 | output = json.loads(output) |
72 | ||
72 | ||
73 | 73 | if len(output) > 0: |
74 | ||
74 | ||
75 | 75 | if len(output[0]) == 3: |
76 | ||
76 | ||
77 | 77 | severity = self.getSeverity(self.getSetting("Severity")) |
78 | ||
78 | ||
79 | 79 | for item in output: |
80 | 80 | ip_address = item[0] |
81 | 81 | macaddress = item[1] |
82 | 82 | hostname = item[2] |
83 | 83 | vuln_name = "FruityWiFi" |
84 | 84 | severity = severity |
85 | ||
85 | ||
86 | 86 | desc = "Client ip: " + ip_address + \ |
87 | 87 | " has been connected to FruityWiFi\n" |
88 | 88 | desc += "More information:" |
89 | 89 | desc += "\nname: " + hostname |
90 | ||
90 | ||
91 | 91 | self.createHostInterfaceVuln(ip_address, macaddress, hostname, desc, vuln_name, severity) |
92 | ||
92 | ||
93 | 93 | elif len(output[0]) == 5: |
94 | 94 | for item in output: |
95 | 95 | ip_address = item[0] |
96 | 96 | macaddress = item[1] |
97 | 97 | hostname = item[2] |
98 | vuln_name = item[3] | |
98 | vuln_name = item[3] | |
99 | 99 | severity = item[4] |
100 | ||
100 | ||
101 | 101 | desc = "Client ip: " + ip_address + \ |
102 | 102 | " has been connected to FruityWiFi\n" |
103 | 103 | desc += "More information:" |
104 | 104 | desc += "\nname: " + hostname |
105 | ||
105 | ||
106 | 106 | self.createHostInterfaceVuln(ip_address, macaddress, hostname, desc, vuln_name, severity) |
107 | ||
107 | ||
108 | 108 | except: |
109 | 109 | traceback.print_exc() |
110 | ||
110 | ||
111 | 111 | return True |
112 | 112 | |
113 | 113 | def _isIPV4(self, ip): |
118 | 118 | |
119 | 119 | def processCommandString(self, username, current_path, command_string): |
120 | 120 | """ |
121 | """ | |
121 | """ | |
122 | 122 | super().processCommandString(username, current_path, command_string) |
123 | params = "-t %s -s %s" % (self.getSetting("Token"), self.getSetting("Server")) | |
124 | ||
123 | params = f"-t {self.getSetting('Token')} -s {self.getSetting('Server')}", | |
124 | ||
125 | 125 | return "python " + os.path.dirname(__file__) + "/fruitywifi.py " + params |
126 | 126 | |
127 | 127 | |
128 | 128 | |
129 | def createPlugin(ignore_info=False): | |
130 | return FruityWiFiPlugin(ignore_info=ignore_info) | |
131 | ||
132 | ||
129 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
130 | return FruityWiFiPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
7 | 7 | import os |
8 | 8 | |
9 | 9 | from faraday_plugins.plugins.plugin import PluginBase |
10 | from faraday_plugins.plugins.plugins_utils import resolve_hostname | |
11 | 10 | |
12 | 11 | |
13 | 12 | __author__ = "Javier Victor Mariano Bruno" |
46 | 45 | def parseOutputString(self, output): |
47 | 46 | |
48 | 47 | host_info = re.search(r"Connected to (.+)\.", output) |
49 | banner = re.search("220?([\w\W]+)$", output) | |
48 | banner = re.search(r"220?([\w\W]+)$", output) | |
50 | 49 | if re.search("Connection timed out", output) is None and host_info is not None: |
51 | 50 | hostname = host_info.group(1) |
52 | ip_address = resolve_hostname(hostname) | |
51 | ip_address = self.resolve_hostname(hostname) | |
53 | 52 | self._version = banner.groups(0) if banner else "" |
54 | 53 | h_id = self.createAndAddHost(ip_address, hostnames=[hostname]) |
55 | 54 | s_id = self.createAndAddServiceToHost( |
67 | 66 | count_args = command_string.split() |
68 | 67 | c = count_args.__len__() |
69 | 68 | self._port = "21" |
70 | if re.search("[\d]+", count_args[c - 1]): | |
69 | if re.search(r"[\d]+", count_args[c - 1]): | |
71 | 70 | self._port = count_args[c - 1] |
72 | 71 | |
73 | 72 | |
74 | def createPlugin(ignore_info=False): | |
75 | return CmdFtpPlugin(ignore_info=ignore_info) | |
76 | ||
77 | ||
73 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
74 | return CmdFtpPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
6 | 6 | import os |
7 | 7 | |
8 | 8 | from faraday_plugins.plugins.plugin import PluginBase |
9 | from faraday_plugins.plugins.plugins_utils import resolve_hostname | |
10 | 9 | |
11 | 10 | __author__ = "Francisco Amato" |
12 | 11 | __copyright__ = "Copyright (c) 2013, Infobyte LLC" |
29 | 28 | @param goohost_scantype You could select scan type ip, mail or host |
30 | 29 | """ |
31 | 30 | |
32 | def __init__(self, output, goohost_scantype): | |
31 | def __init__(self, output, goohost_scantype, resolve_hostname): | |
33 | 32 | |
34 | 33 | self.items = [] |
34 | self.resolve_hostname = resolve_hostname | |
35 | 35 | lines = list(filter(None, output.split('\n'))) |
36 | 36 | for line in lines: |
37 | 37 | if goohost_scantype == 'ip': |
40 | 40 | self.add_host_info_to_items(item['ip'], item['host']) |
41 | 41 | elif goohost_scantype == 'host': |
42 | 42 | data = line.strip() |
43 | item = {'host': data, 'ip': resolve_hostname(data)} | |
43 | item = {'host': data, 'ip': self.resolve_hostname(data)} | |
44 | 44 | self.add_host_info_to_items(item['ip'], item['host']) |
45 | 45 | else: |
46 | 46 | item = {'data': line} |
88 | 88 | |
89 | 89 | """ |
90 | 90 | scantype = self.define_scantype_by_output(output) |
91 | parser = GoohostParser(output, scantype) | |
91 | parser = GoohostParser(output, scantype, self.resolve_hostname) | |
92 | 92 | if scantype == 'host' or scantype == 'ip': |
93 | 93 | for item in parser.items: |
94 | 94 | h_id = self.createAndAddHost(item['ip'], hostnames=item['hosts']) |
110 | 110 | return 'ip' |
111 | 111 | |
112 | 112 | def get_report_path_from_output(self, command_output): |
113 | report_name = re.search("Results saved in file (\S+)", command_output) | |
113 | report_name = re.search(r"Results saved in file (\S+)", command_output) | |
114 | 114 | if not report_name: |
115 | 115 | return False |
116 | 116 | else: |
128 | 128 | self.parseOutputString(command_output) |
129 | 129 | |
130 | 130 | |
131 | def createPlugin(ignore_info=False): | |
132 | return GoohostPlugin(ignore_info=ignore_info) | |
133 | ||
131 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
132 | return GoohostPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
76 | 76 | return command_string |
77 | 77 | |
78 | 78 | |
79 | def createPlugin(ignore_info=False): | |
80 | return GrypePlugin(ignore_info=ignore_info) | |
79 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
80 | return GrypePlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
58 | 58 | for linea in lineas: |
59 | 59 | if (re.match(" ", linea)): |
60 | 60 | |
61 | list = re.findall("\w+", linea) | |
61 | list = re.findall(r"\w+", linea) | |
62 | 62 | service = list[1] |
63 | 63 | port = [list[0]] |
64 | 64 | |
67 | 67 | host_id, service, protocol="tcp", ports=port, status="open") |
68 | 68 | |
69 | 69 | |
70 | def createPlugin(ignore_info=False): | |
71 | return hping3(ignore_info=ignore_info) | |
72 | ||
73 | ||
70 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
71 | return hping3(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
3 | 3 | See the file 'doc/LICENSE' for the license information |
4 | 4 | """ |
5 | 5 | from faraday_plugins.plugins.plugin import PluginBase |
6 | from faraday_plugins.plugins.plugins_utils import resolve_hostname | |
7 | 6 | import re |
8 | 7 | from collections import defaultdict |
9 | 8 | |
30 | 29 | for line in lines: |
31 | 30 | |
32 | 31 | reg = re.search( |
33 | "\[([^$]+)\]\[([^$]+)\] host: ([^$]+) login: ([^$]+) password: ([^$]+)", | |
32 | r"\[([^$]+)\]\[([^$]+)\] host: ([^$]+) login: ([^$]+) password: ([^$]+)", | |
34 | 33 | line) |
35 | 34 | |
36 | 35 | if reg: |
83 | 82 | hosts[item['ip']].append([item['login'], item['password']]) |
84 | 83 | |
85 | 84 | for k, v in hosts.items(): |
86 | ip = resolve_hostname(k) | |
85 | ip = self.resolve_hostname(k) | |
87 | 86 | if ip != k: |
88 | 87 | hostnames = [k] |
89 | 88 | else: |
107 | 106 | h_id, |
108 | 107 | s_id, |
109 | 108 | "Weak Credentials", |
110 | "[hydra found the following credentials]\nuser:%s\npass:%s" % (cred[0], cred[1]), | |
109 | f"[hydra found the following credentials]\nuser:{cred[0]}\npass:{cred[1]}", | |
111 | 110 | severity="high") |
112 | 111 | |
113 | 112 | del parser |
129 | 128 | |
130 | 129 | |
131 | 130 | |
132 | def createPlugin(ignore_info=False): | |
133 | return HydraPlugin(ignore_info=ignore_info) | |
134 | ||
135 | ||
131 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
132 | return HydraPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
280 | 280 | del parser |
281 | 281 | |
282 | 282 | |
283 | def createPlugin(ignore_info=False): | |
284 | return ImpactPlugin(ignore_info=ignore_info) | |
283 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
284 | return ImpactPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
102 | 102 | ref=vulnerability.get("ref")) |
103 | 103 | |
104 | 104 | |
105 | def createPlugin(ignore_info=False): | |
106 | return Ip360Plugin(ignore_info=ignore_info) | |
107 | ||
108 | ||
105 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
106 | return Ip360Plugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
22 | 22 | This plugin has been designed to be used with python-unittest2/paramiko script to perform security compliancy verification. It enables to have displayed both security scans results (nmap, |
23 | 23 | nessus, ..) and security verification compliancy (CIS-CAT, compagny's product security requirement) by Faraday-IPE |
24 | 24 | |
25 | This plugin requires that a element "host" is added to <testcase/> (sed -i 's/<testcase/<testcase host=\"192.168.1.1\"/' junit.xml) | |
25 | This plugin requires that a element "host" is added to <testcase/> (sed -i 's/<testcase/<testcase host=\"192.168.1.1\"/' junit.xml) | |
26 | 26 | |
27 | 27 | <testsuite errors="0" failures="1" name="AccountsWithSuperuserPrivilegesShallBeDisabledByDefault-20170118090010" skipped="0" tests="1" time="0.144"> |
28 | 28 | <testcase host="192.168.1.1" classname="AccountsWithSuperuserPrivilegesShallBeDisabledByDefault" name="test_sshdRootLogin" time="0.144"> |
67 | 67 | try: |
68 | 68 | tree = etree.fromstring(xml_output) |
69 | 69 | except SyntaxError as err: |
70 | print("SyntaxError: %s. %s" % (err, xml_output)) | |
70 | print(f"SyntaxError: {err}. {xml_output}") | |
71 | 71 | return None |
72 | 72 | return tree |
73 | 73 | |
130 | 130 | del parser |
131 | 131 | |
132 | 132 | |
133 | def createPlugin(ignore_info=False): | |
134 | return JunitPlugin(ignore_info=ignore_info) | |
133 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
134 | return JunitPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
36 | 36 | return " ".join([name, version]) |
37 | 37 | |
38 | 38 | def ipv4(self): |
39 | ipv4s = re.findall('^network_ipv4_address\[\]=(.+)$', | |
39 | ipv4s = re.findall(r'^network_ipv4_address\[\]=(.+)$', | |
40 | 40 | self.rawcontents, re.MULTILINE) |
41 | 41 | ipv4addrs = self.ipv4_filter(ipv4s) |
42 | 42 | return(ipv4addrs) |
43 | 43 | |
44 | 44 | def ipv6(self): |
45 | ipv6s = re.findall('^network_ipv6_address\[\]=(.+)$', | |
45 | ipv6s = re.findall(r'^network_ipv6_address\[\]=(.+)$', | |
46 | 46 | self.rawcontents, re.MULTILINE) |
47 | 47 | ipv6addrs = self.ipv6_filter(ipv6s) |
48 | 48 | return(ipv6addrs) |
74 | 74 | return versions_dict |
75 | 75 | |
76 | 76 | def listeningservices(self): |
77 | line = re.findall('^network_listen_port\[\]=(.+)$', | |
77 | line = re.findall(r'^network_listen_port\[\]=(.+)$', | |
78 | 78 | self.rawcontents, re.MULTILINE) |
79 | 79 | # To avoid local services, we will create the following list |
80 | 80 | local_services = ['*', 'localhost'] |
196 | 196 | #Ipv6 |
197 | 197 | elif count == 5: |
198 | 198 | port = elements_ip_port[5] |
199 | ip = items_service[0].replace(':{}'.format(port), '') | |
199 | ip = items_service[0].replace(f':{port}', '') | |
200 | 200 | |
201 | 201 | return ip, port |
202 | 202 | |
203 | 203 | def parse_suggestions(self): |
204 | 204 | sugs = {} |
205 | m = re.findall('^suggestion\[\]=(.+)$', self.rawcontents, re.MULTILINE) | |
205 | m = re.findall(r'^suggestion\[\]=(.+)$', self.rawcontents, re.MULTILINE) | |
206 | 206 | for combo in m: |
207 | 207 | x = combo.split('|') |
208 | 208 | sugs[x[0]] = x[1] |
210 | 210 | |
211 | 211 | def parse_warnings(self): |
212 | 212 | warns = {} |
213 | m = re.findall('^warning\[\]=(.+)$', self.rawcontents, re.MULTILINE) | |
213 | m = re.findall(r'^warning\[\]=(.+)$', self.rawcontents, re.MULTILINE) | |
214 | 214 | for combo in m: |
215 | 215 | x = combo.split('|') |
216 | 216 | warns[x[0]] = x[1] |
318 | 318 | ) |
319 | 319 | |
320 | 320 | def processOutput(self, command_output): |
321 | m = re.search('(\/.+\.dat)$', command_output, re.MULTILINE) | |
321 | m = re.search(r'(\/.+\.dat)$', command_output, re.MULTILINE) | |
322 | 322 | file_path = m.group(0).strip() |
323 | 323 | self._parse_filename(file_path) |
324 | 324 | |
325 | 325 | |
326 | def createPlugin(ignore_info=False): | |
327 | return LynisPlugin(ignore_info=ignore_info) | |
328 | ||
329 | ||
326 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
327 | return LynisPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
6 | 6 | import zipfile |
7 | 7 | |
8 | 8 | from faraday_plugins.plugins.plugin import PluginZipFormat |
9 | from faraday_plugins.plugins.plugins_utils import resolve_hostname | |
10 | 9 | |
11 | 10 | __author__ = "Ezequiel Tavella" |
12 | 11 | __copyright__ = "Copyright (c) 2015, Infobyte LLC" |
95 | 94 | return check_files |
96 | 95 | |
97 | 96 | |
98 | class Host(): | |
97 | class Host: | |
99 | 98 | |
100 | 99 | def __init__(self): |
101 | 100 | self.ip = "" |
108 | 107 | self.ns_record = "" |
109 | 108 | |
110 | 109 | |
111 | class MaltegoParser(): | |
112 | ||
113 | def __init__(self, xml_file, extension): | |
114 | ||
110 | class MaltegoParser: | |
111 | ||
112 | def __init__(self, xml_file, extension, resolve_hostname): | |
113 | ||
114 | self.resolve_hostname = resolve_hostname | |
115 | 115 | if extension == '.mtgx': |
116 | 116 | self.xml = readMtgx(xml_file) |
117 | 117 | self.nodes = self.xml.findall( |
168 | 168 | "{http://maltego.paterva.com/xml/mtgx}Property/" |
169 | 169 | "{http://maltego.paterva.com/xml/mtgx}Value") |
170 | 170 | if entity.get("type") in ("maltego.Domain", "maltego.Website"): |
171 | ip = resolve_hostname(value.text) | |
171 | ip = self.resolve_hostname(value.text) | |
172 | 172 | hostname = value.text |
173 | 173 | else: |
174 | 174 | ip = value.text |
376 | 376 | |
377 | 377 | def parseOutputString(self, output): |
378 | 378 | if 'Graphs/Graph1.graphml' in output.namelist(): |
379 | maltego_parser = MaltegoParser(output, self.extension[1]) | |
379 | maltego_parser = MaltegoParser(output, self.extension[1], resolve_hostname=self.resolve_hostname) | |
380 | 380 | hosts = maltego_parser.parse() |
381 | 381 | if not hosts: |
382 | 382 | self.logger.warning("No hosts data found in maltego report") |
439 | 439 | self.createAndAddServiceToHost(host_id=host_id, name=host.ns_record["value"], protocol="DNS", |
440 | 440 | ports=[53], description="DNS Server") |
441 | 441 | else: |
442 | maltego_parser = MaltegoParser(output, self.extension[0]) | |
442 | maltego_parser = MaltegoParser(output, self.extension[0], resolve_hostname=self.resolve_hostname) | |
443 | 443 | if not maltego_parser.xml.get('domain') or not maltego_parser.xml.get('ipv4'): |
444 | 444 | return |
445 | 445 | if maltego_parser.xml.get('domain'): |
495 | 495 | description="DNS Server") |
496 | 496 | |
497 | 497 | |
498 | def createPlugin(ignore_info=False): | |
499 | return MaltegoPlugin(ignore_info=ignore_info) | |
498 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
499 | return MaltegoPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
18 | 18 | class MbsaParser: |
19 | 19 | def __init__(self, log_output): |
20 | 20 | self.computer_name = re.search('(Computer name:) (.*[A-Z])', log_output) |
21 | self.ip = re.search('(IP address:) ([0-9]+(?:\.[0-9]+){3})', log_output) | |
21 | self.ip = re.search(r'(IP address:) ([0-9]+(?:\.[0-9]+){3})', log_output) | |
22 | 22 | self.scan_date = re.search('(Scan date:) (.*[0-9])', log_output) |
23 | 23 | self.issues = re.findall(r'Issue: .*', log_output) |
24 | 24 | self.score = re.findall(r'Score: .*', log_output) |
113 | 113 | i += 1 |
114 | 114 | |
115 | 115 | |
116 | def createPlugin(ignore_info=False): | |
117 | return MbsaPlugin(ignore_info=ignore_info) | |
116 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
117 | return MbsaPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
4 | 4 | """ |
5 | 5 | import re |
6 | 6 | from faraday_plugins.plugins.plugin import PluginBase |
7 | from faraday_plugins.plugins.plugins_utils import resolve_hostname | |
8 | 7 | |
9 | 8 | |
10 | 9 | __author__ = "Francisco Amato" |
24 | 23 | @param medusa_filepath A proper simple report generated by medusa |
25 | 24 | """ |
26 | 25 | |
27 | def __init__(self, xml_output): | |
26 | def __init__(self, xml_output, resolve_hostname): | |
27 | self.resolve_hostname = resolve_hostname | |
28 | 28 | self.srv = { |
29 | 29 | 'ftp': '21', 'http': '80', 'imap': '143', 'mssql': '1433', 'mysql': '3306', |
30 | 30 | 'ncp': '524', 'nntp': '119', 'pcanywhere': '5631', 'pop3': '110', 'postgres': '5432', |
36 | 36 | |
37 | 37 | lines = xml_output.splitlines() |
38 | 38 | self.items = [] |
39 | ||
39 | ||
40 | 40 | for line in lines: |
41 | 41 | |
42 | reg = re.search("ACCOUNT FOUND: \[([^$]+)\] Host: ([^$]+) User: ([^$]+) Password: ([^$]+) \[SUCCESS\]", line) | |
42 | reg = re.search(r"ACCOUNT FOUND: \[([^$]+)\] Host: ([^$]+) User: ([^$]+) Password: ([^$]+) \[SUCCESS\]", line) | |
43 | 43 | if reg: |
44 | ||
44 | ||
45 | 45 | item = { |
46 | 46 | 'service': reg.group(1), |
47 | 47 | 'host': reg.group(2), |
80 | 80 | NOTE: if 'debug' is true then it is being run from a test case and the |
81 | 81 | output being sent is valid. |
82 | 82 | """ |
83 | parser = MedusaParser(output) | |
84 | ||
83 | parser = MedusaParser(output, resolve_hostname=self.resolve_hostname) | |
84 | ||
85 | 85 | for item in parser.items: |
86 | ||
86 | ||
87 | 87 | h_id = self.createAndAddHost(item['ip'], hostnames=[item['host']]) |
88 | 88 | |
89 | 89 | port = self.port if self.port else item['port'] |
104 | 104 | self.createAndAddVulnToService(h_id, |
105 | 105 | s_id, |
106 | 106 | "Weak Credentials", |
107 | "[medusa found the following credentials]\nuser:%s\npass:%s" % (item['user'], item['pass']), | |
107 | f"[medusa found the following credentials]\nuser:{item['user']}\npass:{item['pass']}", | |
108 | 108 | severity="high") |
109 | 109 | |
110 | 110 | del parser |
132 | 132 | |
133 | 133 | |
134 | 134 | |
135 | def createPlugin(ignore_info=False): | |
136 | return MedusaPlugin(ignore_info=ignore_info) | |
135 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
136 | return MedusaPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
350 | 350 | self.createAndAddCredToService( |
351 | 351 | h_id, s_id, c.user, c.passwd) |
352 | 352 | self.createAndAddVulnToService(h_id, s_id, "Weak Credentials", |
353 | "[metasploit found the following credentials]\nuser:%s\npass:%s" % ( | |
353 | "[metasploit found the following credentials]\nuser:{}\npass:{}".format( | |
354 | 354 | c.user, c.passwd), severity="high") |
355 | 355 | |
356 | 356 | for v in item.vulnsByService[s['id']]: |
374 | 374 | return False |
375 | 375 | |
376 | 376 | |
377 | def createPlugin(ignore_info=False): | |
378 | return MetasploitPlugin(ignore_info=ignore_info) | |
377 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
378 | return MetasploitPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
40 | 40 | port = host_dict.get('port') |
41 | 41 | try: |
42 | 42 | service = socket.getservbyport(port) |
43 | except socket.error: | |
43 | except OSError: | |
44 | 44 | service = 'Unknown service on port ' + str(port) |
45 | 45 | host_id = self.createAndAddHost( |
46 | 46 | name=ip, |
66 | 66 | command_string += " -silent" |
67 | 67 | return command_string |
68 | 68 | |
69 | def createPlugin(ignore_info=False): | |
70 | return NaabuPlugin(ignore_info=ignore_info) | |
69 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
70 | return NaabuPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
41 | 41 | try: |
42 | 42 | tree = ET.fromstring(xml_output) |
43 | 43 | except SyntaxError as err: |
44 | print('SyntaxError In xml: %s. %s' % (err, xml_output)) | |
44 | print(f'SyntaxError In xml: {err}. {xml_output}') | |
45 | 45 | return None |
46 | 46 | return tree |
47 | 47 | |
118 | 118 | password=service_vuln['passw']) |
119 | 119 | |
120 | 120 | |
121 | def createPlugin(ignore_info=False): | |
122 | return NcrackPlugin(ignore_info=ignore_info) | |
121 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
122 | return NcrackPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
17 | 17 | __status__ = "Development" |
18 | 18 | |
19 | 19 | |
20 | class NdiffXmlParser(): | |
20 | class NdiffXmlParser: | |
21 | 21 | """ |
22 | 22 | The objective of this class is to parse an xml file generated by |
23 | 23 | the ndiff tool. |
38 | 38 | try: |
39 | 39 | return ET.fromstring(xmlOutput) |
40 | 40 | except SyntaxError as err: |
41 | print("SyntaxError: %s" % err) | |
41 | print(f"SyntaxError: {err}") | |
42 | 42 | return None |
43 | 43 | |
44 | 44 | def getHostsDiffs(self, tree): |
119 | 119 | continue |
120 | 120 | if host.isNewHost: |
121 | 121 | hostId = self.createAndAddHost(host.ip, '') |
122 | description = '%s is a NEW host active.\n' % host.ip | |
122 | description = f'{host.ip} is a NEW host active.\n' | |
123 | 123 | for port in host.ports: |
124 | description += 'Port: %s/%s\n' % (port[0], port[1]) | |
124 | description += f'Port: {port[0]}/{port[1]}\n' | |
125 | 125 | self.createAndAddVulnToHost( |
126 | 126 | hostId, |
127 | 127 | 'New host active', |
135 | 135 | hostId = self.createAndAddHost(host.ip, '') |
136 | 136 | description = 'New service/s found.\n' |
137 | 137 | for port in host.ports: |
138 | description += 'Port: %s/%s\n' % (port[0], port[1]) | |
138 | description += f'Port: {port[0]}/{port[1]}\n' | |
139 | 139 | |
140 | 140 | self.createAndAddVulnToHost( |
141 | 141 | hostId, |
151 | 151 | return f"{command_string} --xml " |
152 | 152 | |
153 | 153 | |
154 | def createPlugin(ignore_info=False): | |
155 | return CmdNdiffPlugin(ignore_info=ignore_info) | |
156 | ||
157 | ||
154 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
155 | return CmdNdiffPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
357 | 357 | return _dict.get("host-fqdn", None) |
358 | 358 | |
359 | 359 | @property |
360 | def host_rdns(self) -> str: | |
361 | _dict = self.dict_tags | |
362 | return _dict.get("host-rdns", None) | |
363 | ||
364 | @property | |
360 | 365 | def dict_tags(self): |
361 | 366 | host_tags = {} |
362 | 367 | for t in self.node: |
68 | 68 | compliance_data[compliance_name] = value |
69 | 69 | return compliance_data |
70 | 70 | |
71 | @staticmethod | |
72 | def map_properties(host: ReportHost): | |
71 | def map_properties(self, host: ReportHost): | |
72 | if self.hostname_resolution: | |
73 | name = host.host_properties.host_ip if host.host_properties.host_ip else host.name | |
74 | else: | |
75 | name = host.name | |
76 | hostnames = [host.host_properties.host_fqdn] | |
77 | if host.host_properties.host_rdns and host.host_properties.host_rdns not in hostnames: | |
78 | hostnames.append(host.host_properties.host_rdns) | |
73 | 79 | return { |
74 | "name": host.host_properties.host_ip if host.host_properties.host_ip else host.name, | |
75 | "hostnames": host.host_properties.host_fqdn, | |
80 | "name": name, | |
81 | "hostnames": hostnames, | |
76 | 82 | "mac": host.host_properties.mac_address, |
77 | 83 | "os": host.host_properties.operating_system |
78 | 84 | } |
191 | 197 | return kwargs |
192 | 198 | |
193 | 199 | |
194 | def createPlugin(ignore_info=False): | |
195 | return NessusPlugin(ignore_info=ignore_info) | |
200 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
201 | return NessusPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
26 | 26 | def parseOutputString(self, output): |
27 | 27 | #regexp get ip, mac and hostname |
28 | 28 | reg = re.findall(r"(([0-9]+\.?){4})\s+(([0-9a-f]+\:?){6})((\s+[0-9]+){2})(.*)", output) |
29 | ||
29 | ||
30 | 30 | if output.find('Finished!') != -1 and len(reg) > 0: |
31 | 31 | |
32 | 32 | for stdout in reg: |
38 | 38 | |
39 | 39 | |
40 | 40 | |
41 | def createPlugin(ignore_info=False): | |
42 | return NetdiscoverPlugin(ignore_info=ignore_info) | |
43 | ||
44 | ||
41 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
42 | return NetdiscoverPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
10 | 10 | from bs4 import BeautifulSoup |
11 | 11 | |
12 | 12 | from faraday_plugins.plugins.plugin import PluginXMLFormat |
13 | from faraday_plugins.plugins.plugins_utils import resolve_hostname, CVE_regex | |
13 | from faraday_plugins.plugins.plugins_utils import CVE_regex | |
14 | 14 | |
15 | 15 | __author__ = "Francisco Amato" |
16 | 16 | __copyright__ = "Copyright (c) 2013, Infobyte LLC" |
55 | 55 | try: |
56 | 56 | tree = ET.fromstring(xml_output) |
57 | 57 | except SyntaxError as err: |
58 | self.plugin.logger.error("SyntaxError: %s. %s" % (err, xml_output)) | |
58 | self.plugin.logger.error(f"SyntaxError: {err}. {xml_output}") | |
59 | 59 | return None |
60 | 60 | |
61 | 61 | return tree |
81 | 81 | self.url = self.get_text_from_subnode("url") |
82 | 82 | |
83 | 83 | host = re.search( |
84 | "(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 | "{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 | "[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 | "{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\.\,\?\'\\\+&%\$#\=~_\-]+)).*?$", | |
84 | 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 | 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 | 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 | 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\\.\\,\\?\'\\\\+&%\\$#\\=~_\\-]+)).*?$", | |
89 | 89 | self.url) |
90 | 90 | |
91 | 91 | self.protocol = host.group(1) |
144 | 144 | if self.owasp: |
145 | 145 | self.ref.append("OWASP-" + self.owasp) |
146 | 146 | if self.reference: |
147 | self.ref.extend(sorted(set(re.findall('https?://(?:[-\w.]|(?:%[\da-fA-F]{2}))+', self.reference)))) | |
147 | self.ref.extend(sorted(set(re.findall(r'https?://(?:[-\w.]|(?:%[\da-fA-F]{2}))+', self.reference)))) | |
148 | 148 | if self.cvss: |
149 | 149 | self.ref.append(self.cvss) |
150 | ||
150 | ||
151 | 151 | self.data = "" |
152 | 152 | self.data += "\nKnowVulns: " + \ |
153 | 153 | "\n".join(self.kvulns) if self.kvulns else "" |
200 | 200 | host_names_resolve = {} |
201 | 201 | for i in parser.items: |
202 | 202 | |
203 | if (i.hostname not in host_names_resolve): | |
204 | ip = resolve_hostname(i.hostname) | |
203 | if i.hostname not in host_names_resolve: | |
204 | ip = self.resolve_hostname(i.hostname) | |
205 | 205 | host_names_resolve[i.hostname] = ip |
206 | 206 | else: |
207 | 207 | ip = host_names_resolve[i.hostname] |
208 | 208 | h_id = self.createAndAddHost(ip, hostnames=[i.hostname]) |
209 | ||
209 | ||
210 | 210 | s_id = self.createAndAddServiceToHost(h_id, str(i.port), |
211 | 211 | protocol = str(i.protocol), |
212 | 212 | ports=[str(i.port)], |
233 | 233 | del parser |
234 | 234 | |
235 | 235 | |
236 | def createPlugin(ignore_info=False): | |
237 | return NetsparkerPlugin(ignore_info=ignore_info) | |
238 | ||
239 | ||
236 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
237 | return NetsparkerPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
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 resolve_hostname | |
12 | 11 | |
13 | 12 | __author__ = "Francisco Amato" |
14 | 13 | __copyright__ = "Copyright (c) 2013, Infobyte LLC" |
23 | 22 | def get_urls(string): |
24 | 23 | if isinstance(string, bytes): |
25 | 24 | string_decode = string.decode("utf-8") |
26 | urls = re.findall('(?:(?:https?|ftp):\/\/)?[\w/\-?=%.]+\.[\w/\-?=%.]+', string_decode) | |
25 | urls = re.findall(r'(?:(?:https?|ftp):\/\/)?[\w/\-?=%.]+\.[\w/\-?=%.]+', string_decode) | |
27 | 26 | else: |
28 | urls = re.findall('(?:(?:https?|ftp):\/\/)?[\w/\-?=%.]+\.[\w/\-?=%.]+', string) | |
27 | urls = re.findall(r'(?:(?:https?|ftp):\/\/)?[\w/\-?=%.]+\.[\w/\-?=%.]+', string) | |
29 | 28 | return urls |
30 | 29 | |
31 | 30 | |
60 | 59 | try: |
61 | 60 | tree = ET.fromstring(xml_output) |
62 | 61 | except SyntaxError as err: |
63 | self.logger.error("SyntaxError: %s. %s" % (err, xml_output)) | |
62 | self.logger.error(f"SyntaxError: {err}. {xml_output}") | |
64 | 63 | return None |
65 | 64 | return tree |
66 | 65 | |
123 | 122 | |
124 | 123 | self.ref = [] |
125 | 124 | if self.cwe: |
126 | self.ref.append("CWE-{}".format(self.cwe)) | |
125 | self.ref.append(f"CWE-{self.cwe}") | |
127 | 126 | if self.owasp: |
128 | self.ref.append("OWASP-{}".format(self.owasp)) | |
127 | self.ref.append(f"OWASP-{self.owasp}") | |
129 | 128 | |
130 | 129 | self.node = item_node |
131 | 130 | self.remedyreferences = self.get_text_from_subnode("remedy-references") |
185 | 184 | first = True |
186 | 185 | for i in parser.items: |
187 | 186 | if first: |
188 | ip = resolve_hostname(i.hostname) | |
187 | ip = self.resolve_hostname(i.hostname) | |
189 | 188 | h_id = self.createAndAddHost(ip, hostnames=[i.hostname]) |
190 | 189 | s_id = self.createAndAddServiceToHost(h_id, i.protocol, ports=[i.port], status="open") |
191 | 190 | first = False |
196 | 195 | del parser |
197 | 196 | |
198 | 197 | |
199 | def createPlugin(ignore_info=False): | |
200 | return NetsparkerCloudPlugin(ignore_info=ignore_info) | |
198 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
199 | return NetsparkerCloudPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
319 | 319 | del parser |
320 | 320 | |
321 | 321 | |
322 | def createPlugin(ignore_info=False): | |
323 | return NexposeFullPlugin(ignore_info=ignore_info) | |
322 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
323 | return NexposeFullPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
4 | 4 | |
5 | 5 | """ |
6 | 6 | import re |
7 | import os | |
8 | 7 | import json |
9 | 8 | from faraday_plugins.plugins.plugin import PluginBase |
10 | from faraday_plugins.plugins.plugins_utils import resolve_hostname | |
11 | 9 | |
12 | 10 | |
13 | 11 | __author__ = "Blas Moyano" |
64 | 62 | return True |
65 | 63 | |
66 | 64 | |
67 | def createPlugin(ignore_info=False): | |
68 | return CmdNextNetin(ignore_info=ignore_info) | |
65 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
66 | return CmdNextNetin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
51 | 51 | try: |
52 | 52 | tree = ET.fromstring(xml_output) |
53 | 53 | except SyntaxError as err: |
54 | print("SyntaxError: %s. %s" % (err, xml_output)) | |
54 | print(f"SyntaxError: {err}. {xml_output}") | |
55 | 55 | return None |
56 | 56 | |
57 | 57 | return tree |
310 | 310 | if arg_match is None: |
311 | 311 | return re.sub(r"(^.*?nikto(\.pl)?)", r"\1 -output %s -Format XML" % self._output_file_path, command_string) |
312 | 312 | else: |
313 | data = re.sub(" \-Format XML", "", command_string) | |
313 | data = re.sub(r" \-Format XML", "", command_string) | |
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): | |
318 | return NiktoPlugin(ignore_info=ignore_info) | |
317 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
318 | return NiktoPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
0 | 0 | import xml.etree.ElementTree as ET |
1 | from colorama import Fore, Style | |
2 | 1 | |
3 | from faraday_plugins.plugins.plugins_utils import resolve_hostname | |
4 | 2 | from faraday_plugins.plugins.plugin import PluginXMLFormat |
5 | 3 | |
6 | 4 | __author__ = "@rfocke and @pasta <3" |
133 | 131 | parser = NipperParser(output, debug=False) |
134 | 132 | for vuln in parser.vulns_first: |
135 | 133 | for device in vuln.affected_devices: |
136 | ip = resolve_hostname(device) | |
134 | ip = self.resolve_hostname(device) | |
137 | 135 | h_id = self.createAndAddHost(ip, hostnames=device) |
138 | 136 | self.createAndAddVulnToHost(h_id, |
139 | 137 | name=vuln.name, |
147 | 145 | ) |
148 | 146 | for vuln in parser.vulns_audit: |
149 | 147 | if vuln.data: |
150 | ip = resolve_hostname(device) | |
148 | ip = self.resolve_hostname(device) | |
151 | 149 | h_id = self.createAndAddHost(ip, hostnames=vuln.device) |
152 | 150 | self.createAndAddVulnToHost(h_id, |
153 | 151 | name=vuln.name, |
160 | 158 | ) |
161 | 159 | |
162 | 160 | |
163 | def createPlugin(ignore_info=False): | |
164 | return NipperPlugin(ignore_info=ignore_info) | |
161 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
162 | return NipperPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
201 | 201 | os_gen = osclass.get("osgen", "unknown") |
202 | 202 | accuracy = osclass.get("accuracy", "unknown") |
203 | 203 | |
204 | yield ("%s %s %s" % (os_vendor, os_family, os_gen), accuracy) | |
204 | yield (f"{os_vendor} {os_family} {os_gen}", accuracy) | |
205 | 205 | |
206 | 206 | # Os information in services, bad acurracy. |
207 | 207 | if osclasses == []: |
208 | 208 | services = self.node.findall("ports/port/service") |
209 | 209 | for service in services: |
210 | 210 | ostype = service.get("ostype", "unknown") |
211 | yield ("%s" % ostype, 0) | |
211 | yield (f"{ostype}", 0) | |
212 | 212 | |
213 | 213 | def top_os_guess(self): |
214 | 214 | """ |
243 | 243 | def __str__(self): |
244 | 244 | ports = [] |
245 | 245 | for port in self.ports: |
246 | var = " %s" % port | |
246 | var = f" {port}" | |
247 | 247 | ports.append(var) |
248 | 248 | ports = "\n".join(ports) |
249 | 249 | |
250 | return "%s, %s, %s [%s], %s\n%s" % ( | |
251 | self.hostnames, | |
252 | self.status, | |
253 | self.ipv4_address, | |
254 | self.mac_address, | |
255 | self.os, ports) | |
250 | return f"{self.hostnames}, {self.status}, {self.ipv4_address} [{self.mac_address}], {self.os}\n{ports}" | |
256 | 251 | |
257 | 252 | |
258 | 253 | class Port: |
323 | 318 | yield Script(s) |
324 | 319 | |
325 | 320 | def __str__(self): |
326 | return "%s, %s, Service: %s" % (self.number, self.state, self.service) | |
321 | return f"{self.number}, {self.state}, Service: {self.service}" | |
327 | 322 | |
328 | 323 | |
329 | 324 | class ScriptVulners: |
363 | 358 | self.severity = get_severity_from_cvss(self.table["cvss"]) |
364 | 359 | |
365 | 360 | def __str__(self): |
366 | return "%s, %s, %s" % (self.name, self.product, self.version) | |
361 | return f"{self.name}, {self.product}, {self.version}" | |
367 | 362 | |
368 | 363 | |
369 | 364 | class Script: |
379 | 374 | """ |
380 | 375 | |
381 | 376 | def parse_output(self, output): |
382 | block_re = re.compile('^\s{4}References:((?:.|[\r\n])+[\r\n](?:\s{4}\w|\s*$))', re.MULTILINE) | |
377 | block_re = re.compile('^\\s{4}References:((?:.|[\r\n])+[\r\n](?:\\s{4}\\w|\\s*$))', re.MULTILINE) | |
383 | 378 | m1 = block_re.findall(output) |
384 | 379 | if len(m1) > 0: |
385 | 380 | links_re = re.compile('[ \t]+([^ \t\n\r]+)[ \t]*') |
399 | 394 | self.web = re.search("(http-|https-)", self.name) |
400 | 395 | |
401 | 396 | def __str__(self): |
402 | return "%s, %s, %s" % (self.name, self.product, self.version) | |
397 | return f"{self.name}, {self.product}, {self.version}" | |
403 | 398 | |
404 | 399 | |
405 | 400 | class Service: |
438 | 433 | self.ostype = self.node.get("ostype") |
439 | 434 | |
440 | 435 | def __str__(self): |
441 | return "%s, %s, %s" % (self.name, self.product, self.version) | |
436 | return f"{self.name}, {self.product}, {self.version}" | |
442 | 437 | |
443 | 438 | |
444 | 439 | class NmapPlugin(PluginXMLFormat): |
578 | 573 | command_string) |
579 | 574 | |
580 | 575 | |
581 | def createPlugin(ignore_info=False): | |
582 | return NmapPlugin(ignore_info=ignore_info) | |
576 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
577 | return NmapPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
11 | 11 | from urllib.parse import urlparse |
12 | 12 | from packaging import version |
13 | 13 | from faraday_plugins.plugins.plugin import PluginMultiLineJsonFormat |
14 | from faraday_plugins.plugins.plugins_utils import resolve_hostname | |
15 | 14 | |
16 | 15 | __author__ = "Nicolas Rebagliati" |
17 | 16 | __copyright__ = "Copyright (c) 2021, Infobyte LLC" |
32 | 31 | super().__init__(*arg, **kwargs) |
33 | 32 | self.id = "nuclei" |
34 | 33 | self.name = "Nuclei" |
35 | self.plugin_version = "1.0.2" | |
36 | self.version = "2.5.3" | |
34 | self.plugin_version = "1.0.3" | |
35 | self.version = "2.5.5" | |
37 | 36 | self.json_keys = {"matched-at", "template-id", "host"} |
38 | 37 | self._command_regex = re.compile(r'^(sudo nuclei|nuclei|\.\/nuclei|^.*?nuclei)\s+.*?') |
39 | 38 | self.xml_arg_re = re.compile(r"^.*(-o\s*[^\s]+).*$") |
45 | 44 | vuln_dict = json.loads(vuln_json) |
46 | 45 | host = vuln_dict.get('host') |
47 | 46 | url_data = urlparse(host) |
48 | ip = vuln_dict.get("ip", resolve_hostname(url_data.hostname)) | |
47 | if url_data.hostname is None: | |
48 | host = 'http://' + host | |
49 | url_data = urlparse(host) | |
50 | ip = vuln_dict.get("ip") | |
51 | if not ip: | |
52 | ip = self.resolve_hostname(url_data.hostname) | |
49 | 53 | host_id = self.createAndAddHost( |
50 | 54 | name=ip, |
51 | 55 | hostnames=[url_data.hostname]) |
87 | 91 | references = [references] |
88 | 92 | else: |
89 | 93 | references = [] |
90 | cwe = vuln_dict['info'].get('cwe', []) | |
91 | capec = vuln_dict['info'].get('capec', []) | |
92 | refs = sorted(list(set(reference + references + cwe + capec))) | |
94 | ||
95 | cve = vuln_dict['info'].get('classification', {}).get('cve-id', []) | |
96 | if cve: | |
97 | cve = [x.upper() for x in cve] | |
98 | ||
99 | # TODO CVSSv2, CVSSv3, CWE and CAPEC | |
100 | #cvssv2 = vuln_dict['info'].get('classification', {}).get('cvss-score') | |
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] | |
104 | #capec = vuln_dict['info'].get('metadata', {}).get('capec', []) | |
105 | #if isinstance(capec, str): | |
106 | # capec = capec.upper().split(',') | |
107 | ||
108 | refs = sorted(list(set(reference + references))) | |
109 | refs = list(filter(None, refs)) | |
110 | ||
93 | 111 | tags = vuln_dict['info'].get('tags', []) |
94 | 112 | if isinstance(tags, str): |
95 | 113 | tags = tags.split(',') |
96 | impact = vuln_dict['info'].get('impact') | |
97 | resolution = vuln_dict['info'].get('resolution', '') | |
98 | easeofresolution = vuln_dict['info'].get('easeofresolution') | |
114 | ||
115 | impact = {} | |
116 | impacted = vuln_dict['info'].get('metadata', {}).get('impact') | |
117 | if isinstance(impacted, str): | |
118 | for x in impacted.split(','): | |
119 | impact[x] = True | |
120 | ||
121 | resolution = vuln_dict['info'].get('metadata', {}).get('resolution', '') | |
122 | easeofresolution = vuln_dict['info'].get('metadata', {}).get('easeofresolution', None) | |
123 | ||
99 | 124 | request = vuln_dict.get('request', '') |
100 | 125 | if request: |
101 | 126 | method = request.split(" ")[0] |
121 | 146 | impact=impact, |
122 | 147 | resolution=resolution, |
123 | 148 | easeofresolution=easeofresolution, |
149 | cve=cve, | |
150 | # TODO CVSSv2, CVSSv3, CWE and CAPEC | |
151 | #cvssv2=cvssv2, | |
152 | #cvssv3=cvssv3, | |
153 | #cwe=cwe, | |
154 | #capec=capec, | |
124 | 155 | website=host, |
125 | 156 | request=request, |
126 | 157 | response=vuln_dict.get('response', ''), |
161 | 192 | return False |
162 | 193 | |
163 | 194 | |
164 | def createPlugin(ignore_info=False): | |
165 | return NucleiPlugin(ignore_info=ignore_info) | |
166 | ||
167 | ||
195 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
196 | return NucleiPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
4 | 4 | from packaging import version |
5 | 5 | from urllib.parse import urlparse |
6 | 6 | from faraday_plugins.plugins.plugin import PluginMultiLineJsonFormat |
7 | from faraday_plugins.plugins.plugins_utils import resolve_hostname | |
8 | 7 | |
9 | 8 | __author__ = "Emilio Couto" |
10 | 9 | __copyright__ = "Copyright (c) 2021, Faraday Security" |
38 | 37 | vuln_dict = json.loads(vuln_json) |
39 | 38 | host = vuln_dict.get('host') |
40 | 39 | url_data = urlparse(host) |
41 | ip = vuln_dict.get("ip", resolve_hostname(url_data.hostname)) | |
40 | ip = vuln_dict.get("ip", self.resolve_hostname(url_data.hostname)) | |
42 | 41 | host_id = self.createAndAddHost( |
43 | 42 | name=ip, |
44 | 43 | hostnames=[url_data.hostname]) |
148 | 147 | except Exception as e: |
149 | 148 | return False |
150 | 149 | |
151 | def createPlugin(ignore_info=False): | |
152 | return NucleiLegacyPlugin(ignore_info=ignore_info) | |
150 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
151 | return NucleiLegacyPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
0 | 0 | #!/usr/bin/env python |
1 | # -*- coding: utf-8 -*- | |
2 | 1 | """ |
3 | 2 | Faraday Penetration Test IDE |
4 | 3 | Copyright (C) 2020 Infobyte LLC (http://www.infobytesec.com/) |
33 | 32 | parser = etree.XMLParser(recover=True) |
34 | 33 | tree = etree.fromstring(xml_output, parser=parser) |
35 | 34 | except SyntaxError as err: |
36 | print('SyntaxError In xml: %s. %s' % (err, xml_output)) | |
35 | print(f'SyntaxError In xml: {err}. {xml_output}') | |
37 | 36 | return None |
38 | 37 | return tree |
39 | 38 | |
207 | 206 | cve=[vuln_cve]) |
208 | 207 | |
209 | 208 | |
210 | def createPlugin(ignore_info=False): | |
211 | return OpenScapPlugin(ignore_info=ignore_info) | |
209 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
210 | return OpenScapPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
116 | 116 | def do_clean(self, value): |
117 | 117 | myreturn = "" |
118 | 118 | if value is not None: |
119 | myreturn = re.sub("\s+", " ", value) | |
119 | myreturn = re.sub(r"\s+", " ", value) | |
120 | 120 | return myreturn.strip() |
121 | 121 | |
122 | 122 | |
233 | 233 | def do_clean(self, value): |
234 | 234 | myreturn = "" |
235 | 235 | if value is not None: |
236 | myreturn = re.sub("\s+", " ", value) | |
236 | myreturn = re.sub(r"\s+", " ", value) | |
237 | 237 | |
238 | 238 | return myreturn.strip() |
239 | 239 | |
348 | 348 | if item.bid: |
349 | 349 | bids = item.bid.split(',') |
350 | 350 | for bid in bids: |
351 | ref.append("BID-%s" % bid.strip()) | |
351 | ref.append(f"BID-{bid.strip()}") | |
352 | 352 | if item.xref: |
353 | 353 | ref.append(item.xref) |
354 | 354 | if item.tags and item.cvss_vector: |
357 | 357 | ref.append(f"CVSS_BASE: {item.cvss_base}") |
358 | 358 | if item.cpe: |
359 | 359 | ref.append(f"{item.cpe}") |
360 | if item.severity_nr: | |
361 | if float(item.severity_nr) >= 9.0: | |
362 | item.threat = "Critical" | |
363 | item.severity = "Critical" | |
364 | ref.append(f"SEVERITY NUMBER: {item.severity_nr}") | |
360 | 365 | if item.threat: |
361 | 366 | ref.append(f"THREAT: {item.threat}") |
362 | if item.severity_nr: | |
363 | ref.append(f"SEVERITY NUMBER: {item.severity_nr}") | |
364 | 367 | |
365 | 368 | if item.subnet in ids: |
366 | 369 | h_id = ids[item.host] |
379 | 382 | severity=item.severity, |
380 | 383 | resolution=item.resolution, |
381 | 384 | ref=ref, |
382 | external_id=item.id, | |
385 | external_id=f"OPENVAS-{item.id}", | |
383 | 386 | data=item.data, |
384 | 387 | cve=cve) |
385 | 388 | else: |
411 | 414 | severity=item.severity, |
412 | 415 | ref=ref, |
413 | 416 | resolution=item.resolution, |
414 | external_id=item.id, | |
417 | external_id=f"OPENVAS-{item.id}", | |
415 | 418 | data=item.data, |
416 | 419 | cve=cve) |
417 | 420 | elif item.severity not in self.ignored_severities: |
423 | 426 | severity=item.severity, |
424 | 427 | ref=ref, |
425 | 428 | resolution=item.resolution, |
426 | external_id=item.id, | |
429 | external_id=f"OPENVAS-{item.id}", | |
427 | 430 | data=item.data, |
428 | 431 | cve=cve) |
429 | 432 | del parser |
436 | 439 | return False |
437 | 440 | |
438 | 441 | |
439 | def createPlugin(ignore_info=False): | |
440 | return OpenvasPlugin(ignore_info=ignore_info) | |
442 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
443 | return OpenvasPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
5 | 5 | """ |
6 | 6 | |
7 | 7 | # Author: @EzequielTBH |
8 | from builtins import str | |
9 | 8 | |
10 | 9 | from faraday_plugins.plugins.plugin import PluginBase |
11 | 10 | import json |
36 | 35 | indexStart:self.command_string.find(" ", indexStart)] |
37 | 36 | fileJson = self._current_path + "/" + fileJson |
38 | 37 | try: |
39 | with open(fileJson, "r") as fileJ: | |
38 | with open(fileJson) as fileJ: | |
40 | 39 | results = json.loads(fileJ.read()) |
41 | 40 | except Exception as e: |
42 | 41 | return |
85 | 84 | return command_string |
86 | 85 | |
87 | 86 | |
88 | def createPlugin(ignore_info=False): | |
89 | return pasteAnalyzerPlugin(ignore_info=ignore_info) | |
90 | ||
91 | ||
87 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
88 | return pasteAnalyzerPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
16 | 16 | __status__ = "Development" |
17 | 17 | |
18 | 18 | from faraday_plugins.plugins.plugin import PluginBase |
19 | from faraday_plugins.plugins.plugins_utils import resolve_hostname | |
20 | 19 | |
21 | 20 | |
22 | 21 | class PeepingTomPlugin(PluginBase): |
48 | 47 | for url in re.findall(r'href=[\'"]?([^\'" >]+)', html): |
49 | 48 | if "://" in url: |
50 | 49 | url_parsed = urlparse(url) |
51 | address = resolve_hostname(url_parsed.netloc) | |
50 | address = self.resolve_hostname(url_parsed.netloc) | |
52 | 51 | host = self.createAndAddHost(address) |
53 | 52 | service = self.createAndAddServiceToHost(host, "http", protocol="tcp", ports=[80]) |
54 | 53 | self.createAndAddNoteToService( |
70 | 69 | self._path = current_path |
71 | 70 | |
72 | 71 | |
73 | def createPlugin(ignore_info=False): | |
74 | return PeepingTomPlugin(ignore_info=ignore_info) | |
75 | ||
76 | ||
72 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
73 | return PeepingTomPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
47 | 47 | return False |
48 | 48 | |
49 | 49 | |
50 | def createPlugin(ignore_info=False): | |
51 | return CmdPingPlugin(ignore_info=ignore_info) | |
50 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
51 | return CmdPingPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
60 | 60 | self._port = count_args[2] |
61 | 61 | |
62 | 62 | |
63 | def createPlugin(ignore_info=False): | |
64 | return CmdPropeciaPlugin(ignore_info=ignore_info) | |
65 | ||
66 | ||
63 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
64 | return CmdPropeciaPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
107 | 107 | ref=[issue.doc_link]) |
108 | 108 | |
109 | 109 | |
110 | def createPlugin(ignore_info=False): | |
111 | return ProwlerPlugin(ignore_info=ignore_info) | |
110 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
111 | return ProwlerPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
145 | 145 | |
146 | 146 | self.severity_dict = { |
147 | 147 | '1': 'info', |
148 | '2': 'info', | |
148 | '2': 'low', | |
149 | 149 | '3': 'med', |
150 | 150 | '4': 'high', |
151 | 151 | '5': 'critical'} |
179 | 179 | self.cve.append(cve_id) |
180 | 180 | |
181 | 181 | if self.cvss: |
182 | self.ref.append('CVSS SCORE: {}'.format(self.cvss)) | |
182 | self.ref.append(f'CVSS SCORE: {self.cvss}') | |
183 | 183 | |
184 | 184 | if self.pci: |
185 | self.ref.append('PCI: {}'.format(self.pci)) | |
185 | self.ref.append(f'PCI: {self.pci}') | |
186 | 186 | |
187 | 187 | def get_text_from_glossary(self, tag): |
188 | 188 | """ |
285 | 285 | |
286 | 286 | self.severity_dict = { |
287 | 287 | '1': 'info', |
288 | '2': 'info', | |
288 | '2': 'low', | |
289 | 289 | '3': 'med', |
290 | 290 | '4': 'high', |
291 | 291 | '5': 'critical'} |
414 | 414 | del parser |
415 | 415 | |
416 | 416 | |
417 | def createPlugin(ignore_info=False): | |
418 | return QualysguardPlugin(ignore_info=ignore_info) | |
417 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
418 | return QualysguardPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
0 | 0 | #!/usr/bin/env python |
1 | # -*- coding: utf-8 -*- | |
2 | 1 | """ |
3 | 2 | Faraday Penetration Test IDE |
4 | 3 | Copyright (C) 2016 Infobyte LLC (http://www.infobytesec.com/) |
23 | 22 | def __init__(self, xml_output): |
24 | 23 | self.tree = self.parse_xml(xml_output) |
25 | 24 | if self.tree: |
26 | self.info_results = self.get_results_vul(self.tree.find('RESULTS')) | |
25 | if self.tree.find('RESULTS/WEB_APPLICATION'): | |
26 | self.info_results = self.get_results_vul(self.tree.find('RESULTS/WEB_APPLICATION')) | |
27 | else: | |
28 | self.info_results = self.get_results_vul(self.tree.find('RESULTS')) | |
27 | 29 | self.info_glossary = self.get_glossary_qid(self.tree.find('GLOSSARY')) |
28 | 30 | self.info_appendix = self.get_appendix(self.tree.find('APPENDIX')) |
29 | 31 | else: |
33 | 35 | try: |
34 | 36 | tree = ET.fromstring(xml_output) |
35 | 37 | except SyntaxError as err: |
36 | print('SyntaxError In xml: %s. %s' % (err, xml_output)) | |
38 | print(f'SyntaxError In xml: {err} {xml_output}') | |
37 | 39 | return None |
38 | 40 | return tree |
39 | 41 | |
40 | def get_appendix(self, tree): | |
41 | for self.appendix_tags in tree: | |
42 | yield Appendix(self.appendix_tags) | |
42 | @staticmethod | |
43 | def get_appendix(tree): | |
44 | for appendix_tags in tree: | |
45 | yield Appendix(appendix_tags) | |
43 | 46 | |
44 | def get_glossary_qid(self, tree): | |
45 | for self.glossary_tags in tree.find('QID_LIST'): | |
46 | yield Glossary(self.glossary_tags) | |
47 | @staticmethod | |
48 | def get_glossary_qid(tree): | |
49 | for glossary_tags in tree.find('QID_LIST'): | |
50 | yield Glossary(glossary_tags) | |
47 | 51 | |
48 | def get_results_vul(self, tree): | |
49 | for self.results_tags in tree.find('VULNERABILITY_LIST'): | |
50 | yield Results(self.results_tags) | |
52 | @staticmethod | |
53 | def get_results_vul(tree): | |
54 | for results_tags in tree.find('VULNERABILITY_LIST'): | |
55 | yield Results(results_tags) | |
51 | 56 | |
52 | 57 | |
53 | class Appendix(): | |
58 | class Appendix: | |
54 | 59 | def __init__(self, appendix_tags): |
55 | 60 | if appendix_tags.tag == 'SCAN_LIST': |
56 | 61 | self.lista_scan = self.get_scan(appendix_tags.find('SCAN')) |
58 | 63 | elif appendix_tags.tag == 'WEBAPP': |
59 | 64 | self.lista_webapp = self.get_webapp(appendix_tags) |
60 | 65 | |
61 | def get_scan(self, appendix_tags): | |
62 | self.result_scan = {} | |
66 | @staticmethod | |
67 | def get_scan(appendix_tags): | |
68 | result_scan = {} | |
63 | 69 | for scan in appendix_tags: |
64 | self.result_scan[scan.tag] = scan.text | |
65 | return self.result_scan | |
70 | result_scan[scan.tag] = scan.text | |
71 | return result_scan | |
66 | 72 | |
67 | def get_webapp(self, appendix_tags): | |
68 | self.result_webapp = {} | |
73 | @staticmethod | |
74 | def get_webapp(appendix_tags): | |
75 | result_webapp = {} | |
69 | 76 | for webapp in appendix_tags: |
70 | self.result_webapp[webapp.tag] = webapp.text | |
71 | return self.result_webapp | |
77 | result_webapp[webapp.tag] = webapp.text | |
78 | return result_webapp | |
72 | 79 | |
73 | 80 | |
74 | class Glossary(): | |
81 | class Glossary: | |
75 | 82 | def __init__(self, glossary_tags): |
76 | 83 | self.lista_qid = self.get_qid_list(glossary_tags) |
77 | 84 | |
82 | 89 | return self.dict_result_qid |
83 | 90 | |
84 | 91 | |
85 | class Results(): | |
92 | class Results: | |
86 | 93 | def __init__(self, glossary_tags): |
87 | 94 | self.lista_vul = self.get_qid_list(glossary_tags) |
88 | 95 | |
97 | 104 | |
98 | 105 | def __init__(self, *arg, **kwargs): |
99 | 106 | super().__init__(*arg, **kwargs) |
100 | self.identifier_tag = ["WAS_SCAN_REPORT"] | |
107 | self.identifier_tag = ["WAS_WEBAPP_REPORT", "WAS_SCAN_REPORT"] | |
101 | 108 | self.id = 'QualysWebapp' |
102 | 109 | self.name = 'QualysWebapp XML Output Plugin' |
103 | 110 | self.plugin_version = '1.0.0' |
120 | 127 | for host_create in parser.info_appendix: |
121 | 128 | self.scan_list_result.append(host_create) |
122 | 129 | |
130 | operating_system = "" | |
123 | 131 | for k in self.scan_list_result: |
124 | 132 | if 'result_scan' in k.__dict__: |
125 | 133 | self.credential = k.lista_scan.get('AUTHENTICATION_RECORD') |
136 | 144 | |
137 | 145 | for v in parser.info_results: |
138 | 146 | url = urlparse(v.dict_result_vul.get('URL')) |
139 | ||
140 | 147 | host_id = self.createAndAddHost(name=url.netloc, os=operating_system, hostnames=hostnames) |
141 | 148 | |
142 | 149 | vuln_scan_id = v.dict_result_vul.get('QID') |
144 | 151 | # Data in the xml is in different parts, we look into the glossary |
145 | 152 | vuln_data = next((item for item in glossary if item["QID"] == vuln_scan_id), None) |
146 | 153 | vuln_name = vuln_data.get('TITLE') |
147 | vuln_desc = vuln_data.get('DESCRIPTION') | |
148 | ||
154 | vuln_desc = vuln_data.get('DESCRIPTION') + v.dict_result_vul.get('URL') | |
149 | 155 | raw_severity = int(vuln_data.get('SEVERITY', 0)) |
150 | 156 | vuln_severity = raw_severity - 1 |
151 | 157 | |
158 | 164 | |
159 | 165 | vuln_ref = [] |
160 | 166 | if vuln_data.get('CVSS_BASE'): |
161 | vuln_ref = ["CVSS: {}".format(vuln_data.get('CVSS_BASE'))] | |
167 | vuln_ref = [f"CVSS: {vuln_data.get('CVSS_BASE')}"] | |
162 | 168 | |
163 | vuln_data_add = "ID: {}, DETECTION_ID: {}, CATEGORY: {}, GROUP: {}, URL: {}, IMPACT: {}".format( | |
164 | v.dict_result_vul.get('ID'), v.dict_result_vul.get('DETECTION_ID'), vuln_data.get('CATEGORY'), | |
165 | vuln_data.get('GROUP'), v.dict_result_vul.get('URL'), vuln_data.get('IMPACT')) | |
169 | vuln_data_add = f"ID: {v.dict_result_vul.get('ID')}, DETECTION_ID: {v.dict_result_vul.get('DETECTION_ID')}" \ | |
170 | f", CATEGORY: {vuln_data.get('CATEGORY')}, GROUP: {vuln_data.get('GROUP')}" \ | |
171 | f", URL: {v.dict_result_vul.get('URL')}, IMPACT: {vuln_data.get('IMPACT')}" | |
166 | 172 | |
167 | 173 | self.createAndAddVulnToHost(host_id=host_id, name=vuln_name, desc=vuln_desc, ref=vuln_ref, |
168 | 174 | severity=vuln_severity, resolution=vuln_resolution, run_date=run_date, |
169 | external_id=vuln_scan_id, data=vuln_data_add) | |
175 | external_id="QUALYS-"+vuln_scan_id, data=vuln_data_add) | |
170 | 176 | |
171 | 177 | |
172 | def createPlugin(ignore_info=False): | |
173 | return QualysWebappPlugin(ignore_info=ignore_info) | |
178 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
179 | return QualysWebappPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
1 | 1 | from collections import defaultdict |
2 | 2 | |
3 | 3 | from faraday_plugins.plugins.plugin import PluginBase |
4 | from faraday_plugins.plugins.plugins_utils import resolve_hostname | |
5 | ||
6 | 4 | |
7 | 5 | class RDPScanPlugin(PluginBase): |
8 | 6 | |
42 | 40 | ) |
43 | 41 | |
44 | 42 | |
45 | def createPlugin(ignore_info=False): | |
46 | return RDPScanPlugin(ignore_info=ignore_info) | |
43 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
44 | return RDPScanPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
12 | 12 | import xml.etree.ElementTree as ET |
13 | 13 | |
14 | 14 | from faraday_plugins.plugins.plugin import PluginXMLFormat |
15 | from faraday_plugins.plugins.plugins_utils import resolve_hostname | |
16 | 15 | |
17 | 16 | __author__ = 'Leonardo Lazzaro' |
18 | 17 | __copyright__ = 'Copyright (c) 2017, Infobyte LLC' |
149 | 148 | self.host_mapper[host['host']] = h_id |
150 | 149 | for vuln in parser.vulns: |
151 | 150 | if vuln['host'] not in list(self.host_mapper.keys()): |
152 | ip = resolve_hostname(vuln['host']) | |
151 | ip = self.resolve_hostname(vuln['host']) | |
153 | 152 | h_id = self.createAndAddHost( |
154 | 153 | ip, |
155 | 154 | hostnames=[vuln['host']] |
170 | 169 | |
171 | 170 | |
172 | 171 | |
173 | def createPlugin(ignore_info=False): | |
174 | return ReconngPlugin(ignore_info=ignore_info) | |
175 | ||
176 | ||
172 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
173 | return ReconngPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
48 | 48 | try: |
49 | 49 | tree = ET.fromstring(xml_output) |
50 | 50 | except SyntaxError as err: |
51 | print("SyntaxError: %s. %s" % (err, xml_output)) | |
51 | print(f"SyntaxError: {err}. {xml_output}") | |
52 | 52 | return None |
53 | 53 | |
54 | 54 | return tree |
211 | 211 | del parser |
212 | 212 | |
213 | 213 | |
214 | def createPlugin(ignore_info=False): | |
215 | return RetinaPlugin(ignore_info=ignore_info) | |
214 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
215 | return RetinaPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
35 | 35 | |
36 | 36 | for line in lists: |
37 | 37 | if line != "": |
38 | print("(%s)" % line) | |
38 | print(f"({line})") | |
39 | 39 | info = line.split("\t") |
40 | 40 | if info.__len__() > 0: |
41 | 41 | item = {'host': info[0], 'ip': info[1]} |
42 | print("host = %s, ip = %s" % (info[0], info[1])) | |
42 | print(f"host = {info[0]}, ip = {info[1]}") | |
43 | 43 | self.items.append(item) |
44 | 44 | |
45 | 45 | |
77 | 77 | |
78 | 78 | |
79 | 79 | |
80 | def createPlugin(ignore_info=False): | |
81 | return ReverseraiderPlugin(ignore_info=ignore_info) | |
82 | ||
83 | ||
80 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
81 | return ReverseraiderPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
12 | 12 | import shutil |
13 | 13 | |
14 | 14 | from faraday_plugins.plugins.plugin import PluginMultiLineJsonFormat |
15 | ||
15 | from faraday_plugins.plugins.plugins_utils import get_severity_from_cvss | |
16 | 16 | __author__ = "Valentin Vila" |
17 | 17 | __copyright__ = "Copyright (c) 2021, Faraday" |
18 | 18 | __credits__ = ["Valentin Vila"] |
71 | 71 | for name, vuln_info in vulns.items(): |
72 | 72 | description = vuln_info.get('summary') |
73 | 73 | references = vuln_info.get('references') |
74 | self.createAndAddVulnToService(h_id, s_id, name, desc=description, severity=0, ref=references, cve=name) | |
74 | cvss = vuln_info.get('cvss') | |
75 | severity = get_severity_from_cvss(cvss) if cvss else "info" | |
76 | self.createAndAddVulnToService(h_id, s_id, name, desc=description, severity=severity, ref=references, cve=name) | |
75 | 77 | |
76 | 78 | def processCommandString(self, username, current_path, command_string): |
77 | 79 | """ |
101 | 103 | return cmd |
102 | 104 | |
103 | 105 | |
104 | def createPlugin(ignore_info=False): | |
105 | return ShodanPlugin(ignore_info=ignore_info) | |
106 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
107 | return ShodanPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
11 | 11 | import tempfile |
12 | 12 | |
13 | 13 | from faraday_plugins.plugins.plugin import PluginBase |
14 | from faraday_plugins.plugins.plugins_utils import resolve_hostname | |
15 | 14 | |
16 | 15 | |
17 | 16 | __author__ = "Nicolas Rodriguez" |
40 | 39 | def __init__(self, skipfish_filepath): |
41 | 40 | self.filepath = skipfish_filepath |
42 | 41 | |
43 | tmp = open(skipfish_filepath + "/samples.js", "r").read() | |
42 | tmp = open(skipfish_filepath + "/samples.js").read() | |
44 | 43 | data = self.extract_data( |
45 | 44 | tmp, |
46 | 45 | "var issue_samples =", "];", |
51 | 50 | # Also remove \n character and space for have a valid JSON. |
52 | 51 | issues = json.loads(repr(data[1]).replace("\\n"," ").replace("'","") + "]") |
53 | 52 | |
54 | tmp = open(skipfish_filepath + "/index.html", "r").read() | |
53 | tmp = open(skipfish_filepath + "/index.html").read() | |
55 | 54 | err_msg = json.loads( |
56 | 55 | self.extract_data( |
57 | 56 | tmp, |
151 | 150 | for sample in issue["samples"]: |
152 | 151 | if not sample["url"] in hostc: |
153 | 152 | reg = re.search( |
154 | "(http|https|ftp)\://([a-zA-Z0-9\.\-]+(\:[a-zA-Z0-9\.&%\$\-]+)*@)*((25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{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[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]{1}|[0-9])|localhost|([a-zA-Z0-9\-]+\.)*[a-zA-Z0-9\-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))[\:]*([0-9]+)*([/]*($|[a-zA-Z0-9\.\,\?\'\\\+&%\$#\=~_\-]+)).*?$", sample["url"]) | |
153 | "(http|https|ftp)\\://([a-zA-Z0-9\\.\\-]+(\\:[a-zA-Z0-9\\.&%\\$\\-]+)*@)*((25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{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[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]{1}|[0-9])|localhost|([a-zA-Z0-9\\-]+\\.)*[a-zA-Z0-9\\-]+\\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))[\\:]*([0-9]+)*([/]*($|[a-zA-Z0-9\\.\\,\\?\'\\\\+&%\\$#\\=~_\\-]+)).*?$", sample["url"]) | |
155 | 154 | |
156 | 155 | protocol = reg.group(1) |
157 | 156 | host = reg.group(4) |
160 | 159 | else: |
161 | 160 | port = 443 if protocol == "https" else 80 |
162 | 161 | |
163 | ip = resolve_hostname(host) | |
162 | ip = self.resolve_hostname(host) | |
164 | 163 | |
165 | 164 | h_id = self.createAndAddHost(ip, hostnames=[host]) |
166 | 165 | s_id = self.createAndAddServiceToHost(h_id, "http", "tcp", ports=[port], status="open") |
203 | 202 | |
204 | 203 | |
205 | 204 | |
206 | def createPlugin(ignore_info=False): | |
207 | return SkipfishPlugin(ignore_info=ignore_info) | |
208 | ||
209 | ||
205 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
206 | return SkipfishPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
21 | 21 | } |
22 | 22 | STATUSES = { |
23 | 23 | 'OPEN': 'open', |
24 | 'CONFIRMED': 'opened', | |
24 | 'CONFIRMED': 'open', | |
25 | 25 | 'REOPENED': 're-opened', |
26 | 26 | 'CLOSED': 'closed', |
27 | 27 | 'RESOLVED': 'closed' |
93 | 93 | ) |
94 | 94 | |
95 | 95 | |
96 | def createPlugin(ignore_info=False): | |
97 | return SonarQubeAPIPlugin(ignore_info=ignore_info) | |
96 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
97 | return SonarQubeAPIPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
62 | 62 | for vuln in vulns: |
63 | 63 | v_name = vuln['title'] |
64 | 64 | v_desc = vuln['overview'] |
65 | v_ref = "CVSS: {}".format(vuln['cvssScore']) | |
65 | v_ref = f"CVSS: {vuln['cvssScore']}" | |
66 | 66 | v_data = vuln['libraries'] |
67 | 67 | v_website = vuln['_links']['html'] |
68 | 68 | url_data = parser.parse_url(v_website) |
81 | 81 | website=v_website) |
82 | 82 | |
83 | 83 | |
84 | def createPlugin(ignore_info=False): | |
85 | return SourceclearPlugin(ignore_info=ignore_info) | |
84 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
85 | return SourceclearPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
65 | 65 | return None |
66 | 66 | |
67 | 67 | |
68 | def createPlugin(ignore_info=False): | |
69 | return SSHDefaultScanPlugin(ignore_info=ignore_info) | |
70 | ||
71 | ||
68 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
69 | return SSHDefaultScanPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
3 | 3 | See the file 'doc/LICENSE' for the license information |
4 | 4 | |
5 | 5 | """ |
6 | import re | |
7 | 6 | import json |
8 | from urllib.parse import urlparse | |
9 | 7 | from faraday_plugins.plugins.plugin import PluginJsonFormat |
10 | from faraday_plugins.plugins.plugins_utils import resolve_hostname | |
11 | 8 | |
12 | 9 | __author__ = "Blas Moyano" |
13 | 10 | __copyright__ = "Copyright (c) 2020, Infobyte LLC" |
109 | 106 | data=vuln['data']) |
110 | 107 | |
111 | 108 | |
112 | def createPlugin(ignore_info=False): | |
113 | return SslLabsPlugin(ignore_info=ignore_info) | |
109 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
110 | return SslLabsPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
131 | 131 | host_id, |
132 | 132 | service_id, |
133 | 133 | name="Certificate mismatch", |
134 | desc="Certificate does not match server hostname {}".format(server_hostname), | |
134 | desc=f"Certificate does not match server hostname {server_hostname}", | |
135 | 135 | severity="info") |
136 | 136 | # Ciphers |
137 | 137 | cipher = parser.cipher_suite |
142 | 142 | host_id, |
143 | 143 | service_id, |
144 | 144 | name=value, |
145 | desc="In protocol [{}], weak cipher suite: {}".format(key, value), | |
145 | desc=f"In protocol [{key}], weak cipher suite: {value}", | |
146 | 146 | severity="low") |
147 | 147 | |
148 | 148 | # Heartbleed |
168 | 168 | severity="medium") |
169 | 169 | |
170 | 170 | |
171 | def createPlugin(ignore_info=False): | |
172 | return SslyzePlugin(ignore_info=ignore_info) | |
171 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
172 | return SslyzePlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
6 | 6 | import re |
7 | 7 | import json |
8 | 8 | from faraday_plugins.plugins.plugin import PluginJsonFormat |
9 | from faraday_plugins.plugins.plugins_utils import resolve_hostname | |
10 | 9 | |
11 | 10 | __author__ = "Blas Moyano" |
12 | 11 | __copyright__ = "Copyright (c) 2020, Infobyte LLC" |
20 | 19 | |
21 | 20 | class SslyzeJsonParser: |
22 | 21 | |
23 | def __init__(self, json_output): | |
22 | def __init__(self, json_output, resolve_hostname): | |
23 | self.resolve_hostname = resolve_hostname | |
24 | 24 | json_sslyze = json.loads(json_output) |
25 | 25 | scan_result = json_sslyze.get('server_scan_results') |
26 | 26 | self.list_vul = self.get_vuln(scan_result) |
66 | 66 | def get_host(self, server_location): |
67 | 67 | port = server_location.get('port', None) |
68 | 68 | hostname = server_location.get('hostname', None) |
69 | ip = server_location.get('ip_address', resolve_hostname(hostname)) | |
69 | ip = server_location.get('ip_address', self.resolve_hostname(hostname)) | |
70 | 70 | if port != 443: |
71 | 71 | url = f"https://{hostname}:{port}" |
72 | 72 | else: |
192 | 192 | self._temp_file_extension = "json" |
193 | 193 | |
194 | 194 | def parseOutputString(self, output): |
195 | parser = SslyzeJsonParser(output) | |
195 | parser = SslyzeJsonParser(output, self.resolve_hostname) | |
196 | 196 | |
197 | 197 | for info_sslyze in parser.list_vul: |
198 | 198 | info_sslyze['host_info'].get('hostname') |
286 | 286 | command_string) |
287 | 287 | |
288 | 288 | |
289 | def createPlugin(ignore_info=False): | |
290 | return SslyzePlugin(ignore_info=ignore_info) | |
291 | ||
289 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
290 | return SslyzePlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
0 | from faraday_plugins.plugins.plugin import PluginXMLFormat | |
1 | ||
2 | import xml.etree.ElementTree as ET | |
3 | ||
4 | __author__ = "Gonzalo Martinez" | |
5 | __copyright__ = "Copyright (c) 2021, Infobyte LLC" | |
6 | __credits__ = ["Gonzalo Martinez"] | |
7 | __license__ = "" | |
8 | __version__ = "1.0" | |
9 | __maintainer__ = "Gonzalo Martinez" | |
10 | __status__ = "Development" | |
11 | ||
12 | ||
13 | class SyhuntParser: | |
14 | ||
15 | def __init__(self, xml_output): | |
16 | tree = self.parse_xml(xml_output) | |
17 | if tree: | |
18 | self.scan_type = "SAST" if "Application Code Scan" in tree.find("scan_method").text else "DAST" | |
19 | self.issues = self.get_issues(tree.find("hosts")) | |
20 | ||
21 | @staticmethod | |
22 | def parse_xml(xml_output): | |
23 | try: | |
24 | tree = ET.fromstring(xml_output) | |
25 | except SyntaxError as err: | |
26 | print(f'SyntaxError In xml: {err}. {xml_output}') | |
27 | return None | |
28 | return tree | |
29 | ||
30 | def get_issues(self, tree): | |
31 | issues = [] | |
32 | if self.scan_type == "DAST": | |
33 | for host in tree: | |
34 | h = self.get_host(host) | |
35 | vulns = [self.get_vulns(vuln) for vuln in host.find("vulnerabilities")] | |
36 | issues.append({ | |
37 | "host": h, | |
38 | "vulns": vulns | |
39 | }) | |
40 | else: | |
41 | for host in tree: | |
42 | for vuln in host.find("vulnerabilities"): | |
43 | issues.append(self.get_vulns(vuln)) | |
44 | return issues | |
45 | ||
46 | def get_vulns(self, vuln): | |
47 | name = vuln.find("check_name").text | |
48 | desc = vuln.find("description").text | |
49 | resolution = vuln.find("solution").text | |
50 | cvss2 = self.get_cvss(vuln.find("cvss/cvss2")) | |
51 | cvss3 = self.get_cvss(vuln.find("cvss/cvss3")) | |
52 | severity = vuln.find("cvss/cvss3/severity").text | |
53 | ref = [] | |
54 | if vuln.find("references/cwe"): | |
55 | ref.append("CWE:" + vuln.find("references/cwe").text) | |
56 | v = { | |
57 | "name": name, | |
58 | "desc": desc, | |
59 | "resolution": resolution, | |
60 | "ref": ref, | |
61 | "severity": severity | |
62 | } | |
63 | if self.scan_type == "DAST": | |
64 | v['data'] = vuln.find("request").text + "\n" | |
65 | v['data'] += f"Location {vuln.find('location').text}" | |
66 | else: | |
67 | v['location'] = vuln.find('location_appsource').text | |
68 | v['data'] = vuln.find('vulnerable_code').text | |
69 | return v | |
70 | ||
71 | @staticmethod | |
72 | def get_cvss(tree): | |
73 | cvss_vector = tree.find("vector").text | |
74 | cvss_score = tree.find("score").text | |
75 | return {'base_score':cvss_score, 'cvss_vector': cvss_vector} | |
76 | ||
77 | def get_host(self, tree): | |
78 | host = { | |
79 | "ip": tree.find("host_details/ip_address").text, | |
80 | "hostname": tree.find("host_details/host_name").text, | |
81 | "port": tree.find("scan_progress/port/port_number").text, | |
82 | "service_name": "https" if "https" in tree.find("host_details/host_name").text else "http" | |
83 | } | |
84 | return host | |
85 | ||
86 | ||
87 | class SyhuntPlugin(PluginXMLFormat): | |
88 | ||
89 | def __init__(self, *arg, **kwargs): | |
90 | super().__init__(*arg, **kwargs) | |
91 | self.identifier_tag = "report" | |
92 | self.id = 'Syhunt' | |
93 | self.name = 'Syhunt XML Plugin' | |
94 | self.plugin_version = '0.0.1' | |
95 | self.version = '1.0.0' | |
96 | self.framework_version = '1.0.0' | |
97 | ||
98 | #uggly fix because wakiti and syhunt share identifier_tag | |
99 | def report_belongs_to(self, main_tag="", main_tag_attributes={}, **kwargs): | |
100 | match = super().report_belongs_to(main_tag, main_tag_attributes,**kwargs) | |
101 | if match: | |
102 | match = main_tag_attributes == {} | |
103 | return match | |
104 | ||
105 | def parseOutputString(self, output): | |
106 | parser = SyhuntParser(output) | |
107 | scan_type = parser.scan_type | |
108 | ||
109 | if scan_type == 'DAST': | |
110 | for issue in parser.issues: | |
111 | ip = issue["host"].pop("ip") | |
112 | port = issue["host"].pop("port") | |
113 | hostname = issue["host"].pop("hostname") | |
114 | service_name = issue["host"].pop("service_name") | |
115 | host_id = self.createAndAddHost(ip, hostnames=hostname) | |
116 | service_id = self.createAndAddServiceToHost(host_id, service_name, ports=port) | |
117 | for vuln in issue['vulns']: | |
118 | self.createAndAddVulnWebToService(host_id=host_id, service_id=service_id, **vuln) | |
119 | ||
120 | elif scan_type == 'SAST': | |
121 | for issue in parser.issues: | |
122 | source_file = issue.pop('location') | |
123 | host_id = self.createAndAddHost(source_file) | |
124 | self.createAndAddVulnToHost(host_id=host_id, **issue) | |
125 | ||
126 | ||
127 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
128 | return SyhuntPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
5 | 5 | """ |
6 | 6 | import re |
7 | 7 | from faraday_plugins.plugins.plugin import PluginBase |
8 | from faraday_plugins.plugins.plugins_utils import resolve_hostname | |
9 | 8 | |
10 | 9 | __author__ = "Facundo de Guzmán, Esteban Guillardoy" |
11 | 10 | __copyright__ = "Copyright (c) 2013, Infobyte LLC" |
60 | 59 | host_info = re.search(r"Connected to (.+)\.", output) |
61 | 60 | |
62 | 61 | hostname = host_info.group(1) |
63 | ip_address = resolve_hostname(hostname) | |
62 | ip_address = self.resolve_hostname(hostname) | |
64 | 63 | |
65 | 64 | if host_info is not None: |
66 | 65 | h_id = self.createAndAddHost(ip_address, hostnames=[hostname]) |
76 | 75 | self._port = count_args[c - 1] |
77 | 76 | |
78 | 77 | |
79 | def createPlugin(ignore_info=False): | |
80 | return TelnetRouterPlugin(ignore_info=ignore_info) | |
81 | ||
82 | ||
78 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
79 | return TelnetRouterPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
35 | 35 | _hosts, _vhosts = [], [] |
36 | 36 | |
37 | 37 | mregex = re.search( |
38 | "\[\+\] Hosts found in search engines:[-=\s]+([\w\W]*)\[\+\]", output) | |
38 | r"\[\+\] Hosts found in search engines:[-=\s]+([\w\W]*)\[\+\]", output) | |
39 | 39 | if mregex is None: |
40 | 40 | mregex = re.search( |
41 | "\[\+\] Hosts found in search engines:[-=\s]+([\w\W]*)\n", output) | |
42 | mregex2 = re.search("\[\+\] Virtual hosts:[-=\s]+([\w\W]*)\n", output) | |
41 | "\\[\\+\\] Hosts found in search engines:[-=\\s]+([\\w\\W]*)\n", output) | |
42 | mregex2 = re.search("\\[\\+\\] Virtual hosts:[-=\\s]+([\\w\\W]*)\n", output) | |
43 | 43 | |
44 | 44 | if mregex is None and mregex2 is None: |
45 | 45 | return |
114 | 114 | |
115 | 115 | |
116 | 116 | |
117 | def createPlugin(ignore_info=False): | |
118 | return TheharvesterPlugin(ignore_info=ignore_info) | |
119 | ||
120 | ||
121 | ||
117 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
118 | return TheharvesterPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
55 | 55 | return None |
56 | 56 | |
57 | 57 | |
58 | def createPlugin(ignore_info=False): | |
59 | return traceroutePlugin(ignore_info=ignore_info) | |
60 | ||
61 | ||
58 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
59 | return traceroutePlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
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 resolve_hostname | |
12 | 11 | |
13 | 12 | __author__ = "Francisco Amato" |
14 | 13 | __copyright__ = "Copyright (c) 2013, Infobyte LLC" |
146 | 145 | |
147 | 146 | self.req = hreq.find('status').text |
148 | 147 | for h in hreq.findall('headers/header'): |
149 | self.req += "\n%s: %s" % (h.get('field'), h.get('content')) | |
150 | ||
151 | if hreq.findtext('body',""): | |
152 | self.req += "\n%s" % hreq.findtext('body',"") | |
148 | self.req += f"\n{h.get('field')}: {h.get('content')}" | |
149 | ||
150 | if hreq.findtext('body', ""): | |
151 | self.req += f"\n{hreq.findtext('body', '')}" | |
153 | 152 | |
154 | 153 | self.resp = hres.find('status').text |
155 | 154 | for h in hres.findall('headers/header'): |
156 | self.resp += "\n%s: %s" % (h.get('field'), h.get('content')) | |
157 | ||
158 | if hres.findtext('body',""): | |
159 | self.resp += "\n%s" % hres.findtext('body',"") | |
155 | self.resp += f"\n{h.get('field')}: {h.get('content')}" | |
156 | ||
157 | if hres.findtext('body', ""): | |
158 | self.resp += f"\n{hres.findtext('body', '')}" | |
160 | 159 | |
161 | 160 | def do_clean(self, value): |
162 | 161 | myreturn = "" |
201 | 200 | |
202 | 201 | def parseOutputString(self, output): |
203 | 202 | parser = W3afXmlParser(output) |
204 | ip = resolve_hostname(parser.host) | |
203 | ip = self.resolve_hostname(parser.host) | |
205 | 204 | h_id = self.createAndAddHost(ip, hostnames=[parser.host]) |
206 | 205 | s_id = self.createAndAddServiceToHost(h_id, "http", "tcp", ports=[parser.port], status="open") |
207 | 206 | |
213 | 212 | del parser |
214 | 213 | |
215 | 214 | |
216 | def createPlugin(ignore_info=False): | |
217 | return W3afPlugin(ignore_info=ignore_info) | |
215 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
216 | return W3afPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
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 resolve_hostname | |
12 | 11 | |
13 | 12 | __author__ = "Francisco Amato" |
14 | 13 | __copyright__ = "Copyright (c) 2013, Infobyte LLC" |
31 | 30 | @param wapiti_xml_filepath A proper xml generated by wapiti |
32 | 31 | """ |
33 | 32 | |
34 | def __init__(self, xml_output): | |
33 | def __init__(self, xml_output, resolve_hostname): | |
34 | self.resolve_hostname = resolve_hostname | |
35 | 35 | tree = self.parse_xml(xml_output) |
36 | 36 | if tree: |
37 | 37 | self.items = [data for data in self.get_items(tree)] |
50 | 50 | try: |
51 | 51 | tree = ET.fromstring(xml_output) |
52 | 52 | except SyntaxError as err: |
53 | print("SyntaxError: %s. %s" % (err, xml_output)) | |
53 | print(f"SyntaxError: {err}. {xml_output}") | |
54 | 54 | return None |
55 | 55 | |
56 | 56 | return tree |
60 | 60 | @return items A list of Host instances |
61 | 61 | """ |
62 | 62 | |
63 | yield Item(tree) | |
63 | yield Item(tree, self.resolve_hostname) | |
64 | 64 | |
65 | 65 | |
66 | 66 | def get_attrib_from_subnode(xml_node, subnode_xpath_expr, attrib_name): |
87 | 87 | @param item_node A item_node taken from an wapiti xml tree |
88 | 88 | """ |
89 | 89 | |
90 | def __init__(self, item_node): | |
90 | def __init__(self, item_node, resolve_hostname): | |
91 | 91 | self.node = item_node |
92 | 92 | self.url = self.get_url(item_node) |
93 | 93 | if self.url.hostname is not None: |
199 | 199 | |
200 | 200 | def __init__(self, *arg, **kwargs): |
201 | 201 | super().__init__(*arg, **kwargs) |
202 | self.identifier_tag = "report" | |
202 | #self.identifier_tag = "report" | |
203 | self.identifier_tag_attributes = {'type'} | |
203 | 204 | self.id = "Wapiti" |
204 | 205 | self.name = "Wapiti XML Output Plugin" |
205 | 206 | self.plugin_version = "0.0.1" |
268 | 269 | the xml where it expects it to be present. |
269 | 270 | """ |
270 | 271 | |
271 | parser = WapitiXmlParser(output) | |
272 | parser = WapitiXmlParser(output, self.resolve_hostname) | |
272 | 273 | for item in parser.items: |
273 | 274 | host_id = self.createAndAddHost(item.ip, hostnames=[item.hostname]) |
274 | 275 | if item.port is None: |
298 | 299 | """ |
299 | 300 | super().processCommandString(username, current_path, command_string) |
300 | 301 | host = re.search( |
301 | "(http|https|ftp)\://([a-zA-Z0-9\.\-]+(\:[a-zA-Z0-9\.&%\$\-]+)*@)*((25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]" | |
302 | "{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" | |
303 | "[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]" | |
304 | "{1}|[0-9])|localhost|([a-zA-Z0-9\-]+\.)*[a-zA-Z0-9\-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|" | |
305 | "pro|aero|coop|museum|[a-zA-Z]{2}))[\:]*([0-9]+)*([/]*($|[a-zA-Z0-9\.\,\?\'\\\+&%\$#\=~_\-]+)).*?$", | |
302 | 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]" | |
303 | 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" | |
304 | 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]" | |
305 | r"{1}|[0-9])|localhost|([a-zA-Z0-9\-]+\.)*[a-zA-Z0-9\-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|" | |
306 | "pro|aero|coop|museum|[a-zA-Z]{2}))[\\:]*([0-9]+)*([/]*($|[a-zA-Z0-9\\.\\,\\?\'\\\\+&%\\$#\\=~_\\-]+)).*?$", | |
306 | 307 | command_string) |
307 | 308 | |
308 | 309 | self.protocol = host.group(1) |
312 | 313 | if self.protocol == 'https': |
313 | 314 | self.port = 443 |
314 | 315 | self.logger.debug("host = %s, port = %s", self.host, self.port) |
315 | return "%s -o %s -f xml \n" % (command_string, self._output_file_path) | |
316 | ||
317 | ||
318 | def createPlugin(ignore_info=False): | |
319 | return WapitiPlugin(ignore_info=ignore_info) | |
316 | return f"{command_string} -o {self._output_file_path} -f xml \n" | |
317 | ||
318 | ||
319 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
320 | return WapitiPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
112 | 112 | arg_match = self.xml_arg_re.match(command_string) |
113 | 113 | |
114 | 114 | if arg_match is None: |
115 | return "%s --xml %s" % (command_string, self._output_file_path) | |
115 | return f"{command_string} --xml {self._output_file_path}" | |
116 | 116 | else: |
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): | |
121 | return WcscanPlugin(ignore_info=ignore_info) | |
120 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
121 | return WcscanPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
35 | 35 | def __init__(self, webfuzzer_filepath): |
36 | 36 | self.filepath = webfuzzer_filepath |
37 | 37 | |
38 | with open(self.filepath, "r") as f: | |
38 | with open(self.filepath) as f: | |
39 | 39 | try: |
40 | 40 | data = f.read() |
41 | 41 | f.close() |
42 | 42 | m = re.search( |
43 | "Scan of ([\w.]+):([\d]+) \[([/\w]+)\] \(([\w.]+)\)", data) | |
43 | r"Scan of ([\w.]+):([\d]+) \[([/\w]+)\] \(([\w.]+)\)", data) | |
44 | 44 | self.hostname = m.group(1) |
45 | 45 | self.port = m.group(2) |
46 | 46 | self.uri = m.group(3) |
47 | 47 | self.ipaddress = m.group(4) |
48 | 48 | |
49 | m = re.search("Server header:\n\n([\w\W]+)\n\n\n", data) | |
49 | m = re.search("Server header:\n\n([\\w\\W]+)\n\n\n", data) | |
50 | 50 | self.header = m.group(1) |
51 | 51 | |
52 | 52 | self.items = [] |
57 | 57 | |
58 | 58 | method = m.group(1) |
59 | 59 | info = re.search( |
60 | "^([\w\W]+)\(([\w\W]+)\)\n--\[ ([\w\W]+)$", m.group(2)) | |
60 | "^([\\w\\W]+)\\(([\\w\\W]+)\\)\n--\\[ ([\\w\\W]+)$", m.group(2)) | |
61 | 61 | |
62 | 62 | vuln = {'method': m.group(1), 'desc': info.group( |
63 | 63 | 1), 'url': info.group(2), 'resp': info.group(3)} |
128 | 128 | """ |
129 | 129 | """ |
130 | 130 | super().processCommandString(username, current_path, command_string) |
131 | host = re.search("\-([G|P]) ([\w\.\-]+)", command_string) | |
131 | host = re.search(r"\-([G|P]) ([\w\.\-]+)", command_string) | |
132 | 132 | if host is not None: |
133 | 133 | self.host = host.group(2) |
134 | 134 | self._output_path = current_path + "/" + self.host + ".txt" |
135 | 135 | |
136 | 136 | |
137 | def createPlugin(ignore_info=False): | |
138 | return WebfuzzerPlugin(ignore_info=ignore_info) | |
139 | ||
140 | ||
137 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
138 | return WebfuzzerPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
43 | 43 | return text |
44 | 44 | except: |
45 | 45 | return "" |
46 | ||
46 | ||
47 | 47 | def parse(self): |
48 | 48 | |
49 | 49 | map_objects_fields = { |
122 | 122 | self.identifier_tag = ["Scan"] |
123 | 123 | |
124 | 124 | def parseOutputString(self, output): |
125 | ||
125 | ||
126 | 126 | parser = WebInspectParser(output) |
127 | 127 | vulns = parser.parse() |
128 | 128 | |
132 | 132 | service_id = self.createAndAddServiceToHost(host_id, vuln.get("Service").get("name"), |
133 | 133 | protocol=vuln.get("Service").get("name"), |
134 | 134 | ports=[vuln.get("Service").get("port")]) |
135 | ||
135 | ||
136 | 136 | self.createAndAddVulnWebToService( |
137 | 137 | host_id, service_id, |
138 | 138 | vuln.get("Vuln").get("name"), |
149 | 149 | ) |
150 | 150 | |
151 | 151 | |
152 | def createPlugin(ignore_info=False): | |
153 | return WebInspectPlugin(ignore_info=ignore_info) | |
154 | ||
152 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
153 | return WebInspectPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
76 | 76 | lines = item['lines'] |
77 | 77 | chars = item['chars'] |
78 | 78 | words = item['words'] |
79 | name = "Wfuzz found: {path} with status {status} on url {url}".format(path=path, status=status, url=url) | |
79 | name = f"Wfuzz found: {path} with status {status} on url {url}" | |
80 | 80 | desc = 'Wfuzz found a response with status {status}. Response contains: \n* {words} words \n* {lines} ' \ |
81 | 81 | 'lines \n* {chars} chars'.format(words=words, lines=lines, chars=chars, status=status) |
82 | 82 | self.createAndAddVulnWebToService(host_id, service_id, name, desc, severity="info", website=target, |
83 | 83 | path=path) |
84 | 84 | |
85 | 85 | |
86 | def createPlugin(ignore_info=False): | |
87 | return WfuzzPlugin(ignore_info=ignore_info) | |
88 | ||
89 | ||
86 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
87 | return WfuzzPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
73 | 73 | description=desc) |
74 | 74 | |
75 | 75 | |
76 | def createPlugin(ignore_info=False): | |
77 | return WhatWebPlugin(ignore_info=ignore_info) | |
76 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
77 | return WhatWebPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
97 | 97 | ) |
98 | 98 | |
99 | 99 | |
100 | def createPlugin(ignore_info=False): | |
101 | return WhitesourcePlugin(ignore_info=ignore_info) | |
100 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
101 | return WhitesourcePlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
7 | 7 | import os |
8 | 8 | |
9 | 9 | from faraday_plugins.plugins.plugin import PluginBase |
10 | from faraday_plugins.plugins.plugins_utils import resolve_hostname | |
11 | 10 | |
12 | 11 | |
13 | 12 | __author__ = "Facundo de Guzmán, Esteban Guillardoy" |
69 | 68 | |
70 | 69 | def processCommandString(self, username, current_path, command_string): |
71 | 70 | self.command_string = command_string |
72 | super(CmdWhoisPlugin, self).processCommandString(username, current_path, command_string) | |
71 | super().processCommandString(username, current_path, command_string) | |
73 | 72 | |
74 | 73 | def parseOutputString(self, output): |
75 | matches = re.findall("Name Server:\s*(.*)\s*", output) | |
74 | matches = re.findall(r"Name Server:\s*(.*)\s*", output) | |
76 | 75 | if not matches: |
77 | matches = re.findall("nserver:\s*(.*)\s*", output) | |
76 | matches = re.findall(r"nserver:\s*(.*)\s*", output) | |
78 | 77 | |
79 | 78 | if not matches: |
80 | 79 | ip = re.findall(r'[0-9]+(?:\.[0-9]+){3}', self.command_string) |
81 | 80 | if not ip: |
82 | 81 | url = self.command_string.replace('whois ', '') |
83 | ip = [resolve_hostname(url)] | |
84 | matches_descr = re.findall("descr:\s*(.*)\s*", output) | |
82 | ip = [self.resolve_hostname(url)] | |
83 | matches_descr = re.findall(r"descr:\s*(.*)\s*", output) | |
85 | 84 | |
86 | matches_netname = re.findall("NetName:\s*(.*)\s*", output) | |
85 | matches_netname = re.findall(r"NetName:\s*(.*)\s*", output) | |
87 | 86 | if not matches_netname: |
88 | matches_netname = re.findall("netname:\s*(.*)\s*", output) | |
89 | matches_ref = re.findall("Ref:\s*(.*)\s*", output) | |
87 | matches_netname = re.findall(r"netname:\s*(.*)\s*", output) | |
88 | matches_ref = re.findall(r"Ref:\s*(.*)\s*", output) | |
90 | 89 | desc = "" |
91 | 90 | ref = [] |
92 | 91 | os_name = "unknown" |
109 | 108 | for m in matches: |
110 | 109 | m = m.strip() |
111 | 110 | url = re.findall(r'https?://[^\s<>"]+|.[^\s<>"]+', str(m)) |
112 | ip = resolve_hostname(url[0]) | |
111 | ip = self.resolve_hostname(url[0]) | |
113 | 112 | self.createAndAddHost( |
114 | 113 | ip, |
115 | 114 | hostnames=[m] |
116 | 115 | ) |
117 | matches_domain = re.findall("Domain Name:\s*(.*)\s*", output) | |
116 | matches_domain = re.findall(r"Domain Name:\s*(.*)\s*", output) | |
118 | 117 | for md in matches_domain: |
119 | 118 | md = md.strip() |
120 | ip = resolve_hostname(md) | |
119 | ip = self.resolve_hostname(md) | |
121 | 120 | self.createAndAddHost( |
122 | 121 | ip, |
123 | 122 | hostnames=[md] |
125 | 124 | return True |
126 | 125 | |
127 | 126 | |
128 | def createPlugin(ignore_info=False): | |
129 | return CmdWhoisPlugin(ignore_info=ignore_info) | |
127 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
128 | return CmdWhoisPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
17 | 17 | __status__ = "Development" |
18 | 18 | |
19 | 19 | from faraday_plugins.plugins.plugin import PluginJsonFormat |
20 | from faraday_plugins.plugins.plugins_utils import resolve_hostname | |
21 | 20 | |
22 | 21 | |
23 | 22 | class WPScanJsonParser: |
24 | 23 | |
25 | def __init__(self, json_output): | |
24 | def __init__(self, json_output, resolve_hostname): | |
26 | 25 | self.json_data = json.loads(json_output) |
26 | self.resolve_hostname = resolve_hostname | |
27 | 27 | |
28 | 28 | def parse_url(self, url): |
29 | 29 | # Strips protocol and gets hostname from URL. |
38 | 38 | elif protocol == 'http': |
39 | 39 | if not port: |
40 | 40 | port = 80 |
41 | address = resolve_hostname(hostname) | |
41 | address = self.resolve_hostname(hostname) | |
42 | 42 | return {'protocol': protocol, 'hostname': hostname, 'port': port, 'address': address} |
43 | 43 | |
44 | 44 | |
57 | 57 | self.json_keys = {"target_url", "effective_url", "interesting_findings"} |
58 | 58 | |
59 | 59 | def parseOutputString(self, output): |
60 | parser = WPScanJsonParser(output) | |
60 | parser = WPScanJsonParser(output, self.resolve_hostname) | |
61 | 61 | url_data = parser.parse_url(parser.json_data['target_url']) |
62 | 62 | host_id = self.createAndAddHost(url_data['address'], hostnames=[url_data['hostname']]) |
63 | 63 | service_id = self.createAndAddServiceToHost( |
90 | 90 | severity='unclassified') |
91 | 91 | |
92 | 92 | |
93 | def createPlugin(ignore_info=False): | |
94 | return WPScanPlugin(ignore_info=ignore_info) | |
93 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
94 | return WPScanPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
52 | 52 | try: |
53 | 53 | tree = ET.fromstring(xml_output) |
54 | 54 | except SyntaxError as err: |
55 | print("SyntaxError: %s. %s" % (err, xml_output)) | |
55 | print(f"SyntaxError: {err}. {xml_output}") | |
56 | 56 | return None |
57 | 57 | |
58 | 58 | return tree |
176 | 176 | del parser |
177 | 177 | |
178 | 178 | |
179 | def createPlugin(ignore_info=False): | |
180 | return X1Plugin(ignore_info=ignore_info) | |
179 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
180 | return X1Plugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
10 | 10 | __version__ = "1.0.0" |
11 | 11 | |
12 | 12 | from faraday_plugins.plugins.plugin import PluginBase |
13 | from faraday_plugins.plugins.plugins_utils import resolve_hostname | |
14 | 13 | |
15 | 14 | |
16 | 15 | class xsssniper(PluginBase): |
33 | 32 | if not linea: |
34 | 33 | continue |
35 | 34 | linea = linea.lower() |
36 | if ((linea.find("target:")>0)): | |
37 | url = re.findall('(?:[-\w.]|(?:%[\da-fA-F]{2}))+', linea) | |
38 | address = resolve_hostname(url[3]) | |
35 | if (linea.find("target:")>0): | |
36 | url = re.findall(r'(?:[-\w.]|(?:%[\da-fA-F]{2}))+', linea) | |
37 | address = self.resolve_hostname(url[3]) | |
39 | 38 | host_id = self.createAndAddHost(address, hostnames=url[3]) |
40 | if ((linea.find("method")>0)): | |
41 | list_a = re.findall("\w+", linea) | |
39 | if (linea.find("method")>0): | |
40 | list_a = re.findall(r"\w+", linea) | |
42 | 41 | metodo= list_a[1] |
43 | if ((linea.find("query string:")>0)): | |
42 | if (linea.find("query string:")>0): | |
44 | 43 | lista_parametros=linea.split('=') |
45 | 44 | aux=len(lista_parametros) |
46 | if ((linea.find("param:")>0)): | |
47 | list2 = re.findall("\w+",linea) | |
45 | if (linea.find("param:")>0): | |
46 | list2 = re.findall(r"\w+",linea) | |
48 | 47 | parametro.append(list2[1]) |
49 | 48 | service_id = self.createAndAddServiceToHost(host_id, self.protocol, 'tcp', ports=['80'], status='Open', |
50 | 49 | version="", description="") |
54 | 53 | params=''.join(parametro), request='', response='') |
55 | 54 | |
56 | 55 | |
57 | def createPlugin(ignore_info=False): | |
58 | return xsssniper(ignore_info=ignore_info) | |
59 | ||
60 | ||
56 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
57 | return xsssniper(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
7 | 7 | from urllib.parse import urlparse |
8 | 8 | |
9 | 9 | from faraday_plugins.plugins.plugin import PluginXMLFormat |
10 | from faraday_plugins.plugins.plugins_utils import resolve_hostname | |
11 | 10 | |
12 | 11 | __author__ = "Francisco Amato" |
13 | 12 | __copyright__ = "Copyright (c) 2013, Infobyte LLC" |
33 | 32 | @param zap_xml_filepath A proper xml generated by zap |
34 | 33 | """ |
35 | 34 | |
36 | def __init__(self, xml_output): | |
37 | ||
35 | def __init__(self, xml_output, resolve_hostname): | |
36 | self.resolve_hostname = resolve_hostname | |
38 | 37 | tree = self.parse_xml(xml_output) |
39 | 38 | |
40 | 39 | if tree is not None: |
58 | 57 | tree = parser.close() |
59 | 58 | |
60 | 59 | except SyntaxError as err: |
61 | print("SyntaxError: %s. %s" % (err, xml_output)) | |
60 | print(f"SyntaxError: {err}. {xml_output}") | |
62 | 61 | return None |
63 | 62 | |
64 | 63 | return tree |
65 | 64 | |
66 | @staticmethod | |
67 | def get_items(tree): | |
65 | def get_items(self, tree): | |
68 | 66 | """ |
69 | 67 | @return items A list of Host instances |
70 | 68 | """ |
71 | 69 | for node in tree.findall('site'): |
72 | yield Site(node) | |
70 | yield Site(node, self.resolve_hostname) | |
73 | 71 | |
74 | 72 | |
75 | 73 | def get_attrib_from_subnode(xml_node, subnode_xpath_expr, attrib_name): |
98 | 96 | |
99 | 97 | class Site: |
100 | 98 | |
101 | def __init__(self, item_node): | |
102 | ||
99 | def __init__(self, item_node, resolve_hostname): | |
103 | 100 | self.node = item_node |
104 | 101 | |
105 | 102 | self.host = self.node.get('host') |
209 | 206 | |
210 | 207 | @staticmethod |
211 | 208 | def extract_params_from_uri(uri): |
212 | params = re.findall("(\w+)=", uri) | |
209 | params = re.findall(r"(\w+)=", uri) | |
213 | 210 | return params if params else '' |
214 | 211 | |
215 | 212 | def get_text_from_subnode(self, subnode_xpath_expr): |
246 | 243 | from the xml where it expects it to be present. |
247 | 244 | """ |
248 | 245 | |
249 | parser = ZapXmlParser(output) | |
246 | parser = ZapXmlParser(output, self.resolve_hostname) | |
250 | 247 | |
251 | 248 | for site in parser.sites: |
252 | 249 | |
286 | 283 | del parser |
287 | 284 | |
288 | 285 | |
289 | def createPlugin(ignore_info=False): | |
290 | return ZapPlugin(ignore_info=ignore_info) | |
286 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
287 | return ZapPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
0 | from typing import List | |
1 | from urllib.parse import urlparse | |
2 | import re | |
3 | ||
4 | ||
5 | def extract_params_from_uri(uri): | |
6 | f = re.compile(r"(\w+)=") | |
7 | params = re.findall(f, uri) | |
8 | return params if params else '' | |
9 | ||
10 | ||
11 | class Uri: | |
12 | def __init__(self, uri): | |
13 | self.uri = uri | |
14 | self.parsed_url = urlparse(uri) | |
15 | self.query = self.parsed_url.query | |
16 | self.path = self.parsed_url.path | |
17 | self.params = extract_params_from_uri(uri) | |
18 | ||
19 | ||
20 | class Instance: | |
21 | def __init__(self, node): | |
22 | self.node = node | |
23 | ||
24 | @property | |
25 | def uri(self) -> Uri: | |
26 | return Uri(self.node.get('uri')) if self.node is not None else "" | |
27 | ||
28 | @property | |
29 | def method(self) -> str: | |
30 | return self.node.get('method') if self.node is not None else "" | |
31 | ||
32 | @property | |
33 | def param(self) -> str: | |
34 | return self.node.get('param') if self.node is not None else "" | |
35 | ||
36 | @property | |
37 | def attack(self) -> str: | |
38 | return self.node.get('attack') if self.node is not None else "" | |
39 | ||
40 | @property | |
41 | def evidence(self) -> str: | |
42 | return self.node.get('evidence') if self.node is not None else "" | |
43 | ||
44 | @property | |
45 | def request_header(self) -> str: | |
46 | return self.node.get('request-header') if self.node is not None else "" | |
47 | ||
48 | @property | |
49 | def request(self) -> str: | |
50 | return self.node.get('request-body') if self.node is not None else "" | |
51 | ||
52 | @property | |
53 | def response_header(self) -> str: | |
54 | return self.node.get('response-header') if self.node is not None else "" | |
55 | ||
56 | @property | |
57 | def response(self) -> str: | |
58 | return self.node.get('response-body') if self.node is not None else "" | |
59 | ||
60 | ||
61 | class Alert: | |
62 | def __init__(self, node): | |
63 | self.node = node | |
64 | ||
65 | @property | |
66 | def plugin_id(self) -> str: | |
67 | return self.node.get('pluginid') if self.node is not None else "" | |
68 | ||
69 | @property | |
70 | def alert_id(self) -> str: | |
71 | return self.node.get('alertRef') if self.node is not None else "" | |
72 | ||
73 | @property | |
74 | def name(self) -> str: | |
75 | return self.node.get('name') if self.node is not None else "" | |
76 | ||
77 | @property | |
78 | def riskcode(self) -> str: | |
79 | return self.node.get('riskcode') if self.node is not None else "" | |
80 | ||
81 | @property | |
82 | def confidence(self) -> str: | |
83 | return self.node.get('confidence') if self.node is not None else "" | |
84 | ||
85 | @property | |
86 | def riskdesc(self) -> str: | |
87 | return self.node.get('riskdesc') if self.node is not None else "" | |
88 | ||
89 | @property | |
90 | def desc(self) -> str: | |
91 | return self.node.get('desc') if self.node is not None else "" | |
92 | ||
93 | @property | |
94 | def instances(self) -> List[Instance]: | |
95 | return [Instance(i) for i in self.node.get('instances', [])] | |
96 | ||
97 | @property | |
98 | def count(self) -> str: | |
99 | return self.node.get('count') if self.node is not None else "" | |
100 | ||
101 | @property | |
102 | def solution(self) -> str: | |
103 | return self.node.get('solution') if self.node is not None else "" | |
104 | ||
105 | @property | |
106 | def otherinfo(self) -> str: | |
107 | return self.node.get('otherinfo') if self.node is not None else "" | |
108 | ||
109 | @property | |
110 | def reference(self) -> str: | |
111 | return self.node.get('reference') if self.node is not None else "" | |
112 | ||
113 | @property | |
114 | def cwe(self) -> str: | |
115 | return self.node.get('cweid') if self.node is not None else "" | |
116 | ||
117 | @property | |
118 | def wasc(self) -> str: | |
119 | return self.node.get('wascid') if self.node is not None else "" | |
120 | ||
121 | @property | |
122 | def sourceid(self) -> str: | |
123 | return self.node.get("sourceid") if self.node is not None else "" | |
124 | ||
125 | ||
126 | class Site: | |
127 | def __init__(self, node): | |
128 | self.node = node | |
129 | ||
130 | @property | |
131 | def host(self) -> str: | |
132 | return self.node.get('@host') if self.node is not None else "" | |
133 | ||
134 | @property | |
135 | def name(self) -> str: | |
136 | return self.node.get('@name') if self.node is not None else "" | |
137 | ||
138 | @property | |
139 | def port(self) -> str: | |
140 | return self.node.get('@port') if self.node is not None else "" | |
141 | ||
142 | @property | |
143 | def ssl(self) -> str: | |
144 | return self.node.get('@ssl') if self.node is not None else "" | |
145 | ||
146 | @property | |
147 | def alerts(self) -> List[Alert]: | |
148 | return [Alert(i) for i in self.node.get('alerts', [])] | |
149 | ||
150 | ||
151 | class ZapJsonParser: | |
152 | def __init__(self, node): | |
153 | self.node = node | |
154 | ||
155 | @property | |
156 | def sites(self) -> List[Site]: | |
157 | return [Site(i) for i in self.node.get('site', [])] |
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 | """ |
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 | import re | |
6 | from json import loads | |
7 | ||
8 | from faraday_plugins.plugins.plugin import PluginJsonFormat | |
9 | from faraday_plugins.plugins.repo.zap_json.DTO import ZapJsonParser | |
10 | ||
11 | __author__ = "Gonzalo Martinez" | |
12 | __copyright__ = "Copyright (c) 2013, Infobyte LLC" | |
13 | __credits__ = ["Gonzalo Martinez"] | |
14 | __license__ = "" | |
15 | __version__ = "1.0.0" | |
16 | __maintainer__ = "Gonzalo Martinez" | |
17 | __email__ = "[email protected]" | |
18 | __status__ = "Development" | |
19 | ||
20 | ||
21 | def split_and_strip_tags(data): | |
22 | """ | |
23 | Split string using closing html tags | |
24 | then remove them | |
25 | @return list Stripped string | |
26 | """ | |
27 | r = [] | |
28 | split = re.compile('</.*?>') | |
29 | for i in re.split(split, data)[:-1]: | |
30 | r += [strip_tags(i)] | |
31 | return r | |
32 | ||
33 | ||
34 | def strip_tags(data): | |
35 | """ | |
36 | Remove html tags from a string | |
37 | @return Stripped string | |
38 | """ | |
39 | clean = re.compile('<.*?>') | |
40 | return re.sub(clean, '', data) | |
41 | ||
42 | ||
43 | class ZapJsonPlugin(PluginJsonFormat): | |
44 | ||
45 | def __init__(self, *arg, **kwargs): | |
46 | super().__init__(*arg, **kwargs) | |
47 | self.identifier_tag = "OWASPZAPReport" | |
48 | self.id = "Zap_Json" | |
49 | self.name = "Zap Json Output Plugin" | |
50 | self.plugin_version = "0.1" | |
51 | self.version = "2.11.1" | |
52 | self.framework_version = "1.0.0" | |
53 | self.options = None | |
54 | self._temp_file_extension = "json" | |
55 | self.json_keys = {'@version'} | |
56 | ||
57 | def parseOutputString(self, output): | |
58 | """ | |
59 | This method will discard the output the shell sends, it will read it | |
60 | from the json where it expects it to be present. | |
61 | """ | |
62 | ||
63 | parser = ZapJsonParser(loads(output)) | |
64 | ||
65 | for site in parser.sites: | |
66 | ip = self.resolve_hostname(site.host) | |
67 | host = [] | |
68 | if site.host != ip: | |
69 | host = [site.host] | |
70 | ||
71 | if site.ssl == "true": | |
72 | service = "https" | |
73 | else: | |
74 | service = "http" | |
75 | ||
76 | h_id = self.createAndAddHost(ip, hostnames=host) | |
77 | ||
78 | s_id = self.createAndAddServiceToHost(h_id, service, "tcp", ports=[site.port], status='open') | |
79 | ||
80 | for item in site.alerts: | |
81 | for instance in item.instances: | |
82 | data = f"URL:\n {instance.uri.uri}\n" | |
83 | if instance.evidence: | |
84 | data += f" Parameter:\n {instance.param}\n Evidence:\n {instance.evidence}" | |
85 | elif instance.attack and instance.param: | |
86 | data += f" Payload:\n {instance.param} = {instance.attack}" | |
87 | elif instance.param: | |
88 | data += f" Parameter:\n {instance.param}" | |
89 | ||
90 | ref = [] | |
91 | if item.reference: | |
92 | ref += split_and_strip_tags(item.reference) | |
93 | if item.cwe: | |
94 | ref += [f"CWE:{item.cwe}"] | |
95 | if item.wasc: | |
96 | ref += [f"WASC:{item.wasc}"] | |
97 | ||
98 | self.createAndAddVulnWebToService( | |
99 | h_id, | |
100 | s_id, | |
101 | item.name, | |
102 | strip_tags(item.desc), | |
103 | website=site.name, | |
104 | query=instance.uri.query, | |
105 | severity=item.riskcode, | |
106 | path=instance.uri.path, | |
107 | params=', '.join(instance.uri.params), | |
108 | method=instance.method, | |
109 | ref=ref, | |
110 | resolution=strip_tags(item.solution), | |
111 | data=data, | |
112 | pname=instance.param, | |
113 | external_id="ZAP-" + str(item.plugin_id) | |
114 | ) | |
115 | ||
116 | del parser | |
117 | ||
118 | ||
119 | def createPlugin(ignore_info=False, hostname_resolution=True): | |
120 | return ZapJsonPlugin(ignore_info=ignore_info, hostname_resolution=hostname_resolution) |
0 | 0 | from setuptools import setup, find_packages |
1 | 1 | from re import search |
2 | 2 | |
3 | with open('faraday_plugins/__init__.py', 'rt', encoding='utf8') as f: | |
3 | with open('faraday_plugins/__init__.py', encoding='utf8') as f: | |
4 | 4 | version = search(r'__version__ = \'(.*?)\'', f.read()).group(1) |
5 | 5 | |
6 | 6 | |
14 | 14 | 'pytz', |
15 | 15 | 'python-dateutil', |
16 | 16 | 'colorama', |
17 | 'tabulate' | |
17 | 'tabulate', | |
18 | 'packaging' | |
18 | 19 | ] |
19 | 20 | |
20 | 21 |
41 | 41 | generated_summaries = 0 |
42 | 42 | analysed_reports = 0 |
43 | 43 | click.echo(f"{colorama.Fore.GREEN}Generate Faraday Plugins Tests Summary") |
44 | plugins_manager = PluginsManager() | |
44 | plugins_manager = PluginsManager(hostname_resolution=False) | |
45 | 45 | analyzer = ReportAnalyzer(plugins_manager) |
46 | 46 | for report_file_path in list_report_files(): |
47 | 47 | if debug: |
15 | 15 | |
16 | 16 | ] |
17 | 17 | |
18 | plugins_manager = PluginsManager() | |
18 | plugins_manager = PluginsManager(hostname_resolution=False) | |
19 | 19 | analyzer = ReportAnalyzer(plugins_manager) |
20 | 20 | |
21 | 21 | PLUGINS_CACHE = {} |
73 | 73 | except AttributeError: # no inet_pton here, sorry |
74 | 74 | try: |
75 | 75 | socket.inet_aton(address) |
76 | except socket.error: | |
76 | except OSError: | |
77 | 77 | return False |
78 | 78 | return address.count('.') == 3 |
79 | except socket.error: # not a valid address | |
79 | except OSError: # not a valid address | |
80 | 80 | return False |
81 | 81 | return True |
82 | 82 | |
84 | 84 | def is_valid_ipv6_address(address): |
85 | 85 | try: |
86 | 86 | socket.inet_pton(socket.AF_INET6, address) |
87 | except socket.error: # not a valid address | |
87 | except OSError: # not a valid address | |
88 | 88 | return False |
89 | 89 | return True |
90 | 90 | |
162 | 162 | assert "hosts" in plugin_json |
163 | 163 | assert "command" in plugin_json |
164 | 164 | assert os.path.isfile(report_filename) is True |
165 |