Codebase list faraday-plugins / 2c3a59d
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
140 changed file(s) with 1319 addition(s) and 693 deletion(s). Raw diff Collapse all Expand all
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
09 stages:
10 - SAST
111 - pre_testing
212 - testing
313 - post_testing
3141 - git checkout $REPORT_REF
3242 - cd ..
3343
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
3467
3568 flake8:
3669 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 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 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 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
053 1.5.9 [Dec 27th, 2021]:
154 ---
2 * ADD cve in faraday_csv plugin
55 * Add cve in faraday_csv plugin
356 * ADD Grype plugin
457
558 1.5.8 [Dec 13th, 2021]:
0 __version__ = '1.5.9'
0 __version__ = '1.6.8'
6464 @click.option('--summary', is_flag=True)
6565 @click.option('-o', '--output-file', type=click.Path(exists=False))
6666 @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):
6870 if not os.path.isfile(report_file):
6971 click.echo(click.style(f"File {report_file} Don't Exists", fg="red"), err=True)
7072 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)
7275 analyzer = ReportAnalyzer(plugins_manager)
7376 if plugin_id:
7477 plugin = plugins_manager.get_plugin(plugin_id)
100103 @click.option('-o', '--output-file', type=click.Path(exists=False))
101104 @click.option('-sh', '--show-output', is_flag=True)
102105 @click.option('--ignore-info', is_flag=True, help="Ignore information vulnerabilities")
106 @click.option('--hostname-resolution', is_flag=True, help="Resolve hostname")
103107 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)
106111 analyzer = CommandAnalyzer(plugins_manager)
107112 if plugin_id:
108113 plugin = plugins_manager.get_plugin(plugin_id)
151151
152152 class PluginsManager:
153153
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):
155155 self.ignore_info = ignore_info
156 self.hostname_resolution = hostname_resolution
156157 self.plugins = {}
157158 self.plugin_modules = {}
158159 self._load_plugins(custom_plugins_folder)
215216 plugin = None
216217 plugin_id = plugin_id.lower()
217218 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)
219220 else:
220221 logger.debug("Unknown Plugin: %s", plugin_id)
221222 return plugin
223224 def get_plugins(self):
224225 for plugin_id, plugin_module in self.plugin_modules.items():
225226 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)
1515 from collections import defaultdict
1616 from datetime import datetime
1717 from pathlib import Path
18 import socket
1819
1920 # Related third party imports
2021 import pytz
3334 # TODO: Add class generic identifier
3435 class_signature = "PluginBase"
3536
36 def __init__(self, ignore_info=False):
37 def __init__(self, ignore_info=False, hostname_resolution=True, *args, **kwargs):
3738 # Must be unique. Check that there is not
3839 # an existent plugin with the same id.
3940 # TODO: Make script that list current ids.
4041 self.ignore_info = ignore_info
42 self.hostname_resolution = hostname_resolution
4143 self.id = None
4244 self.auto_load = True
4345 self._rid = id(self)
8284 temp_file_path = os.path.join(temp_dir, temp_filename)
8385 return temp_file_path
8486
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
85102 @staticmethod
86103 def get_utctimestamp(date):
87104 if date is not None:
278295 command that it's going to be executed.
279296 """
280297 self._current_path = current_path
281 if command_string.startswith(("sudo","python","python3")):
298 if command_string.startswith(("sudo", "python", "python3")):
282299 params = " ".join(command_string.split()[2:])
283300 else:
284301 params = " ".join(command_string.split()[1:])
392409 if ref is None:
393410 ref = []
394411 if status == "":
395 status = "opened"
412 status = "open"
396413 if impact is None:
397414 impact = {}
398415 if policyviolations is None:
426443 if ref is None:
427444 ref = []
428445 if status == "":
429 status = "opened"
446 status = "open"
430447 if impact is None:
431448 impact = {}
432449 if policyviolations is None:
484501 if ref is None:
485502 ref = []
486503 if status == "":
487 status = "opened"
504 status = "open"
488505 if impact is None:
489506 impact = {}
490507 if policyviolations is None:
592609
593610
594611 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)
597614 self.extension = []
598615
599616 def report_belongs_to(self, extension="", **kwargs):
608625
609626 class PluginXMLFormat(PluginByExtension):
610627
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)
613630 self.identifier_tag = []
614631 self.identifier_tag_attributes = {}
615632 self.extension = ".xml"
630647
631648 class PluginJsonFormat(PluginByExtension):
632649
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)
635652 self.json_keys = set()
636653 self.extension = ".json"
637654
647664
648665 class PluginMultiLineJsonFormat(PluginByExtension):
649666
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)
652669 self.json_keys = set()
653670 self.extension = ".json"
654671
671688
672689 class PluginCSVFormat(PluginByExtension):
673690
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)
676693 self.extension = ".csv"
677694 self.csv_headers = set()
678695
691708
692709 class PluginZipFormat(PluginByExtension):
693710
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)
696713 self.extension = ".zip"
697714 self.files_list = set()
698715
1919 """Given a URL, return kwargs to pass to createAndAddVulnWebToService."""
2020 parse = urlsplit(url)
2121 return {
22 "website": "{}://{}".format(parse.scheme, parse.netloc),
22 "website": f"{parse.scheme}://{parse.netloc}",
2323 "path": parse.path,
2424 "query": parse.query
2525 }
9393 'mobility-header'
9494 ]
9595
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
11297
11398
11499 def get_severity_from_cvss(cvss):
99 from lxml import etree
1010
1111 from faraday_plugins.plugins.plugin import PluginXMLFormat
12 from faraday_plugins.plugins.plugins_utils import resolve_hostname
1312 from faraday_plugins.plugins.repo.acunetix.DTO import Acunetix, Scan
1413
1514 __author__ = "Francisco Amato"
106105 host = request_host[0]
107106 url = f'http://{host}'
108107 url_data = urlsplit(url)
109 site_ip = resolve_hostname(host)
108 site_ip = self.resolve_hostname(host)
110109 h_id = self.createAndAddHost(site_ip, site.os, hostnames=[host])
111110 s_id = self.createAndAddServiceToHost(
112111 h_id,
120119 self.logger.warning("No host in request")
121120
122121 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)
124123 if url_data.hostname:
125124 hostnames = [url_data.hostname]
126125 else:
174173 return url_data
175174
176175
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)
77
88 from lxml import etree
99
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
1211 from faraday_plugins.plugins.repo.acunetix.DTO import Acunetix, Scan
1312 from json import loads
1413
9392 def new_structure(self, site: Scan):
9493 start_url = site.info.host
9594 url_data = urlsplit(start_url)
96 site_ip = resolve_hostname(url_data.hostname)
95 site_ip = self.resolve_hostname(url_data.hostname)
9796 ports = '443' if (url_data.scheme == 'https') else '80'
9897 vulnerability_type = {i.vt_id: i for i in site.vul_types}
9998 h_id = self.createAndAddHost(site_ip, None, hostnames=[url_data.hostname])
131130 return url_data
132131
133132
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)
136136 return final
137137
138138
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)
00 from urllib.parse import urlparse
11
22 from faraday_plugins.plugins.plugin import PluginXMLFormat
3 from faraday_plugins.plugins.plugins_utils import resolve_hostname
43
54 import xml.etree.ElementTree as ET
65
3433 try:
3534 tree = ET.fromstring(xml_output)
3635 except SyntaxError as err:
37 print('SyntaxError In xml: %s. %s' % (err, xml_output))
36 print(f'SyntaxError In xml: {err}. {xml_output}')
3837 return None
3938 return tree
4039
162161 }
163162 if cve:
164163 issue_data["cve"].append(cve)
164 issue_data["desc"] += cve
165165 if cve_url:
166166 issue_data["ref"].append(cve_url)
167167 if cwe:
181181 sast_issues = []
182182 for item in tree:
183183 name = self.issue_types[item.find("issue-type/ref").text]
184 source_file = item.attrib["filename"].replace('\\','/')
184 source_file = item.attrib["filename"].replace('\\', '/')
185185 severity = 0 if item.find("severity-id") is None else int(item.find("severity-id").text)
186186 description = item.find("fix/item/general/text").text
187187 resolution = "" if item.find("variant-group/item/issue-information/fix-resolution-text") is None \
217217 "cve": []
218218 }
219219
220 if cve:
221 issue_data["cve"].append(cve)
222220 if cve_url:
223221 issue_data["ref"].append(cve_url)
224222 if cwe:
231229 issue_data["ref"].append(cvss_temporal_vector)
232230 if cvss_environmental_vector:
233231 issue_data["ref"].append(cvss_environmental_vector)
232 if cve:
233 issue_data["cve"].append(cve)
234 issue_data["desc"] += f"\nCVE: {cve}"
234235 # Build data
235236 data = []
236237 if item.attrib.get("caller"):
240241 if item.find("variant-group/item/issue-information/method-signature2") is not None:
241242 data.append(f"Location: {item.find('variant-group/item/issue-information/method-signature2').text}")
242243 issue_data['data'] = "\n".join(data)
244 issue_data['desc'] += "\n".join(data)
243245 sast_issues.append(issue_data)
244246 return sast_issues
245247
264266 host = issue.pop("host")
265267 port = issue.pop("port")
266268 service_name = issue.pop("service_name")
267 ip = resolve_hostname(host)
269 ip = self.resolve_hostname(host)
268270 host_os = issue.pop("os")
269271 host_id = self.createAndAddHost(ip, hostnames=host, os=host_os)
270272 service_id = self.createAndAddServiceToHost(host_id, service_name, ports=port)
277279 self.createAndAddVulnToHost(host_id=host_id, **issue)
278280
279281
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)
00 #!/usr/bin/env python
1 # -*- coding: utf-8 -*-
21 """
32 Faraday Penetration Test IDE
43 Copyright (C) 2016 Infobyte LLC (http://www.infobytesec.com/)
3130 try:
3231 tree = ET.fromstring(xml_output)
3332 except SyntaxError as err:
34 print('SyntaxError In xml: %s. %s' % (err, xml_output))
33 print(f'SyntaxError In xml: {err}. {xml_output}')
3534 return None
3635 return tree
3736
112111 external_id=vuln_external_id, data=str_data)
113112
114113
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)
88 from urllib.parse import urlparse
99
1010 from faraday_plugins.plugins.plugin import PluginXMLFormat
11 from faraday_plugins.plugins.plugins_utils import resolve_hostname
1211
1312 __author__ = 'Ezequiel Tavella'
1413 __copyright__ = 'Copyright 2016, Faraday Project'
164163 data = request.findtext("method", "").upper()
165164 data += f" {request.findtext('url', '')}"
166165 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')}"
168167 if request.findtext('body',""):
169 data += "\n%s" % request.findtext('body',"")
168 data += f"\n{request.findtext('body','')}"
170169 return data
171170
172171 @staticmethod
419418
420419 self.hostname = self.getHostname(parser.system.url)
421420 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)
425424
426425 # Create host and interface
427426 host_id = self.createAndAddHost(self.address, hostnames=[self.hostname])
494493 # add reporter
495494 cmd_prefix_match = re.match(r"(^.*?)arachni ", command_string)
496495 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,
498497 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,
500499 afr_file_path,
501500 reporter_cmd)
502501
516515 return self.hostname
517516
518517
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)
5959
6060
6161
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)
6767 return vulns
6868
6969
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)
9595
9696
9797
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)
1111 __version__ = "1.0.0"
1212
1313 from faraday_plugins.plugins.plugin import PluginBase
14 from faraday_plugins.plugins.plugins_utils import resolve_hostname
1514
1615
1716 class brutexss (PluginBase):
3231 found_vuln = False
3332 for linea in lineas:
3433 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]
3635 port = 80
3736 if urlparse(url).scheme == 'https':
3837 port = 443
4039 if len(netloc_splitted) > 1:
4140 port = netloc_splitted[1]
4241 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)
4443 if vuln_list[2] == "Vulnerable":
4544 parametro.append(vuln_list[1])
4645 found_vuln = len(parametro) > 0
47 address = resolve_hostname(url)
46 address = self.resolve_hostname(url)
4847 host_id = self.createAndAddHost(url, hostnames=[url])
4948 service_id = self.createAndAddServiceToHost(host_id, self.protocol, 'tcp',
5049 ports=[port], status='Open', version="",
5655
5756
5857
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)
5959 try:
6060 tree = ET.fromstring(xml_output)
6161 except SyntaxError as err:
62 print("SyntaxError: %s. %s" % (err, xml_output))
62 print(f"SyntaxError: {err}. {xml_output}")
6363 return None
6464
6565 return tree
104104 external_id = item_node.findall('type')[0]
105105 request = self.decode_binary_node('./requestresponse/request')
106106 response = self.decode_binary_node('./requestresponse/response')
107
108107 detail = self.do_clean(item_node.findall('issueDetail'))
109108 remediation = self.do_clean(item_node.findall('remediationBackground'))
110109 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'))
111112 self.cve = []
112113 if background:
113114 cve = CVE_regex.search(background)
126127 else 80)
127128
128129 self.name = name.text
129 self.location = location.text
130130 self.path = path.text
131 loc = re.search(r"(?<=\[).+?(?=\])", location.text.replace(self.path, ""))
132 self.location = loc.group().split(" ")[0] if loc else ""
131133
132134 self.ip = host_node.get('ip')
133135 self.url = self.node.get('url')
143145 def do_clean(value):
144146
145147 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
149150 return myreturn
150151
151152 def decode_binary_node(self, path):
209210 ports=[str(item.port)],
210211 status="open")
211212
213 desc = ""
212214 if item.background:
213 desc = item.background
214 else:
215 desc = ""
215 desc += item.background
216216 desc = self.removeHtml(desc)
217 data = ""
217218 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
222227 resolution = self.removeHtml(item.remediation) if item.remediation else ""
223228
224229 self.createAndAddVulnWebToService(
233238 request=item.request,
234239 response=item.response,
235240 resolution=resolution,
241 ref=ref,
242 params=item.location,
236243 external_id=item.external_id,
237244 cve=item.cve
238245 )
266273
267274 return str(soup)
268275
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)
2828 try:
2929 tree = ET.fromstring(xml_output)
3030 except SyntaxError as err:
31 print('SyntaxError In xml: %s. %s' % (err, xml_output))
31 print(f'SyntaxError In xml: {err}. {xml_output}')
3232 return None
3333 return tree
3434
131131 resolution=data, ref=refs)
132132
133133
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)
2020 __email__ = "[email protected]"
2121 __status__ = "Development"
2222
23 from faraday_plugins.plugins.plugins_utils import resolve_hostname
2423
2524
2625 class CobaltParser:
8483 port = 80
8584 else:
8685 port = url_data.port
87 name = resolve_hostname(url_data.netloc)
86 name = self.resolve_hostname(url_data.netloc)
8887 references = []
8988 if row['RefKey']:
9089 references.append(row['RefKey'])
101100 data=row['StepsToReproduce'], external_id=row['Tag'], run_date=run_date)
102101
103102
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)
66 """
77 import re
88
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"
1717
1818 from faraday_plugins.plugins.plugin import PluginBase
19 from faraday_plugins.plugins.plugins_utils import resolve_hostname
2019
2120
2221 class DigPlugin(PluginBase):
3534 def parseOutputString(self, output):
3635 # Ignore all lines that start with ";"
3736 parsed_output = [line for line in output.splitlines() if line and line[
38 0] != u";"]
37 0] != ";"]
3938 if not parsed_output:
4039 return True
4140
4241 # Parse results
4342 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"]
4645 for line in parsed_output:
4746 line_split = line.split() # the first 4 elements are domain, ttl, class, type; everything else data
4847 results.append(dict(zip(answer_section_columns, line_split[:4] + [line_split[4:]] )))
5049 # Create hosts is results information is relevant
5150 try:
5251 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"]
5453 # TODO implement more types from https://en.wikipedia.org/wiki/List_of_DNS_record_types
5554
56 if result.get(u"type") in relevant_types:
55 if result.get("type") in relevant_types:
5756
5857 # get domain
59 domain = result.get(u"domain")
58 domain = result.get("domain")
6059
6160
6261 # 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]
6564 else: # if not, from socket
66 ip_address = resolve_hostname(domain)
65 ip_address = self.resolve_hostname(domain)
6766
6867 # Create host
6968 host_id = self.createAndAddHost(ip_address, hostnames=[domain])
7069
7170
7271 # 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]
7675
7776 service_id = self.createAndAddServiceToHost(
7877 host_id=host_id,
8887 name="priority",
8988 text=text.encode('ascii', 'ignore'))
9089
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]
9392 self.createAndAddServiceToHost(
9493 name=ns_record,
9594 protocol="DNS",
9695 ports=[53],
9796 description="DNS Server")
9897
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]
107106
108107 service_id = self.createAndAddServiceToHost(
109108 host_id=host_id,
126125 name="priority",
127126 text=text.encode('ascii', 'ignore'))
128127
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")[:])
131130 self.createAndAddNoteToHost(
132131 host_id=host_id,
133132 name="TXT Information",
140139 return True
141140
142141
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)
1313 __status__ = "Development"
1414
1515 from faraday_plugins.plugins.plugin import PluginBase
16 from faraday_plugins.plugins.plugins_utils import resolve_hostname
1716
1817
1918 class dirbPlugin(PluginBase):
4039
4140 def getIP(self, host):
4241 try:
43 ip = resolve_hostname(host)
42 ip = self.resolve_hostname(host)
4443 except Exception:
4544 pass
4645
112111 arg_search = re.search(silent_mode_re,command_string)
113112 if arg_search is None:
114113 extra_arg +=" -S"
115 return "%s%s" % (command_string, extra_arg)
114 return f"{command_string}{extra_arg}"
116115
117116
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)
88 import argparse
99 import urllib.parse as urlparse
1010 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
1212
1313
1414 __author__ = "Matías Lang"
8282 return
8383 for (base_url, items) in data.items():
8484 base_split = urlparse.urlsplit(base_url)
85 ip = resolve_hostname(base_split.hostname)
85 ip = self.resolve_hostname(base_split.hostname)
8686 h_id = self.createAndAddHost(ip, hostnames=[base_split.hostname])
8787 s_id = self.createAndAddServiceToHost(
8888 h_id,
103103 item['content-length'])
104104 redirect = item.get('redirect')
105105 if redirect is not None:
106 response += '\nLocation: {}'.format(redirect)
106 response += f'\nLocation: {redirect}'
107107 self.createAndAddVulnWebToService(
108108 h_id,
109109 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()}",
113112 severity="info",
114113 method='GET',
115114 response=response,
128127 return None
129128 else:
130129 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}'
132131
133132
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)
4949 try:
5050 tree = ET.fromstring(xml_output)
5151 except SyntaxError as err:
52 print("SyntaxError: %s. %s" % (err, xml_output))
52 print(f"SyntaxError: {err}. {xml_output}")
5353 return None
5454
5555 return tree
164164 return re.sub(arg_match.group(1), r"-o %s" % self._output_file_path, command_string)
165165
166166
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)
129129 arg_match = self.xml_arg_re.match(command_string)
130130
131131 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"
133133 else:
134134 return re.sub(arg_match.group(1),
135135 r"-r %s" % self._output_file_path,
136136 command_string)
137137
138138
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)
4949 try:
5050 tree = ET.fromstring(xml_output)
5151 except SyntaxError as err:
52 print("SyntaxError: %s. %s" % (err, xml_output))
52 print(f"SyntaxError: {err}. {xml_output}")
5353 return None
5454
5555 return tree
211211 command_string)
212212
213213
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)
66 import re
77
88 from faraday_plugins.plugins.plugin import PluginBase
9 from faraday_plugins.plugins.plugins_utils import resolve_hostname
109
1110 __author__ = "Francisco Amato"
1211 __copyright__ = "Copyright (c) 2013, Infobyte LLC"
3130 @param dnswalk_filepath A proper simple report generated by dnswalk
3231 """
3332
34 def __init__(self, output):
33 def __init__(self, output, resolve_hostName):
3534
3635 lists = output.split("\n")
3736 self.items = []
37 self.resolve_hostName = resolve_hostName
3838
3939 for line in lists:
40 mregex = re.search("WARN: ([\w\.]+) ([\w]+) ([\w\.]+):", line)
40 mregex = re.search(r"WARN: ([\w\.]+) ([\w]+) ([\w\.]+):", line)
4141 if mregex is not None:
4242 item = {
4343 'host': mregex.group(1),
4747 self.items.append(item)
4848
4949 mregex = re.search(
50 "Getting zone transfer of ([\w\.]+) from ([\w\.]+)\.\.\.done\.",
50 r"Getting zone transfer of ([\w\.]+) from ([\w\.]+)\.\.\.done\.",
5151 line)
5252
5353 if mregex is not None:
54 ip = resolve_hostname(mregex.group(2))
54 ip = self.resolve_hostname(mregex.group(2))
5555 item = {
5656 'host': mregex.group(1),
5757 'ip': ip,
8686 """
8787 output is the shell output of command Dnswalk.
8888 """
89 parser = DnswalkParser(output)
89 parser = DnswalkParser(output, self.resolve_hostname)
9090
9191 for item in parser.items:
9292 if item['type'] == "A":
108108 return True
109109
110110
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)
125125
126126 if (port and not protocol) or (protocol and not port):
127127 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."
131131 )
132132 return None
133133 else:
139139
140140 if (vuln_name and not vuln_desc) or (vuln_desc and not vuln_name):
141141 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."
145145 )
146146 return None
147147 else:
153153 def get_custom_fields_names(headers):
154154 custom_fields_names = []
155155 for header in headers:
156 match = re.match(r"cf_(\w+)", header)
156 match = re.match(r"cf_(\S+)", header)
157157 if match:
158158 custom_fields_names.append(match.group(1))
159159
363363 )
364364
365365
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)
44
55 """
66 import re
7 import os
8 import random
97
108 from faraday_plugins.plugins.plugin import PluginBase
11 from faraday_plugins.plugins.plugins_utils import resolve_hostname
129
1310
1411 __author__ = "Francisco Amato"
4138 self.items = []
4239
4340 regex = re.search(
44 "DNS Servers for ([\w\.-]+):\n([^$]+)Trying zone transfer first...",
41 "DNS Servers for ([\\w\\.-]+):\n([^$]+)Trying zone transfer first...",
4542 output)
4643
4744 if regex is not None:
5047 self.dns = list(filter(None, mstr.splitlines()))
5148
5249 regex = re.search(
53 "Now performing [\d]+ test\(s\)...\n([^$]+)\nSubnets found ",
50 "Now performing [\\d]+ test\\(s\\)...\n([^$]+)\nSubnets found ",
5451 output)
5552 if regex is not None:
5653 hosts_list = regex.group(1).splitlines()
118115 item['ip'] = i['ip']
119116 return item
120117 try:
121 item['ip'] = resolve_hostname(item['ip'])
118 item['ip'] = self.resolve_hostname(item['ip'])
122119 except:
123120 pass
124121 return item
126123 def resolveNS(self, item, items):
127124 try:
128125 item['hosts'][0] = item['ip']
129 item['ip'] = resolve_hostname(item['ip'])
126 item['ip'] = self.resolve_hostname(item['ip'])
130127 except:
131128 pass
132129 return item
138135
139136 item['isResolver'] = False
140137 item['isZoneVuln'] = False
141 if (item['record'] == "CNAME"):
138 if item['record'] == "CNAME":
142139 self.resolveCNAME(item, parser.items)
143 if (item['record'] == "NS"):
140 if item['record'] == "NS":
144141 self.resolveNS(item, parser.items)
145142 item['isResolver'] = True
146143 item['isZoneVuln'] = parser.isZoneVuln
174171 ref=["CVE-1999-0532"])
175172
176173
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)
5757 service_name,
5858 protocol=protocol_name,
5959 ports=[vuln_data['service']['port']])
60
6160 self.createAndAddVulnWebToService(
6261 host_id, service_id,
6362 vuln_data['name'],
8483
8584
8685 class FortifyParser:
87 """
86 """
8887 Parser for fortify on demand
8988 """
9089
221220 references.append(classification.text)
222221
223222 # Build description
224 description = u''
223 description = ''
225224 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'
229228
230229 h = html2text.HTML2Text()
231230 description = h.handle(description)
232231
233232 for repro_step in issue_data.findall('./ReproSteps'):
234233 step = repro_step.ReproStep
235
234
236235 if step is not None:
237236 try:
238237 params = step.PostParams.text
258257 "method": method,
259258 "query": query,
260259 "response": response,
261 "request": request,
260 "request": request.decode('utf-8'),
262261 "path": path,
263262 "params": params,
264263 "status_code": status_code,
371370 idx = match.group(1)
372371 if match.group(3):
373372 idx = match.group(3)
374 _filekey = "{}.file".format(idx)
375 _linekey = "{}.line".format(idx)
373 _filekey = f"{idx}.file"
374 _linekey = f"{idx}.line"
376375 text = text.replace(placeholder, "").replace(
377376 torepl.format(_filekey), replacements[_filekey]).replace(
378377 torepl.format(_linekey), replacements[_linekey])
386385
387386 text = text.replace(placeholder, replace_with)
388387
389 text += '{}\n Instance ID: {} \n'.format(text, vulnID)
388 text += f'{text}\n Instance ID: {vulnID} \n'
390389 h = html2text.HTML2Text()
391390 return text
392391
393392
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)
3333 self.options = None
3434 self._current_output = None
3535 self.target = None
36
36
3737 self._command_regex = re.compile(r'^(fruitywifi)\s+.*?')
38
38
3939 self.addSetting("Token", str, "e5dab9a69988dd65e578041416773149ea57a054")
4040 self.addSetting("Server", str, "http://127.0.0.1:8000")
4141 self.addSetting("Severity", str, "high")
42
42
4343 def getSeverity(self, severity):
4444 if severity.lower() == "critical" or severity == "4":
4545 return 4
5353 return 0
5454 else:
5555 return 5
56
56
5757 def createHostInterfaceVuln(self, ip_address, macaddress, hostname, desc, vuln_name, severity):
5858 h_id = self.createAndAddHost(ip_address, hostnames=[hostname])
5959
6464 ref=["http://www.fruitywifi.com/"],
6565 severity=severity
6666 )
67
67
6868 def parseOutputString(self, output):
69
69
7070 try:
7171 output = json.loads(output)
72
72
7373 if len(output) > 0:
74
74
7575 if len(output[0]) == 3:
76
76
7777 severity = self.getSeverity(self.getSetting("Severity"))
78
78
7979 for item in output:
8080 ip_address = item[0]
8181 macaddress = item[1]
8282 hostname = item[2]
8383 vuln_name = "FruityWiFi"
8484 severity = severity
85
85
8686 desc = "Client ip: " + ip_address + \
8787 " has been connected to FruityWiFi\n"
8888 desc += "More information:"
8989 desc += "\nname: " + hostname
90
90
9191 self.createHostInterfaceVuln(ip_address, macaddress, hostname, desc, vuln_name, severity)
92
92
9393 elif len(output[0]) == 5:
9494 for item in output:
9595 ip_address = item[0]
9696 macaddress = item[1]
9797 hostname = item[2]
98 vuln_name = item[3]
98 vuln_name = item[3]
9999 severity = item[4]
100
100
101101 desc = "Client ip: " + ip_address + \
102102 " has been connected to FruityWiFi\n"
103103 desc += "More information:"
104104 desc += "\nname: " + hostname
105
105
106106 self.createHostInterfaceVuln(ip_address, macaddress, hostname, desc, vuln_name, severity)
107
107
108108 except:
109109 traceback.print_exc()
110
110
111111 return True
112112
113113 def _isIPV4(self, ip):
118118
119119 def processCommandString(self, username, current_path, command_string):
120120 """
121 """
121 """
122122 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
125125 return "python " + os.path.dirname(__file__) + "/fruitywifi.py " + params
126126
127127
128128
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)
77 import os
88
99 from faraday_plugins.plugins.plugin import PluginBase
10 from faraday_plugins.plugins.plugins_utils import resolve_hostname
1110
1211
1312 __author__ = "Javier Victor Mariano Bruno"
4645 def parseOutputString(self, output):
4746
4847 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)
5049 if re.search("Connection timed out", output) is None and host_info is not None:
5150 hostname = host_info.group(1)
52 ip_address = resolve_hostname(hostname)
51 ip_address = self.resolve_hostname(hostname)
5352 self._version = banner.groups(0) if banner else ""
5453 h_id = self.createAndAddHost(ip_address, hostnames=[hostname])
5554 s_id = self.createAndAddServiceToHost(
6766 count_args = command_string.split()
6867 c = count_args.__len__()
6968 self._port = "21"
70 if re.search("[\d]+", count_args[c - 1]):
69 if re.search(r"[\d]+", count_args[c - 1]):
7170 self._port = count_args[c - 1]
7271
7372
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)
66 import os
77
88 from faraday_plugins.plugins.plugin import PluginBase
9 from faraday_plugins.plugins.plugins_utils import resolve_hostname
109
1110 __author__ = "Francisco Amato"
1211 __copyright__ = "Copyright (c) 2013, Infobyte LLC"
2928 @param goohost_scantype You could select scan type ip, mail or host
3029 """
3130
32 def __init__(self, output, goohost_scantype):
31 def __init__(self, output, goohost_scantype, resolve_hostname):
3332
3433 self.items = []
34 self.resolve_hostname = resolve_hostname
3535 lines = list(filter(None, output.split('\n')))
3636 for line in lines:
3737 if goohost_scantype == 'ip':
4040 self.add_host_info_to_items(item['ip'], item['host'])
4141 elif goohost_scantype == 'host':
4242 data = line.strip()
43 item = {'host': data, 'ip': resolve_hostname(data)}
43 item = {'host': data, 'ip': self.resolve_hostname(data)}
4444 self.add_host_info_to_items(item['ip'], item['host'])
4545 else:
4646 item = {'data': line}
8888
8989 """
9090 scantype = self.define_scantype_by_output(output)
91 parser = GoohostParser(output, scantype)
91 parser = GoohostParser(output, scantype, self.resolve_hostname)
9292 if scantype == 'host' or scantype == 'ip':
9393 for item in parser.items:
9494 h_id = self.createAndAddHost(item['ip'], hostnames=item['hosts'])
110110 return 'ip'
111111
112112 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)
114114 if not report_name:
115115 return False
116116 else:
128128 self.parseOutputString(command_output)
129129
130130
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)
7676 return command_string
7777
7878
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)
5858 for linea in lineas:
5959 if (re.match(" ", linea)):
6060
61 list = re.findall("\w+", linea)
61 list = re.findall(r"\w+", linea)
6262 service = list[1]
6363 port = [list[0]]
6464
6767 host_id, service, protocol="tcp", ports=port, status="open")
6868
6969
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)
33 See the file 'doc/LICENSE' for the license information
44 """
55 from faraday_plugins.plugins.plugin import PluginBase
6 from faraday_plugins.plugins.plugins_utils import resolve_hostname
76 import re
87 from collections import defaultdict
98
3029 for line in lines:
3130
3231 reg = re.search(
33 "\[([^$]+)\]\[([^$]+)\] host: ([^$]+) login: ([^$]+) password: ([^$]+)",
32 r"\[([^$]+)\]\[([^$]+)\] host: ([^$]+) login: ([^$]+) password: ([^$]+)",
3433 line)
3534
3635 if reg:
8382 hosts[item['ip']].append([item['login'], item['password']])
8483
8584 for k, v in hosts.items():
86 ip = resolve_hostname(k)
85 ip = self.resolve_hostname(k)
8786 if ip != k:
8887 hostnames = [k]
8988 else:
107106 h_id,
108107 s_id,
109108 "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]}",
111110 severity="high")
112111
113112 del parser
129128
130129
131130
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)
280280 del parser
281281
282282
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)
102102 ref=vulnerability.get("ref"))
103103
104104
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)
2222 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,
2323 nessus, ..) and security verification compliancy (CIS-CAT, compagny's product security requirement) by Faraday-IPE
2424
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)
2626
2727 <testsuite errors="0" failures="1" name="AccountsWithSuperuserPrivilegesShallBeDisabledByDefault-20170118090010" skipped="0" tests="1" time="0.144">
2828 <testcase host="192.168.1.1" classname="AccountsWithSuperuserPrivilegesShallBeDisabledByDefault" name="test_sshdRootLogin" time="0.144">
6767 try:
6868 tree = etree.fromstring(xml_output)
6969 except SyntaxError as err:
70 print("SyntaxError: %s. %s" % (err, xml_output))
70 print(f"SyntaxError: {err}. {xml_output}")
7171 return None
7272 return tree
7373
130130 del parser
131131
132132
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)
3636 return " ".join([name, version])
3737
3838 def ipv4(self):
39 ipv4s = re.findall('^network_ipv4_address\[\]=(.+)$',
39 ipv4s = re.findall(r'^network_ipv4_address\[\]=(.+)$',
4040 self.rawcontents, re.MULTILINE)
4141 ipv4addrs = self.ipv4_filter(ipv4s)
4242 return(ipv4addrs)
4343
4444 def ipv6(self):
45 ipv6s = re.findall('^network_ipv6_address\[\]=(.+)$',
45 ipv6s = re.findall(r'^network_ipv6_address\[\]=(.+)$',
4646 self.rawcontents, re.MULTILINE)
4747 ipv6addrs = self.ipv6_filter(ipv6s)
4848 return(ipv6addrs)
7474 return versions_dict
7575
7676 def listeningservices(self):
77 line = re.findall('^network_listen_port\[\]=(.+)$',
77 line = re.findall(r'^network_listen_port\[\]=(.+)$',
7878 self.rawcontents, re.MULTILINE)
7979 # To avoid local services, we will create the following list
8080 local_services = ['*', 'localhost']
196196 #Ipv6
197197 elif count == 5:
198198 port = elements_ip_port[5]
199 ip = items_service[0].replace(':{}'.format(port), '')
199 ip = items_service[0].replace(f':{port}', '')
200200
201201 return ip, port
202202
203203 def parse_suggestions(self):
204204 sugs = {}
205 m = re.findall('^suggestion\[\]=(.+)$', self.rawcontents, re.MULTILINE)
205 m = re.findall(r'^suggestion\[\]=(.+)$', self.rawcontents, re.MULTILINE)
206206 for combo in m:
207207 x = combo.split('|')
208208 sugs[x[0]] = x[1]
210210
211211 def parse_warnings(self):
212212 warns = {}
213 m = re.findall('^warning\[\]=(.+)$', self.rawcontents, re.MULTILINE)
213 m = re.findall(r'^warning\[\]=(.+)$', self.rawcontents, re.MULTILINE)
214214 for combo in m:
215215 x = combo.split('|')
216216 warns[x[0]] = x[1]
318318 )
319319
320320 def processOutput(self, command_output):
321 m = re.search('(\/.+\.dat)$', command_output, re.MULTILINE)
321 m = re.search(r'(\/.+\.dat)$', command_output, re.MULTILINE)
322322 file_path = m.group(0).strip()
323323 self._parse_filename(file_path)
324324
325325
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)
66 import zipfile
77
88 from faraday_plugins.plugins.plugin import PluginZipFormat
9 from faraday_plugins.plugins.plugins_utils import resolve_hostname
109
1110 __author__ = "Ezequiel Tavella"
1211 __copyright__ = "Copyright (c) 2015, Infobyte LLC"
9594 return check_files
9695
9796
98 class Host():
97 class Host:
9998
10099 def __init__(self):
101100 self.ip = ""
108107 self.ns_record = ""
109108
110109
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
115115 if extension == '.mtgx':
116116 self.xml = readMtgx(xml_file)
117117 self.nodes = self.xml.findall(
168168 "{http://maltego.paterva.com/xml/mtgx}Property/"
169169 "{http://maltego.paterva.com/xml/mtgx}Value")
170170 if entity.get("type") in ("maltego.Domain", "maltego.Website"):
171 ip = resolve_hostname(value.text)
171 ip = self.resolve_hostname(value.text)
172172 hostname = value.text
173173 else:
174174 ip = value.text
376376
377377 def parseOutputString(self, output):
378378 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)
380380 hosts = maltego_parser.parse()
381381 if not hosts:
382382 self.logger.warning("No hosts data found in maltego report")
439439 self.createAndAddServiceToHost(host_id=host_id, name=host.ns_record["value"], protocol="DNS",
440440 ports=[53], description="DNS Server")
441441 else:
442 maltego_parser = MaltegoParser(output, self.extension[0])
442 maltego_parser = MaltegoParser(output, self.extension[0], resolve_hostname=self.resolve_hostname)
443443 if not maltego_parser.xml.get('domain') or not maltego_parser.xml.get('ipv4'):
444444 return
445445 if maltego_parser.xml.get('domain'):
495495 description="DNS Server")
496496
497497
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)
1818 class MbsaParser:
1919 def __init__(self, log_output):
2020 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)
2222 self.scan_date = re.search('(Scan date:) (.*[0-9])', log_output)
2323 self.issues = re.findall(r'Issue: .*', log_output)
2424 self.score = re.findall(r'Score: .*', log_output)
113113 i += 1
114114
115115
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)
44 """
55 import re
66 from faraday_plugins.plugins.plugin import PluginBase
7 from faraday_plugins.plugins.plugins_utils import resolve_hostname
87
98
109 __author__ = "Francisco Amato"
2423 @param medusa_filepath A proper simple report generated by medusa
2524 """
2625
27 def __init__(self, xml_output):
26 def __init__(self, xml_output, resolve_hostname):
27 self.resolve_hostname = resolve_hostname
2828 self.srv = {
2929 'ftp': '21', 'http': '80', 'imap': '143', 'mssql': '1433', 'mysql': '3306',
3030 'ncp': '524', 'nntp': '119', 'pcanywhere': '5631', 'pop3': '110', 'postgres': '5432',
3636
3737 lines = xml_output.splitlines()
3838 self.items = []
39
39
4040 for line in lines:
4141
42 reg = re.search("ACCOUNT FOUND: \[([^$]+)\] Host: ([^$]+) User: ([^$]+) Password: ([^$]+) \[SUCCESS\]", line)
42 reg = re.search(r"ACCOUNT FOUND: \[([^$]+)\] Host: ([^$]+) User: ([^$]+) Password: ([^$]+) \[SUCCESS\]", line)
4343 if reg:
44
44
4545 item = {
4646 'service': reg.group(1),
4747 'host': reg.group(2),
8080 NOTE: if 'debug' is true then it is being run from a test case and the
8181 output being sent is valid.
8282 """
83 parser = MedusaParser(output)
84
83 parser = MedusaParser(output, resolve_hostname=self.resolve_hostname)
84
8585 for item in parser.items:
86
86
8787 h_id = self.createAndAddHost(item['ip'], hostnames=[item['host']])
8888
8989 port = self.port if self.port else item['port']
104104 self.createAndAddVulnToService(h_id,
105105 s_id,
106106 "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']}",
108108 severity="high")
109109
110110 del parser
132132
133133
134134
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)
350350 self.createAndAddCredToService(
351351 h_id, s_id, c.user, c.passwd)
352352 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(
354354 c.user, c.passwd), severity="high")
355355
356356 for v in item.vulnsByService[s['id']]:
374374 return False
375375
376376
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)
4040 port = host_dict.get('port')
4141 try:
4242 service = socket.getservbyport(port)
43 except socket.error:
43 except OSError:
4444 service = 'Unknown service on port ' + str(port)
4545 host_id = self.createAndAddHost(
4646 name=ip,
6666 command_string += " -silent"
6767 return command_string
6868
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)
4141 try:
4242 tree = ET.fromstring(xml_output)
4343 except SyntaxError as err:
44 print('SyntaxError In xml: %s. %s' % (err, xml_output))
44 print(f'SyntaxError In xml: {err}. {xml_output}')
4545 return None
4646 return tree
4747
118118 password=service_vuln['passw'])
119119
120120
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)
1717 __status__ = "Development"
1818
1919
20 class NdiffXmlParser():
20 class NdiffXmlParser:
2121 """
2222 The objective of this class is to parse an xml file generated by
2323 the ndiff tool.
3838 try:
3939 return ET.fromstring(xmlOutput)
4040 except SyntaxError as err:
41 print("SyntaxError: %s" % err)
41 print(f"SyntaxError: {err}")
4242 return None
4343
4444 def getHostsDiffs(self, tree):
119119 continue
120120 if host.isNewHost:
121121 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'
123123 for port in host.ports:
124 description += 'Port: %s/%s\n' % (port[0], port[1])
124 description += f'Port: {port[0]}/{port[1]}\n'
125125 self.createAndAddVulnToHost(
126126 hostId,
127127 'New host active',
135135 hostId = self.createAndAddHost(host.ip, '')
136136 description = 'New service/s found.\n'
137137 for port in host.ports:
138 description += 'Port: %s/%s\n' % (port[0], port[1])
138 description += f'Port: {port[0]}/{port[1]}\n'
139139
140140 self.createAndAddVulnToHost(
141141 hostId,
151151 return f"{command_string} --xml "
152152
153153
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)
357357 return _dict.get("host-fqdn", None)
358358
359359 @property
360 def host_rdns(self) -> str:
361 _dict = self.dict_tags
362 return _dict.get("host-rdns", None)
363
364 @property
360365 def dict_tags(self):
361366 host_tags = {}
362367 for t in self.node:
6868 compliance_data[compliance_name] = value
6969 return compliance_data
7070
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)
7379 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,
7682 "mac": host.host_properties.mac_address,
7783 "os": host.host_properties.operating_system
7884 }
191197 return kwargs
192198
193199
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)
2626 def parseOutputString(self, output):
2727 #regexp get ip, mac and hostname
2828 reg = re.findall(r"(([0-9]+\.?){4})\s+(([0-9a-f]+\:?){6})((\s+[0-9]+){2})(.*)", output)
29
29
3030 if output.find('Finished!') != -1 and len(reg) > 0:
3131
3232 for stdout in reg:
3838
3939
4040
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)
1010 from bs4 import BeautifulSoup
1111
1212 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
1414
1515 __author__ = "Francisco Amato"
1616 __copyright__ = "Copyright (c) 2013, Infobyte LLC"
5555 try:
5656 tree = ET.fromstring(xml_output)
5757 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}")
5959 return None
6060
6161 return tree
8181 self.url = self.get_text_from_subnode("url")
8282
8383 host = re.search(
84 "(http|https|ftp)\://([a-zA-Z0-9\.\-]+(\:[a-zA-Z0-9\.&amp;%\$\-]+)*@)*((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\.\,\?\'\\\+&amp;%\$#\=~_\-]+)).*?$",
84 r"(http|https|ftp)\://([a-zA-Z0-9\.\-]+(\:[a-zA-Z0-9\.&amp;%\$\-]+)*@)*((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\\.\\,\\?\'\\\\+&amp;%\\$#\\=~_\\-]+)).*?$",
8989 self.url)
9090
9191 self.protocol = host.group(1)
144144 if self.owasp:
145145 self.ref.append("OWASP-" + self.owasp)
146146 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))))
148148 if self.cvss:
149149 self.ref.append(self.cvss)
150
150
151151 self.data = ""
152152 self.data += "\nKnowVulns: " + \
153153 "\n".join(self.kvulns) if self.kvulns else ""
200200 host_names_resolve = {}
201201 for i in parser.items:
202202
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)
205205 host_names_resolve[i.hostname] = ip
206206 else:
207207 ip = host_names_resolve[i.hostname]
208208 h_id = self.createAndAddHost(ip, hostnames=[i.hostname])
209
209
210210 s_id = self.createAndAddServiceToHost(h_id, str(i.port),
211211 protocol = str(i.protocol),
212212 ports=[str(i.port)],
233233 del parser
234234
235235
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)
88 from urllib.parse import urlparse
99
1010 from faraday_plugins.plugins.plugin import PluginXMLFormat
11 from faraday_plugins.plugins.plugins_utils import resolve_hostname
1211
1312 __author__ = "Francisco Amato"
1413 __copyright__ = "Copyright (c) 2013, Infobyte LLC"
2322 def get_urls(string):
2423 if isinstance(string, bytes):
2524 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)
2726 else:
28 urls = re.findall('(?:(?:https?|ftp):\/\/)?[\w/\-?=%.]+\.[\w/\-?=%.]+', string)
27 urls = re.findall(r'(?:(?:https?|ftp):\/\/)?[\w/\-?=%.]+\.[\w/\-?=%.]+', string)
2928 return urls
3029
3130
6059 try:
6160 tree = ET.fromstring(xml_output)
6261 except SyntaxError as err:
63 self.logger.error("SyntaxError: %s. %s" % (err, xml_output))
62 self.logger.error(f"SyntaxError: {err}. {xml_output}")
6463 return None
6564 return tree
6665
123122
124123 self.ref = []
125124 if self.cwe:
126 self.ref.append("CWE-{}".format(self.cwe))
125 self.ref.append(f"CWE-{self.cwe}")
127126 if self.owasp:
128 self.ref.append("OWASP-{}".format(self.owasp))
127 self.ref.append(f"OWASP-{self.owasp}")
129128
130129 self.node = item_node
131130 self.remedyreferences = self.get_text_from_subnode("remedy-references")
185184 first = True
186185 for i in parser.items:
187186 if first:
188 ip = resolve_hostname(i.hostname)
187 ip = self.resolve_hostname(i.hostname)
189188 h_id = self.createAndAddHost(ip, hostnames=[i.hostname])
190189 s_id = self.createAndAddServiceToHost(h_id, i.protocol, ports=[i.port], status="open")
191190 first = False
196195 del parser
197196
198197
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)
319319 del parser
320320
321321
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)
44
55 """
66 import re
7 import os
87 import json
98 from faraday_plugins.plugins.plugin import PluginBase
10 from faraday_plugins.plugins.plugins_utils import resolve_hostname
119
1210
1311 __author__ = "Blas Moyano"
6462 return True
6563
6664
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)
5151 try:
5252 tree = ET.fromstring(xml_output)
5353 except SyntaxError as err:
54 print("SyntaxError: %s. %s" % (err, xml_output))
54 print(f"SyntaxError: {err}. {xml_output}")
5555 return None
5656
5757 return tree
310310 if arg_match is None:
311311 return re.sub(r"(^.*?nikto(\.pl)?)", r"\1 -output %s -Format XML" % self._output_file_path, command_string)
312312 else:
313 data = re.sub(" \-Format XML", "", command_string)
313 data = re.sub(r" \-Format XML", "", command_string)
314314 return re.sub(arg_match.group(1), r"-output %s -Format XML" % self._output_file_path, data)
315315
316316
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)
00 import xml.etree.ElementTree as ET
1 from colorama import Fore, Style
21
3 from faraday_plugins.plugins.plugins_utils import resolve_hostname
42 from faraday_plugins.plugins.plugin import PluginXMLFormat
53
64 __author__ = "@rfocke and @pasta <3"
133131 parser = NipperParser(output, debug=False)
134132 for vuln in parser.vulns_first:
135133 for device in vuln.affected_devices:
136 ip = resolve_hostname(device)
134 ip = self.resolve_hostname(device)
137135 h_id = self.createAndAddHost(ip, hostnames=device)
138136 self.createAndAddVulnToHost(h_id,
139137 name=vuln.name,
147145 )
148146 for vuln in parser.vulns_audit:
149147 if vuln.data:
150 ip = resolve_hostname(device)
148 ip = self.resolve_hostname(device)
151149 h_id = self.createAndAddHost(ip, hostnames=vuln.device)
152150 self.createAndAddVulnToHost(h_id,
153151 name=vuln.name,
160158 )
161159
162160
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)
201201 os_gen = osclass.get("osgen", "unknown")
202202 accuracy = osclass.get("accuracy", "unknown")
203203
204 yield ("%s %s %s" % (os_vendor, os_family, os_gen), accuracy)
204 yield (f"{os_vendor} {os_family} {os_gen}", accuracy)
205205
206206 # Os information in services, bad acurracy.
207207 if osclasses == []:
208208 services = self.node.findall("ports/port/service")
209209 for service in services:
210210 ostype = service.get("ostype", "unknown")
211 yield ("%s" % ostype, 0)
211 yield (f"{ostype}", 0)
212212
213213 def top_os_guess(self):
214214 """
243243 def __str__(self):
244244 ports = []
245245 for port in self.ports:
246 var = " %s" % port
246 var = f" {port}"
247247 ports.append(var)
248248 ports = "\n".join(ports)
249249
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}"
256251
257252
258253 class Port:
323318 yield Script(s)
324319
325320 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}"
327322
328323
329324 class ScriptVulners:
363358 self.severity = get_severity_from_cvss(self.table["cvss"])
364359
365360 def __str__(self):
366 return "%s, %s, %s" % (self.name, self.product, self.version)
361 return f"{self.name}, {self.product}, {self.version}"
367362
368363
369364 class Script:
379374 """
380375
381376 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)
383378 m1 = block_re.findall(output)
384379 if len(m1) > 0:
385380 links_re = re.compile('[ \t]+([^ \t\n\r]+)[ \t]*')
399394 self.web = re.search("(http-|https-)", self.name)
400395
401396 def __str__(self):
402 return "%s, %s, %s" % (self.name, self.product, self.version)
397 return f"{self.name}, {self.product}, {self.version}"
403398
404399
405400 class Service:
438433 self.ostype = self.node.get("ostype")
439434
440435 def __str__(self):
441 return "%s, %s, %s" % (self.name, self.product, self.version)
436 return f"{self.name}, {self.product}, {self.version}"
442437
443438
444439 class NmapPlugin(PluginXMLFormat):
578573 command_string)
579574
580575
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)
1111 from urllib.parse import urlparse
1212 from packaging import version
1313 from faraday_plugins.plugins.plugin import PluginMultiLineJsonFormat
14 from faraday_plugins.plugins.plugins_utils import resolve_hostname
1514
1615 __author__ = "Nicolas Rebagliati"
1716 __copyright__ = "Copyright (c) 2021, Infobyte LLC"
3231 super().__init__(*arg, **kwargs)
3332 self.id = "nuclei"
3433 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"
3736 self.json_keys = {"matched-at", "template-id", "host"}
3837 self._command_regex = re.compile(r'^(sudo nuclei|nuclei|\.\/nuclei|^.*?nuclei)\s+.*?')
3938 self.xml_arg_re = re.compile(r"^.*(-o\s*[^\s]+).*$")
4544 vuln_dict = json.loads(vuln_json)
4645 host = vuln_dict.get('host')
4746 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)
4953 host_id = self.createAndAddHost(
5054 name=ip,
5155 hostnames=[url_data.hostname])
8791 references = [references]
8892 else:
8993 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
93111 tags = vuln_dict['info'].get('tags', [])
94112 if isinstance(tags, str):
95113 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
99124 request = vuln_dict.get('request', '')
100125 if request:
101126 method = request.split(" ")[0]
121146 impact=impact,
122147 resolution=resolution,
123148 easeofresolution=easeofresolution,
149 cve=cve,
150 # TODO CVSSv2, CVSSv3, CWE and CAPEC
151 #cvssv2=cvssv2,
152 #cvssv3=cvssv3,
153 #cwe=cwe,
154 #capec=capec,
124155 website=host,
125156 request=request,
126157 response=vuln_dict.get('response', ''),
161192 return False
162193
163194
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)
44 from packaging import version
55 from urllib.parse import urlparse
66 from faraday_plugins.plugins.plugin import PluginMultiLineJsonFormat
7 from faraday_plugins.plugins.plugins_utils import resolve_hostname
87
98 __author__ = "Emilio Couto"
109 __copyright__ = "Copyright (c) 2021, Faraday Security"
3837 vuln_dict = json.loads(vuln_json)
3938 host = vuln_dict.get('host')
4039 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))
4241 host_id = self.createAndAddHost(
4342 name=ip,
4443 hostnames=[url_data.hostname])
148147 except Exception as e:
149148 return False
150149
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)
00 #!/usr/bin/env python
1 # -*- coding: utf-8 -*-
21 """
32 Faraday Penetration Test IDE
43 Copyright (C) 2020 Infobyte LLC (http://www.infobytesec.com/)
3332 parser = etree.XMLParser(recover=True)
3433 tree = etree.fromstring(xml_output, parser=parser)
3534 except SyntaxError as err:
36 print('SyntaxError In xml: %s. %s' % (err, xml_output))
35 print(f'SyntaxError In xml: {err}. {xml_output}')
3736 return None
3837 return tree
3938
207206 cve=[vuln_cve])
208207
209208
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)
116116 def do_clean(self, value):
117117 myreturn = ""
118118 if value is not None:
119 myreturn = re.sub("\s+", " ", value)
119 myreturn = re.sub(r"\s+", " ", value)
120120 return myreturn.strip()
121121
122122
233233 def do_clean(self, value):
234234 myreturn = ""
235235 if value is not None:
236 myreturn = re.sub("\s+", " ", value)
236 myreturn = re.sub(r"\s+", " ", value)
237237
238238 return myreturn.strip()
239239
348348 if item.bid:
349349 bids = item.bid.split(',')
350350 for bid in bids:
351 ref.append("BID-%s" % bid.strip())
351 ref.append(f"BID-{bid.strip()}")
352352 if item.xref:
353353 ref.append(item.xref)
354354 if item.tags and item.cvss_vector:
357357 ref.append(f"CVSS_BASE: {item.cvss_base}")
358358 if item.cpe:
359359 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}")
360365 if item.threat:
361366 ref.append(f"THREAT: {item.threat}")
362 if item.severity_nr:
363 ref.append(f"SEVERITY NUMBER: {item.severity_nr}")
364367
365368 if item.subnet in ids:
366369 h_id = ids[item.host]
379382 severity=item.severity,
380383 resolution=item.resolution,
381384 ref=ref,
382 external_id=item.id,
385 external_id=f"OPENVAS-{item.id}",
383386 data=item.data,
384387 cve=cve)
385388 else:
411414 severity=item.severity,
412415 ref=ref,
413416 resolution=item.resolution,
414 external_id=item.id,
417 external_id=f"OPENVAS-{item.id}",
415418 data=item.data,
416419 cve=cve)
417420 elif item.severity not in self.ignored_severities:
423426 severity=item.severity,
424427 ref=ref,
425428 resolution=item.resolution,
426 external_id=item.id,
429 external_id=f"OPENVAS-{item.id}",
427430 data=item.data,
428431 cve=cve)
429432 del parser
436439 return False
437440
438441
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)
55 """
66
77 # Author: @EzequielTBH
8 from builtins import str
98
109 from faraday_plugins.plugins.plugin import PluginBase
1110 import json
3635 indexStart:self.command_string.find(" ", indexStart)]
3736 fileJson = self._current_path + "/" + fileJson
3837 try:
39 with open(fileJson, "r") as fileJ:
38 with open(fileJson) as fileJ:
4039 results = json.loads(fileJ.read())
4140 except Exception as e:
4241 return
8584 return command_string
8685
8786
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)
1616 __status__ = "Development"
1717
1818 from faraday_plugins.plugins.plugin import PluginBase
19 from faraday_plugins.plugins.plugins_utils import resolve_hostname
2019
2120
2221 class PeepingTomPlugin(PluginBase):
4847 for url in re.findall(r'href=[\'"]?([^\'" >]+)', html):
4948 if "://" in url:
5049 url_parsed = urlparse(url)
51 address = resolve_hostname(url_parsed.netloc)
50 address = self.resolve_hostname(url_parsed.netloc)
5251 host = self.createAndAddHost(address)
5352 service = self.createAndAddServiceToHost(host, "http", protocol="tcp", ports=[80])
5453 self.createAndAddNoteToService(
7069 self._path = current_path
7170
7271
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)
4747 return False
4848
4949
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)
6060 self._port = count_args[2]
6161
6262
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)
107107 ref=[issue.doc_link])
108108
109109
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)
145145
146146 self.severity_dict = {
147147 '1': 'info',
148 '2': 'info',
148 '2': 'low',
149149 '3': 'med',
150150 '4': 'high',
151151 '5': 'critical'}
179179 self.cve.append(cve_id)
180180
181181 if self.cvss:
182 self.ref.append('CVSS SCORE: {}'.format(self.cvss))
182 self.ref.append(f'CVSS SCORE: {self.cvss}')
183183
184184 if self.pci:
185 self.ref.append('PCI: {}'.format(self.pci))
185 self.ref.append(f'PCI: {self.pci}')
186186
187187 def get_text_from_glossary(self, tag):
188188 """
285285
286286 self.severity_dict = {
287287 '1': 'info',
288 '2': 'info',
288 '2': 'low',
289289 '3': 'med',
290290 '4': 'high',
291291 '5': 'critical'}
414414 del parser
415415
416416
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)
00 #!/usr/bin/env python
1 # -*- coding: utf-8 -*-
21 """
32 Faraday Penetration Test IDE
43 Copyright (C) 2016 Infobyte LLC (http://www.infobytesec.com/)
2322 def __init__(self, xml_output):
2423 self.tree = self.parse_xml(xml_output)
2524 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'))
2729 self.info_glossary = self.get_glossary_qid(self.tree.find('GLOSSARY'))
2830 self.info_appendix = self.get_appendix(self.tree.find('APPENDIX'))
2931 else:
3335 try:
3436 tree = ET.fromstring(xml_output)
3537 except SyntaxError as err:
36 print('SyntaxError In xml: %s. %s' % (err, xml_output))
38 print(f'SyntaxError In xml: {err} {xml_output}')
3739 return None
3840 return tree
3941
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)
4346
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)
4751
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)
5156
5257
53 class Appendix():
58 class Appendix:
5459 def __init__(self, appendix_tags):
5560 if appendix_tags.tag == 'SCAN_LIST':
5661 self.lista_scan = self.get_scan(appendix_tags.find('SCAN'))
5863 elif appendix_tags.tag == 'WEBAPP':
5964 self.lista_webapp = self.get_webapp(appendix_tags)
6065
61 def get_scan(self, appendix_tags):
62 self.result_scan = {}
66 @staticmethod
67 def get_scan(appendix_tags):
68 result_scan = {}
6369 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
6672
67 def get_webapp(self, appendix_tags):
68 self.result_webapp = {}
73 @staticmethod
74 def get_webapp(appendix_tags):
75 result_webapp = {}
6976 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
7279
7380
74 class Glossary():
81 class Glossary:
7582 def __init__(self, glossary_tags):
7683 self.lista_qid = self.get_qid_list(glossary_tags)
7784
8289 return self.dict_result_qid
8390
8491
85 class Results():
92 class Results:
8693 def __init__(self, glossary_tags):
8794 self.lista_vul = self.get_qid_list(glossary_tags)
8895
97104
98105 def __init__(self, *arg, **kwargs):
99106 super().__init__(*arg, **kwargs)
100 self.identifier_tag = ["WAS_SCAN_REPORT"]
107 self.identifier_tag = ["WAS_WEBAPP_REPORT", "WAS_SCAN_REPORT"]
101108 self.id = 'QualysWebapp'
102109 self.name = 'QualysWebapp XML Output Plugin'
103110 self.plugin_version = '1.0.0'
120127 for host_create in parser.info_appendix:
121128 self.scan_list_result.append(host_create)
122129
130 operating_system = ""
123131 for k in self.scan_list_result:
124132 if 'result_scan' in k.__dict__:
125133 self.credential = k.lista_scan.get('AUTHENTICATION_RECORD')
136144
137145 for v in parser.info_results:
138146 url = urlparse(v.dict_result_vul.get('URL'))
139
140147 host_id = self.createAndAddHost(name=url.netloc, os=operating_system, hostnames=hostnames)
141148
142149 vuln_scan_id = v.dict_result_vul.get('QID')
144151 # Data in the xml is in different parts, we look into the glossary
145152 vuln_data = next((item for item in glossary if item["QID"] == vuln_scan_id), None)
146153 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')
149155 raw_severity = int(vuln_data.get('SEVERITY', 0))
150156 vuln_severity = raw_severity - 1
151157
158164
159165 vuln_ref = []
160166 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')}"]
162168
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')}"
166172
167173 self.createAndAddVulnToHost(host_id=host_id, name=vuln_name, desc=vuln_desc, ref=vuln_ref,
168174 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)
170176
171177
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)
11 from collections import defaultdict
22
33 from faraday_plugins.plugins.plugin import PluginBase
4 from faraday_plugins.plugins.plugins_utils import resolve_hostname
5
64
75 class RDPScanPlugin(PluginBase):
86
4240 )
4341
4442
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)
1212 import xml.etree.ElementTree as ET
1313
1414 from faraday_plugins.plugins.plugin import PluginXMLFormat
15 from faraday_plugins.plugins.plugins_utils import resolve_hostname
1615
1716 __author__ = 'Leonardo Lazzaro'
1817 __copyright__ = 'Copyright (c) 2017, Infobyte LLC'
149148 self.host_mapper[host['host']] = h_id
150149 for vuln in parser.vulns:
151150 if vuln['host'] not in list(self.host_mapper.keys()):
152 ip = resolve_hostname(vuln['host'])
151 ip = self.resolve_hostname(vuln['host'])
153152 h_id = self.createAndAddHost(
154153 ip,
155154 hostnames=[vuln['host']]
170169
171170
172171
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)
4848 try:
4949 tree = ET.fromstring(xml_output)
5050 except SyntaxError as err:
51 print("SyntaxError: %s. %s" % (err, xml_output))
51 print(f"SyntaxError: {err}. {xml_output}")
5252 return None
5353
5454 return tree
211211 del parser
212212
213213
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)
3535
3636 for line in lists:
3737 if line != "":
38 print("(%s)" % line)
38 print(f"({line})")
3939 info = line.split("\t")
4040 if info.__len__() > 0:
4141 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]}")
4343 self.items.append(item)
4444
4545
7777
7878
7979
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)
1212 import shutil
1313
1414 from faraday_plugins.plugins.plugin import PluginMultiLineJsonFormat
15
15 from faraday_plugins.plugins.plugins_utils import get_severity_from_cvss
1616 __author__ = "Valentin Vila"
1717 __copyright__ = "Copyright (c) 2021, Faraday"
1818 __credits__ = ["Valentin Vila"]
7171 for name, vuln_info in vulns.items():
7272 description = vuln_info.get('summary')
7373 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)
7577
7678 def processCommandString(self, username, current_path, command_string):
7779 """
101103 return cmd
102104
103105
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)
1111 import tempfile
1212
1313 from faraday_plugins.plugins.plugin import PluginBase
14 from faraday_plugins.plugins.plugins_utils import resolve_hostname
1514
1615
1716 __author__ = "Nicolas Rodriguez"
4039 def __init__(self, skipfish_filepath):
4140 self.filepath = skipfish_filepath
4241
43 tmp = open(skipfish_filepath + "/samples.js", "r").read()
42 tmp = open(skipfish_filepath + "/samples.js").read()
4443 data = self.extract_data(
4544 tmp,
4645 "var issue_samples =", "];",
5150 # Also remove \n character and space for have a valid JSON.
5251 issues = json.loads(repr(data[1]).replace("\\n"," ").replace("'","") + "]")
5352
54 tmp = open(skipfish_filepath + "/index.html", "r").read()
53 tmp = open(skipfish_filepath + "/index.html").read()
5554 err_msg = json.loads(
5655 self.extract_data(
5756 tmp,
151150 for sample in issue["samples"]:
152151 if not sample["url"] in hostc:
153152 reg = re.search(
154 "(http|https|ftp)\://([a-zA-Z0-9\.\-]+(\:[a-zA-Z0-9\.&amp;%\$\-]+)*@)*((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\.\,\?\'\\\+&amp;%\$#\=~_\-]+)).*?$", sample["url"])
153 "(http|https|ftp)\\://([a-zA-Z0-9\\.\\-]+(\\:[a-zA-Z0-9\\.&amp;%\\$\\-]+)*@)*((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\\.\\,\\?\'\\\\+&amp;%\\$#\\=~_\\-]+)).*?$", sample["url"])
155154
156155 protocol = reg.group(1)
157156 host = reg.group(4)
160159 else:
161160 port = 443 if protocol == "https" else 80
162161
163 ip = resolve_hostname(host)
162 ip = self.resolve_hostname(host)
164163
165164 h_id = self.createAndAddHost(ip, hostnames=[host])
166165 s_id = self.createAndAddServiceToHost(h_id, "http", "tcp", ports=[port], status="open")
203202
204203
205204
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)
2121 }
2222 STATUSES = {
2323 'OPEN': 'open',
24 'CONFIRMED': 'opened',
24 'CONFIRMED': 'open',
2525 'REOPENED': 're-opened',
2626 'CLOSED': 'closed',
2727 'RESOLVED': 'closed'
9393 )
9494
9595
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)
6262 for vuln in vulns:
6363 v_name = vuln['title']
6464 v_desc = vuln['overview']
65 v_ref = "CVSS: {}".format(vuln['cvssScore'])
65 v_ref = f"CVSS: {vuln['cvssScore']}"
6666 v_data = vuln['libraries']
6767 v_website = vuln['_links']['html']
6868 url_data = parser.parse_url(v_website)
8181 website=v_website)
8282
8383
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)
6565 return None
6666
6767
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)
33 See the file 'doc/LICENSE' for the license information
44
55 """
6 import re
76 import json
8 from urllib.parse import urlparse
97 from faraday_plugins.plugins.plugin import PluginJsonFormat
10 from faraday_plugins.plugins.plugins_utils import resolve_hostname
118
129 __author__ = "Blas Moyano"
1310 __copyright__ = "Copyright (c) 2020, Infobyte LLC"
109106 data=vuln['data'])
110107
111108
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)
131131 host_id,
132132 service_id,
133133 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}",
135135 severity="info")
136136 # Ciphers
137137 cipher = parser.cipher_suite
142142 host_id,
143143 service_id,
144144 name=value,
145 desc="In protocol [{}], weak cipher suite: {}".format(key, value),
145 desc=f"In protocol [{key}], weak cipher suite: {value}",
146146 severity="low")
147147
148148 # Heartbleed
168168 severity="medium")
169169
170170
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)
66 import re
77 import json
88 from faraday_plugins.plugins.plugin import PluginJsonFormat
9 from faraday_plugins.plugins.plugins_utils import resolve_hostname
109
1110 __author__ = "Blas Moyano"
1211 __copyright__ = "Copyright (c) 2020, Infobyte LLC"
2019
2120 class SslyzeJsonParser:
2221
23 def __init__(self, json_output):
22 def __init__(self, json_output, resolve_hostname):
23 self.resolve_hostname = resolve_hostname
2424 json_sslyze = json.loads(json_output)
2525 scan_result = json_sslyze.get('server_scan_results')
2626 self.list_vul = self.get_vuln(scan_result)
6666 def get_host(self, server_location):
6767 port = server_location.get('port', None)
6868 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))
7070 if port != 443:
7171 url = f"https://{hostname}:{port}"
7272 else:
192192 self._temp_file_extension = "json"
193193
194194 def parseOutputString(self, output):
195 parser = SslyzeJsonParser(output)
195 parser = SslyzeJsonParser(output, self.resolve_hostname)
196196
197197 for info_sslyze in parser.list_vul:
198198 info_sslyze['host_info'].get('hostname')
286286 command_string)
287287
288288
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)
55 """
66 import re
77 from faraday_plugins.plugins.plugin import PluginBase
8 from faraday_plugins.plugins.plugins_utils import resolve_hostname
98
109 __author__ = "Facundo de Guzmán, Esteban Guillardoy"
1110 __copyright__ = "Copyright (c) 2013, Infobyte LLC"
6059 host_info = re.search(r"Connected to (.+)\.", output)
6160
6261 hostname = host_info.group(1)
63 ip_address = resolve_hostname(hostname)
62 ip_address = self.resolve_hostname(hostname)
6463
6564 if host_info is not None:
6665 h_id = self.createAndAddHost(ip_address, hostnames=[hostname])
7675 self._port = count_args[c - 1]
7776
7877
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)
3535 _hosts, _vhosts = [], []
3636
3737 mregex = re.search(
38 "\[\+\] Hosts found in search engines:[-=\s]+([\w\W]*)\[\+\]", output)
38 r"\[\+\] Hosts found in search engines:[-=\s]+([\w\W]*)\[\+\]", output)
3939 if mregex is None:
4040 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)
4343
4444 if mregex is None and mregex2 is None:
4545 return
114114
115115
116116
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)
5555 return None
5656
5757
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)
88 from urllib.parse import urlparse
99
1010 from faraday_plugins.plugins.plugin import PluginXMLFormat
11 from faraday_plugins.plugins.plugins_utils import resolve_hostname
1211
1312 __author__ = "Francisco Amato"
1413 __copyright__ = "Copyright (c) 2013, Infobyte LLC"
146145
147146 self.req = hreq.find('status').text
148147 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', '')}"
153152
154153 self.resp = hres.find('status').text
155154 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', '')}"
160159
161160 def do_clean(self, value):
162161 myreturn = ""
201200
202201 def parseOutputString(self, output):
203202 parser = W3afXmlParser(output)
204 ip = resolve_hostname(parser.host)
203 ip = self.resolve_hostname(parser.host)
205204 h_id = self.createAndAddHost(ip, hostnames=[parser.host])
206205 s_id = self.createAndAddServiceToHost(h_id, "http", "tcp", ports=[parser.port], status="open")
207206
213212 del parser
214213
215214
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)
88 from urllib.parse import urlparse
99
1010 from faraday_plugins.plugins.plugin import PluginXMLFormat
11 from faraday_plugins.plugins.plugins_utils import resolve_hostname
1211
1312 __author__ = "Francisco Amato"
1413 __copyright__ = "Copyright (c) 2013, Infobyte LLC"
3130 @param wapiti_xml_filepath A proper xml generated by wapiti
3231 """
3332
34 def __init__(self, xml_output):
33 def __init__(self, xml_output, resolve_hostname):
34 self.resolve_hostname = resolve_hostname
3535 tree = self.parse_xml(xml_output)
3636 if tree:
3737 self.items = [data for data in self.get_items(tree)]
5050 try:
5151 tree = ET.fromstring(xml_output)
5252 except SyntaxError as err:
53 print("SyntaxError: %s. %s" % (err, xml_output))
53 print(f"SyntaxError: {err}. {xml_output}")
5454 return None
5555
5656 return tree
6060 @return items A list of Host instances
6161 """
6262
63 yield Item(tree)
63 yield Item(tree, self.resolve_hostname)
6464
6565
6666 def get_attrib_from_subnode(xml_node, subnode_xpath_expr, attrib_name):
8787 @param item_node A item_node taken from an wapiti xml tree
8888 """
8989
90 def __init__(self, item_node):
90 def __init__(self, item_node, resolve_hostname):
9191 self.node = item_node
9292 self.url = self.get_url(item_node)
9393 if self.url.hostname is not None:
199199
200200 def __init__(self, *arg, **kwargs):
201201 super().__init__(*arg, **kwargs)
202 self.identifier_tag = "report"
202 #self.identifier_tag = "report"
203 self.identifier_tag_attributes = {'type'}
203204 self.id = "Wapiti"
204205 self.name = "Wapiti XML Output Plugin"
205206 self.plugin_version = "0.0.1"
268269 the xml where it expects it to be present.
269270 """
270271
271 parser = WapitiXmlParser(output)
272 parser = WapitiXmlParser(output, self.resolve_hostname)
272273 for item in parser.items:
273274 host_id = self.createAndAddHost(item.ip, hostnames=[item.hostname])
274275 if item.port is None:
298299 """
299300 super().processCommandString(username, current_path, command_string)
300301 host = re.search(
301 "(http|https|ftp)\://([a-zA-Z0-9\.\-]+(\:[a-zA-Z0-9\.&amp;%\$\-]+)*@)*((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\.\,\?\'\\\+&amp;%\$#\=~_\-]+)).*?$",
302 r"(http|https|ftp)\://([a-zA-Z0-9\.\-]+(\:[a-zA-Z0-9\.&amp;%\$\-]+)*@)*((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\\.\\,\\?\'\\\\+&amp;%\\$#\\=~_\\-]+)).*?$",
306307 command_string)
307308
308309 self.protocol = host.group(1)
312313 if self.protocol == 'https':
313314 self.port = 443
314315 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)
112112 arg_match = self.xml_arg_re.match(command_string)
113113
114114 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}"
116116 else:
117117 return re.sub(arg_match.group(1), r"-xml %s" % self._output_file_path, command_string)
118118
119119
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)
3535 def __init__(self, webfuzzer_filepath):
3636 self.filepath = webfuzzer_filepath
3737
38 with open(self.filepath, "r") as f:
38 with open(self.filepath) as f:
3939 try:
4040 data = f.read()
4141 f.close()
4242 m = re.search(
43 "Scan of ([\w.]+):([\d]+) \[([/\w]+)\] \(([\w.]+)\)", data)
43 r"Scan of ([\w.]+):([\d]+) \[([/\w]+)\] \(([\w.]+)\)", data)
4444 self.hostname = m.group(1)
4545 self.port = m.group(2)
4646 self.uri = m.group(3)
4747 self.ipaddress = m.group(4)
4848
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)
5050 self.header = m.group(1)
5151
5252 self.items = []
5757
5858 method = m.group(1)
5959 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))
6161
6262 vuln = {'method': m.group(1), 'desc': info.group(
6363 1), 'url': info.group(2), 'resp': info.group(3)}
128128 """
129129 """
130130 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)
132132 if host is not None:
133133 self.host = host.group(2)
134134 self._output_path = current_path + "/" + self.host + ".txt"
135135
136136
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)
4343 return text
4444 except:
4545 return ""
46
46
4747 def parse(self):
4848
4949 map_objects_fields = {
122122 self.identifier_tag = ["Scan"]
123123
124124 def parseOutputString(self, output):
125
125
126126 parser = WebInspectParser(output)
127127 vulns = parser.parse()
128128
132132 service_id = self.createAndAddServiceToHost(host_id, vuln.get("Service").get("name"),
133133 protocol=vuln.get("Service").get("name"),
134134 ports=[vuln.get("Service").get("port")])
135
135
136136 self.createAndAddVulnWebToService(
137137 host_id, service_id,
138138 vuln.get("Vuln").get("name"),
149149 )
150150
151151
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)
7676 lines = item['lines']
7777 chars = item['chars']
7878 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}"
8080 desc = 'Wfuzz found a response with status {status}. Response contains: \n* {words} words \n* {lines} ' \
8181 'lines \n* {chars} chars'.format(words=words, lines=lines, chars=chars, status=status)
8282 self.createAndAddVulnWebToService(host_id, service_id, name, desc, severity="info", website=target,
8383 path=path)
8484
8585
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)
7373 description=desc)
7474
7575
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)
9797 )
9898
9999
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)
77 import os
88
99 from faraday_plugins.plugins.plugin import PluginBase
10 from faraday_plugins.plugins.plugins_utils import resolve_hostname
1110
1211
1312 __author__ = "Facundo de Guzmán, Esteban Guillardoy"
6968
7069 def processCommandString(self, username, current_path, command_string):
7170 self.command_string = command_string
72 super(CmdWhoisPlugin, self).processCommandString(username, current_path, command_string)
71 super().processCommandString(username, current_path, command_string)
7372
7473 def parseOutputString(self, output):
75 matches = re.findall("Name Server:\s*(.*)\s*", output)
74 matches = re.findall(r"Name Server:\s*(.*)\s*", output)
7675 if not matches:
77 matches = re.findall("nserver:\s*(.*)\s*", output)
76 matches = re.findall(r"nserver:\s*(.*)\s*", output)
7877
7978 if not matches:
8079 ip = re.findall(r'[0-9]+(?:\.[0-9]+){3}', self.command_string)
8180 if not ip:
8281 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)
8584
86 matches_netname = re.findall("NetName:\s*(.*)\s*", output)
85 matches_netname = re.findall(r"NetName:\s*(.*)\s*", output)
8786 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)
9089 desc = ""
9190 ref = []
9291 os_name = "unknown"
109108 for m in matches:
110109 m = m.strip()
111110 url = re.findall(r'https?://[^\s<>"]+|.[^\s<>"]+', str(m))
112 ip = resolve_hostname(url[0])
111 ip = self.resolve_hostname(url[0])
113112 self.createAndAddHost(
114113 ip,
115114 hostnames=[m]
116115 )
117 matches_domain = re.findall("Domain Name:\s*(.*)\s*", output)
116 matches_domain = re.findall(r"Domain Name:\s*(.*)\s*", output)
118117 for md in matches_domain:
119118 md = md.strip()
120 ip = resolve_hostname(md)
119 ip = self.resolve_hostname(md)
121120 self.createAndAddHost(
122121 ip,
123122 hostnames=[md]
125124 return True
126125
127126
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)
1717 __status__ = "Development"
1818
1919 from faraday_plugins.plugins.plugin import PluginJsonFormat
20 from faraday_plugins.plugins.plugins_utils import resolve_hostname
2120
2221
2322 class WPScanJsonParser:
2423
25 def __init__(self, json_output):
24 def __init__(self, json_output, resolve_hostname):
2625 self.json_data = json.loads(json_output)
26 self.resolve_hostname = resolve_hostname
2727
2828 def parse_url(self, url):
2929 # Strips protocol and gets hostname from URL.
3838 elif protocol == 'http':
3939 if not port:
4040 port = 80
41 address = resolve_hostname(hostname)
41 address = self.resolve_hostname(hostname)
4242 return {'protocol': protocol, 'hostname': hostname, 'port': port, 'address': address}
4343
4444
5757 self.json_keys = {"target_url", "effective_url", "interesting_findings"}
5858
5959 def parseOutputString(self, output):
60 parser = WPScanJsonParser(output)
60 parser = WPScanJsonParser(output, self.resolve_hostname)
6161 url_data = parser.parse_url(parser.json_data['target_url'])
6262 host_id = self.createAndAddHost(url_data['address'], hostnames=[url_data['hostname']])
6363 service_id = self.createAndAddServiceToHost(
9090 severity='unclassified')
9191
9292
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)
5252 try:
5353 tree = ET.fromstring(xml_output)
5454 except SyntaxError as err:
55 print("SyntaxError: %s. %s" % (err, xml_output))
55 print(f"SyntaxError: {err}. {xml_output}")
5656 return None
5757
5858 return tree
176176 del parser
177177
178178
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)
1010 __version__ = "1.0.0"
1111
1212 from faraday_plugins.plugins.plugin import PluginBase
13 from faraday_plugins.plugins.plugins_utils import resolve_hostname
1413
1514
1615 class xsssniper(PluginBase):
3332 if not linea:
3433 continue
3534 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])
3938 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)
4241 metodo= list_a[1]
43 if ((linea.find("query string:")>0)):
42 if (linea.find("query string:")>0):
4443 lista_parametros=linea.split('=')
4544 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)
4847 parametro.append(list2[1])
4948 service_id = self.createAndAddServiceToHost(host_id, self.protocol, 'tcp', ports=['80'], status='Open',
5049 version="", description="")
5453 params=''.join(parametro), request='', response='')
5554
5655
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)
77 from urllib.parse import urlparse
88
99 from faraday_plugins.plugins.plugin import PluginXMLFormat
10 from faraday_plugins.plugins.plugins_utils import resolve_hostname
1110
1211 __author__ = "Francisco Amato"
1312 __copyright__ = "Copyright (c) 2013, Infobyte LLC"
3332 @param zap_xml_filepath A proper xml generated by zap
3433 """
3534
36 def __init__(self, xml_output):
37
35 def __init__(self, xml_output, resolve_hostname):
36 self.resolve_hostname = resolve_hostname
3837 tree = self.parse_xml(xml_output)
3938
4039 if tree is not None:
5857 tree = parser.close()
5958
6059 except SyntaxError as err:
61 print("SyntaxError: %s. %s" % (err, xml_output))
60 print(f"SyntaxError: {err}. {xml_output}")
6261 return None
6362
6463 return tree
6564
66 @staticmethod
67 def get_items(tree):
65 def get_items(self, tree):
6866 """
6967 @return items A list of Host instances
7068 """
7169 for node in tree.findall('site'):
72 yield Site(node)
70 yield Site(node, self.resolve_hostname)
7371
7472
7573 def get_attrib_from_subnode(xml_node, subnode_xpath_expr, attrib_name):
9896
9997 class Site:
10098
101 def __init__(self, item_node):
102
99 def __init__(self, item_node, resolve_hostname):
103100 self.node = item_node
104101
105102 self.host = self.node.get('host')
209206
210207 @staticmethod
211208 def extract_params_from_uri(uri):
212 params = re.findall("(\w+)=", uri)
209 params = re.findall(r"(\w+)=", uri)
213210 return params if params else ''
214211
215212 def get_text_from_subnode(self, subnode_xpath_expr):
246243 from the xml where it expects it to be present.
247244 """
248245
249 parser = ZapXmlParser(output)
246 parser = ZapXmlParser(output, self.resolve_hostname)
250247
251248 for site in parser.sites:
252249
286283 del parser
287284
288285
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)
00 from setuptools import setup, find_packages
11 from re import search
22
3 with open('faraday_plugins/__init__.py', 'rt', encoding='utf8') as f:
3 with open('faraday_plugins/__init__.py', encoding='utf8') as f:
44 version = search(r'__version__ = \'(.*?)\'', f.read()).group(1)
55
66
1414 'pytz',
1515 'python-dateutil',
1616 'colorama',
17 'tabulate'
17 'tabulate',
18 'packaging'
1819 ]
1920
2021
4141 generated_summaries = 0
4242 analysed_reports = 0
4343 click.echo(f"{colorama.Fore.GREEN}Generate Faraday Plugins Tests Summary")
44 plugins_manager = PluginsManager()
44 plugins_manager = PluginsManager(hostname_resolution=False)
4545 analyzer = ReportAnalyzer(plugins_manager)
4646 for report_file_path in list_report_files():
4747 if debug:
1515
1616 ]
1717
18 plugins_manager = PluginsManager()
18 plugins_manager = PluginsManager(hostname_resolution=False)
1919 analyzer = ReportAnalyzer(plugins_manager)
2020
2121 PLUGINS_CACHE = {}
7373 except AttributeError: # no inet_pton here, sorry
7474 try:
7575 socket.inet_aton(address)
76 except socket.error:
76 except OSError:
7777 return False
7878 return address.count('.') == 3
79 except socket.error: # not a valid address
79 except OSError: # not a valid address
8080 return False
8181 return True
8282
8484 def is_valid_ipv6_address(address):
8585 try:
8686 socket.inet_pton(socket.AF_INET6, address)
87 except socket.error: # not a valid address
87 except OSError: # not a valid address
8888 return False
8989 return True
9090
162162 assert "hosts" in plugin_json
163163 assert "command" in plugin_json
164164 assert os.path.isfile(report_filename) is True
165