Codebase list faraday-plugins / 272189f3-978c-4b0d-a272-ea8abeef76a0/upstream
Import upstream version 1.4.6 Kali Janitor 2 years ago
138 changed file(s) with 1384 addition(s) and 4141 deletion(s). Raw diff Collapse all Expand all
+0
-3
.flake8 less more
0 [flake8]
1 ignore = W391, E722, E303, E701, W291, E222, E241, E225, E115, E117, E122, E123, E124, E501, E261, E127, E265, F401, W292, W293, W605, E231, E221, E222, F841, E128, W504, E202, F811, E251, E226, E203, E262, E225, E305, E302, E305
2 exclude= report-collection
+0
-132
.gitignore less more
0 # Created by .ignore support plugin (hsz.mobi)
1 ### Python template
2 # Byte-compiled / optimized / DLL files
3 __pycache__/
4 *.py[cod]
5 *$py.class
6
7 # C extensions
8 *.so
9
10 # Distribution / packaging
11 .Python
12 build/
13 develop-eggs/
14 dist/
15 downloads/
16 eggs/
17 .eggs/
18 lib/
19 lib64/
20 parts/
21 sdist/
22 var/
23 wheels/
24 pip-wheel-metadata/
25 share/python-wheels/
26 *.egg-info/
27 .installed.cfg
28 *.egg
29 MANIFEST
30
31 # PyInstaller
32 # Usually these files are written by a python script from a template
33 # before PyInstaller builds the exe, so as to inject date/other infos into it.
34 *.manifest
35 *.spec
36
37 # Installer logs
38 pip-log.txt
39 pip-delete-this-directory.txt
40
41 # Unit test / coverage reports
42 htmlcov/
43 .tox/
44 .nox/
45 .coverage
46 .coverage.*
47 .cache
48 nosetests.xml
49 coverage.xml
50 *.cover
51 .hypothesis/
52 .pytest_cache/
53
54 # Translations
55 *.mo
56 *.pot
57
58 # Django stuff:
59 *.log
60 local_settings.py
61 db.sqlite3
62 db.sqlite3-journal
63
64 # Flask stuff:
65 instance/
66 .webassets-cache
67
68 # Scrapy stuff:
69 .scrapy
70
71 # Sphinx documentation
72 docs/_build/
73
74 # PyBuilder
75 target/
76
77 # Jupyter Notebook
78 .ipynb_checkpoints
79
80 # IPython
81 profile_default/
82 ipython_config.py
83
84 # pyenv
85 .python-version
86
87 # pipenv
88 # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
89 # However, in case of collaboration, if having platform-specific dependencies or dependencies
90 # having no cross-platform support, pipenv may install dependencies that don't work, or not
91 # install all needed dependencies.
92 #Pipfile.lock
93
94 # celery beat schedule file
95 celerybeat-schedule
96
97 # SageMath parsed files
98 *.sage.py
99
100 # Environments
101 .env
102 .venv
103 env/
104 venv/
105 ENV/
106 env.bak/
107 venv.bak/
108
109 # Spyder project settings
110 .spyderproject
111 .spyproject
112
113 # Rope project settings
114 .ropeproject
115
116 # mkdocs documentation
117 /site
118
119 # mypy
120 .mypy_cache/
121 .dmypy.json
122 dmypy.json
123
124 # Pyre type checker
125 .pyre/
126
127 .idea
128 /report-collection/
129
130 #project settings
131 *.project
+0
-84
.gitlab-ci.yml less more
0 stages:
1 - pre_testing
2 - testing
3 - post_testing
4 - publish
5
6 before_script:
7 - apt-get update -qy
8 - pip install pip -U
9
10 workflow:
11 rules:
12 - if: $CI_MERGE_REQUEST_ID
13 when: never
14 - when: always
15
16 .install_faraday_venv: &install_faraday_venv
17 - pip3 install virtualenv
18 - virtualenv -p python3 faraday_venv
19 - source faraday_venv/bin/activate
20 - pip3 install pytest pytest-xdist pytest-cov
21 - git clone https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.com/faradaysec/faraday.git
22 - cd faraday
23 - pip3 install $PIP_FLAGS .
24 - pip uninstall faraday-plugins -y # we need to install fardaysec for marshmallow schemas, we remove plugins from pypi
25 - cd ..
26
27 .clone_reports: &clone_reports
28 - git clone https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.com/faradaysec/support/report-collection.git
29 - cd report-collection
30 - (git branch -a | grep $CI_COMMIT_BRANCH) && export REPORT_REF=$CI_COMMIT_BRANCH || export REPORT_REF=master
31 - git checkout $REPORT_REF
32 - cd ..
33
34
35 flake8:
36 image: python:3
37 stage: pre_testing
38 before_script:
39 - pip install flake8
40 # Help flake8 to find the Python files without .py extension.
41 - find . -name '*.py' >> files.txt
42 - sort -u files.txt | tee files.processed
43 script:
44 - python -m flake8 --statistics --count $(cat files.processed) --verbose
45 after_script:
46 - wc -l files.processed
47
48 .test_base:
49 stage: testing
50 coverage: '/TOTAL\s+\d+\s+\d+\s+(\d+%)/'
51 script:
52 - *clone_reports
53 - *install_faraday_venv
54 - pip3 install $PIP_FLAGS .
55 - pytest tests --capture=sys -v --cov=faraday_plugins --color=yes --disable-warnings $PYTEST_FLAGS
56
57 tests:
58 extends: .test_base
59 image: python:3
60
61 test_performance:
62 extends: .test_base
63 image: python:3
64 stage: post_testing
65 allow_failure: true
66 variables:
67 PYTEST_FLAGS: --performance
68 rules:
69 - if: '$CI_COMMIT_BRANCH == "dev"'
70 when: on_success
71
72 publish_pypi:
73 image: python:3
74 stage: publish
75 script:
76 - apt-get update -qy
77 - apt-get install twine -y
78 - python setup.py sdist bdist_wheel
79 - twine upload -u $PYPI_USER -p $PYPI_PASS dist/* --verbose
80 rules:
81 - if: '$CI_COMMIT_TAG'
82 when: on_success
83
+0
-1
CHANGELOG/1.3.0/add_appspider.md less more
0 ADD plugin AppSpider
+0
-1
CHANGELOG/1.3.0/add_cli_tests.md less more
0 Add tests to faraday-plugins cli
+0
-1
CHANGELOG/1.3.0/add_default_plugin_version.md less more
0 add a default value to plugin_version
+0
-1
CHANGELOG/1.3.0/add_output_file_to_faraday-plugins_command.md less more
0 Add --output-file parameter to faraday-plugins process command
+0
-1
CHANGELOG/1.3.0/add_prowler.md less more
0 Add plugins prowler
+0
-1
CHANGELOG/1.3.0/add_ssl_labs.md less more
0 Add plugins ssl labs
+0
-1
CHANGELOG/1.3.0/add_tenableio_support.md less more
0 Add support for tenable io
+0
-1
CHANGELOG/1.3.0/date.md less more
0 Sep 2nd, 2020
+0
-1
CHANGELOG/1.3.0/delete_old_methods.md less more
0 delete old deprecated methods
+0
-1
CHANGELOG/1.3.0/fix_Arachni.md less more
0 Bug fix: Arachni Plugin 'NoneType' object has no attribute 'find'
+0
-1
CHANGELOG/1.3.0/fix_Openvas.md less more
0 Bug fix: Openvas Plugin - Import xml from OpenVas doesnt work
+0
-1
CHANGELOG/1.3.0/fix_QualysWebapp.md less more
0 Bug fix: QualysWebApp Plugin, error in get info OPERATING_SYSTEM
+0
-1
CHANGELOG/1.3.0/fix_hydra_to_resolve_ip.md less more
0 Fix Hydra plugin to resolve ip address
+0
-1
CHANGELOG/1.3.0/fix_nessus.md less more
0 Fix Nessus mod severity HIGH for Low
+0
-1
CHANGELOG/1.3.0/fix_prowler.md less more
0 Bug Fix: Detect plugins AWS Prowler
+0
-1
CHANGELOG/1.3.0/fix_xml_nmap.md less more
0 Fix broken xml on nmap plugin
+0
-1
CHANGELOG/1.3.0/new_rdpscan_plugin.md less more
0 Add new rdpscan plugin
+0
-1
CHANGELOG/1.3.0/update_appscan.md less more
0 UPDATE xml report to appscan
+0
-1
CHANGELOG/1.3.0/update_readme.md less more
0 Update Readme
+0
-1
CHANGELOG/1.3.0/update_zap.md less more
0 Fix how ZAP genereate vulns
+0
-1
CHANGELOG/1.4.0/date.md less more
0 Dec 23rd, 2020
+0
-1
CHANGELOG/1.4.0/update_nuclei_fields.md less more
0 Update the fields of the nuclei output used to create a vuln
+0
-1
CHANGELOG/1.4.0b1/add_multilinejson_format.md less more
0 Add new plugin base class, for multi line json
+0
-1
CHANGELOG/1.4.0b1/add_ncrack.md less more
0 New ncrack plugin
+0
-1
CHANGELOG/1.4.0b1/add_nuclei.md less more
0 New nuclei plugin
+0
-1
CHANGELOG/1.4.0b1/add_sslyze_json.md less more
0 New sslyze json plugin
+0
-1
CHANGELOG/1.4.0b1/add_whatweb.md less more
0 New WhatWeb plugin
+0
-1
CHANGELOG/1.4.0b1/date.md less more
0 Dec 14th, 2020
+0
-1
CHANGELOG/1.4.0b1/fix_arachni_ip_missing.md less more
0 Fix missing ip in some arachni reports
+0
-1
CHANGELOG/1.4.0b1/fix_netsparker.md less more
0 Fix change name vuln in Netsparker plugin
+0
-1
CHANGELOG/1.4.0b1/fix_whois.md less more
0 Fix whois plugin, command whois IP not parse data
+0
-1
CHANGELOG/1.4.0b1/modify_json_reports_detection.md less more
0 Change the way we detect json reports when they are lists of dictionaries
+0
-1
CHANGELOG/1.4.0b2/date.md less more
0 Dec 15th, 2020
+0
-1
CHANGELOG/1.4.0b2/fix_nuclei.md less more
0 Fix nuclei plugin bug when url is None
+0
-1
CHANGELOG/1.4.1/add_microsoft_baseline.md less more
0 ADD microsoft baseline security analyzer plugin
+0
-1
CHANGELOG/1.4.1/add_nextnet.md less more
0 ADD nextnet plugin
+0
-1
CHANGELOG/1.4.1/add_openscap.md less more
0 ADD openscap plugin
+0
-1
CHANGELOG/1.4.1/date.md less more
0 Feb 26th, 2021
+0
-1
CHANGELOG/1.4.1/fix_nessus_plugin.md less more
0 FIX old versions of Nessus plugins bugs
+0
-1
CHANGELOG/1.4.2/date.md less more
0 Mar 10th, 2021
+0
-1
CHANGELOG/1.4.2/fix_bug_in_sslyze_output_file.md less more
0 Fix bug with sslyze output file
+0
-1
CHANGELOG/1.4.2/fix_sslyze_plugin.md less more
0 FIX change id sslyze for JSON/XML
+0
-1
CHANGELOG/1.4.3/date.md less more
0 Mar 17th, 2021
+0
-1
CHANGELOG/1.4.3/new_ignore_info_option.md less more
0 Add Ignore information vulnerabilities option
+0
-1
CHANGELOG/1.4.4/csv_plugin_dont_user_ignore_info.md less more
0 Faraday CSV Plugin do not consider ignore_info
+0
-1
CHANGELOG/1.4.4/date.md less more
0 Mar 30th, 2021
+0
-1
CHANGELOG/1.4.5/add_bandit_plugin.md less more
0 Add Bandit plugin
+0
-1
CHANGELOG/1.4.5/change_burp_fields.md less more
0 Use background for description and detail for data en Burp plugin.
+0
-1
CHANGELOG/1.4.5/date.md less more
0 Apr 15th, 2021
+0
-1
CHANGELOG/1.4.5/fix_appscan.md less more
0 Rewrite Appscan Plugin
+0
-1
CHANGELOG/1.4.5/parse_nmap_vulnes.md less more
0 Parse Nmap vulners script data
+0
-0
CHANGELOG/current/.keep less more
(Empty file)
0 Metadata-Version: 1.0
1 Name: faraday-plugins
2 Version: 1.4.6
3 Summary: Faraday plugins package
4 Home-page: UNKNOWN
5 Author: Faradaysec
6 Author-email: [email protected]
7 License: GNU General Public License v3
8 Description: UNKNOWN
9 Platform: UNKNOWN
+0
-69
RELEASE.md less more
0 1.4.5 [Apr 15th, 2021]:
1 ---
2 * Add Bandit plugin
3 * Use background for description and detail for data en Burp plugin.
4 * Rewrite Appscan Plugin
5 * Parse Nmap vulners script data
6
7 1.4.4 [Mar 30th, 2021]:
8 ---
9 * Faraday CSV Plugin do not consider ignore_info
10
11 1.4.3 [Mar 17th, 2021]:
12 ---
13 * Add Ignore information vulnerabilities option
14
15 1.4.2 [Mar 10th, 2021]:
16 ---
17 * Fix bug with sslyze output file
18 * FIX change id sslyze for JSON/XML
19
20 1.4.1 [Feb 26th, 2021]:
21 ---
22 * ADD microsoft baseline security analyzer plugin
23 * ADD nextnet plugin
24 * ADD openscap plugin
25 * FIX old versions of Nessus plugins bugs
26
27 1.4.0 [Dec 23rd, 2020]:
28 ---
29 * Update the fields of the nuclei output used to create a vuln
30
31 1.4.0b2 [Dec 15th, 2020]:
32 ---
33 * Fix nuclei plugin bug when url is None
34
35 1.4.0b1 [Dec 14th, 2020]:
36 ---
37 * Add new plugin base class, for multi line json
38 * New ncrack plugin
39 * New nuclei plugin
40 * New sslyze json plugin
41 * New WhatWeb plugin
42 * Fix missing ip in some arachni reports
43 * Fix change name vuln in Netsparker plugin
44 * Fix whois plugin, command whois IP not parse data
45 * Change the way we detect json reports when they are lists of dictionaries
46
47 1.3.0 [Sep 2nd, 2020]:
48 ---
49 * ADD plugin AppSpider
50 * Add tests to faraday-plugins cli
51 * add a default value to plugin_version
52 * Add --output-file parameter to faraday-plugins process command
53 * Add plugins prowler
54 * Add plugins ssl labs
55 * Add support for tenable io
56 * delete old deprecated methods
57 * Bug fix: Arachni Plugin 'NoneType' object has no attribute 'find'
58 * Bug fix: Openvas Plugin - Import xml from OpenVas doesnt work
59 * Bug fix: QualysWebApp Plugin, error in get info OPERATING_SYSTEM
60 * Fix Hydra plugin to resolve ip address
61 * Fix Nessus mod severity HIGH for Low
62 * Bug Fix: Detect plugins AWS Prowler
63 * Fix broken xml on nmap plugin
64 * Add new rdpscan plugin
65 * UPDATE xml report to appscan
66 * Update Readme
67 * Fix how ZAP genereate vulns
68
+0
-24
default.nix less more
0 with import <nixpkgs> {};
1 pkgs.python38Packages.buildPythonPackage rec {
2 name = "env";
3
4 env = buildEnv { name = name; paths = buildInputs; };
5
6 buildInputs = [
7 (python38.buildEnv.override {
8 ignoreCollisions = true;
9 extraLibs = with python38Packages; [
10 requests
11 click
12 simplejson
13 requests
14 lxml
15 html2text
16 beautifulsoup4
17 pytz
18 python-dateutil
19 colorama
20 ];
21 })
22 ];
23 }
+0
-35
doc/development.md less more
0 ## Write you own plugins
1
2 > XML report plugin
3
4 ```python
5 class XXXPLugin(PluginXMLFormat):
6
7 def __init__(self):
8 super().__init__()
9 # Tags to be compared with the xml mail tag, can be a list or a string
10 self.identifier_tag = ["tag1", "tag2"]
11 self.id = 'SOME_PLUGIN_ID' # Can't be repeated
12 self.name = 'Some plugin name'
13 self.plugin_version = 'X.X'
14 # The extension is optional, only if its different than xml
15 self.extension = ".xxx"
16 ```
17
18 > JSON report plugin
19
20 ```python
21 class XXXPLugin(PluginJsonFormat):
22
23 def __init__(self):
24 super().__init__()
25 # keys of the json that identify the report
26 # you don't need to put all the keys, just some of them
27 # it must be a set and will be compared as a subset of the json report keys
28 self.json_keys = {"target_url", "effective_url", "interesting_findings"}
29 self.id = 'SOME_PLUGIN_ID' # Can't be repeated
30 self.name = 'Some plugin name'
31 self.plugin_version = 'X.X'
32 # The extension is optional, only if its different than json
33 self.extension = ".xxx"
34 ```
0 __version__ = '1.4.5'
0 __version__ = '1.4.6'
0 import getpass
01 import io
2 import json
13 import logging
24 import os
5 import shlex
6 import subprocess
37 import sys
4 import json
8
59 import click
6 import subprocess
7 import shlex
8 import getpass
10 from tabulate import tabulate
911
12 from faraday_plugins import __version__
1013 from faraday_plugins.plugins.manager import PluginsManager, ReportAnalyzer, CommandAnalyzer
1114 from faraday_plugins.plugins.plugin import PluginByExtension
1215
2023 root_logger.addHandler(out_hdlr)
2124 root_logger.setLevel(logging.DEBUG)
2225
26 CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help'])
2327
24 @click.group()
28 @click.group(context_settings=CONTEXT_SETTINGS)
29 @click.version_option(__version__, '-v', '--version')
2530 def cli():
2631 pass
2732
3035 @click.option('-cpf', '--custom-plugins-folder', type=str)
3136 def list_plugins(custom_plugins_folder):
3237 plugins_manager = PluginsManager(custom_plugins_folder)
33 click.echo(click.style("Available Plugins:", fg="cyan"))
38 click.echo(click.style(f"Faraday Plugins v{__version__}", fg="cyan"))
39 click.echo(click.style("Available Plugins :", fg="cyan"))
3440 loaded_plugins = 0
41 plugins_data = []
3542 for plugin_id, plugin in plugins_manager.get_plugins():
3643 console_enabled = plugin._command_regex is not None
3744 console_enabled_color = "green" if console_enabled else "red"
3946 report_enabled = isinstance(plugin, PluginByExtension)
4047 report_enabled_color = "green" if report_enabled else "red"
4148 report_enabled_text = click.style(f"{'Yes' if report_enabled else 'No'}", fg=report_enabled_color)
42 click.echo(f"{plugin.id:15} - [Command: {console_enabled_text:>12} - Report: {report_enabled_text:>12}] - {plugin.name} ")
43
44 loaded_plugins += 1
45 click.echo(click.style(f"Loaded Plugins: {loaded_plugins}", fg="cyan"))
49 plugins_data.append({"Name": plugin.name, "ID": plugin.id, "Command": console_enabled_text,
50 "Report": report_enabled_text})
51 click.echo(tabulate(
52 plugins_data,
53 headers="keys",
54 tablefmt="simple",
55 ))
56 click.echo(click.style(f"Loaded Plugins: {len(plugins_data)}", fg="cyan"))
4657
4758
4859 @cli.command()
0 import csv
1 import json
02 import logging
3 import os
4 import pkgutil
5 import re
6 import sys
17 import traceback
2 import re
3 import os
4 import sys
5 import json
6 import pkgutil
8 import xml.etree.ElementTree as ET
79 import zipfile
810 from importlib import import_module
911 from importlib.machinery import SourceFileLoader
10 import csv
1112 from io import StringIO
1213
1314 from . import repo
1415
1516 logger = logging.getLogger("faraday").getChild(__name__)
16
17 try:
18 import xml.etree.cElementTree as ET
19 except ImportError:
20 logger.warning("cElementTree could not be imported. Using ElementTree instead")
21 import xml.etree.ElementTree as ET
2217
2318
2419 class ReportAnalyzer:
3429 else:
3530 file_name = os.path.basename(report_path)
3631 plugin = self._get_plugin_by_name(file_name)
37 if not plugin: # Was unable to detect plugin from report file name
32 if not plugin: # Was unable to detect plugin from report file name
3833 logger.debug("Plugin by name not found")
3934 plugin = self._get_plugin_by_file_type(report_path)
4035 if not plugin:
6762 file_name_base, file_extension = os.path.splitext(file_name)
6863 file_extension = file_extension.lower()
6964 main_tag = None
70 file_json_keys = {}
7165 file_csv_headers = set()
7266 file_json_keys = set()
7367 files_in_zip = set()
150144
151145 class PluginsManager:
152146
153 def __init__(self, custom_plugins_folder=None, ignore_info = False):
147 def __init__(self, custom_plugins_folder=None, ignore_info=False):
154148 self.ignore_info = ignore_info
155149 self.plugins = {}
156150 self.plugin_modules = {}
33 See the file 'doc/LICENSE' for the license information
44
55 """
6 import hashlib
7 import logging
68 import os
9 import re
710 import shutil
811 import tempfile
9
12 import uuid
13 import zipfile
1014 from collections import defaultdict
15 from datetime import datetime
1116
1217 import pytz
13 import re
14 import uuid
15 import logging
1618 import simplejson as json
17 import zipfile
18 from datetime import datetime
19 import hashlib
20
2119
2220 logger = logging.getLogger("faraday").getChild(__name__)
2321
2422 VALID_SERVICE_STATUS = ("open", "closed", "filtered")
2523 VULN_SKIP_FIELDS_TO_HASH = ['run_date']
24
2625
2726 class PluginBase:
2827 # TODO: Add class generic identifier
4039 self.name = None
4140 self.description = ""
4241 self._command_regex = None
42 self.command = None
4343 self._output_file_path = None
4444 self._use_temp_file = False
4545 self._delete_temp_file = False
101101 if severity[0:3] in sev:
102102 return sev
103103 return severity
104
104105 severity = align_string_based_vulns(severity)
105106 # Transform numeric severity into desc severity
106107 numeric_severities = {"0": "info",
124125 self._hosts_cache[cache_id] = obj_uuid
125126 else:
126127 obj_uuid = self._hosts_cache[cache_id]
128 if host['hostnames']:
129 chached_host = self.get_from_cache(obj_uuid)
130 chached_host['hostnames'] = list(set(chached_host['hostnames'] + host['hostnames']))
127131 return obj_uuid
128132
129133 def save_service_cache(self, host_id, service):
169173 def _get_dict_hash(d, keys):
170174 return hash(frozenset(map(lambda x: (x, d.get(x, None)), keys)))
171175
172
173176 @classmethod
174177 def get_host_cache_id(cls, host):
175178 cache_id = cls._get_dict_hash(host, ['ip'])
186189 def get_service_vuln_cache_id(cls, host_id, service_id, vuln):
187190 vuln_copy = vuln.copy()
188191 vuln_copy.update({"host_cache_id": host_id, "service_cache_id": service_id})
189 cache_id = cls._get_dict_hash(vuln_copy, ['host_cache_id', 'service_cache_id', 'name', 'desc', 'website', 'path', 'pname', 'method'])
192 cache_id = cls._get_dict_hash(vuln_copy,
193 ['host_cache_id', 'service_cache_id', 'name', 'desc', 'website', 'path', 'pname',
194 'method'])
190195 return cache_id
191196
192197 @classmethod
193198 def get_host_vuln_cache_id(cls, host_id, vuln):
194199 vuln_copy = vuln.copy()
195200 vuln_copy.update({"host_cache_id": host_id})
196 cache_id = cls._get_dict_hash(vuln_copy, ['host_cache_id', 'name', 'desc', 'website', 'path', 'pname', 'method'])
201 cache_id = cls._get_dict_hash(vuln_copy,
202 ['host_cache_id', 'name', 'desc', 'website', 'path', 'pname', 'method'])
197203 return cache_id
198204
199205 def save_cache(self, obj):
227233 for param, (param_type, value) in self._settings.items():
228234 yield param, value
229235
230 def get_ws(self): # TODO Borrar
236 def get_ws(self): # TODO Borrar
231237 return ""
232238
233239 def getSetting(self, name):
248254 This method can be overriden in the plugin implementation
249255 if a different kind of check is needed
250256 """
251 return (self._command_regex is not None and
252 self._command_regex.match(current_input.strip()) is not None)
257 if (self._command_regex is not None and
258 self._command_regex.match(current_input.strip()) is not None):
259 self.command = self.get_command(current_input)
260 return True
261
262 def get_command(self, current_input: str) -> str:
263 command = self._command_regex.findall(current_input)[0]
264 if isinstance(command, tuple):
265 return "".join(command).strip()
266
267 return command.strip()
253268
254269 def processCommandString(self, username, current_path, command_string):
255270 """
333348 tags = []
334349 if isinstance(tags, str):
335350 tags = [tags]
336 host = {"ip": name, "os": os, "hostnames": hostnames, "description": description, "mac": mac,
351 host = {"ip": name, "os": os, "hostnames": hostnames, "description": description, "mac": mac,
337352 "credentials": [], "services": [], "vulnerabilities": [], "tags": tags}
338353 host_id = self.save_host_cache(host)
339354 return host_id
340355
341356 def createAndAddServiceToHost(self, host_id, name,
342 protocol="tcp", ports=None,
343 status="open", version="unknown",
344 description="", tags=None):
357 protocol="tcp", ports=None,
358 status="open", version="",
359 description="", tags=None):
345360 if ports:
346361 if isinstance(ports, list):
347362 ports = int(ports[0])
411426 tags = [tags]
412427 vulnerability = {"name": name, "desc": desc, "severity": self.normalize_severity(severity), "refs": ref,
413428 "external_id": external_id, "type": "Vulnerability", "resolution": resolution, "data": data,
414 "custom_fields": custom_fields, "status": status, "impact": impact, "policyviolations": policyviolations,
429 "custom_fields": custom_fields, "status": status, "impact": impact,
430 "policyviolations": policyviolations,
415431 "easeofresolution": easeofresolution, "confirmed": confirmed, "tags": tags
416432 }
417433 if run_date:
425441 response="", method="", pname="",
426442 params="", query="", category="", data="", external_id=None,
427443 confirmed=False, status="", easeofresolution=None, impact=None,
428 policyviolations=None, status_code=None, custom_fields=None, run_date=None, tags=None):
444 policyviolations=None, status_code=None, custom_fields=None, run_date=None,
445 tags=None):
429446 if params is None:
430447 params = ""
431448 if response is None:
475492 def createAndAddNoteToHost(self, host_id, name, text):
476493 return None
477494
478
479495 def createAndAddNoteToService(self, host_id, service_id, name, text):
480496 return None
481497
491507
492508 def get_data(self):
493509 self.vulns_data["command"]["tool"] = self.id
494 self.vulns_data["command"]["command"] = self.id
510 self.vulns_data["command"]["command"] = self.command if self.command else self.id
495511 self.vulns_data["command"]["duration"] = (datetime.now() - self.start_date).microseconds
496512 return self.vulns_data
497513
528544 summary['vuln_hashes'].append(dict_hash)
529545 return summary
530546
547
531548 # TODO Borrar
532549 class PluginTerminalOutput(PluginBase):
533550 def __init__(self):
666683 match = bool(self.files_list & files_in_zip)
667684 self.logger.debug("Files List Match: [%s =/in %s] -> %s", files_in_zip, self.files_list, match)
668685 return match
669
670
33 See the file 'doc/LICENSE' for the license information
44
55 """
6 import logging
67 import os
7 import logging
88 import socket
9 from collections import defaultdict
10
119 from urllib.parse import urlsplit
12
1310
1411 SERVICE_MAPPER = None
1512
2320 "website": "{}://{}".format(parse.scheme, parse.netloc),
2421 "path": parse.path,
2522 "query": parse.query
26 }
23 }
24
2725
2826 def filter_services():
2927 global SERVICE_MAPPER
110108 else:
111109 return ip_address
112110
111
113112 def get_severity_from_cvss(cvss):
114113 try:
115114 if type(cvss) != float:
116115 cvss = float(cvss)
117
118 cvss_ranges = [(0.0, 0.1, 'info'),
119 (0.1, 4.0, 'low'),
120 (4.0, 7.0, 'med'),
121 (7.0, 9.0, 'high'),
122 (9.0, 10.1, 'critical')]
116
117 cvss_ranges = [(0.0, 0.1, 'info'),
118 (0.1, 4.0, 'low'),
119 (4.0, 7.0, 'med'),
120 (7.0, 9.0, 'high'),
121 (9.0, 10.1, 'critical')]
123122 for (lower, upper, severity) in cvss_ranges:
124123 if lower <= cvss < upper:
125124 return severity
126125 except ValueError:
127126 return 'unclassified'
128
44
55 """
66 from urllib.parse import urlsplit
7 import re
8 import os
97
108 from lxml import etree
11
12 try:
13 import xml.etree.cElementTree as ET
14 import xml.etree.ElementTree as ET_ORIG
15 ETREE_VERSION = ET_ORIG.VERSION
16 except ImportError:
17 import xml.etree.ElementTree as ET
18 ETREE_VERSION = ET.VERSION
199
2010 from faraday_plugins.plugins.plugin import PluginXMLFormat
2111 from faraday_plugins.plugins.plugins_utils import resolve_hostname
22
23 ETREE_VERSION = [int(i) for i in ETREE_VERSION.split(".")]
24
2512
2613 __author__ = "Francisco Amato"
2714 __copyright__ = "Copyright (c) 2013, Infobyte LLC"
5239 else:
5340 self.sites = []
5441
55 def parse_xml(self, xml_output):
42 @staticmethod
43 def parse_xml(xml_output):
5644 """
5745 Open and parse an xml file.
5846
7058
7159 return tree
7260
73 def get_items(self, tree):
61 @staticmethod
62 def get_items(tree):
7463 """
7564 @return items A list of Host instances
7665 """
8574
8675 @return An attribute value
8776 """
88 global ETREE_VERSION
89 node = None
90
91 if ETREE_VERSION[0] <= 1 and ETREE_VERSION[1] < 3:
92
93 match_obj = re.search("([^\@]+?)\[\@([^=]*?)=\'([^\']*?)\'", subnode_xpath_expr)
94
95 if match_obj is not None:
96 node_to_find = match_obj.group(1)
97 xpath_attrib = match_obj.group(2)
98 xpath_value = match_obj.group(3)
99 for node_found in xml_node.findall(node_to_find):
100 if node_found.attrib[xpath_attrib] == xpath_value:
101 node = node_found
102 break
103 else:
104 node = xml_node.find(subnode_xpath_expr)
105
106 else:
107 node = xml_node.find(subnode_xpath_expr)
77
78 node = xml_node.find(subnode_xpath_expr)
10879
10980 if node is not None:
11081 return node.get(attrib_name)
286257 ref=item.ref)
287258 del parser
288259
289 def setHost(self):
290 pass
291
292260
293261 def createPlugin(ignore_info=False):
294 return AcunetixPlugin(ignore_info=ignore_info)
262 return AcunetixPlugin(ignore_info=ignore_info)
33 See the file 'doc/LICENSE' for the license information
44 """
55 import argparse
6 import random
6 import re
77 import shlex
8 import tempfile
8 import socket
99
1010 from faraday_plugins.plugins.plugin import PluginBase
11 import socket
12 import re
13 import os
14
15 from faraday_plugins.plugins.plugins_utils import resolve_hostname
16
1711
1812
1913 class AmapPlugin(PluginBase):
3024 self._command_regex = re.compile(r'^(amap|sudo amap)\s+.*?')
3125 self._use_temp_file = True
3226 self._hosts = []
27 self.args = None
3328
3429 def parseOutputString(self, output):
3530 services = {}
106101
107102 return ip6[0][4][0]
108103
109 def setHost(self):
110 pass
111
112104 def processCommandString(self, username, current_path, command_string):
113105 """
114106 Adds the -m parameter to get machine readable output.
135127 cmd.remove("-6")
136128 cmd.insert(1, "-6")
137129
138 args = None
139130 if len(cmd) > 4:
140131 try:
141 args, unknown = parser.parse_known_args(cmd)
132 self.args, unknown = parser.parse_known_args(cmd)
142133 except SystemExit:
143134 pass
144135
145 self.args = args
146136 return final
147137
148138
149139 def createPlugin(ignore_info=False):
150140 return AmapPlugin(ignore_info=ignore_info)
151
152
0 from urllib.parse import urlparse
1
02 from faraday_plugins.plugins.plugin import PluginXMLFormat
13 from faraday_plugins.plugins.plugins_utils import resolve_hostname
2 import dateutil.parser
3 from urllib.parse import urlparse
4 try:
5 import xml.etree.cElementTree as ET
6 except ImportError:
7 import xml.etree.ElementTree as ET
8
4
5 import xml.etree.ElementTree as ET
96
107 __author__ = "Nicolas Rebagliati"
118 __copyright__ = "Copyright (c) 2021, Infobyte LLC"
3229 self.entities = self.get_entity_groups(tree.find('entity-group'))
3330 self.issues = self.get_dast_issues(tree.find("issue-group"))
3431
35
36
37 def parse_xml(self, xml_output):
32 @staticmethod
33 def parse_xml(xml_output):
3834 try:
3935 tree = ET.fromstring(xml_output)
4036 except SyntaxError as err:
4238 return None
4339 return tree
4440
45 def get_fixes(self, tree):
41 @staticmethod
42 def get_fixes(tree):
4643 fixes = {}
4744 for item in tree:
4845 fix_id = item.attrib['id']
5148 fixes[fix_id] = {"library": library, "location": location}
5249 return fixes
5350
54 def get_issue_types(self, tree):
51 @staticmethod
52 def get_issue_types(tree):
5553 issue_types = {}
5654 for item in tree:
5755 type_id = item.attrib['id']
5957 issue_types[type_id] = name
6058 return issue_types
6159
62 def get_remediations(self, tree):
60 @staticmethod
61 def get_remediations(tree):
6362 remediations = {}
6463 for item in tree:
6564 remediation_id = item.attrib['id']
6766 remediations[remediation_id] = name
6867 return remediations
6968
70 def get_hosts(self, tree):
69 @staticmethod
70 def get_hosts(tree):
7171 hosts = {}
7272 for item in tree:
7373 host = item.find("host").text
8383 "service_name": service_name}
8484 return hosts
8585
86 def get_entity_groups(self, tree):
86 @staticmethod
87 def get_entity_groups(tree):
8788 entity_groups = {}
8889 for item in tree:
8990 entity_id = item.attrib['id']
237238 return sast_issues
238239
239240
240
241241 class AppScanPlugin(PluginXMLFormat):
242242
243243 def __init__(self, *arg, **kwargs):
249249 self.version = '1.0.0'
250250 self.framework_version = '1.0.0'
251251
252
253252 def parseOutputString(self, output):
254253 parser = AppScanParser(output)
255254 scan_type = parser.scan_type
256
257255
258256 if scan_type == 'DAST':
259257 for issue in parser.issues:
260258 host = issue.pop("host")
261259 port = issue.pop("port")
262 host_os = issue.pop("os")
263260 service_name = issue.pop("service_name")
264261 ip = resolve_hostname(host)
265 host_id = self.createAndAddHost(ip, hostnames=host)
262 host_os = issue.pop("os")
263 host_id = self.createAndAddHost(ip, hostnames=host, os=host_os)
266264 service_id = self.createAndAddServiceToHost(host_id, service_name, ports=port)
267265 self.createAndAddVulnWebToService(host_id=host_id, service_id=service_id, **issue)
268266
44 Copyright (C) 2016 Infobyte LLC (http://www.infobytesec.com/)
55 See the file 'doc/LICENSE' for the license information
66 """
7 import xml.etree.ElementTree as ET
8 from datetime import datetime
9
710 from faraday_plugins.plugins.plugin import PluginXMLFormat
8 from datetime import datetime
9 try:
10 import xml.etree.cElementTree as ET
11 except ImportError:
12 import xml.etree.ElementTree as ET
1311
1412 __author__ = 'Blas Moyano'
1513 __copyright__ = 'Copyright 2020, Faraday Project'
2422 self.tree = self.parse_xml(xml_output)
2523 if self.tree:
2624 self.vuln_list = self.tree.find('VulnList')
27 self.name_scan = self.tree.find('ScanName').text
25 self.name_scan = self.tree.findtext('ScanName')
2826 else:
2927 self.tree = None
3028
31 def parse_xml(self, xml_output):
29 @staticmethod
30 def parse_xml(xml_output):
3231 try:
3332 tree = ET.fromstring(xml_output)
3433 except SyntaxError as err:
7170 data_info = []
7271
7372 for vulns in parser.vuln_list:
74 vuln_name = vulns.find('VulnType').text
75 vuln_desc = vulns.find('Description').text
76 vuln_ref = vulns.find('VulnUrl').text
77 severity = vulns.find('AttackScore').text
78 vuln_resolution = vulns.find('Recommendation').text
79 vuln_external_id = vulns.find('DbId').text
80 vuln_run_date = vulns.find('ScanDate').text
81 data_info.append(vulns.find('AttackClass').text)
82 data_info.append(vulns.find('CweId').text)
83 data_info.append(vulns.find('CAPEC').text)
84 data_info.append(vulns.find('DISSA_ASC').text)
85 data_info.append(vulns.find('OWASP2007').text)
86 data_info.append(vulns.find('OWASP2010').text)
87 data_info.append(vulns.find('OWASP2013').text)
88 data_info.append(vulns.find('OVAL').text)
89 data_info.append(vulns.find('WASC').text)
73 vuln_name = vulns.findtext('VulnType')
74 vuln_desc = vulns.findtext('Description')
75 vuln_ref = vulns.findtext('VulnUrl')
76 severity = vulns.findtext('AttackScore')
77 vuln_resolution = vulns.findtext('Recommendation')
78 vuln_external_id = vulns.findtext('DbId')
79 vuln_run_date = vulns.findtext('ScanDate')
80 data_info.append(vulns.findtext('AttackClass'))
81 data_info.append(vulns.findtext('CweId'))
82 data_info.append(vulns.findtext('CAPEC'))
83 data_info.append(vulns.findtext('DISSA_ASC'))
84 data_info.append(vulns.findtext('OWASP2007'))
85 data_info.append(vulns.findtext('OWASP2010'))
86 data_info.append(vulns.findtext('OWASP2013'))
87 data_info.append(vulns.findtext('OVAL'))
88 data_info.append(vulns.findtext('WASC'))
9089
9190 if severity == '1-Informational':
9291 severity = 0
22 Copyright (C) 2016 Infobyte LLC (http://www.infobytesec.com/)
33 See the file 'doc/LICENSE' for the license information
44 """
5 import os
56 import re
7 import xml.etree.ElementTree as ET
68 from urllib.parse import urlparse
7 import os
9
810 from faraday_plugins.plugins.plugin import PluginXMLFormat
911 from faraday_plugins.plugins.plugins_utils import resolve_hostname
10
11 try:
12 import xml.etree.cElementTree as ET
13 except ImportError:
14 import xml.etree.ElementTree as ET
1512
1613 __author__ = 'Ezequiel Tavella'
1714 __copyright__ = 'Copyright 2016, Faraday Project'
199196 else:
200197 options_string = None
201198
202
203199 try:
204200 self.user_agent = self.node.find('user_agent').text
205201 except:
230226
231227 def getNote(self):
232228 result = ('Scan url:\n {} \nUser Agent:\n {} \nVersion Arachni:\n {} \nStart time:\n {} \nFinish time:\n {}'
233 '\nAudited Elements:\n {} \nModules:\n {} \nCookies:\n {}').format(self.url, self.user_agent,
234 self.version, self.start_time,
235 self.finish_time,
236 self.audited_elements,
237 self.modules, self.cookies)
229 '\nAudited Elements:\n {} \nModules:\n {} \nCookies:\n {}').format(self.url, self.user_agent,
230 self.version, self.start_time,
231 self.finish_time,
232 self.audited_elements,
233 self.modules, self.cookies)
238234
239235 return result
240236
241237
242238 class Plugins():
243
244239 """
245240 Support:
246241 WAF (Web Application Firewall) Detector (waf_detector)
492487
493488 def createPlugin(ignore_info=False):
494489 return ArachniPlugin(ignore_info=ignore_info)
495
496
9494 severity=3)
9595
9696
97 def setHost(self):
98 pass
99
10097
10198 def createPlugin(ignore_info=False):
10299 return BeefPlugin(ignore_info=ignore_info)
faraday_plugins/plugins/repo/burp/burp-2.0-SNAPSHOT.jar less more
Binary diff not shown
33 See the file 'doc/LICENSE' for the license information
44
55 """
6 import re
7 import os
86 import base64
7 import distutils.util # pylint: disable=import-error
8 import xml.etree.ElementTree as ET
9 from urllib.parse import urlsplit
10
911 from bs4 import BeautifulSoup, Comment
12
1013 from faraday_plugins.plugins.plugin import PluginXMLFormat
11 from urllib.parse import urlsplit
12 import distutils.util #pylint: disable=import-error
13
14
15 try:
16 import xml.etree.cElementTree as ET
17 import xml.etree.ElementTree as ET_ORIG
18 ETREE_VERSION = ET_ORIG.VERSION
19 except ImportError:
20 import xml.etree.ElementTree as ET
21 ETREE_VERSION = ET.VERSION
22
23 ETREE_VERSION = [int(i) for i in ETREE_VERSION.split(".")]
24
2514
2615 __author__ = "Francisco Amato"
2716 __copyright__ = "Copyright (c) 2013, Infobyte LLC"
7766 """
7867 @return items A list of Host instances
7968 """
80 bugtype = ''
8169
8270 for node in tree.findall('issue'):
8371 yield Item(node)
8977
9078 @return An attribute value
9179 """
92 global ETREE_VERSION
93 node = None
94
95 if ETREE_VERSION[0] <= 1 and ETREE_VERSION[1] < 3:
96
97 match_obj = re.search(
98 "([^\@]+?)\[\@([^=]*?)=\'([^\']*?)\'", subnode_xpath_expr)
99 if match_obj is not None:
100
101 node_to_find = match_obj.group(1)
102 xpath_attrib = match_obj.group(2)
103 xpath_value = match_obj.group(3)
104 for node_found in xml_node.findall(node_to_find):
105 if node_found.attrib[xpath_attrib] == xpath_value:
106 node = node_found
107 break
108 else:
109 node = xml_node.find(subnode_xpath_expr)
110
111 else:
112 node = xml_node.find(subnode_xpath_expr)
80 node = xml_node.find(subnode_xpath_expr)
11381
11482 if node is not None:
11583 return node.get(attrib_name)
164132 self.background = background
165133 self.external_id = external_id.text
166134
167
168 def do_clean(self, value):
135 @staticmethod
136 def do_clean(value):
169137
170138 myreturn = ""
171139 if value is not None:
221189 self._current_output = None
222190 self.target = None
223191
224
225192 def parseOutputString(self, output):
226193
227194 parser = BurpXmlParser(output)
247214 data = self.removeHtml(data)
248215 resolution = self.removeHtml(item.remediation) if item.remediation else ""
249216
250 v_id = self.createAndAddVulnWebToService(
217 self.createAndAddVulnWebToService(
251218 h_id,
252219 s_id,
253220 item.name,
263230
264231 del parser
265232
266
267233 def removeHtml(self, markup):
268234 soup = BeautifulSoup(markup, "html.parser")
269235
291257
292258 return str(soup)
293259
294 def setHost(self):
295 pass
296
297260
298261 def createPlugin(ignore_info=False):
299262 return BurpPlugin(ignore_info=ignore_info)
300
301
22 Copyright (C) 2016 Infobyte LLC (http://www.infobytesec.com/)
33 See the file 'doc/LICENSE' for the license information
44 """
5 import re
5 import xml.etree.ElementTree as ET
66 from urllib.parse import urlparse
77
88 from faraday_plugins.plugins.plugin import PluginXMLFormat
9
10
11 try:
12 import xml.etree.cElementTree as ET
13 except ImportError:
14 import xml.etree.ElementTree as ET
159
1610 __author__ = 'Blas Moyano'
1711 __copyright__ = 'Copyright 2020, Faraday Project'
6963 for info_pn in pn:
7064 if info_pn.tag == 'Snippet':
7165 valor = (
72 'Number', info_pn.find('Line').find('Number').text, 'Code', info_pn.find('Line').find('Code').text)
66 'Number', info_pn.find('Line').find('Number').text, 'Code',
67 info_pn.find('Line').find('Code').text)
7368 else:
7469 valor = (info_pn.tag, info_pn.text)
7570 lista_v.append(valor)
8883 self.version = '1.0.0'
8984 self.framework_version = '1.0.0'
9085 self.options = None
91
9286
9387 def parseOutputString(self, output):
9488 parser = CheckmarxXmlParser(output)
139133
140134 def createPlugin(ignore_info=False):
141135 return CheckmarxPlugin(ignore_info=ignore_info)
142
2525 self.plugin_version = "0.0.1"
2626 self.version = "2.22"
2727 self.regexpUrl = r'((http[s]?)\:\/\/([\w\.]+)[.\S]+)'
28 self._command_regex = re.compile(r'^(?:sudo dirb|dirb|\.\/dirb|sudo \.\/dirb)\s+(?:(http[s]?)'
29 r'\:\/\/([\w\.]+)[.\S]+)')
28 self._command_regex = re.compile(r'^(sudo dirb|dirb|\.\/dirb|sudo \.\/dirb)\s+.*?')
29
3030 self.text = []
3131
3232 def getPort(self, host, proto):
5858 self.name = "dirsearch"
5959 self.plugin_version = "0.0.1"
6060 self.version = "0.0.1"
61 self._command_regex = re.compile(r'^(sudo )?(python[0-9\.]? )?dirsearch(\.py)\s+?')
61 self._command_regex = re.compile(r'^(sudo )?(python[0-9\.]? )?(dirsearch\.py)\s+?')
6262 self.addSetting("Ignore 403", str, "1")
6363 self._use_temp_file = True
6464 self._temp_file_extension = "json"
6565
6666 def parseOutputString(self, output):
6767 self.parse_json(output)
68
6968
7069 @property
7170 def should_ignore_403(self):
33 See the file 'doc/LICENSE' for the license information
44
55 """
6 import re
7 import xml.etree.ElementTree as ET
8
69 from faraday_plugins.plugins.plugin import PluginBase
7 import re
8 import os
9
10 try:
11 import xml.etree.cElementTree as ET
12 import xml.etree.ElementTree as ET_ORIG
13 ETREE_VERSION = ET_ORIG.VERSION
14 except ImportError:
15 import xml.etree.ElementTree as ET
16 ETREE_VERSION = ET.VERSION
17
18 ETREE_VERSION = [int(i) for i in ETREE_VERSION.split(".")]
19
2010
2111 __author__ = "Francisco Amato"
2212 __copyright__ = "Copyright (c) 2013, Infobyte LLC"
6858 """
6959 @return items A list of Host instances
7060 """
71 bugtype = ''
7261
7362 node = tree.findall('testdata')[0]
7463 for hostnode in node.findall('host'):
8170
8271 @return An attribute value
8372 """
84 global ETREE_VERSION
85 node = None
8673
87 if ETREE_VERSION[0] <= 1 and ETREE_VERSION[1] < 3:
88
89 match_obj = re.search(
90 "([^\@]+?)\[\@([^=]*?)=\'([^\']*?)\'", subnode_xpath_expr)
91 if match_obj is not None:
92 node_to_find = match_obj.group(1)
93 xpath_attrib = match_obj.group(2)
94 xpath_value = match_obj.group(3)
95 for node_found in xml_node.findall(node_to_find):
96 if node_found.attrib[xpath_attrib] == xpath_value:
97 node = node_found
98 break
99 else:
100 node = xml_node.find(subnode_xpath_expr)
101
102 else:
103 node = xml_node.find(subnode_xpath_expr)
74 node = xml_node.find(subnode_xpath_expr)
10475
10576 if node is not None:
10677 return node.get(attrib_name)
175146 parser = DnsenumXmlParser(output)
176147
177148 for item in parser.items:
178 h_id = self.createAndAddHost(item.ip, hostnames=[item.hostname])
149 self.createAndAddHost(item.ip, hostnames=[item.hostname])
179150
180151 del parser
181152
192163 else:
193164 return re.sub(arg_match.group(1), r"-o %s" % self._output_file_path, command_string)
194165
195 def setHost(self):
196 pass
197
198166
199167 def createPlugin(ignore_info=False):
200168 return DnsenumPlugin(ignore_info=ignore_info)
201
202
22 Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
33 See the file 'doc/LICENSE' for the license information
44 """
5 from faraday_plugins.plugins.plugin import PluginBase
65 import re
76 from collections import defaultdict
87
8 from faraday_plugins.plugins.plugin import PluginBase
99
1010 __author__ = "Francisco Amato"
1111 __copyright__ = "Copyright (c) 2013, Infobyte LLC"
103103 self._use_temp_file = True
104104 self._temp_file_extension = "txt"
105105
106
107106 def canParseCommandString(self, current_input):
108107 if self._command_regex.match(current_input.strip()):
108 self.command = self.get_command(current_input)
109109 return True
110110 else:
111111 return False
138138
139139 def createPlugin(ignore_info=False):
140140 return DnsmapPlugin(ignore_info=ignore_info)
141
142
22 Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
33 See the file 'doc/LICENSE' for the license information
44 """
5 import re
6 import xml.etree.ElementTree as ET
7
58 from faraday_plugins.plugins.plugin import PluginBase
6 import re
7
8 try:
9 import xml.etree.cElementTree as ET
10 import xml.etree.ElementTree as ET_ORIG
11 ETREE_VERSION = ET_ORIG.VERSION
12 except ImportError:
13 import xml.etree.ElementTree as ET
14 ETREE_VERSION = ET.VERSION
15
16 ETREE_VERSION = [int(i) for i in ETREE_VERSION.split(".")]
17
189
1910 __author__ = "Francisco Amato"
2011 __copyright__ = "Copyright (c) 2013, Infobyte LLC"
7768
7869 @return An attribute value
7970 """
80 global ETREE_VERSION
81 node = None
82
83 if ETREE_VERSION[0] <= 1 and ETREE_VERSION[1] < 3:
84
85 match_obj = re.search(
86 "([^\@]+?)\[\@([^=]*?)=\'([^\']*?)\'", subnode_xpath_expr)
87 if match_obj is not None:
88
89 node_to_find = match_obj.group(1)
90 xpath_attrib = match_obj.group(2)
91 xpath_value = match_obj.group(3)
92 for node_found in xml_node.findall(node_to_find):
93 if node_found.attrib[xpath_attrib] == xpath_value:
94 node = node_found
95 break
96 else:
97 node = xml_node.find(subnode_xpath_expr)
98
99 else:
100 node = xml_node.find(subnode_xpath_expr)
71
72 node = xml_node.find(subnode_xpath_expr)
10173
10274 if node is not None:
10375 return node.get(attrib_name)
204176 status="open")
205177
206178 if host.zonetransfer == "success":
207 v_id = self.createAndAddVulnToService(
179 self.createAndAddVulnToService(
208180 h_id,
209181 s_id,
210182 name="Zone transfer",
238210 r"--xml %s" % self._output_file_path,
239211 command_string)
240212
241 def setHost(self):
242 pass
243
244213
245214 def createPlugin(ignore_info=False):
246215 return DnsreconPlugin(ignore_info=ignore_info)
247
248
44
55 """
66 import re
7 import os
87
98 from faraday_plugins.plugins.plugin import PluginBase
109 from faraday_plugins.plugins.plugins_utils import resolve_hostname
11
1210
1311 __author__ = "Francisco Amato"
1412 __copyright__ = "Copyright (c) 2013, Infobyte LLC"
4139 for line in lists:
4240 mregex = re.search("WARN: ([\w\.]+) ([\w]+) ([\w\.]+):", line)
4341 if mregex is not None:
44
4542 item = {
4643 'host': mregex.group(1),
4744 'ip': mregex.group(3),
6259 self.items.append(item)
6360
6461
65
6662 class DnswalkPlugin(PluginBase):
6763 """
6864 Example plugin to parse dnswalk output.
7975 self._command_regex = re.compile(
8076 r'^(sudo dnswalk|dnswalk|\.\/dnswalk)\s+.*?')
8177
82
8378 def canParseCommandString(self, current_input):
8479 if self._command_regex.match(current_input.strip()):
80 self.command = self.get_command(current_input)
8581 return True
8682 else:
8783 return False
114110
115111 def createPlugin(ignore_info=False):
116112 return DnswalkPlugin(ignore_info=ignore_info)
117
118
126126 else:
127127 return False
128128
129 def setHost(self):
130 pass
129
131130
132131
133132 def createPlugin(ignore_info=False):
33 See the file 'doc/LICENSE' for the license information
44
55 """
6 import re
6
7 import xml.etree.ElementTree as ET
78
89 from faraday_plugins.plugins.plugin import PluginXMLFormat
9 try:
10 import xml.etree.cElementTree as ET
11 import xml.etree.ElementTree as ET_ORIG
12 ETREE_VERSION = ET_ORIG.VERSION
13 except ImportError:
14 import xml.etree.ElementTree as ET
15 ETREE_VERSION = ET.VERSION
16
17 ETREE_VERSION = [int(i) for i in ETREE_VERSION.split(".")]
18
1910
2011 __author__ = "Francisco Amato"
2112 __copyright__ = "Copyright (c) 2013, Infobyte LLC"
4132 def __init__(self, xml_output):
4233 tree = self.parse_xml(xml_output)
4334 if tree:
44 self.items = [data for data in self.get_items(tree)]
35 self.items = self.get_items(tree)
4536 else:
4637 self.items = []
4738
10394 agentip = node.get('name').split("/")[1]
10495
10596 if self.ip == agentip:
106
10797 self.agentip = agentip
10898
10999 self.ipfrom = self.get_text_from_subnode(
227217 mapped_services = {}
228218 mapped_ports = {}
229219 for item in parser.items:
230 os_string = f"{item.os} {item.arch }"
220 os_string = f"{item.os} {item.arch}"
231221 h_id = self.createAndAddHost(item.ip, os=os_string, hostnames=[item.host])
232222
233223 for service in item.services:
281271 del parser
282272
283273
284 def setHost(self):
285 pass
286
287
288274 def createPlugin(ignore_info=False):
289275 return ImpactPlugin(ignore_info=ignore_info)
290
291
44
55 """
66 import os
7
78 from lxml import etree
9
810 from faraday_plugins.plugins.plugin import PluginXMLFormat
9
10
11 try:
12 import xml.etree.cElementTree as ET
13 import xml.etree.ElementTree as ET_ORIG
14 ETREE_VERSION = ET_ORIG.VERSION
15 except ImportError:
16 import xml.etree.ElementTree as ET
17 ETREE_VERSION = ET.VERSION
18
19 ETREE_VERSION = [int(i) for i in ETREE_VERSION.split(".")]
2011
2112 current_path = os.path.abspath(os.getcwd())
2213
6657 self.items = [data for data in self.get_items(tree)]
6758 else:
6859 self.items = []
69
60
7061 def parse_xml(self, xml_output):
7162 """
7263 Open and parse an xml file.
132123 self._current_output = None
133124
134125 def parseOutputString(self, output):
135
136126 parser = JunitXmlParser(output)
137127 for item in parser.items:
138128 h_id = self.createAndAddHost(item.host, os="Linux")
22 Copyright (C) 2015 Infobyte LLC (http://www.infobytesec.com/)
33 See the file 'doc/LICENSE' for the license information
44 """
5 import xml.etree.ElementTree as ET
6 import zipfile
7
58 from faraday_plugins.plugins.plugin import PluginZipFormat
6 import re
7 import os
8 import zipfile
9
109 from faraday_plugins.plugins.plugins_utils import resolve_hostname
11
12 try:
13 import xml.etree.cElementTree as ET
14 import xml.etree.ElementTree as ET_ORIG
15 ETREE_VERSION = ET_ORIG.VERSION
16 except ImportError:
17 import xml.etree.ElementTree as ET
18 ETREE_VERSION = ET.VERSION
19
20 ETREE_VERSION = [int(i) for i in ETREE_VERSION.split(".")]
21
2210
2311 __author__ = "Ezequiel Tavella"
2412 __copyright__ = "Copyright (c) 2015, Infobyte LLC"
169157 entity = node.find(
170158 "{http://graphml.graphdrawing.org/xmlns}data/"
171159 "{http://maltego.paterva.com/xml/mtgx}MaltegoEntity")
172
173160
174161 # Check if is IPv4Address
175162 if entity.get("type") not in ("maltego.IPv4Address", "maltego.Domain", "maltego.Website"):
418405 try:
419406 text = f'Location:\n {host.location["name"]} \nArea:\n {host.location["area"]} ' \
420407 f'\nArea 2:\n {host.location["area_2"]} ' \
421 f'\nCountry_code:\n { host.location["country_code"]} ' \
408 f'\nCountry_code:\n {host.location["country_code"]} ' \
422409 f'\nLatitude:\n {host.location["latitude"]} \nLongitude:\n {host.location["longitude"]}'
423410 except TypeError:
424411 text = "unknown"
466453 host_ip = '0.0.0.0'
467454 host_id = self.createAndAddHost(name=host_ip, hostnames=hostnames)
468455
469
470456 if maltego_parser.xml.get('location'):
471457 location_name = maltego_parser.getInfoMtgl(maltego_parser.xml['location'], 'location.name')
472458 location_area = maltego_parser.getInfoMtgl(maltego_parser.xml['location'], 'location.area')
509495 description="DNS Server")
510496
511497
512
513
514498 def createPlugin(ignore_info=False):
515499 return MaltegoPlugin(ignore_info=ignore_info)
129129 else:
130130 return False
131131
132 def setHost(self):
133 pass
132
134133
135134
136135 def createPlugin(ignore_info=False):
22 Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
33 See the file 'doc/LICENSE' for the license information
44 """
5 import xml.etree.ElementTree as ET
6
57 from faraday_plugins.plugins.plugin import PluginXMLFormat
6 import re
7
8
9 try:
10 import xml.etree.cElementTree as ET
11 import xml.etree.ElementTree as ET_ORIG
12 ETREE_VERSION = ET_ORIG.VERSION
13 except ImportError:
14 import xml.etree.ElementTree as ET
15 ETREE_VERSION = ET.VERSION
16
17 ETREE_VERSION = [int(i) for i in ETREE_VERSION.split(".")]
188
199 __author__ = "Francisco Amato"
2010 __copyright__ = "Copyright (c) 2013, Infobyte LLC"
7666 """
7767 @return items A list of Host instances
7868 """
79 bugtype = ""
8069
8170 for node in tree.findall('hosts/host'):
8271 yield Host(node, webVulns)
8574 """
8675 @return items A list of WebVuln instances
8776 """
88 bugtype = ""
8977 for node in tree.findall('web_vulns/web_vuln'):
9078 yield WebVuln(node, services)
9179
9684
9785 @return An attribute value
9886 """
99 global ETREE_VERSION
100 node = None
101
102 if ETREE_VERSION[0] <= 1 and ETREE_VERSION[1] < 3:
103
104 match_obj = re.search(
105 "([^\@]+?)\[\@([^=]*?)=\'([^\']*?)\'", subnode_xpath_expr)
106 if match_obj is not None:
107 node_to_find = match_obj.group(1)
108 xpath_attrib = match_obj.group(2)
109 xpath_value = match_obj.group(3)
110 for node_found in xml_node.findall(node_to_find):
111 if node_found.attrib[xpath_attrib] == xpath_value:
112 node = node_found
113 break
114 else:
115 node = xml_node.find(subnode_xpath_expr)
116
117 else:
118 node = xml_node.find(subnode_xpath_expr)
87
88 node = xml_node.find(subnode_xpath_expr)
11989
12090 if node is not None:
12191 return node.get(attrib_name)
210180 self.query = self.get_text_from_subnode('query')
211181 self.request = self.get_text_from_subnode('request')
212182 self.category = self.get_text_from_subnode('category-id')
213 self.service_id = services[self.get_text_from_subnode('web-site-id')]
183 web_id = self.get_text_from_subnode('web-site-id')
184 self.service_id = None
185 if web_id:
186 self.service_id = services[web_id]
187
214188 self.isWeb = True
215189
216190 def get_text_from_subnode(self, subnode_xpath_expr):
219193
220194 @return An attribute value
221195 """
196
222197 sub_node = self.node.find(subnode_xpath_expr)
223198 if sub_node is not None:
224199 if sub_node.text is not None:
335310 self.options = None
336311 self.target = None
337312
338
339313 def parseOutputString(self, output):
340314 """
341315 This method will discard the output the shell sends, it will read it from
348322 self.hostnames = []
349323 if item.host:
350324 self.hostnames = [item.host]
351
325
352326 h_id = self.createAndAddHost(item.ip, os=item.os, hostnames=self.hostnames)
353327
354328 if item.id + "_" in item.notesByService:
356330 self.createAndAddNoteToHost(h_id, n.ntype, n.data)
357331
358332 for v in item.vulnsByHost:
359 v_id = self.createAndAddVulnToHost(
333 self.createAndAddVulnToHost(
360334 h_id, v.name, v.desc, ref=v.refs)
361335
362336 for s in item.services:
363337 s_id = self.createAndAddServiceToHost(h_id, s['name'],
364 protocol=s['proto'],
365 ports=[s['port']],
366 status=s['state'],
367 description=s['info'])
338 protocol=s['proto'],
339 ports=[s['port']],
340 status=s['state'],
341 description=s['info'])
368342
369343 if item.id + "_" + s['id'] in item.notesByService:
370344 for n in item.notesByService[item.id + "_" + s['id']]:
375349 for c in item.credsByService[s['port']]:
376350 self.createAndAddCredToService(
377351 h_id, s_id, c.user, c.passwd)
378 self.createAndAddVulnToService(h_id, s_id, "Weak Credentials", "[metasploit found the following credentials]\nuser:%s\npass:%s" % (
379 c.user, c.passwd), severity="high")
352 self.createAndAddVulnToService(h_id, s_id, "Weak Credentials",
353 "[metasploit found the following credentials]\nuser:%s\npass:%s" % (
354 c.user, c.passwd), severity="high")
380355
381356 for v in item.vulnsByService[s['id']]:
382357 if v.isWeb:
383 v_id = self.createAndAddVulnWebToService(h_id, s_id, v.name, v.desc,
358 self.createAndAddVulnWebToService(h_id, s_id, v.name, v.desc,
384359 severity=v.risk, website=v.host,
385360 path=v.path, request=v.request, method=v.method,
386361 pname=v.pname, params=v.params, query=v.query,
387362 category=v.category)
388363 else:
389 v_id = self.createAndAddVulnToService(
364 self.createAndAddVulnToService(
390365 h_id, s_id, v.name, v.desc, ref=v.refs)
391366
392367 del parser
393368
394 def _isIPV4(self, ip):
369 @staticmethod
370 def _isIPV4(ip):
395371 if len(ip.split(".")) == 4:
396372 return True
397373 else:
398374 return False
399375
400376
401 def setHost(self):
402 pass
403
404
405377 def createPlugin(ignore_info=False):
406378 return MetasploitPlugin(ignore_info=ignore_info)
407
408
0 """
1 Faraday Plugins
2 Copyright (c) 2021 Faraday Security LLC (https://www.faradaysec.com/)
3 See the file 'doc/LICENSE' for the license information
4
5 """
6 import socket
7 import json
8 import re
9 from faraday_plugins.plugins.plugin import PluginMultiLineJsonFormat
10
11 __author__ = 'Emilio Couto'
12 __copyright__ = 'Copyright (c) 2021, Faraday Security LLC'
13 __credits__ = ['Emilio Couto']
14 __license__ = ''
15 __version__ = '0.0.1'
16 __maintainer__ = 'Emilio Couto'
17 __email__ = '[email protected]'
18 __status__ = 'Development'
19
20
21 class NaabuPlugin(PluginMultiLineJsonFormat):
22 """
23 Parse Naabu (from Project Discovery) scanner JSON output
24 """
25
26 def __init__(self, *arg, **kwargs):
27 super().__init__(*arg, **kwargs)
28 self.id = 'naabu'
29 self.name = 'Naabu'
30 self.plugin_version = '0.1'
31 self.version = '2.0.3'
32 self.json_keys = {'host', 'ip', 'port'}
33 self._command_regex = re.compile(r'^(sudo naabu|naabu|\.\/nmap)\s+.*?')
34
35 def parseOutputString(self, output, debug=False):
36 for host_json in filter(lambda x: x != '', output.split('\n')):
37 host_dict = json.loads(host_json)
38 host = host_dict.get('host')
39 ip = host_dict.get('ip')
40 port = host_dict.get('port')
41 try:
42 service = socket.getservbyport(port)
43 except socket.error:
44 service = 'Unknown service on port ' + str(port)
45 host_id = self.createAndAddHost(
46 name=ip,
47 hostnames=[host])
48 self.createAndAddServiceToHost(
49 host_id,
50 name=service,
51 ports=port,
52 protocol='tcp',
53 status='open',
54 version='',
55 description='')
56
57 def processCommandString(self, username, current_path, command_string):
58 """
59 Adds the -oX parameter to get xml output to the command string that the
60 user has set.
61 """
62 super().processCommandString(username, current_path, command_string)
63 if " -json" not in command_string:
64 command_string += " -json"
65 if " -silent" not in command_string:
66 command_string += " -silent"
67 return command_string
68
69 def createPlugin(ignore_info=False):
70 return NaabuPlugin(ignore_info=ignore_info)
44
55 """
66
7 import xml.etree.ElementTree as ET
8
79 from faraday_plugins.plugins.plugin import PluginXMLFormat
8 try:
9 import xml.etree.cElementTree as ET
10 except ImportError:
11 import xml.etree.ElementTree as ET
12
1310
1411 __author__ = "Blas Moyano"
1512 __copyright__ = "Copyright (c) 2020, Infobyte LLC"
66 from faraday_plugins.plugins.plugin import PluginBase
77 import re
88
9 try:
10 import xml.etree.cElementTree as ET
11 import xml.etree.ElementTree as ET_ORIG
12 except ImportError:
13 import xml.etree.ElementTree as ET
9 import xml.etree.ElementTree as ET
1410
1511 __author__ = 'Ezequiel Tavella'
1612 __copyright__ = 'Copyright (c) 2016, Infobyte LLC'
0 from typing import List
1
2
3 class Attachment:
4 def __init__(self, node):
5 self.node = node
6
7 @property
8 def name_attr(self):
9 return self.node.get("name")
10
11 @property
12 def type_attr(self):
13 return self.node.get("type")
14
15 @property
16 def text(self):
17 return self.node.text
18
19
20 class ReportItem:
21 def __init__(self, node):
22 self.node = node
23
24 @property
25 def port_attr(self):
26 return self.node.get("port")
27
28 @property
29 def svc_name_attr(self):
30 return self.node.get("svc_name")
31
32 @property
33 def protocol_attr(self):
34 return self.node.get("protocol")
35
36 @property
37 def severity_attr(self):
38 return self.node.get("severity")
39
40 @property
41 def plugin_id_attr(self):
42 plugin_id = self.node.get("pluginID")
43 if plugin_id:
44 plugin_id = f'NESSUS-{plugin_id}'
45 return plugin_id
46
47 @property
48 def plugin_name_attr(self):
49 return self.node.get("pluginName")
50
51 @property
52 def plugin_family_attr(self):
53 return self.node.get("pluginFamily")
54
55 @property
56 def agent(self):
57 return self.node.findtext("agent")
58
59 @property
60 def description(self):
61 return self.node.findtext("description", "Not Description")
62
63 @property
64 def fname(self):
65 return self.node.findtext("fname")
66
67 @property
68 def plugin_modification_date(self):
69 return self.node.findtext("plugin_modification_date")
70
71 @property
72 def plugin_name(self):
73
74 plugin_name = self.node.findtext("plugin_name")
75 if not plugin_name:
76 plugin_name = self.plugin_name_attr
77 return plugin_name
78
79 @property
80 def plugin_publication_date(self):
81 return self.node.findtext("plugin_publication_date")
82
83 @property
84 def plugin_type(self):
85 return self.node.findtext("plugin_type")
86
87 @property
88 def risk_factor(self):
89 risk_factor = self.node.findtext("risk_factor")
90 if risk_factor == 'None' or risk_factor is None:
91 risk_factor = self.severity_attr # I checked several external id and most of them were info
92 return risk_factor
93
94 @property
95 def script_version(self):
96 return self.node.findtext("script_version")
97
98 @property
99 def see_also(self):
100 return self.node.findtext("see_also")
101
102 @property
103 def solution(self):
104 return self.node.findtext("solution", '')
105
106 @property
107 def synopsis(self):
108 return self.node.findtext("synopsis")
109
110 @property
111 def plugin_output(self):
112 return self.node.findtext("plugin_output", "")
113
114 @property
115 def always_run(self):
116 return self.node.findtext("always_run")
117
118 @property
119 def asset_inventory(self):
120 return self.node.findtext("asset_inventory")
121
122 @property
123 def canvas_package(self):
124 return self.node.findtext("canvas_package")
125
126 @property
127 def cvss3_base_score(self):
128 cvss_base_score = self.node.findtext("cvss3_base_score")
129 if cvss_base_score:
130 cvss_base_score = f"CVSS3:{cvss_base_score}"
131 return cvss_base_score
132
133 @property
134 def cvss3_temporal_score(self):
135 return self.node.findtext("cvss3_temporal_score")
136
137 @property
138 def cpe(self):
139 return self.node.findtext("cpe")
140
141 @property
142 def cvss3_temporal_vector(self):
143 return self.node.findtext("cvss3_temporal_vector")
144
145 @property
146 def cvss3_vector(self):
147 return self.node.findtext("cvss3_vector")
148
149 @property
150 def cvss_base_score(self):
151 cvss_base_score = self.node.findtext("cvss_base_score")
152 if cvss_base_score:
153 cvss_base_score = f"CVSS:{cvss_base_score}"
154 return cvss_base_score
155
156 @property
157 def cvss_score_rationale(self):
158 return self.node.findtext("cvss_score_rationale")
159
160 @property
161 def cvss_score_source(self):
162 return self.node.findtext("cvss_score_source")
163
164 @property
165 def cvss_temporal_score(self):
166 return self.node.findtext("cvss_temporal_score")
167
168 @property
169 def cvss_temporal_vector(self):
170 return self.node.findtext("cvss_temporal_vector")
171
172 @property
173 def cvss_vector(self):
174 cvss_vector = self.node.findtext("cvss_vector")
175 if cvss_vector:
176 cvss_vector = f"CVSSVECTOR:{cvss_vector}"
177 return cvss_vector
178
179 @property
180 def exploit_available(self):
181 exploit_avalible = self.node.findtext("exploit_available", "")
182 if exploit_avalible:
183 exploit_avalible = f"Exploit available: {exploit_avalible.capitalize()}\n"
184 return exploit_avalible
185
186 @property
187 def exploit_framework_canvas(self):
188 return self.node.findtext("exploit_framework_canvas")
189
190 @property
191 def exploit_framework_core(self):
192 return self.node.findtext("exploit_framework_core")
193
194 @property
195 def exploit_framework_d2_elliot(self):
196 return self.node.findtext("exploit_framework_d2_elliot")
197
198 @property
199 def exploit_framework_metasploit(self):
200 return self.node.findtext("exploit_framework_metasploit")
201
202 @property
203 def exploitability_ease(self):
204 return self.node.findtext("exploitability_ease")
205
206 @property
207 def exploited_by_malware(self):
208 return self.node.findtext("exploited_by_malware")
209
210 @property
211 def exploited_by_nessus(self):
212 return self.node.findtext("exploited_by_nessus")
213
214 @property
215 def hardware_inventory(self):
216 return self.node.findtext("hardware_inventory")
217
218 @property
219 def iava(self):
220 return self.node.findtext("iava")
221
222 @property
223 def iavb(self):
224 return self.node.findtext("iavb")
225
226 @property
227 def iavt(self):
228 return self.node.findtext("iavt")
229
230 @property
231 def in_the_news(self):
232 return self.node.findtext("in_the_news")
233
234 @property
235 def metasploit_name(self):
236 return self.node.findtext("metasploit_name")
237
238 @property
239 def os_identification(self):
240 return self.node.findtext("os_identification")
241
242 @property
243 def owasp(self):
244 return self.node.findtext("owasp")
245
246 @property
247 def patch_publication_date(self):
248 return self.node.findtext("patch_publication_date")
249
250
251 @property
252 def stig_severity(self):
253 return self.node.findtext("stig_severity")
254
255 @property
256 def d2_elliot_name(self):
257 return self.node.findtext("d2_elliot_name")
258
259 @property
260 def unsupported_by_vendor(self):
261 return self.node.findtext("unsupported_by_vendor")
262
263 @property
264 def vuln_publication_date(self):
265 return self.node.findtext("vuln_publication_date")
266
267 @property
268 def msft(self):
269 return self.node.findtext("msft")
270
271
272 @property
273 def cert(self) -> list:
274 return self.node.findall("cert")
275
276 @property
277 def bid(self) -> list:
278 return self.node.findall("bid")
279
280 @property
281 def cve(self) -> list:
282 return [i.text for i in self.node.findall("cve")]
283
284 @property
285 def cwe(self) -> list:
286 return [i.text for i in self.node.findall("cwe")]
287
288 @property
289 def edb_id(self) -> list:
290 return self.node.findall("edb-id")
291
292 @property
293 def mskb(self) -> list:
294 return self.node.findall("mskb")
295
296 @property
297 def xref(self) -> str:
298 return self.node.findtext("xref")
299
300 @property
301 def attachment(self) -> Attachment:
302 attachment = self.node.find("attachment")
303 return Attachment(attachment) if attachment else None
304
305 def get_data(self):
306 item_tags = {}
307 for i in self.node:
308 item_tags.setdefault(i.tag, i.text)
309 return item_tags
310
311
312 class Tag:
313 def __init__(self, node):
314 self.node = node
315
316 @property
317 def name_attr(self) -> str:
318 return self.node.get("name")
319
320 @property
321 def text(self) -> str:
322 return self.node.text
323
324
325 class HostProperties:
326 def __init__(self, node):
327 self.node = node
328
329 @property
330 def tag(self) -> list:
331 return [Tag(i) for i in self.node.findall('tag')]
332
333 @property
334 def host_end(self) -> str:
335 _dict = self.dict_tags
336 return _dict.get("HOST_END")
337
338 @property
339 def mac_address(self) -> str:
340 _dict = self.dict_tags
341 return _dict.get("mac-address", "")
342
343 @property
344 def operating_system(self) -> str:
345 _dict = self.dict_tags
346 return _dict.get("operating-system", None)
347
348 @property
349 def host_ip(self) -> str:
350 _dict = self.dict_tags
351
352 return _dict.get("host-ip", None)
353
354 @property
355 def host_fqdn(self) -> str:
356 _dict = self.dict_tags
357 return _dict.get("host-fqdn", None)
358
359 @property
360 def dict_tags(self):
361 host_tags = {}
362 for t in self.node:
363 host_tags.setdefault(t.attrib.get('name'), t.text)
364 return host_tags
365
366
367 class ReportHost:
368 def __init__(self, node):
369 self.node = node
370
371 @property
372 def name(self) -> str:
373 return self.node.get("name")
374
375 @property
376 def host_properties(self) -> HostProperties:
377 return HostProperties(self.node.find("HostProperties"))
378
379 @property
380 def report_items(self) -> List[ReportItem]:
381 return [ReportItem(i) for i in self.node.findall("ReportItem")]
382
383
384 class Report:
385
386 def __init__(self, node):
387 self.node = node
388
389 @property
390 def name_attr(self) -> str:
391 return self.node.get("name")
392
393 @property
394 def report_hosts(self) -> List[ReportHost]:
395 return [ReportHost(i) for i in self.node.findall('ReportHost')]
396
33 See the file 'doc/LICENSE' for the license information
44
55 """
6 import dateutil
7 from collections import namedtuple
86
9 from faraday_plugins.plugins.plugin import PluginXMLFormat
107 import xml.etree.ElementTree as ET
118
9 import dateutil
10 from faraday_plugins.plugins.plugin import PluginXMLFormat
1211
1312 __author__ = "Blas"
1413 __copyright__ = "Copyright (c) 2019, Infobyte LLC"
1918 __email__ = "[email protected]"
2019 __status__ = "Development"
2120
22 ReportItem = namedtuple('ReportItem', ['port', 'svc_name', 'protocol', 'severity', 'plugin_id',
23 'plugin_name', 'plugin_family', 'description', 'plugin_output', 'info'])
21 from faraday_plugins.plugins.repo.nessus.DTO import ReportHost, Report, ReportItem
22
2423
2524 class NessusParser:
2625 """
3534
3635 def __init__(self, output):
3736 self.tree = ET.fromstring(output)
38 self.tag_control = []
39 for x in self.tree:
40 self.tag_control.append(x)
37 self.report = []
4138 if self.tree:
42 self.policy = self.getPolicy(self.tree)
43 self.report = self.getReport(self.tree)
44 else:
45 self.policy = None
46 self.report = None
39 self.report = self.__get_report()
4740
48 def getPolicy(self, tree):
49 policy_tree = tree.find('Policy')
50 if policy_tree:
51 return Policy(policy_tree)
52 else:
53 return None
41 def __get_report(self) -> Report:
42 report = self.tree.find('Report')
43 return Report(report) if report else None
5444
55 def getReport(self, tree):
56 report_tree = tree.find('Report')
57 return Report(report_tree)
58
59 def parse_compliance_data(self, data: dict):
60 compliance_data = {}
61 for key, value in data.items():
62 if 'compliance-' in key:
63 compliance_name = key.split("}")[-1]
64 compliance_data[compliance_name] = value
65 return compliance_data
66
67 class Policy():
68 def __init__(self, policy_node):
69 self.node = policy_node
70 self.policy_name = self.node.find('policyName').text
71 self.preferences = self.getPreferences(self.node.find('Preferences'))
72 self.family_selection = self.getFamilySelection(self.node.find('FamilySelection'))
73 self.individual_plugin_selection = self.getIndividualPluginSelection(
74 self.node.find('IndividualPluginSelection'))
75
76 def getPreferences(self, preferences):
77 server_preferences = preferences.find('ServerPreferences')
78 plugins_preferences = preferences.find('PluginsPreferences')
79 server_preferences_all = []
80 plugins_preferences_json = {}
81 plugins_preferences_all = []
82 for sp in server_preferences:
83 sp_value = sp.find('value').text
84 sp_name = sp.find('name').text
85 server_preferences_all.append("Server Preferences name: {}, Server Preferences value: {}".format(sp_name,
86 sp_value))
87 for pp in plugins_preferences:
88 for pp_detail in pp:
89 plugins_preferences_json.setdefault(pp_detail.tag, pp_detail.text)
90 plugins_preferences_all.append(plugins_preferences_json)
91 return server_preferences_all, plugins_preferences_all
92
93 def getFamilySelection(self, family):
94 family_all = []
95 for f in family:
96 family_name = f.find('FamilyName').text
97 family_value = f.find('Status').text
98 family_all.append("Family Name: {}, Family Value: {}".format(family_name, family_value))
99 return family_all
100
101 def getIndividualPluginSelection(self, individual):
102 item_plugin = []
103 for i in individual:
104 plugin_id = i.find('PluginId').text
105 plugin_name = i.find('PluginName').text
106 plugin_family = i.find('Family').text
107 plugin_status = i.find('Status').text
108 item_plugin.append("Plugin ID: {}, Plugin Name: {}, Family: {}, Status: {}".format(plugin_id, plugin_name,
109 plugin_family,
110 plugin_status))
111 return item_plugin
112
113 class Report():
114 def __init__(self, report_node):
115 self.node = report_node
116 self.report_name = self.node.attrib.get('name')
117 self.report_host = self.node.find('ReportHost')
118 self.report_desc = []
119 self.report_ip = []
120 self.report_serv = []
121 self.report_json = {}
122 if self.report_host is not None:
123 for x in self.node:
124 report_host_ip = x.attrib.get('name')
125 host_properties = self.gethosttag(x.find('HostProperties'))
126 report_items = self.getreportitems(x.findall('ReportItem'))
127 self.report_ip.append(report_host_ip)
128 self.report_desc.append(host_properties)
129 self.report_serv.append(report_items)
130 self.report_json['ip'] = self.report_ip
131 self.report_json['desc'] = self.report_desc
132 self.report_json['serv'] = self.report_serv
133 self.report_json['host_end'] = host_properties.get('HOST_END')
134
135 else:
136 self.report_host_ip = None
137 self.host_properties = None
138 self.report_items = None
139 self.report_json = None
140
141 def getreportitems(self, items):
142 report_items = []
143
144 for item in items:
145 port = item.attrib.get('port')
146 svc_name = item.attrib.get('svc_name')
147 protocol = item.attrib.get('protocol')
148 severity = item.attrib.get('severity')
149 plugin_id = item.attrib.get('pluginID')
150 plugin_name = item.attrib.get('pluginName')
151 plugin_family = item.attrib.get('pluginFamily')
152 if item.find('plugin_output') is not None:
153 plugin_output = item.find('plugin_output').text
154 else:
155 plugin_output = "Not Description"
156 if item.find('description') is not None:
157 description = item.find('description').text
158 else:
159 description = "Not Description"
160 info = self.getinfoitem(item)
161 report_items.append(ReportItem(*[port, svc_name, protocol, severity, plugin_id,
162 plugin_name, plugin_family, description, plugin_output, info]))
163 return report_items
164
165 def getinfoitem(self, item):
166 item_tags = {}
167 for i in item:
168 item_tags.setdefault(i.tag, i.text)
169 return item_tags
170
171 def gethosttag(self, tags):
172 host_tags = {}
173 for t in tags:
174 host_tags.setdefault(t.attrib.get('name'), t.text)
175 return host_tags
17645
17746 class NessusPlugin(PluginXMLFormat):
17847 """
19059 self.framework_version = "1.0.1"
19160 self.options = None
19261
62 @staticmethod
63 def parse_compliance_data(data: dict):
64 compliance_data = {}
65 for key, value in data.items():
66 if 'compliance-' in key:
67 compliance_name = key.split("}")[-1]
68 compliance_data[compliance_name] = value
69 return compliance_data
70
71 @staticmethod
72 def map_properties(host: ReportHost):
73 return {
74 "name": host.host_properties.host_ip if host.host_properties.host_ip else host.name,
75 "hostnames": host.host_properties.host_fqdn,
76 "mac": host.host_properties.mac_address,
77 "os": host.host_properties.operating_system
78 }
79
80 @staticmethod
81 def map_item(host_id, run_date, plugin_name, item: ReportItem) -> dict:
82 cvss_base_score = item.cvss_base_score
83 data = item.plugin_output
84 data += f'{item.exploit_available}'
85 return {
86 "host_id": host_id,
87 "name": plugin_name,
88 "severity": item.risk_factor,
89 "data": data,
90 "external_id": item.plugin_id_attr,
91 "run_date": run_date,
92 "desc": item.description,
93 "resolution": item.solution,
94 "ref": [cvss_base_score] if cvss_base_score else []
95 }
96
97 def map_policy_general(self, kwargs, item: ReportItem):
98 kwargs.update({"policyviolations": []})
99 if item.plugin_family_attr == 'Policy Compliance':
100 data = item.get_data()
101 bis_benchmark_data = kwargs["desc"].split('\n')
102 compliance_data = self.parse_compliance_data(data)
103 compliance_info = compliance_data.get('compliance-info', '')
104 if compliance_info and not kwargs["desc"]:
105 kwargs["desc"] = compliance_info
106 compliance_reference = compliance_data.get(
107 'compliance-reference', '').replace('|', ':').split(',')
108 compliance_result = compliance_data.get('compliance-result', '')
109 for reference in compliance_reference:
110 kwargs["ref"].append(reference)
111 compliance_check_name = compliance_data.get('compliance-check-name', '')
112 compliance_solution = compliance_data.get('compliance-solution', '')
113 if compliance_solution and not kwargs["resolution"]:
114 kwargs["resolution"] = compliance_solution
115 policy_item = f'{compliance_check_name} - {compliance_result}'
116 for policy_check_data in bis_benchmark_data:
117 if 'ref.' in policy_check_data:
118 kwargs["ref"].append(policy_check_data)
119 if 'compliance-see-also' in compliance_data:
120 kwargs["ref"].append(compliance_data.get('compliance-see-also'))
121 # We used this info from tenable: https://community.tenable.com/s/article/Compliance-checks-in-SecurityCenter
122 kwargs["policyviolations"].append(policy_item)
123 kwargs["name"] = f'{kwargs["name"]}: {policy_item}'
124
125 return kwargs
126
193127 def parseOutputString(self, output):
194128 """
195129 This method will discard the output the shell sends, it will read it from
198132 NOTE: if 'debug' is true then it is being run from a test case and the
199133 output being sent is valid.
200134 """
135
201136 try:
202137 parser = NessusParser(output)
203138 except Exception as e:
204139 self.logger.error(str(e))
205140 return None
141 report_hosts = parser.report.report_hosts
206142
207 if parser.report.report_json is not None:
208 run_date = parser.report.report_json.get('host_end')
209 if run_date:
210 run_date = dateutil.parser.parse(run_date)
211 for set_info, ip in enumerate(parser.report.report_json['ip'], start=1):
212 website = None
213 mac = parser.report.report_json['desc'][set_info - 1].get('mac-address', '')
214 os = parser.report.report_json['desc'][set_info - 1].get('operating-system', None)
215 ip_host = parser.report.report_json['desc'][set_info - 1].get('host-ip', ip)
216 host_name = parser.report.report_json['desc'][set_info - 1].get('host-fqdn', None)
217 if host_name:
218 website = host_name
219 host_id = self.createAndAddHost(ip_host, os=os, hostnames=host_name, mac=mac)
143 if report_hosts:
144 for host in report_hosts:
145 run_date = host.host_properties.host_end
146 if run_date:
147 run_date = dateutil.parser.parse(run_date)
148 website = host.host_properties.host_fqdn
149 host_id = self.createAndAddHost(**self.map_properties(host))
220150
221 for report_item in parser.report.report_json['serv'][set_info -1]:
222 vulnerability_name = report_item.plugin_name
151 for item in host.report_items:
152 vulnerability_name = item.plugin_name
223153 if not vulnerability_name:
224154 continue
225 item_name = report_item.svc_name
226 item_port = report_item.port
227 item_protocol = report_item.protocol
228 item_severity = report_item.severity
229 external_id = report_item.plugin_id
230 serv_description = report_item.description
231 #cve.append(report_item.plugin_output)
232 description = report_item.plugin_output
233 data = report_item.info
234 risk_factor = data.get('risk_factor', None)
235 cve = []
236 ref = []
237 if risk_factor == 'None' or risk_factor is None:
238 risk_factor = item_severity # I checked several external id and most of them were info
155 item_name = item.svc_name_attr
156
157 _main_data = self.map_item(
158 host_id, run_date, vulnerability_name, item)
159
160 _main_data = self.map_add_ref(_main_data, item)
239161 if item_name == 'general':
240 description = data.get('description', '')
241 resolution = data.get('solution', '')
242 data_pluin_ouput = data.get('plugin_output', '')
243 if 'cvss_base_score' in data:
244 cvss_base_score = f"CVSS:{data['cvss_base_score']}"
245 ref.append(cvss_base_score)
246 policyviolations = []
247 if report_item.plugin_family == 'Policy Compliance':
248 # This condition was added to support CIS Benchmark in policy violation field.
249 bis_benchmark_data = report_item.description.split('\n')
250 compliance_data = parser.parse_compliance_data(data)
251 compliance_info = compliance_data.get('compliance-info', '')
252 if compliance_info and not description:
253 description = compliance_info
254 compliance_reference = compliance_data.get('compliance-reference', '').replace('|', ':').split(',')
255 compliance_result = compliance_data.get('compliance-result', '')
256 for reference in compliance_reference:
257 ref.append(reference)
258 compliance_check_name = compliance_data.get('compliance-check-name', '')
259 compliance_solution = compliance_data.get('compliance-solution', '')
260 if compliance_solution and not resolution:
261 resolution = compliance_solution
262 policy_item = f'{compliance_check_name} - {compliance_result}'
263 for policy_check_data in bis_benchmark_data:
264 if 'ref.' in policy_check_data:
265 ref.append(policy_check_data)
266 if 'compliance-see-also' in compliance_data:
267 ref.append(compliance_data.get('compliance-see-also'))
268 # We used this info from tenable: https://community.tenable.com/s/article/Compliance-checks-in-SecurityCenter
269 policyviolations.append(policy_item)
270 vulnerability_name = f'{vulnerability_name}: {policy_item}'
271 self.createAndAddVulnToHost(host_id,
272 vulnerability_name,
273 desc=description,
274 severity=risk_factor,
275 resolution=resolution,
276 data=data_pluin_ouput,
277 ref=ref,
278 policyviolations=policyviolations,
279 external_id=external_id,
280 run_date=run_date)
162 _main_data = self.map_policy_general(_main_data, item)
163 self.createAndAddVulnToHost(**_main_data)
281164 else:
282 vulnerability_name = report_item.plugin_name
283 description = data.get('description', '')
284 resolution = data.get('solution', '')
285 data_pluin_ouput = data.get('plugin_output', '')
286 if 'cvss_base_score' in data:
287 cvss_base_score = f"CVSS:{data['cvss_base_score']}"
288 ref.append(cvss_base_score)
289 if 'cvss_vector' in data:
290 cvss_vector = f"CVSSVECTOR:{data['cvss_vector']}"
291 ref.append(cvss_vector)
292 if 'see_also' in data:
293 ref.append(data['see_also'])
294 if 'cpe' in data:
295 ref.append(data['cpe'])
296 if 'xref' in data:
297 ref.append(data['xref'])
165 _main_data["service_id"] = self.createAndAddServiceToHost(
166 host_id, name=item_name, protocol=item.protocol_attr,
167 ports=item.port_attr)
168 if item_name == 'www' or item_name == 'http':
169 _main_data.update({"website": website})
170 self.createAndAddVulnWebToService(**_main_data)
171 else:
172 self.createAndAddVulnToService(**_main_data)
298173
299 service_id = self.createAndAddServiceToHost(host_id, name=item_name, protocol=item_protocol,
300 ports=item_port)
174 @staticmethod
175 def map_add_ref(kwargs, item: ReportItem):
301176
302 if item_name == 'www' or item_name == 'http':
303 self.createAndAddVulnWebToService(host_id,
304 service_id,
305 name=vulnerability_name,
306 desc=description,
307 data=data_pluin_ouput,
308 severity=risk_factor,
309 resolution=resolution,
310 ref=ref,
311 external_id=external_id,
312 website=website,
313 run_date=run_date)
314 else:
315 self.createAndAddVulnToService(host_id,
316 service_id,
317 name=vulnerability_name,
318 severity=risk_factor,
319 desc=description,
320 ref=ref,
321 data=data_pluin_ouput,
322 external_id=external_id,
323 resolution=resolution,
324 run_date=run_date)
177 if item.cvss_vector:
178 kwargs["ref"].append(item.cvss_vector)
179 if item.see_also:
180 kwargs["ref"].append(item.see_also)
181 if item.cpe:
182 kwargs["ref"].append(item.cpe)
183 if item.xref:
184 kwargs["ref"].append(item.xref)
185 if item.cve:
186 kwargs["ref"] = kwargs["ref"] + item.cve
187 if item.cvss3_base_score:
188 kwargs["ref"].append(item.cvss3_base_score)
189 if item.cvss3_vector:
190 kwargs["ref"].append(item.cvss3_vector)
191
192 return kwargs
325193
326194
327195 def createPlugin(ignore_info=False):
44
55 """
66 import re
7 import xml.etree.ElementTree as ET
8
79 from bs4 import BeautifulSoup
10
811 from faraday_plugins.plugins.plugin import PluginXMLFormat
912 from faraday_plugins.plugins.plugins_utils import resolve_hostname
10
11 try:
12 import xml.etree.cElementTree as ET
13 import xml.etree.ElementTree as ET_ORIG
14 ETREE_VERSION = ET_ORIG.VERSION
15 except ImportError:
16 import xml.etree.ElementTree as ET
17 ETREE_VERSION = ET.VERSION
18
19 ETREE_VERSION = [int(i) for i in ETREE_VERSION.split(".")]
20
2113
2214 __author__ = "Francisco Amato"
2315 __copyright__ = "Copyright (c) 2013, Infobyte LLC"
8274 @param item_node A item_node taken from an netsparker xml tree
8375 """
8476
85 def re_map_severity(self, severity):
86 if severity == "Important":
87 return "high"
88 return severity
89
90 def __init__(self, item_node, encoding="ascii"):
77 def __init__(self, item_node):
9178 self.node = item_node
9279 self.url = self.get_text_from_subnode("url")
9380
117104 self.param = self.get_text_from_subnode("vulnerableparameter")
118105 self.paramval = self.get_text_from_subnode("vulnerableparametervalue")
119106 self.reference = self.get_text_from_subnode("externalReferences")
120 self.resolution = self.get_text_from_subnode("actionsToTake")
107 remedy = self.get_text_from_subnode("remedy")
108 self.resolution = self.get_text_from_subnode("actionsToTake") + remedy if remedy else ""
121109 self.request = self.get_text_from_subnode("rawrequest")
122110 self.response = self.get_text_from_subnode("rawresponse")
123111 self.kvulns = []
166154 repr(self.paramval) if self.paramval else ""
167155 self.data += "\nExtra: " + "\n".join(self.extra) if self.extra else ""
168156
157 @staticmethod
158 def re_map_severity(severity):
159 if severity == "Important":
160 return "high"
161 return severity
162
169163 def get_text_from_subnode(self, subnode_xpath_expr):
170164 """
171165 Finds a subnode in the host node and the retrieves a value from it.
207201 ports=[str(i.port)],
208202 status="open")
209203 first = False
204
210205 if i.resolution is not None:
211206 resolution = BeautifulSoup(i.resolution, "lxml").text
212207 else:
220215 name = i.name
221216 else:
222217 name = i.name_title
223 v_id = self.createAndAddVulnWebToService(h_id, s_id, name, ref=i.ref, website=i.hostname,
218 self.createAndAddVulnWebToService(h_id, s_id, name, ref=i.ref, website=i.hostname,
224219 severity=i.severity, desc=desc, path=i.url, method=i.method,
225220 request=i.request, response=i.response, resolution=resolution,
226221 pname=i.param, data=i.data)
44
55 """
66 import re
7 import xml.etree.ElementTree as ET
78 from urllib.parse import urlparse
9
810 from faraday_plugins.plugins.plugin import PluginXMLFormat
911 from faraday_plugins.plugins.plugins_utils import resolve_hostname
10
11 try:
12 import xml.etree.cElementTree as ET
13 import xml.etree.ElementTree as ET_ORIG
14 ETREE_VERSION = ET_ORIG.VERSION
15 except ImportError:
16 import xml.etree.ElementTree as ET
17 ETREE_VERSION = ET.VERSION
18
19 ETREE_VERSION = [int(i) for i in ETREE_VERSION.split(".")]
20
2112
2213 __author__ = "Francisco Amato"
2314 __copyright__ = "Copyright (c) 2013, Infobyte LLC"
2920 __status__ = "Development"
3021
3122
32
3323 def get_urls(string):
3424 if isinstance(string, bytes):
3525 string_decode = string.decode("utf-8")
5444 self.filepath = xml_output
5545 tree = self.parse_xml(xml_output)
5646 if tree:
57 self.items = [data for data in self.get_items(tree)]
47 self.items = self.get_items(tree)
5848 else:
5949 self.items = []
6050
8979
9080 @param item_node A item_node taken from an netsparkercloud xml tree
9181 """
82
9283 def re_map_severity(self, severity):
9384 if severity == "Important":
9485 return "high"
119110 self.response = self.get_text_from_subnode("content")
120111 self.extra = []
121112 for v in item_node.findall("extra-information/info"):
122 self.extra.append(v.get('name') + ":" + v.get('value') )
113 self.extra.append(v.get('name') + ":" + v.get('value'))
123114
124115 self.node = item_node.find("classification")
125116 self.owasp = self.get_text_from_subnode("owasp")
205196 del parser
206197
207198
208 def setHost(self):
209 pass
210
211
212199 def createPlugin(ignore_info=False):
213200 return NetsparkerCloudPlugin(ignore_info=ignore_info)
33 See the file 'doc/LICENSE' for the license information
44
55 """
6 import re
7 import xml.etree.ElementTree as ET
8
69 from faraday_plugins.plugins.plugin import PluginXMLFormat
7 import re
8
9 try:
10 import xml.etree.cElementTree as ET
11 import xml.etree.ElementTree as ET_ORIG
12
13 ETREE_VERSION = ET_ORIG.VERSION
14 except ImportError:
15 import xml.etree.ElementTree as ET
16
17 ETREE_VERSION = ET.VERSION
18
19 ETREE_VERSION = [int(i) for i in ETREE_VERSION.split(".")]
20
2110
2211 __author__ = "Micaela Ranea Sanchez"
2312 __copyright__ = "Copyright (c) 2013, Infobyte LLC"
5039 else:
5140 self.items = []
5241
53 def parse_xml(self, xml_output):
42 @staticmethod
43 def parse_xml(xml_output):
5444 """
5545 Open and parse an xml file.
5646
121111
122112 for tests in node.findall('tests'):
123113 for test in tests.iter('test'):
124 vuln = dict()
125114 if test.get('id').lower() in vulnsDefinitions:
126115 vuln = vulnsDefinitions[test.get('id').lower()].copy()
127116 key = test.get('key', '')
274263 h_id = self.createAndAddHost(item['name'], item['os'], hostnames=item['hostnames'], mac=mac)
275264 for v in item['vulns']:
276265 v['data'] = {"vulnerable_since": v['vulnerable_since'], "scan_id": v['scan_id'], "PCI": v['pci']}
277 v_id = self.createAndAddVulnToHost(
266 self.createAndAddVulnToHost(
278267 h_id,
279268 v['name'],
280269 v['desc'],
284273 )
285274
286275 for s in item['services']:
287 web = False
288276 version = s.get("version", "")
289277 s_id = self.createAndAddServiceToHost(
290278 h_id,
297285 for v in s['vulns']:
298286
299287 if v['is_web']:
300 v_id = self.createAndAddVulnWebToService(
288 self.createAndAddVulnWebToService(
301289 h_id,
302290 s_id,
303291 v['name'],
307295 v['resolution'],
308296 path=v.get('path', ''))
309297 else:
310 v_id = self.createAndAddVulnToService(
298 self.createAndAddVulnToService(
311299 h_id,
312300 s_id,
313301 v['name'],
320308 del parser
321309
322310
323 def setHost(self):
324 pass
325
326
327311 def createPlugin(ignore_info=False):
328312 return NexposeFullPlugin(ignore_info=ignore_info)
329
330
33 See the file 'doc/LICENSE' for the license information
44 """
55 import re
6 import xml.etree.ElementTree as ET
67 from html.parser import HTMLParser
8
9 from faraday_plugins.plugins import plugins_utils
710 from faraday_plugins.plugins.plugin import PluginXMLFormat
8 from faraday_plugins.plugins import plugins_utils
9
10
11 try:
12 import xml.etree.cElementTree as ET
13 import xml.etree.ElementTree as ET_ORIG
14 ETREE_VERSION = ET_ORIG.VERSION
15 except ImportError:
16 import xml.etree.ElementTree as ET
17 ETREE_VERSION = ET.VERSION
18
19 ETREE_VERSION = [int(i) for i in ETREE_VERSION.split(".")]
20
2111
2212 __author__ = "Francisco Amato"
2313 __copyright__ = "Copyright (c) 2013, Infobyte LLC"
4535 tree = self.parse_xml(xml_output)
4636
4737 if tree:
48 self.hosts = [host for host in self.get_hosts(tree)]
38 self.hosts = self.get_hosts(tree)
4939 else:
5040 self.hosts = []
5141
8474
8575 @return An attribute value
8676 """
87 global ETREE_VERSION
88 node = None
89
90 if ETREE_VERSION[0] <= 1 and ETREE_VERSION[1] < 3:
91
92 match_obj = re.search(
93 "([^\@]+?)\[\@([^=]*?)=\'([^\']*?)\'", subnode_xpath_expr)
94 if match_obj is not None:
95
96 node_to_find = match_obj.group(1)
97 xpath_attrib = match_obj.group(2)
98 xpath_value = match_obj.group(3)
99 for node_found in xml_node.findall(node_to_find):
100
101 if node_found.attrib[xpath_attrib] == xpath_value:
102 node = node_found
103 break
104 else:
105 node = xml_node.find(subnode_xpath_expr)
106
107 else:
108 node = xml_node.find(subnode_xpath_expr)
77
78 node = xml_node.find(subnode_xpath_expr)
10979
11080 if node is not None:
11181 return node.get(attrib_name)
221191 self.starttime = self.node.get('starttime')
222192 self.sitename = self.node.get('sitename')
223193 self.siteip = self.node.get('hostheader')
224 self.items = [item for item in self.get_items()]
194 self.items = self.get_items()
225195
226196 def get_items(self):
227197 """
300270 "-vhost+": "Virtual host (for Host header)",
301271 }
302272
303
304
305273 def parseOutputString(self, output):
306274 """
307275 This method will discard the output the shell sends, it will read it from
329297 )
330298
331299 for item in host.items:
332
333 v_id = self.createAndAddVulnWebToService(
300 self.createAndAddVulnWebToService(
334301 h_id,
335302 s_id,
336303 name=item.desc,
342309
343310 del parser
344311
345
346
347312 def processCommandString(self, username, current_path, command_string):
348313 """
349314 Adds the -oX parameter to get xml output to the command string that the
359324 data = re.sub(" \-Format XML", "", command_string)
360325 return re.sub(arg_match.group(1), r"-output %s -Format XML" % self._output_file_path, data)
361326
362 def setHost(self):
363 pass
364
365327
366328 def createPlugin(ignore_info=False):
367329 return NiktoPlugin(ignore_info=ignore_info)
368
369
0 import os
1 import re
2 from io import BytesIO
3
04 """
15 Faraday Penetration Test IDE
26 Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
37 See the file 'doc/LICENSE' for the license information
48
59 """
6
7 import re
8 import os
9 from io import BytesIO
10
11 try:
12 import xml.etree.cElementTree as ET
13 import xml.etree.ElementTree as ET_ORIG
14 ETREE_VERSION = ET_ORIG.VERSION
15 except ImportError:
16 import xml.etree.ElementTree as ET
17 ETREE_VERSION = ET.VERSION
1810 from lxml import etree
1911 from lxml.etree import XMLParser
2012 from faraday_plugins.plugins.plugin import PluginXMLFormat
2113 from faraday_plugins.plugins.plugins_utils import get_severity_from_cvss
2214
23 ETREE_VERSION = [int(i) for i in ETREE_VERSION.split(".")]
2415 current_path = os.path.abspath(os.getcwd())
25
2616
2717
2818 class NmapXmlParser:
6050 magical_parser = XMLParser(recover=True)
6151 return etree.parse(BytesIO(xml_output), magical_parser)
6252 except SyntaxError as err:
63 #logger.error("SyntaxError: %s." % (err))
53 # logger.error("SyntaxError: %s." % (err))
6454 return None
6555
6656 def get_hosts(self, tree):
7767
7868 @return An attribute value
7969 """
80 global ETREE_VERSION
81 node = None
82
83 if ETREE_VERSION[0] <= 1 and ETREE_VERSION[1] < 3:
84
85 match_obj = re.search(
86 "([^\@]+?)\[\@([^=]*?)=\'([^\']*?)\'",
87 subnode_xpath_expr)
88
89 if match_obj is not None:
90
91 node_to_find = match_obj.group(1)
92 xpath_attrib = match_obj.group(2)
93 xpath_value = match_obj.group(3)
94
95 for node_found in xml_node.findall(node_to_find):
96 if node_found.attrib[xpath_attrib] == xpath_value:
97 node = node_found
98 break
99 else:
100 node = xml_node.find(subnode_xpath_expr)
101
102 else:
103 node = xml_node.find(subnode_xpath_expr)
70
71 node = xml_node.find(subnode_xpath_expr)
10472
10573 if node is not None:
10674 return node.get(attrib_name)
242210 ostype = service.get("ostype", "unknown")
243211 yield ("%s" % ostype, 0)
244212
245
246213 def top_os_guess(self):
247214 """
248215 @return The most accurate os_guess_id or 'unknown'.
295262 @param port_node A port_node taken from an nmap xml tree
296263 """
297264
265 PORT_STATUS_FIX = {"filtered": "closed", "open|filtered": "closed"}
266
298267 def __init__(self, port_node):
299268 self.node = port_node
300269
322291
323292 @return (state, reason, reason_ttl) or ('unknown','unknown','unknown')
324293 """
325 state = self.get_attrib_from_subnode('state', 'state')
294 state = self.PORT_STATUS_FIX.get(self.get_attrib_from_subnode('state', 'state'),
295 self.get_attrib_from_subnode('state', 'state'))
326296 reason = self.get_attrib_from_subnode('state', 'reason')
327297 reason_ttl = self.get_attrib_from_subnode('state', 'reason_ttl')
328298
381351 self.table[e.get("key")] = str(e.text)
382352
383353 self.name = self.table["id"]
384
354
385355 self.desc = script_node.get("id") + "-" + self.table["id"]
386356 if self.table["is_exploit"] == 'true':
387357 self.desc += " *EXPLOIT*"
388
358
389359 self.refs = ["https://vulners.com/" + self.table["type"] + "/" + self.table["id"]]
390360 self.refs.append("CVSS: " + self.table["cvss"])
391361 self.response = ""
422392
423393 self.name = script_node.get("id")
424394 self.desc = script_node.get("output")
425 self.refs = self.parse_output(self.desc)
395 self.refs = self.parse_output(self.desc)
426396 self.response = ""
427397 for k in script_node.findall("elem"):
428398 self.response += "\n" + str(k.get('key')) + ": " + str(k.text)
547517 description=srvname)
548518
549519 for v in port.vulns:
550
520
551521 desc = v.desc
552522 refs = v.refs
553523
561531 severity = "unclassified"
562532 if re.search(r"Couldn't", desc):
563533 severity = "unclassified"
564
534
565535 if v.web:
566536 v_id = self.createAndAddVulnWebToService(
567537 h_id,
568538 s_id,
569539 v.name,
570540 desc=desc,
571 response = v.response if v.response else "",
541 response=v.response if v.response else "",
572542 ref=refs,
573543 severity=severity,
574544 website=minterfase,
600570 r"-oX %s" % self._output_file_path,
601571 command_string)
602572
573
603574 def createPlugin(ignore_info=False):
604575 return NmapPlugin(ignore_info=ignore_info)
605
606
55 """
66 import socket
77 import json
8 import dateutil
9 from collections import defaultdict
810 from urllib.parse import urlparse
911 from faraday_plugins.plugins.plugin import PluginMultiLineJsonFormat
1012 from faraday_plugins.plugins.plugins_utils import resolve_hostname
1113
12 __author__ = "Blas Moyano"
13 __copyright__ = "Copyright (c) 2020, Infobyte LLC"
14 __credits__ = ["Blas Moyano"]
14 __author__ = "Nicolas Rebagliati"
15 __copyright__ = "Copyright (c) 2021, Infobyte LLC"
16 __credits__ = ["Nicolas Rebagliati"]
1517 __license__ = ""
1618 __version__ = "0.0.1"
17 __maintainer__ = "Blas Moyano"
18 __email__ = "[email protected]"
19 __maintainer__ = "Nicolas Rebagliati"
20 __email__ = "[email protected]"
1921 __status__ = "Development"
20
21
22 class NucleiJsonParser:
23
24 def __init__(self, json_output):
25 self.list_to_vulns = json_output.split("\n")
2622
2723
2824 class NucleiPlugin(PluginMultiLineJsonFormat):
3531 self.id = "nuclei"
3632 self.name = "Nuclei"
3733 self.plugin_version = "0.1"
38 self.version = "0.0.1"
39 self.json_keys = {"matched", "template"}
34 self.version = "2.3.0"
35 self.json_keys = {"matched", "templateID", "host"}
4036
4137 def parseOutputString(self, output, debug=False):
42 parser = NucleiJsonParser(output)
43 matched_list = []
44 matched_json = {}
45 for vuln in parser.list_to_vulns:
46 if vuln != '':
47 json_vuln = json.loads(vuln)
48 matched = json_vuln.get('matched', None)
49
50 if matched is not None:
51 url_parser = urlparse(matched)
52 url_scheme = f'{url_parser.scheme}://{url_parser.hostname}'
53
54 if url_scheme in matched_list:
55 matched_json[url_scheme].append(json_vuln)
56 else:
57 matched_list.append(url_scheme)
58 matched_json[url_scheme] = [json_vuln]
59
60 for url in matched_list:
61 url_data = urlparse(url)
62 url_name = url_data.hostname
63 url_protocol = url_data.scheme
64 ip = resolve_hostname(url_name)
38 for vuln_json in filter(lambda x: x != '', output.split("\n")):
39 vuln_dict = json.loads(vuln_json)
40 host = vuln_dict.get('host')
41 url_data = urlparse(host)
42 ip = vuln_dict.get("ip", resolve_hostname(url_data.hostname))
6543 host_id = self.createAndAddHost(
6644 name=ip,
67 hostnames=[url_name])
68 port = 80
69 if url_parser.scheme == 'https':
70 port = 443
71
45 hostnames=[url_data.hostname])
46 port = url_data.port
47 if not port:
48 if url_data.scheme == 'https':
49 port = 443
50 else:
51 port = 80
7252 service_id = self.createAndAddServiceToHost(
7353 host_id,
74 name=url_parser.scheme,
54 name=url_data.scheme,
7555 ports=port,
7656 protocol="tcp",
7757 status='open',
7858 version='',
79 description='')
59 description='web server')
60 matched = vuln_dict.get('matched')
61 matched_data = urlparse(matched)
62 references = [f"author: {vuln_dict['info'].get('author', '')}"]
63 request = vuln_dict.get('request', '')
64 if request:
65 method = request.split(" ")[0]
66 else:
67 method = ""
68 data = [f"Matched: {vuln_dict.get('matched')}",
69 f"Tags: {vuln_dict['info'].get('tags')}",
70 f"Template ID: {vuln_dict['templateID']}"]
8071
81 for info_vuln in matched_json[url]:
82 desc = f'{info_vuln.get("template", None)} - {info_vuln.get("author", None)}'
83 if info_vuln.get("author", None):
84 ref = [f"author: {info_vuln.get('author', None)}"]
85 else:
86 ref = None
87 self.createAndAddVulnWebToService(
88 host_id,
89 service_id,
90 name=info_vuln.get('template', ""),
91 desc=info_vuln.get('description', info_vuln.get('name', None)),
92 ref=ref,
93 severity=info_vuln.get('severity', ""),
94 website=url,
95 request=info_vuln.get('request', None),
96 response=info_vuln.get('response', None),
97 method=info_vuln.get('type', None),
98 data=info_vuln.get('matcher_name', info_vuln.get('name', None)),
99 external_id=info_vuln.get('template', ""))
72 name = vuln_dict["info"].get("name")
73 run_date = vuln_dict.get('timestamp')
74 if run_date:
75 run_date = dateutil.parser.parse(run_date)
76 self.createAndAddVulnWebToService(
77 host_id,
78 service_id,
79 name=name,
80 desc=vuln_dict["info"].get("description", name),
81 ref=references,
82 severity=vuln_dict["info"].get('severity'),
83 website=host,
84 request=request,
85 response=vuln_dict.get('response', ''),
86 method=method,
87 query=matched_data.query,
88 params=matched_data.params,
89 path=matched_data.path,
90 data="\n".join(data),
91 external_id=f"NUCLEI-{vuln_dict.get('templateID', '')}",
92 run_date=run_date
93 )
94
95
10096
10197
10298 def createPlugin(ignore_info=False):
44 Copyright (C) 2020 Infobyte LLC (http://www.infobytesec.com/)
55 See the file 'doc/LICENSE' for the license information
66 """
7 import ipaddress
8 from datetime import datetime
9
10 from lxml import etree
11
712 from faraday_plugins.plugins.plugin import PluginXMLFormat
8 from datetime import datetime
9 from lxml import etree
10 import ipaddress
11
12 try:
13 import xml.etree.cElementTree as ET
14 except ImportError:
15 import xml.etree.ElementTree as ET
1613
1714 __author__ = 'Blas Moyano'
1815 __copyright__ = 'Copyright 2020, Faraday Project'
0 import re
1 from collections import defaultdict
2 from copy import copy
3
04 """
15 Faraday Penetration Test IDE
26 Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
37 See the file 'doc/LICENSE' for the license information
48
59 """
6 import re
7 from collections import defaultdict
8 from copy import copy
9
10 try:
11 import xml.etree.cElementTree as ET
12 import xml.etree.ElementTree as ET_ORIG
13 ETREE_VERSION = ET_ORIG.VERSION
14 except ImportError:
15 import xml.etree.ElementTree as ET
16 ETREE_VERSION = ET.VERSION
1710
1811 from faraday_plugins.plugins.plugin import PluginXMLFormat
1912 from faraday_plugins.plugins.plugins_utils import filter_services
2013
21 ETREE_VERSION = [int(i) for i in ETREE_VERSION.split(".")]
22
14 import xml.etree.ElementTree as ET
2315
2416 __author__ = "Francisco Amato"
2517 __copyright__ = "Copyright (c) 2013, Infobyte LLC"
135127
136128 @return An attribute value
137129 """
138 global ETREE_VERSION
139 node = None
140
141 if ETREE_VERSION[0] <= 1 and ETREE_VERSION[1] < 3:
142
143 match_obj = re.search(
144 "([^\@]+?)\[\@([^=]*?)=\'([^\']*?)\'",
145 subnode_xpath_expr)
146
147 if match_obj is not None:
148 node_to_find = match_obj.group(1)
149 xpath_attrib = match_obj.group(2)
150 xpath_value = match_obj.group(3)
151 for node_found in xml_node.findall(node_to_find):
152 if node_found.attrib[xpath_attrib] == xpath_value:
153 node = node_found
154 break
155 else:
156 node = xml_node.find(subnode_xpath_expr)
157
158 else:
159 node = xml_node.find(subnode_xpath_expr)
130
131 node = xml_node.find(subnode_xpath_expr)
160132
161133 if node is not None:
162134 return node.get(attrib_name)
335307 with open(report_path) as f:
336308 output = f.read()
337309 return re.search("OpenVAS", output) is not None \
338 or re.search('<omp>', output) is not None\
310 or re.search('<omp>', output) is not None \
339311 or re.search('<owner>', output) is not None
340312 return False
341313
442414 else:
443415 return False
444416
445 def setHost(self):
446 pass
447
448417
449418 def createPlugin(ignore_info=False):
450419 return OpenvasPlugin(ignore_info=ignore_info)
451
452
33 See the file 'doc/LICENSE' for the license information
44
55 """
6 import re
7
68 from faraday_plugins.plugins.plugin import PluginBase
7 import re
89
910 __author__ = "Facundo de Guzmán, Esteban Guillardoy"
1011 __copyright__ = "Copyright (c) 2013, Infobyte LLC"
3435
3536 reg = re.search(r"PING ([\w\.-:]+)( |)\(([\w\.:]+)\)", output)
3637 if re.search("0 received|unknown host", output) is None and reg is not None:
37
3838 ip_address = reg.group(3)
3939 hostname = reg.group(1)
40 h_id = self.createAndAddHost(ip_address, hostnames=[hostname])
40 self.createAndAddHost(ip_address, hostnames=[hostname])
4141 return True
4242
4343 def _isIPV4(self, ip):
4747 return False
4848
4949
50
5150 def createPlugin(ignore_info=False):
5251 return CmdPingPlugin(ignore_info=ignore_info)
53
54
55
33 See the file 'doc/LICENSE' for the license information
44 """
55 import re
6 import xml.etree.ElementTree as ET
7
68 from faraday_plugins.plugins.plugin import PluginXMLFormat
7
8 import xml.etree.ElementTree as ET
9 ETREE_VERSION = ET.VERSION
10
11 ETREE_VERSION = [int(i) for i in ETREE_VERSION.split('.')]
12
139
1410 __author__ = 'Francisco Amato'
1511 __copyright__ = 'Copyright (c) 2013, Infobyte LLC'
349345
350346 parser = QualysguardXmlParser(output)
351347
352
353348 for item in parser.items:
354349 h_id = self.createAndAddHost(
355350 item.ip,
414409 del parser
415410
416411
417 def setHost(self):
418 pass
419
420
421412 def createPlugin(ignore_info=False):
422413 return QualysguardPlugin(ignore_info=ignore_info)
423
424
44 Copyright (C) 2016 Infobyte LLC (http://www.infobytesec.com/)
55 See the file 'doc/LICENSE' for the license information
66 """
7 import re
7 import xml.etree.ElementTree as ET
88 from urllib.parse import urlparse
99
1010 from dateutil.parser import parse
1111
1212 from faraday_plugins.plugins.plugin import PluginXMLFormat
13
14 try:
15 import xml.etree.cElementTree as ET
16 except ImportError:
17 import xml.etree.ElementTree as ET
1813
1914 __author__ = 'Blas Moyano'
2015 __copyright__ = 'Copyright 2020, Faraday Project'
7974 class Glossary():
8075 def __init__(self, glossary_tags):
8176 self.lista_qid = self.get_qid_list(glossary_tags)
82
8377
8478 def get_qid_list(self, qid_list_tags):
8579 self.dict_result_qid = {}
44
55 """
66 import re
7 import xml.etree.ElementTree as ET
8
79 from faraday_plugins.plugins.plugin import PluginXMLFormat
8
9
10 try:
11 import xml.etree.cElementTree as ET
12 import xml.etree.ElementTree as ET_ORIG
13 ETREE_VERSION = ET_ORIG.VERSION
14 except ImportError:
15 import xml.etree.ElementTree as ET
16 ETREE_VERSION = ET.VERSION
17
18 ETREE_VERSION = [int(i) for i in ETREE_VERSION.split(".")]
19
2010
2111 __author__ = "Francisco Amato"
2212 __copyright__ = "Copyright (c) 2013, Infobyte LLC"
4232 def __init__(self, xml_output):
4333 tree = self.parse_xml(xml_output)
4434 if tree:
45 self.items = [data for data in self.get_items(tree)]
35 self.items = self.get_items(tree)
4636 else:
4737 self.items = []
4838
116106 return None
117107
118108
119 class Results():
109 class Results:
120110
121111 def __init__(self, issue_node):
122112 self.node = issue_node
181171 self.framework_version = "1.0.0"
182172 self.options = None
183173
184
185174 def parseOutputString(self, output):
186175
187176 parser = RetinaXmlParser(output)
188177 for item in parser.items:
189178 hostname = item.hostname if item.hostname else None
190 h_id = self.createAndAddHost(item.ip, item.os,hostnames=[hostname])
179 h_id = self.createAndAddHost(item.ip, item.os, hostnames=[hostname])
191180
192181 if not item.netbiosname == 'N/A':
193182 self.createAndAddNoteToHost(
222211 del parser
223212
224213
225 def setHost(self):
226 pass
227
228
229214 def createPlugin(ignore_info=False):
230215 return RetinaPlugin(ignore_info=ignore_info)
231
232
147147 p = SkipfishParser(self._output_file_path)
148148
149149 hostc = {}
150 port = 80
151150 for issue in p.issues:
152 req = ""
153 res = ""
154151 for sample in issue["samples"]:
155152 if not sample["url"] in hostc:
156153 reg = re.search(
175172 'host': host,
176173 'protocol': protocol,
177174 's_id': s_id}
178
179 try:
180 req = open("%s/request.dat" % sample["dir"], "r").read()
181 except:
182 pass
183
184 try:
185 res = open("%s/request.dat" % sample["dir"], "r").read()
186 except Exception:
187 pass
188175
189176 d = hostc[sample["url"]]
190177 self.createAndAddVulnWebToService(
213200 else:
214201 return re.sub(arg_match.group(1), r"-o %s" % self._output_file_path, command_string, 1)
215202
216 def setHost(self):
217 pass
203
218204
219205
220206 def createPlugin(ignore_info=False):
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 """
0 """
1 Faraday Penetration Test IDE
2 Copyright (C) 2021 Infobyte LLC (http://www.infobytesec.com/)
3 See the file 'doc/LICENSE' for the license information
4
5 """
6 import json
7 from faraday_plugins.plugins.plugin import PluginJsonFormat
8 from datetime import datetime
9 import dateutil
10
11 VULNERABILITY = "VULNERABILITY"
12
13 # ATTENTION: The following mappings are created following the common sense in order to integrate F! with SQ. You
14 # can see what term means in the following website: https://docs.sonarqube.org/latest/user-guide/issues/
15 SEVERITIES = {
16 'INFO': 'unclassified',
17 'MINOR': 'low',
18 'MAJOR': 'medium',
19 'CRITICAL': 'high',
20 'BLOCKER': 'critical'
21 }
22 STATUSES = {
23 'OPEN': 'open',
24 'CONFIRMED': 'opened',
25 'REOPENED': 're-opened',
26 'CLOSED': 'closed',
27 'RESOLVED': 'closed'
28 }
29
30
31 class SonarQubeAPIParser:
32 def __init__(self, json_output):
33 json_data = json.loads(json_output)
34
35 self.vulns = self._parse_vulns(json_data)
36
37 def _parse_vulns(self, json_data):
38 vulns = []
39 components = {item['key']:
40 {'name': item['name'], 'longName': item['longName']}
41 for item in json_data['components'] }
42 for issue in json_data['issues']:
43 if issue['type'] != VULNERABILITY:
44 continue
45
46 component = issue['component']
47 path = components[component]['longName']
48 vuln_description = f"Issue found in line {issue['line']} of {path}"
49 project = f"Project: {issue['project']}"
50 severity = SEVERITIES[issue['severity']]
51 message = issue['message']
52 status = STATUSES[issue['status']]
53 tags = issue['tags']
54 external_id = issue['rule']
55 creation_date = dateutil.parser.parse(issue['creationDate'])
56 data = [] if not issue['flows'] else ["Flows:"]
57 for flow in issue['flows']:
58 for location in flow['locations']:
59 location_message = f"\"{location['msg']}\" in line {location['textRange']['startLine']} " \
60 f"of {components[component]['longName']}"
61 data.append(location_message)
62 vulns.append(
63 {'name': message, 'description': vuln_description, 'project': project, 'path': path, 'severity': severity, 'status': status, 'tags': tags,
64 'creation_date': creation_date, 'data': "\n".join(data), 'external_id': external_id})
65
66 return vulns
67
68
69 class SonarQubeAPIPlugin(PluginJsonFormat):
70 def __init__(self, *arg, **kwargs):
71 super().__init__(*arg, **kwargs)
72 self.json_keys = {'total', 'effortTotal', 'issues', 'components', 'facets'}
73 self.id = "sonarqubeAPI"
74 self.name = "SonarQube API Plugin"
75 self.plugin_version = "0.0.1"
76
77
78 def parseOutputString(self, output, debug=False):
79 parser = SonarQubeAPIParser(output)
80 for vuln in parser.vulns:
81 host_id = self.createAndAddHost(vuln['path'], description=vuln['project'])
82
83 self.createAndAddVulnToHost(
84 host_id=host_id,
85 name=vuln['name'],
86 desc=vuln['description'],
87 status=vuln['status'],
88 run_date=vuln['creation_date'],
89 severity=vuln['severity'],
90 tags=vuln['tags'],
91 data=vuln['data'],
92 external_id=vuln['external_id']
93 )
94
95
96 def createPlugin(ignore_info=False):
97 return SonarQubeAPIPlugin(ignore_info=ignore_info)
66 import re
77 import json
88 from faraday_plugins.plugins.plugin import PluginJsonFormat
9 from faraday_plugins.plugins.plugins_utils import resolve_hostname
910
1011 __author__ = "Blas Moyano"
1112 __copyright__ = "Copyright (c) 2020, Infobyte LLC"
7071
7172 def get_host(self, server_location):
7273 port = server_location.get('port', None)
73 protocol = ''
74 if port is not None:
75 if port == 443:
76 protocol = 'https'
77 else:
78 protocol = 'http'
74 hostname = server_location.get('hostname', None)
75 ip = server_location.get('ip_address', resolve_hostname(hostname))
7976
8077 json_host = {
81 "url": server_location.get('hostname', None),
82 "ip": server_location.get('ip_address', '0.0.0.0'),
78 "name": 'https',
79 "ip": ip,
80 "hostname": hostname,
8381 "port": port,
84 "protocol": protocol
82 "protocol": 'tcp'
8583 }
8684
8785 return json_host
177175 parser = SslyzeJsonParser(output)
178176
179177 for info_sslyze in parser.list_vul:
180 info_sslyze['host_info'].get('url')
178 info_sslyze['host_info'].get('hostname')
181179 host_id = self.createAndAddHost(
182180 info_sslyze['host_info'].get('ip'),
183181 os="unknown",
184182 hostnames=[
185 info_sslyze['host_info'].get('url')
183 info_sslyze['host_info'].get('hostname')
186184 ]
187185 )
188186 service_id = self.createAndAddServiceToHost(
189187 host_id,
190 name=info_sslyze['host_info'].get('protocol'),
188 name=info_sslyze['host_info'].get('name'),
191189 protocol=info_sslyze['host_info'].get('protocol'),
192190 ports=[
193191 info_sslyze['host_info'].get('port')
44
55 """
66 import re
7 import xml.etree.ElementTree as ET
78 from urllib.parse import urlparse
9
810 from faraday_plugins.plugins.plugin import PluginXMLFormat
911 from faraday_plugins.plugins.plugins_utils import resolve_hostname
10
11 try:
12 import xml.etree.cElementTree as ET
13 import xml.etree.ElementTree as ET_ORIG
14 ETREE_VERSION = ET_ORIG.VERSION
15 except ImportError:
16 import xml.etree.ElementTree as ET
17 ETREE_VERSION = ET.VERSION
18
19 ETREE_VERSION = [int(i) for i in ETREE_VERSION.split(".")]
20
2112
2213 __author__ = "Francisco Amato"
2314 __copyright__ = "Copyright (c) 2013, Infobyte LLC"
7263 """
7364 @return items A list of Host instances
7465 """
75 bugtype = ""
7666
7767 if len(tree.findall('scan-info')) == 0:
7868 scaninfo = tree.findall('scaninfo')[0]
10393
10494 @return An attribute value
10595 """
106 global ETREE_VERSION
107 node = None
108
109 if ETREE_VERSION[0] <= 1 and ETREE_VERSION[1] < 3:
110
111 match_obj = re.search(
112 "([^\@]+?)\[\@([^=]*?)=\'([^\']*?)\'", subnode_xpath_expr)
113 if match_obj is not None:
114 node_to_find = match_obj.group(1)
115 xpath_attrib = match_obj.group(2)
116 xpath_value = match_obj.group(3)
117 for node_found in xml_node.findall(node_to_find):
118 if node_found.attrib[xpath_attrib] == xpath_value:
119 node = node_found
120 break
121 else:
122 node = xml_node.find(subnode_xpath_expr)
123
124 else:
125 node = xml_node.find(subnode_xpath_expr)
96 node = xml_node.find(subnode_xpath_expr)
12697
12798 if node is not None:
12899 return node.get(attrib_name)
225196 }
226197
227198 def parseOutputString(self, output):
228
229199 parser = W3afXmlParser(output)
230200 ip = resolve_hostname(parser.host)
231201 h_id = self.createAndAddHost(ip, hostnames=[parser.host])
232202 s_id = self.createAndAddServiceToHost(h_id, "http", "tcp", ports=[parser.port], status="open")
233203
234204 for item in parser.items:
235 v_id = self.createAndAddVulnWebToService(h_id, s_id, item.name,
205 self.createAndAddVulnWebToService(h_id, s_id, item.name,
236206 item.detail, pname=item.param, path=item.url, website=parser.host,
237207 severity=item.severity, method=item.method, request=item.req,
238208 resolution=item.resolution, ref=item.ref, response=item.resp)
239209 del parser
240210
241211
242
243212 def createPlugin(ignore_info=False):
244213 return W3afPlugin(ignore_info=ignore_info)
245
246
44
55 """
66 import re
7 import xml.etree.ElementTree as ET
78 from urllib.parse import urlparse
9
810 from faraday_plugins.plugins.plugin import PluginXMLFormat
911 from faraday_plugins.plugins.plugins_utils import resolve_hostname
10
11 try:
12 import xml.etree.cElementTree as ET
13 import xml.etree.ElementTree as ET_ORIG
14 ETREE_VERSION = ET_ORIG.VERSION
15 except ImportError:
16 import xml.etree.ElementTree as ET
17 ETREE_VERSION = ET.VERSION
18
19 ETREE_VERSION = [int(i) for i in ETREE_VERSION.split(".")]
20
2112
2213 __author__ = "Francisco Amato"
2314 __copyright__ = "Copyright (c) 2013, Infobyte LLC"
7263 yield Item(tree)
7364
7465
75
7666 def get_attrib_from_subnode(xml_node, subnode_xpath_expr, attrib_name):
7767 """
7868 Finds a subnode in the item node and the retrieves a value from it
7969
8070 @return An attribute value
8171 """
82 global ETREE_VERSION
83 node = None
84
85 if ETREE_VERSION[0] <= 1 and ETREE_VERSION[1] < 3:
86 match_obj = re.search(
87 "([^\@]+?)\[\@([^=]*?)=\'([^\']*?)\'", subnode_xpath_expr)
88 if match_obj is not None:
89 node_to_find = match_obj.group(1)
90 xpath_attrib = match_obj.group(2)
91 xpath_value = match_obj.group(3)
92 for node_found in xml_node.findall(node_to_find):
93 if node_found.attrib[xpath_attrib] == xpath_value:
94 node = node_found
95 break
96 else:
97 node = xml_node.find(subnode_xpath_expr)
98 else:
99 node = xml_node.find(subnode_xpath_expr)
72
73 node = xml_node.find(subnode_xpath_expr)
10074 if node is not None:
10175 return node.get(attrib_name)
10276 return None
147121 target = self.get_info(item_node, 'target')
148122 return urlparse(target)
149123
150 def get_info(self, item_node,name):
124 def get_info(self, item_node, name):
151125 path = item_node.findall('report_infos/info')
152126
153127 for item in path:
170144 for vuln in vulns_node:
171145 vulns_dict = {}
172146 vulns_dict['id'] = vuln.attrib['name']
173 vulns_dict['description'] = self.get_text_from_subnode(vuln,'description')
174 vulns_dict['solution'] = self.get_text_from_subnode(vuln,'solution')
147 vulns_dict['description'] = self.get_text_from_subnode(vuln, 'description')
148 vulns_dict['solution'] = self.get_text_from_subnode(vuln, 'solution')
175149 vulns_dict['references'] = self.get_references(vuln)
176150 vulns_dict['entries'] = self.get_entries(vuln)
177151 vulns_list.append(vulns_dict)
182156 refs = node.findall('references/reference')
183157 references_list = []
184158 for ref in refs:
185 references_list.append('Title: ' + self.get_text_from_subnode(ref,'title'))
186 references_list.append('URL: ' + self.get_text_from_subnode(ref,'url'))
159 references_list.append('Title: ' + self.get_text_from_subnode(ref, 'title'))
160 references_list.append('URL: ' + self.get_text_from_subnode(ref, 'url'))
187161
188162 return references_list
189163
190 def get_entries(self,node):
164 def get_entries(self, node):
191165 entries = node.findall('entries/entry')
192166 entries_list = []
193167 for entry in entries:
194168 entries_dict = {}
195 entries_dict['method'] = self.get_text_from_subnode(entry,'method')
196 entries_dict['path'] = self.get_text_from_subnode(entry,'path')
169 entries_dict['method'] = self.get_text_from_subnode(entry, 'method')
170 entries_dict['path'] = self.get_text_from_subnode(entry, 'path')
197171 entries_dict['level'] = self.severity_format(entry)
198 entries_dict['parameter'] = self.get_text_from_subnode(entry,'parameter')
199 entries_dict['http_request'] = self.get_text_from_subnode(entry,'http_request')
200 entries_dict['curl_command'] = self.get_text_from_subnode(entry,'curl_command')
172 entries_dict['parameter'] = self.get_text_from_subnode(entry, 'parameter')
173 entries_dict['http_request'] = self.get_text_from_subnode(entry, 'http_request')
174 entries_dict['curl_command'] = self.get_text_from_subnode(entry, 'curl_command')
201175 entries_list.append(entries_dict)
202176
203177 return entries_list
288262 return re.search("Wapiti", output) is not None
289263 return False
290264
291
292265 def parseOutputString(self, output):
293266 """
294267 This method will discard the output the shell sends, it will read it from
295268 the xml where it expects it to be present.
296269 """
297
270
298271 parser = WapitiXmlParser(output)
299272 for item in parser.items:
300273 host_id = self.createAndAddHost(item.ip, hostnames=[item.hostname])
306279 for vuln in item.vulns:
307280 for entry in vuln['entries']:
308281 vuln_id = self.createAndAddVulnWebToService(host_id,
309 service_id,
310 vuln['id'],
311 desc=vuln['description'],
312 ref=vuln['references'],
313 resolution=vuln['solution'],
314 severity=entry['level'],
315 website=entry['curl_command'],
316 path=entry['path'],
317 request=entry['http_request'],
318 method=entry['method'],
319 params=entry['parameter'])
282 service_id,
283 vuln['id'],
284 desc=vuln['description'],
285 ref=vuln['references'],
286 resolution=vuln['solution'],
287 severity=entry['level'],
288 website=entry['curl_command'],
289 path=entry['path'],
290 request=entry['http_request'],
291 method=entry['method'],
292 params=entry['parameter'])
320293
321294 def processCommandString(self, username, current_path, command_string):
322295 """
338311 self.port = host.group(11)
339312 if self.protocol == 'https':
340313 self.port = 443
341 self.logger.debug("host = %s, port = %s",self.host, self.port)
314 self.logger.debug("host = %s, port = %s", self.host, self.port)
342315 return "%s -o %s -f xml \n" % (command_string, self._output_file_path)
343
344 def setHost(self):
345 pass
346316
347317
348318 def createPlugin(ignore_info=False):
349319 return WapitiPlugin(ignore_info=ignore_info)
350
351
22 Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/)
33 See the file 'doc/LICENSE' for the license information
44 """
5 import re
6 import xml.etree.ElementTree as ET
7
58 from faraday_plugins.plugins.plugin import PluginBase
6 import re
7 import os
8 import sys
9 import random
10
11 try:
12 import xml.etree.cElementTree as ET
13 import xml.etree.ElementTree as ET_ORIG
14 ETREE_VERSION = ET_ORIG.VERSION
15 except ImportError:
16 import xml.etree.ElementTree as ET
17 ETREE_VERSION = ET.VERSION
18
19 ETREE_VERSION = [int(i) for i in ETREE_VERSION.split(".")]
20
219
2210 __author__ = "Morgan Lemarechal"
2311 __copyright__ = "Copyright 2014, Faraday Project"
9179 self._temp_file_extension = "xml"
9280 self.xml_arg_re = re.compile(r"^.*(--xml\s*[^\s]+).*$")
9381
94
9582 def parseOutputString(self, output):
9683 """
9784 This method will discard the output the shell sends, it will read it from
114101 if parser.scaninfo[file]['type'] == "webconfig":
115102 vuln_name = f"{parser.scaninfo[file]['file']}: {str(parser.result[file][vuln][3])}"
116103 vuln_description = f"{str(parser.result[file][vuln][3])} : {str(parser.result[file][vuln][2])} = {str(parser.result[file][vuln][0])}\n{str(parser.result[file][vuln][1])}"
117 v_id = self.createAndAddVulnToService(h_id, s_id, vuln_name, desc=vuln_description, severity=0)
118
119
104 self.createAndAddVulnToService(h_id, s_id, vuln_name, desc=vuln_description, severity=0)
120105
121106 def processCommandString(self, username, current_path, command_string):
122107 """
134119
135120 def createPlugin(ignore_info=False):
136121 return WcscanPlugin(ignore_info=ignore_info)
137
138
77 from faraday_plugins.plugins.plugin import PluginXMLFormat
88 from faraday_plugins.plugins.plugins_utils import get_vulnweb_url_fields
99
10 try:
11 import xml.etree.cElementTree as ET
12 except ImportError:
13 import xml.etree.ElementTree as ET
10 import xml.etree.ElementTree as ET
1411
1512
1613 def cleanhtml(raw_html):
33 See the file 'doc/LICENSE' for the license information
44
55 """
6 import os
7 import re
8 import xml.etree.ElementTree as ET
9
610 from faraday_plugins.plugins.plugin import PluginXMLFormat
7 import re
8 import os
9 import sys
10
11 try:
12 import xml.etree.cElementTree as ET
13 import xml.etree.ElementTree as ET_ORIG
14 ETREE_VERSION = ET_ORIG.VERSION
15 except ImportError:
16 import xml.etree.ElementTree as ET
17 ETREE_VERSION = ET.VERSION
18
19 ETREE_VERSION = [int(i) for i in ETREE_VERSION.split(".")]
2011
2112 current_path = os.path.abspath(os.getcwd())
2213
133124 self.resolution = self.get_text_from_subnode('solution')
134125 self.ref = []
135126 for r in issue_node.findall('refs/reference'):
136
137127 self.ref.append(r.get('type') + "-" + r.get('text'))
138128
139129 def get_text_from_subnode(self, subnode_xpath_expr):
166156 self._current_output = None
167157 self._command_regex = re.compile(r'^(sudo x1|\.\/x1)\s+.*?')
168158
169
170
171159 def parseOutputString(self, output):
172160
173161 parser = X1XmlParser(output)
188176 del parser
189177
190178
191 def setHost(self):
192 pass
193
194
195179 def createPlugin(ignore_info=False):
196180 return X1Plugin(ignore_info=ignore_info)
197
198
+0
-163
faraday_plugins/plugins/repo/zap/java/Configuration.java less more
0 /*
1 * Zed Attack Proxy (ZAP) and its related class files.
2 *
3 * ZAP is an HTTP/HTTPS proxy for assessing web application security.
4 *
5 * Copyright 2018 The ZAP Development Team
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20 package org.zaproxy.zap.extension.faraday;
21
22 import org.parosproxy.paros.Constant;
23
24 import javax.swing.*;
25 import java.io.*;
26 import java.util.Properties;
27
28 public class Configuration {
29 private String server;
30 private String user;
31 private String password;
32 private String session;
33 private String workspace;
34 private boolean autoImport;
35 private static Configuration _instance;
36
37 private Configuration() {
38 this.user = "";
39 this.password = "";
40 this.server = "http://127.0.0.1:5985/";
41 this.autoImport = false;
42 }
43
44 public static Configuration getSingleton() {
45 if (_instance == null)
46 _instance = new Configuration();
47 return _instance;
48 }
49
50 public boolean save() throws IOException {
51
52 Properties prop = new Properties();
53 OutputStream output = null;
54
55 String userHome = System.getProperty("user.home");
56 String outputFolder = Constant.getZapHome() + "faraday";
57 File folder = new File(outputFolder);
58 if (!folder.exists()) {
59 folder.mkdir();
60 }
61
62
63 String filePath = outputFolder + File.separator + this.getUser() + ".properties";
64 output = new FileOutputStream(filePath);
65
66 // set the properties value
67 prop.setProperty("fuser", this.getUser());
68 prop.setProperty("fpassword", this.getPassword());
69 prop.setProperty("fserver", this.getServer());
70 prop.setProperty("fworkspace", this.getWorkspace());
71 prop.setProperty("fsession", this.getSession());
72
73 // save properties to project root folder
74 prop.store(output, null);
75
76 if (output != null) {
77 try {
78 output.close();
79 } catch (IOException e) {
80 e.printStackTrace();
81 return false;
82 }
83 }
84
85 return true;
86 }
87
88
89 public void restore(String fUser) throws IOException {
90 Properties prop = new Properties();
91 InputStream input = null;
92
93 String outputFolder = Constant.getZapHome() + "faraday";
94 String filePath = outputFolder + File.separator + fUser + ".properties";
95 input = new FileInputStream(filePath);
96
97 // load a properties file
98 prop.load(input);
99
100 this.setUser(prop.getProperty("fuser"));
101 this.setPassword(prop.getProperty("fpassword"));
102 this.setServer(prop.getProperty("fserver"));
103 this.setWorkspace(prop.getProperty("fworkspace"));
104
105 if (input != null) {
106 try {
107 input.close();
108 } catch (IOException e) {
109 e.printStackTrace();
110 }
111 }
112
113 }
114
115 public String getUser() {
116 return user;
117 }
118
119 public void setUser(String user) {
120 this.user = user;
121 }
122
123 public String getPassword() {
124 return password;
125 }
126
127 public void setPassword(String password) {
128 this.password = password;
129 }
130
131 public String getServer() {
132 return server;
133 }
134
135 public void setServer(String server) {
136 this.server = server;
137 }
138
139 public boolean isAutoImport() {
140 return autoImport;
141 }
142
143 public void setAutoImport(boolean autoImport) {
144 this.autoImport = autoImport;
145 }
146
147 public String getSession() {
148 return session;
149 }
150
151 public void setSession(String session) {
152 this.session = session;
153 }
154
155 public String getWorkspace() {
156 return workspace;
157 }
158
159 public void setWorkspace(String workspace) {
160 this.workspace = workspace;
161 }
162 }
+0
-589
faraday_plugins/plugins/repo/zap/java/ConfigurationDialog.java less more
0 package org.zaproxy.zap.extension.faraday;
1
2
3 import org.apache.log4j.Logger;
4 import org.parosproxy.paros.Constant;
5
6 import javax.swing.*;
7 import javax.swing.border.Border;
8 import java.awt.*;
9 import java.awt.event.*;
10 import java.io.*;
11 import java.util.ArrayList;
12 import java.util.Properties;
13 import java.util.ResourceBundle;
14
15 public class ConfigurationDialog extends JFrame {
16 private static final Logger logger = Logger.getLogger(ConfigurationDialog.class);
17 private ResourceBundle messages = null;
18 private FaradayClient faradayClient;
19
20 private static String LOGIN_BUTTON = "Login";
21 private static String LOGOUT_BUTTON = "Logout";
22 private static String WORKSPACES_FIELD = "Select faraday workspace";
23 private static String IMPORT_NEW_VULNS_FIELD = "Import new vulnerabilities";
24 private static String SET_CONFIG_AS_DEFAULT = "Set this configuration as default";
25 private static String IMPORT_BUTTON = "Import vulnerabilities";
26 private static String REFRESH_BUTTON = "Refresh";
27 private static String RESTORE_BUTTON = "Restore";
28 private static String SAVE_BUTTON = "Save";
29
30 private JTabbedPane tabbedPane;
31 private JPanel authPanel;
32 private JPanel configPanel;
33
34 private JTextField fldUser;
35 private JTextField fldPass;
36 private JTextField fldServer;
37
38 private JComboBox cmbWorkspaces;
39 private JCheckBox cboxSetConfigDefault;
40
41
42 private JButton loginButton;
43 private JButton logoutButton;
44 private JButton refreshButton;
45 private JButton restoreButton;
46 private JButton importButton;
47 private JButton saveButton;
48 private JButton closeButton;
49
50
51 public ConfigurationDialog(String s) throws HeadlessException {
52 super(s);
53 }
54
55
56 public void init() {
57 logger.debug("Init Faraday configuration dialog");
58 messages = ResourceBundle.getBundle(
59 this.getClass().getPackage().getName() +
60 ".Messages", Constant.getLocale());
61 // Setup the content-pane of JFrame in BorderLayout
62 Container cp = this.getContentPane();
63 cp.setLayout(new BorderLayout(5, 5));
64 Border padding = BorderFactory.createEmptyBorder(10, 10, 10, 10);
65
66
67 String USERNAME_FIELD = messages.getString("faraday.config.dialog.auth.user");
68 String PASS_FIELD = messages.getString("faraday.config.dialog.auth.pass");
69 String SERVER_FIELD = messages.getString("faraday.config.dialog.server");
70 LOGIN_BUTTON = messages.getString("faraday.config.dialog.auth.login");
71 LOGOUT_BUTTON = messages.getString("faraday.config.dialog.auth.logout");
72 WORKSPACES_FIELD = messages.getString("faraday.config.dialog.workspace");
73 IMPORT_NEW_VULNS_FIELD = messages.getString("faraday.config.dialog.import.new");
74 SET_CONFIG_AS_DEFAULT = messages.getString("faraday.config.dialog.default");
75 IMPORT_BUTTON = messages.getString("faraday.config.dialog.import.new");
76 REFRESH_BUTTON = messages.getString("faraday.config.dialog.refresh");
77 RESTORE_BUTTON = messages.getString("faraday.config.dialog.restore");
78 SAVE_BUTTON = messages.getString("faraday.config.dialog.save");
79 tabbedPane = new JTabbedPane();
80
81 JPanel buttonLoginPanel = new JPanel();
82 buttonLoginPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
83
84 JPanel buttonConfigPanel = new JPanel();
85 buttonConfigPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
86
87 authPanel = new JPanel(new GridLayout(4, 2, 10, 2));
88 authPanel.setBorder(padding);
89 configPanel = new JPanel(new GridLayout(3, 2, 10, 2));
90 configPanel.setBorder(padding);
91
92
93 Configuration configuration = Configuration.getSingleton();
94 faradayClient = new FaradayClient(configuration.getServer());
95
96 authPanel.add(new JLabel(USERNAME_FIELD));
97 fldUser = new JTextField(10);
98 authPanel.add(fldUser);
99
100 authPanel.add(new JLabel(PASS_FIELD));
101 fldPass = new JPasswordField(10);
102 authPanel.add(fldPass);
103
104 authPanel.add(new JLabel(SERVER_FIELD));
105 fldServer = new JTextField(10);
106 fldServer.setText(configuration.getServer());
107 authPanel.add(fldServer);
108
109 configPanel.add(getCBoxSetDefaultConfig());
110
111 buttonConfigPanel.add(getCloseButton());
112 buttonConfigPanel.add(getCloseButton());
113 buttonConfigPanel.add(getRefreshButton());
114 buttonConfigPanel.add(getRestoreButton());
115 buttonConfigPanel.add(getSaveButton());
116 // buttonConfigPanel.add(getImportButton());
117 buttonConfigPanel.add(getLoginButton());
118 buttonConfigPanel.add(getLogoutButton());
119
120
121 authPanel.addComponentListener(new ComponentListener() {
122 @Override
123 public void componentResized(ComponentEvent componentEvent) {
124
125 }
126
127 @Override
128 public void componentMoved(ComponentEvent componentEvent) {
129
130 }
131
132 @Override
133 public void componentShown(ComponentEvent componentEvent) {
134
135 refreshButton.setVisible(false);
136 restoreButton.setVisible(false);
137 // importButton.setVisible(false);
138 saveButton.setVisible(false);
139 }
140
141 @Override
142 public void componentHidden(ComponentEvent componentEvent) {
143 refreshButton.setVisible(true);
144 restoreButton.setVisible(true);
145 // importButton.setVisible(true);
146 saveButton.setVisible(true);
147 }
148 });
149
150 configPanel.addComponentListener(new ComponentListener() {
151 @Override
152 public void componentResized(ComponentEvent componentEvent) {
153
154 }
155
156 @Override
157 public void componentMoved(ComponentEvent componentEvent) {
158
159 }
160
161 @Override
162 public void componentShown(ComponentEvent componentEvent) {
163 loginButton.setVisible(false);
164 logoutButton.setVisible(false);
165 }
166
167 @Override
168 public void componentHidden(ComponentEvent componentEvent) {
169 if (configuration.getSession().equals("")) {
170 loginButton.setVisible(true);
171 } else {
172 logoutButton.setVisible(true);
173 }
174 }
175 });
176
177 tabbedPane.addTab(messages.getString("faraday.config.dialog.tab.auth"), null, authPanel, null);
178 tabbedPane.setMnemonicAt(0, KeyEvent.VK_1);
179
180
181 tabbedPane.addTab(messages.getString("faraday.config.dialog.tabs.conf"), null, configPanel, null);
182 tabbedPane.setMnemonicAt(1, KeyEvent.VK_2);
183
184 tabbedPane.setEnabledAt(1, false);
185
186 cp.add(tabbedPane, BorderLayout.NORTH);
187 cp.add(buttonConfigPanel, BorderLayout.SOUTH);
188
189 if (configuration.getSession() != null && !configuration.getSession().equals("")) {
190 logoutButton.setVisible(true);
191 loginButton.setVisible(false);
192 } else {
193 loginButton.setVisible(true);
194 logoutButton.setVisible(false);
195 }
196
197
198 if (!configuration.getUser().equals("") && !configuration.getPassword().equals("")) {
199 if (faradayClient.Login(configuration.getUser(), configuration.getPassword(), configuration.getServer())) {
200 fldUser.setText(configuration.getUser());
201 fldPass.setText(configuration.getPassword());
202 fldServer.setText(configuration.getServer());
203
204 tabbedPane.setEnabledAt(1, true);
205 tabbedPane.setSelectedIndex(1);
206
207 cboxSetConfigDefault.setSelected(true);
208
209 if (cmbWorkspaces == null) {
210 configPanel.add(new JLabel(WORKSPACES_FIELD));
211 configPanel.add(getWSComboBox());
212 }
213 }
214 }
215
216 this.setSize(550, 300);
217 this.setResizable(false);
218 this.setLocationRelativeTo(null);
219 this.setVisible(true);
220 }
221
222
223 private JButton getLoginButton() {
224 if (this.loginButton == null) {
225 this.loginButton = new JButton();
226 this.loginButton.setText(LOGIN_BUTTON);
227 this.loginButton.addActionListener(new ActionListener() {
228 public void actionPerformed(ActionEvent e) {
229 if (fldUser.getText().equals("") || fldPass.getText().equals("") || fldServer.getText().equals("")) {
230 showMessage(messages.getString("faraday.message.invalid.check.credentials"), messages.getString("faraday.dialog.login.title"), JOptionPane.ERROR_MESSAGE);
231 } else {
232 if (faradayClient.Login(fldUser.getText(), fldPass.getText(), fldServer.getText())) {
233 logoutButton.setVisible(true);
234 loginButton.setVisible(false);
235 if (!tabbedPane.isEnabledAt(1)) {
236 tabbedPane.setEnabledAt(1, true);
237 }
238 tabbedPane.setSelectedIndex(1);
239 if (cmbWorkspaces == null) {
240 configPanel.add(new JLabel(WORKSPACES_FIELD));
241 configPanel.add(getWSComboBox());
242 } else {
243 configPanel.remove(cmbWorkspaces);
244 configPanel.add(getWSComboBox());
245 }
246 } else {
247 showMessage(messages.getString("faraday.message.invalid.credentials"), messages.getString("faraday.dialog.login.title"), JOptionPane.ERROR_MESSAGE);
248 }
249 }
250
251
252 }
253 });
254
255
256 }
257
258 return this.loginButton;
259 }
260
261
262 private JButton getLogoutButton() {
263 if (this.logoutButton == null) {
264 this.logoutButton = new JButton();
265 this.logoutButton.setText(LOGOUT_BUTTON);
266 this.logoutButton.addActionListener(new ActionListener() {
267 public void actionPerformed(ActionEvent e) {
268 Configuration configuration = Configuration.getSingleton();
269 String userTemp = configuration.getUser();
270 if (faradayClient.Logout()) {
271 logoutButton.setVisible(false);
272 loginButton.setVisible(true);
273
274 if (tabbedPane.isEnabledAt(1)) {
275 tabbedPane.setEnabledAt(1, false);
276 }
277 tabbedPane.setSelectedIndex(0);
278
279 Properties prop = new Properties();
280 InputStream input = null;
281 try {
282 String filePath = Constant.getZapHome() + "faraday" + File.separator + "default.properties";
283 input = new FileInputStream(filePath);
284 // load a properties file
285 prop.load(input);
286 // set the properties value
287 String fUser = prop.getProperty("default");
288 if (fUser.equals(userTemp)) {
289 removeDefaultConfig();
290 }
291
292 } catch (IOException io) {
293 System.out.println("We can't found default.properties file");
294 } finally {
295 if (input != null) {
296 try {
297 input.close();
298 } catch (IOException er) {
299 er.printStackTrace();
300 }
301 }
302 }
303
304
305 showMessage(messages.getString("faraday.dialog.logout.success"), messages.getString("faraday.dialog.logout.title"), JOptionPane.INFORMATION_MESSAGE);
306 } else {
307 showMessage(messages.getString("faraday.dialog.logout.error"), messages.getString("faraday.dialog.logout.title"), JOptionPane.ERROR_MESSAGE);
308 }
309 }
310 });
311 }
312
313 return this.logoutButton;
314 }
315
316
317 private JButton getRefreshButton() {
318 if (this.refreshButton == null) {
319 this.refreshButton = new JButton();
320 this.refreshButton.setText(REFRESH_BUTTON);
321 this.refreshButton.addActionListener(new ActionListener() {
322 public void actionPerformed(ActionEvent e) {
323 refreshWorkspaces(true);
324 }
325 });
326 }
327
328 return this.refreshButton;
329 }
330
331
332 private JButton getCloseButton() {
333 if (this.closeButton == null) {
334 this.closeButton = new JButton();
335 this.closeButton.setText(messages.getString("faraday.dialog.button.close"));
336 this.closeButton.addActionListener(new ActionListener() {
337 public void actionPerformed(ActionEvent e) {
338 setVisible(false);
339 dispose();
340 }
341 });
342 }
343
344 return this.closeButton;
345 }
346
347
348 private JButton getRestoreButton() {
349 if (this.restoreButton == null) {
350 this.restoreButton = new JButton();
351 this.restoreButton.setText(RESTORE_BUTTON);
352 this.restoreButton.addActionListener(new ActionListener() {
353 public void actionPerformed(ActionEvent e) {
354 String fUser = JOptionPane.showInputDialog(messages.getString("faraday.config.dialog.restore"), messages.getString("faraday.dialog.enter.user"));
355 if (fUser != null) {
356 restoreConfiguration(fUser);
357 }
358 }
359 });
360 }
361
362 return this.restoreButton;
363 }
364
365
366 private JButton getImportButton() {
367 if (this.importButton == null) {
368 this.importButton = new JButton();
369 this.importButton.setText(IMPORT_BUTTON);
370 this.importButton.addActionListener(new ActionListener() {
371 public void actionPerformed(ActionEvent e) {
372
373 }
374 });
375 }
376
377 return this.importButton;
378 }
379
380
381 private JButton getSaveButton() {
382 if (this.saveButton == null) {
383 this.saveButton = new JButton();
384 this.saveButton.setText(SAVE_BUTTON);
385 this.saveButton.addActionListener(new ActionListener() {
386 public void actionPerformed(ActionEvent e) {
387 saveConfiguration();
388 }
389 });
390 }
391
392 return this.saveButton;
393 }
394
395
396 private JComboBox getWSComboBox() {
397 Configuration configuration = Configuration.getSingleton();
398
399 ArrayList<String> wsList = faradayClient.GetWorkspaces();
400 String[] workspaces = new String[wsList.size()];
401 for (int i = 0; i < wsList.size(); i++) {
402 workspaces[i] = wsList.get(i);
403 }
404 cmbWorkspaces = new JComboBox(workspaces);
405 if (workspaces.length > 0) {
406 if (configuration.getWorkspace() != null) {
407 cmbWorkspaces.setSelectedItem(configuration.getWorkspace());
408 } else {
409 configuration.setWorkspace(workspaces[0]);
410 }
411 }
412 cmbWorkspaces.addActionListener(new ActionListener() {
413 @Override
414 public void actionPerformed(ActionEvent actionEvent) {
415 Configuration.getSingleton().setWorkspace(cmbWorkspaces.getSelectedItem().toString());
416 }
417 });
418
419
420 return cmbWorkspaces;
421 }
422
423
424 private JCheckBox getCBoxSetDefaultConfig() {
425 if (this.cboxSetConfigDefault == null) {
426 cboxSetConfigDefault = new JCheckBox(SET_CONFIG_AS_DEFAULT, false);
427
428 cboxSetConfigDefault.addActionListener(new ActionListener() {
429 @Override
430 public void actionPerformed(ActionEvent actionEvent) {
431 if (cboxSetConfigDefault.isSelected()) {
432 setConfigAsDefault();
433 } else {
434 removeDefaultConfig();
435 }
436 }
437 });
438 }
439
440 return cboxSetConfigDefault;
441 }
442
443
444 private void showMessage(String message, String title, int icon) {
445 JOptionPane.showMessageDialog(
446 this,
447 message,
448 title,
449 icon);
450 }
451
452
453 private void saveConfiguration() {
454 try {
455 if (Configuration.getSingleton().save()) {
456 JOptionPane.showMessageDialog(
457 this,
458 messages.getString("faraday.save.config.success"),
459 messages.getString("faraday.config.dialog.title"),
460 JOptionPane.INFORMATION_MESSAGE);
461 } else {
462 JOptionPane.showMessageDialog(
463 this,
464 messages.getString("faraday.save.config.error"),
465 messages.getString("faraday.config.dialog.title"),
466 JOptionPane.ERROR_MESSAGE);
467
468 }
469 } catch (IOException io) {
470 JOptionPane.showMessageDialog(
471 this,
472 messages.getString("faraday.save.config.error"),
473 messages.getString("faraday.config.dialog.title"),
474 JOptionPane.ERROR_MESSAGE);
475 io.printStackTrace();
476
477 }
478 }
479
480
481 private void restoreConfiguration(String fUser) {
482 try {
483 Configuration configuration = Configuration.getSingleton();
484 configuration.restore(fUser);
485 if (faradayClient.Login(configuration.getUser(), configuration.getPassword(), configuration.getServer())) {
486 fldUser.setText(configuration.getUser());
487 fldPass.setText(configuration.getPassword());
488 fldServer.setText(configuration.getServer());
489
490 tabbedPane.setEnabledAt(1, true);
491 tabbedPane.setSelectedIndex(0);
492
493 cboxSetConfigDefault.setSelected(false);
494 refreshWorkspaces(false);
495 } else {
496 JOptionPane.showMessageDialog(
497 this,
498 messages.getString("faraday.restore.config.error.login"),
499 messages.getString("faraday.config.dialog.title"),
500 JOptionPane.ERROR_MESSAGE);
501 }
502 } catch (IOException ex) {
503 JOptionPane.showMessageDialog(
504 this,
505 messages.getString("faraday.restore.config.error"),
506 messages.getString("faraday.config.dialog.title"),
507 JOptionPane.ERROR_MESSAGE);
508 }
509
510 }
511
512
513 private void setConfigAsDefault() {
514 Configuration configuration = Configuration.getSingleton();
515
516 Properties prop = new Properties();
517 OutputStream output = null;
518
519 try {
520 String outputFolder = Constant.getZapHome() + "faraday";
521 File folder = new File(outputFolder);
522 if (!folder.exists()) {
523 folder.mkdir();
524 }
525
526 String filePath = outputFolder + File.separator + "default.properties";
527 output = new FileOutputStream(filePath);
528
529 // set the properties value
530 prop.setProperty("default", configuration.getUser());
531
532 // save properties to project root folder
533 prop.store(output, null);
534
535 } catch (IOException io) {
536 JOptionPane.showMessageDialog(
537 this,
538 messages.getString("faraday.set.default.config.error"),
539 messages.getString("faraday.config.dialog.title"),
540 JOptionPane.ERROR_MESSAGE);
541 io.printStackTrace();
542 } finally {
543 if (output != null) {
544 try {
545 output.close();
546 } catch (IOException e) {
547 e.printStackTrace();
548 }
549 }
550
551 }
552 }
553
554
555 private void removeDefaultConfig() {
556 try {
557
558 String filePath = Constant.getZapHome() + "faraday" + File.separator + "default.properties";
559 File file = new File(filePath);
560 if (file.delete()) {
561 System.out.println(file.getName() + " is deleted!");
562 } else {
563 System.out.println("Delete operation is failed.");
564 }
565
566 } catch (Exception e) {
567
568 e.printStackTrace();
569
570 }
571 }
572
573
574 private void refreshWorkspaces(boolean canShowAlert) {
575 if (cmbWorkspaces != null) {
576 configPanel.remove(cmbWorkspaces);
577 configPanel.add(getWSComboBox());
578 if (canShowAlert) {
579 JOptionPane.showMessageDialog(
580 this,
581 messages.getString("faraday.refresh.workspace.done"),
582 messages.getString("faraday.config.dialog.title"),
583 JOptionPane.INFORMATION_MESSAGE);
584 }
585 }
586 }
587
588 }
+0
-525
faraday_plugins/plugins/repo/zap/java/FaradayClient.java less more
0 package org.zaproxy.zap.extension.faraday;
1
2 import net.sf.json.JSONArray;
3 import net.sf.json.JSONObject;
4 import org.apache.commons.httpclient.URIException;
5 import org.apache.commons.httpclient.methods.PostMethod;
6 import org.apache.http.HttpEntity;
7 import org.apache.http.HttpResponse;
8
9 import org.apache.http.client.ClientProtocolException;
10 import org.apache.http.client.HttpClient;
11 import org.apache.http.entity.StringEntity;
12 import org.apache.http.client.entity.UrlEncodedFormEntity;
13 import org.apache.http.client.methods.HttpGet;
14 import org.apache.http.client.methods.HttpPost;
15 import org.apache.http.impl.client.HttpClients;
16 import org.apache.http.NameValuePair;
17 import org.apache.http.message.BasicNameValuePair;
18 import org.apache.http.util.EntityUtils;
19 import org.parosproxy.paros.Constant;
20 import org.parosproxy.paros.core.scanner.Alert;
21 import org.parosproxy.paros.model.HistoryReference;
22
23 import java.io.*;
24 import java.net.*;
25 import java.nio.charset.StandardCharsets;
26 import java.sql.Time;
27 import java.time.Instant;
28 import java.util.*;
29
30
31 public class FaradayClient {
32
33 private String baseUrl;
34 private ResourceBundle messages = null;
35
36 public FaradayClient(String baseUrl) {
37 this.baseUrl = baseUrl;
38 messages = ResourceBundle.getBundle(
39 this.getClass().getPackage().getName() +
40 ".Messages", Constant.getLocale());
41
42 }
43
44 public boolean Login(String username, String password, String server) {
45 Logout();
46 HttpClient httpClient = HttpClients.createDefault();
47 String LOGIN_URL = "_api/login";
48 HttpPost httpPost = new HttpPost(server + LOGIN_URL);
49
50 // Request parameters and other properties.
51 List<BasicNameValuePair> params = new ArrayList<>(2);
52 params.add(new BasicNameValuePair("email", username));
53 params.add(new BasicNameValuePair("password", password));
54
55 try {
56 httpPost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
57 HttpResponse response = httpClient.execute(httpPost);
58 if (response.getFirstHeader("Set-Cookie") != null) {
59 Configuration configuration = Configuration.getSingleton();
60 configuration.setSession(response.getFirstHeader("Set-Cookie").getValue());
61 configuration.setUser(username);
62 configuration.setPassword(password);
63 configuration.setServer(server);
64 setBaseUrl(server);
65 return true;
66 } else if (response.getStatusLine().getStatusCode() == 302) {
67 return true;
68 }
69 return false;
70 } catch (UnsupportedEncodingException e) {
71 // writing error to Log
72 e.printStackTrace();
73 return false;
74 } catch (ClientProtocolException e) {
75 e.printStackTrace();
76 return false;
77 } catch (IOException e) {
78 e.printStackTrace();
79 return false;
80 }
81
82 }
83
84 public boolean Logout() {
85 String LOGOUT_URL = "_api/logout";
86 HttpGet httpGet = new HttpGet(this.baseUrl + LOGOUT_URL);
87 Configuration configuration = Configuration.getSingleton();
88
89 if (!Objects.equals(configuration.getSession(), "")) {
90 httpGet.setHeader("Cookie", configuration.getSession());
91
92 //Execute and get the response.
93 HttpResponse response = null;
94
95 try {
96 HttpClient httpClient = HttpClients.createDefault();
97 response = httpClient.execute(httpGet);
98 HttpEntity entity = response.getEntity();
99 if (response.getStatusLine().getStatusCode() == 200) {
100 configuration.setSession("");
101 configuration.setUser("");
102 configuration.setPassword("");
103 return true;
104 }
105 return false;
106 } catch (IOException e) {
107 e.printStackTrace();
108 return false;
109 }
110 }
111 return true;
112 }
113
114 public ArrayList<String> GetWorkspaces() {
115 ArrayList<String> workspaces = new ArrayList<>();
116 String WORKSPACES_URL = "_api/v2/ws/";
117 HttpGet httpGet = new HttpGet(this.baseUrl + WORKSPACES_URL);
118 Configuration configuration = Configuration.getSingleton();
119
120 if (configuration.getSession() != "") {
121 httpGet.setHeader("Cookie", configuration.getSession());
122
123 //Execute and get the response.
124 HttpResponse response = null;
125 InputStream instream = null;
126 try {
127 HttpClient httpClient = HttpClients.createDefault();
128 response = httpClient.execute(httpGet);
129 HttpEntity entity = response.getEntity();
130
131 if (entity != null && response.getStatusLine().getStatusCode() == 200) {
132 instream = entity.getContent();
133
134 BufferedReader br = new BufferedReader(new InputStreamReader(instream));
135 String output;
136 JSONArray jsonArray = new JSONArray();
137 while ((output = br.readLine()) != null) {
138 System.out.println(output);
139 jsonArray = JSONArray.fromObject(output);
140 }
141
142 for (int i = 0; i < jsonArray.size(); i++) {
143 JSONObject jsonObject = jsonArray.getJSONObject(i);
144 workspaces.add(jsonObject.get("name").toString());
145 }
146 }
147 } catch (IOException e) {
148 e.printStackTrace();
149 } finally {
150 try {
151 instream.close();
152 } catch (IOException e) {
153 e.printStackTrace();
154 }
155 }
156 }
157
158 return workspaces;
159 }
160
161
162 private int AddCommand(String commandName, String workspace, String session) {
163 String COMMAND_URL = "_api/v2/ws/" + workspace + "/commands/";
164 HttpClient httpClient = HttpClients.createDefault();
165 HttpPost httpPost = new HttpPost(this.baseUrl + COMMAND_URL);
166
167 try {
168 StringEntity stringEntity = new StringEntity(ConvertCommandToParams(commandName).toString());
169 httpPost.setHeader("Cookie", session);
170 httpPost.setHeader("Content-Type", "application/json");
171 httpPost.setEntity(stringEntity);
172 HttpResponse response = httpClient.execute(httpPost);
173 HttpEntity entity = response.getEntity();
174
175 if (response.getStatusLine().getStatusCode() == 200 || response.getStatusLine().getStatusCode() == 201 || response.getStatusLine().getStatusCode() == 409) {
176 BufferedReader br = new BufferedReader(new InputStreamReader(entity.getContent()));
177 String output;
178 JSONObject json;
179 String commandStr = "-1";
180 while ((output = br.readLine()) != null) {
181 json = JSONObject.fromObject(output);
182 if (response.getStatusLine().getStatusCode() == 409) {
183 JSONObject jsonObject = JSONObject.fromObject(json.get("object"));
184 commandStr = jsonObject.get("_id").toString();
185 } else {
186 commandStr = json.get("_id").toString();
187 }
188 }
189 return Integer.parseInt(commandStr);
190 }
191 return -1;
192 } catch (UnsupportedEncodingException e) {
193 // writing error to Log
194 e.printStackTrace();
195 return -1;
196 } catch (ClientProtocolException e) {
197 e.printStackTrace();
198 return -1;
199 } catch (IOException e) {
200 e.printStackTrace();
201 return -1;
202 }
203 }
204
205 private int AddHost(Alert alert, String workspace, String session) {
206 String VULN_URL = "_api/v2/ws/" + workspace + "/hosts/";
207 HttpClient httpClient = HttpClients.createDefault();
208 HttpPost httpPost = new HttpPost(this.baseUrl + VULN_URL);
209
210 try {
211 StringEntity stringEntity = new StringEntity(ConvertHostToParams(alert).toString());
212 httpPost.setHeader("Cookie", session);
213 httpPost.setHeader("Content-Type", "application/json");
214 httpPost.setEntity(stringEntity);
215 HttpResponse response = httpClient.execute(httpPost);
216 HttpEntity entity = response.getEntity();
217
218 if (response.getStatusLine().getStatusCode() == 200 || response.getStatusLine().getStatusCode() == 201 || response.getStatusLine().getStatusCode() == 409) {
219 BufferedReader br = new BufferedReader(new InputStreamReader(entity.getContent()));
220 String output;
221 JSONObject json;
222 String hostStr = "-1";
223 while ((output = br.readLine()) != null) {
224 json = JSONObject.fromObject(output);
225 if (response.getStatusLine().getStatusCode() == 409) {
226 JSONObject jsonObject = JSONObject.fromObject(json.get("object"));
227 hostStr = jsonObject.get("id").toString();
228 } else {
229 hostStr = json.get("id").toString();
230 }
231 }
232 return Integer.parseInt(hostStr);
233 }
234 return -1;
235 } catch (UnsupportedEncodingException e) {
236 // writing error to Log
237 e.printStackTrace();
238 return -1;
239 } catch (ClientProtocolException e) {
240 e.printStackTrace();
241 return -1;
242 } catch (IOException e) {
243 e.printStackTrace();
244 return -1;
245 }
246 }
247
248 private int AddService(Alert alert, String workspace, String session, int hostId) {
249 String VULN_URL = "_api/v2/ws/" + workspace + "/services/";
250 HttpClient httpClient = HttpClients.createDefault();
251 HttpPost httpPost = new HttpPost(this.baseUrl + VULN_URL);
252
253 try {
254 StringEntity stringEntity = new StringEntity(ConvertServiceToParams(alert, hostId).toString());
255 httpPost.setHeader("Cookie", session);
256 httpPost.setHeader("Content-Type", "application/json");
257 httpPost.setEntity(stringEntity);
258 HttpResponse response = httpClient.execute(httpPost);
259 HttpEntity entity = response.getEntity();
260
261 BufferedReader br = new BufferedReader(new InputStreamReader(entity.getContent()));
262 String output;
263 if (response.getStatusLine().getStatusCode() == 200 || response.getStatusLine().getStatusCode() == 201 || response.getStatusLine().getStatusCode() == 409) {
264 JSONObject json;
265 String serviceStr = "-1";
266 while ((output = br.readLine()) != null) {
267 json = JSONObject.fromObject(output);
268 if (response.getStatusLine().getStatusCode() == 409) {
269 JSONObject jsonObject = JSONObject.fromObject(json.get("object"));
270 serviceStr = jsonObject.get("id").toString();
271 } else {
272 serviceStr = json.get("id").toString();
273 }
274 }
275 return Integer.parseInt(serviceStr);
276 } else {
277 while ((output = br.readLine()) != null) {
278 System.out.println(output);
279 }
280
281 return -1;
282 }
283
284 } catch (UnsupportedEncodingException e) {
285 // writing error to Log
286 e.printStackTrace();
287 return -1;
288 } catch (ClientProtocolException e) {
289 e.printStackTrace();
290 return -1;
291 } catch (IOException e) {
292 e.printStackTrace();
293 return -1;
294 }
295 }
296
297 public int AddVulnerability(Alert alert, String workspace, String session) {
298 int hostId = AddHost(alert, workspace, session);
299 if (hostId == -1) {
300 return 500;
301 }
302
303 String parentType = "Service";
304 int serviceId = AddService(alert, workspace, session, hostId);
305 if (serviceId == -1) {
306 return 500;
307 }
308
309
310 String commandName = messages.getString("faraday.tool.command.name");
311 int commandId = AddCommand(commandName, workspace, session);
312 if (commandId == -1) {
313 return 500;
314 }
315
316
317 String VULN_URL = "_api/v2/ws/" + workspace + "/vulns/?command_id=" + commandId;
318 HttpClient httpClient = HttpClients.createDefault();
319 HttpPost httpPost = new HttpPost(this.baseUrl + VULN_URL);
320 try {
321
322 StringEntity stringEntity = new StringEntity(ConvertAlertToParams(alert, workspace, parentType, serviceId).toString());
323 httpPost.setHeader("Cookie", session);
324 httpPost.setHeader("Content-Type", "application/json");
325 httpPost.setEntity(stringEntity);
326 HttpResponse response = httpClient.execute(httpPost);
327 return response.getStatusLine().getStatusCode();
328
329 } catch (UnsupportedEncodingException e) {
330 // writing error to Log
331 e.printStackTrace();
332 return 402;
333 } catch (ClientProtocolException e) {
334 e.printStackTrace();
335 return 402;
336 } catch (IOException e) {
337 e.printStackTrace();
338 return 402;
339 }
340 }
341
342 private JSONObject ConvertAlertToParams(Alert alert, String workspace, String parentType, int parentId) {
343 // Request parameters and other properties.
344 JSONObject params = new JSONObject();
345
346 params.put("name", alert.getName());
347 params.put("ws", workspace);
348 params.put("request", alert.getMessage().getRequestHeader().toString());
349 params.put("response", alert.getMessage().getResponseHeader().toString());
350 String desc = !alert.getParam().equals("") ? alert.getDescription() + "\nWith parameter: '" + alert.getParam() + "'" :
351 alert.getDescription();
352 params.put("desc", desc);
353 params.put("resolution", alert.getSolution());
354 params.put("type", "VulnerabilityWeb");
355 params.put("data", alert.getPostData());
356 params.put("policyviolations", "[]");
357 params.put("parent_type", parentType);
358 params.put("parent", parentId);
359 params.put("params", alert.getParam());
360
361 JSONObject metadata = new JSONObject();
362 metadata.put("creator", "OWASP");
363 params.put("metadata", metadata);
364
365 String hostname = alert.getMessage().getRequestHeader().getHostName();
366 String IpAddres = GetIPFromHostname(hostname);
367 JSONArray hostNamesArray = new JSONArray();
368 hostNamesArray.add(hostname);
369 hostNamesArray.add(IpAddres);
370 params.put("hostnames", hostNamesArray);
371 params.put("target", IpAddres);
372 params.put("website", hostname);
373
374 JSONArray refsJsonArray = new JSONArray();
375 String[] resfArray = alert.getReference().split("\n");
376 Collections.addAll(refsJsonArray, resfArray);
377 params.put("refs", refsJsonArray);
378
379 try {
380 params.put("path", alert.getMsgUri().getPath());
381 } catch (URIException e) {
382 e.printStackTrace();
383 }
384
385 if (alert.getConfidence() == 4) {
386 params.put("confirmed", true);
387 }
388
389 switch (alert.getRisk()) {
390 case 0:
391 params.put("severity", "informational");
392 break;
393 case 1:
394 params.put("severity", "low");
395 break;
396 case 2:
397 params.put("severity", "medium");
398 break;
399 case 3:
400 params.put("severity", "high");
401 break;
402 }
403 return params;
404
405 }
406
407 private JSONObject ConvertHostToParams(Alert alert) {
408 // Request parameters and other properties.
409 JSONObject params = new JSONObject();
410
411 try {
412 String ipAddress = GetIPFromHostname(alert.getMsgUri().getHost());
413 params.put("ip", ipAddress);
414 params.put("name", alert.getMsgUri().getName());
415 params.put("os", "Unknown");
416 params.put("description", "");
417 JSONObject metadata = new JSONObject();
418 metadata.put("creator", "Zap");
419 params.put("metadata", metadata);
420
421 String hostname = alert.getMessage().getRequestHeader().getHostName();
422 JSONArray hostNamesArray = new JSONArray();
423 hostNamesArray.add(hostname);
424 params.put("hostnames", hostNamesArray);
425
426 } catch (URIException e) {
427 e.printStackTrace();
428 }
429 return params;
430 }
431
432 private JSONObject ConvertServiceToParams(Alert alert, int parentId) {
433 // Request parameters and other properties.
434 JSONObject params = new JSONObject();
435 JSONArray portsJson = new JSONArray();
436 portsJson.add(alert.getMessage().getRequestHeader().getHostPort());
437 params.put("ports", portsJson);
438 params.put("parent", parentId);
439 params.put("status", "open");
440 params.put("type", "Service");
441 params.put("description", "");
442 JSONObject metadata = new JSONObject();
443 metadata.put("creator", "OWASP");
444 params.put("metadata", metadata);
445
446 switch (alert.getMessage().getRequestHeader().getHostPort()) {
447 case 21:
448 params.put("name", "FTP");
449 params.put("protocol", "tcp");
450 break;
451 case 22:
452 params.put("name", "SSH");
453 params.put("protocol", "tcp");
454 break;
455 case 23:
456 params.put("name", "TELNET");
457 params.put("protocol", "tcp");
458 break;
459 case 25:
460 params.put("name", "SMTP");
461 params.put("protocol", "tcp");
462 break;
463 case 80:
464 params.put("name", "HTTP");
465 params.put("protocol", "tcp");
466 break;
467 case 110:
468 params.put("name", "POP");
469 params.put("protocol", "tcp");
470 break;
471 case 443:
472 params.put("name", "SSL");
473 params.put("protocol", "tcp");
474 break;
475 default:
476 params.put("name", "unknown");
477 params.put("protocol", "unknown");
478 break;
479 }
480
481 return params;
482 }
483
484 private JSONObject ConvertCommandToParams(String commandName) {
485 // Request parameters and other properties.
486 JSONObject params = new JSONObject();
487 params.put("itime", Instant.EPOCH.getEpochSecond());
488 params.put("import_source", "shell");
489 params.put("duration", "");
490 params.put("command", "Zap");
491 params.put("tool", commandName);
492 return params;
493 }
494
495 private String GetIPFromHostname(String hostname) {
496 try {
497 InetAddress inetAddr = InetAddress.getByName(hostname);
498 byte[] addr = inetAddr.getAddress();
499
500 // Convert to dot representation
501 String ipAddr = "";
502 for (int i = 0; i < addr.length; i++) {
503 if (i > 0) {
504 ipAddr += ".";
505 }
506
507 ipAddr += addr[i] & 0xFF;
508 }
509
510 System.out.println("IP Address: " + ipAddr);
511 return ipAddr;
512 } catch (UnknownHostException e) {
513 System.out.println("Host not found: " + e.getMessage());
514 return "";
515 }
516 }
517
518 public void setBaseUrl(String baseUrl) {
519 this.baseUrl = baseUrl;
520 }
521 }
522
523
524
+0
-167
faraday_plugins/plugins/repo/zap/java/FaradayExtension.java less more
0 /*
1 * Zed Attack Proxy (ZAP) and its related class files.
2 *
3 * ZAP is an HTTP/HTTPS proxy for assessing web application security.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.zaproxy.zap.extension.faraday;
18
19 import org.apache.log4j.Logger;
20 import org.parosproxy.paros.Constant;
21 import org.parosproxy.paros.control.Control;
22 import org.parosproxy.paros.extension.ExtensionAdaptor;
23 import org.parosproxy.paros.extension.ExtensionHook;
24 import org.parosproxy.paros.extension.ExtensionPopupMenuItem;
25 import org.zaproxy.zap.view.ZapMenuItem;
26
27 import javax.swing.*;
28 import java.awt.*;
29 import java.awt.event.KeyEvent;
30 import java.io.*;
31 import java.util.Properties;
32 import java.util.ResourceBundle;
33
34 public class FaradayExtension extends ExtensionAdaptor {
35 private static final Logger logger = Logger.getLogger(FaradayExtension.class);
36 private ZapMenuItem menuItemFaradayConfig;
37 private ConfigurationDialog configurationDialog;
38 private PopupMenuItemSendAlert popupMenuItemSendAlert;
39 private PopupMenuItemSendRequest popupMenuItemSendRequest;
40 private ResourceBundle messages = null;
41
42
43
44 public FaradayExtension(String name) {
45 super(name);
46 }
47
48
49 public FaradayExtension() {
50 super();
51 initialize();
52 }
53
54
55 private void initialize() {
56 messages = ResourceBundle.getBundle(
57 this.getClass().getPackage().getName() +
58 ".Messages", Constant.getLocale());
59 this.setName(messages.getString("faraday.extension.name"));
60 this.initConfiguration();
61 }
62
63 @Override
64 public String getAuthor() {
65 return messages.getString("faraday.extension.author");
66 }
67
68 @Override
69 public void hook(ExtensionHook extensionHook) {
70 super.hook(extensionHook);
71
72 if (getView() != null) {
73 extensionHook.getHookMenu().addToolsMenuItem(getMenuItemFaradayConfig());
74 extensionHook.getHookMenu().addPopupMenuItem(this.getPopupMenuItem());
75 extensionHook.getHookMenu().addPopupMenuItem(this.getPopupMenuItemRequest());
76 }
77 }
78
79 @Override
80 public boolean canUnload() {
81 return true;
82 }
83
84 private ZapMenuItem getMenuItemFaradayConfig() {
85 if (menuItemFaradayConfig == null) {
86 menuItemFaradayConfig = new ZapMenuItem(
87 "faraday.menu.tools.label",
88 KeyStroke.getKeyStroke(
89 KeyEvent.VK_F,
90 Toolkit.getDefaultToolkit().getMenuShortcutKeyMask() | KeyEvent.ALT_DOWN_MASK,
91 false));
92 menuItemFaradayConfig.setEnabled(Control.getSingleton().getMode() != Control.Mode.safe);
93
94 menuItemFaradayConfig.addActionListener(new java.awt.event.ActionListener() {
95
96 @Override
97 public void actionPerformed(java.awt.event.ActionEvent e) {
98 showConfigurationDialog();
99 }
100 });
101 }
102 return menuItemFaradayConfig;
103 }
104
105
106 private void showConfigurationDialog() {
107 if (configurationDialog == null) {
108 configurationDialog = new ConfigurationDialog(messages.getString("faraday.config.dialog.title"));
109 configurationDialog.init();
110 }
111 configurationDialog.setVisible(true);
112 }
113
114
115 private ExtensionPopupMenuItem getPopupMenuItem() {
116 if (popupMenuItemSendAlert == null) {
117 popupMenuItemSendAlert = new PopupMenuItemSendAlert(messages.getString("faraday.button.send.alert"));
118 }
119
120 return popupMenuItemSendAlert;
121
122 }
123
124
125 private ExtensionPopupMenuItem getPopupMenuItemRequest() {
126 if (popupMenuItemSendRequest == null) {
127 popupMenuItemSendRequest = new PopupMenuItemSendRequest(messages.getString("faraday.button.send.request"));
128 }
129
130 return popupMenuItemSendRequest;
131
132 }
133
134
135 private void initConfiguration() {
136 Configuration configuration = Configuration.getSingleton();
137
138 Properties prop = new Properties();
139 InputStream input = null;
140
141 try {
142 String filePath = Constant.getZapHome() + "faraday" + File.separator + "default.properties";
143 input = new FileInputStream(filePath);
144
145 // load a properties file
146 prop.load(input);
147
148 // set the properties value
149 String fUser = prop.getProperty("default");
150 configuration.restore(fUser);
151
152 } catch (IOException io) {
153 System.out.println("We can't found default.properties file");
154 } finally {
155 if (input != null) {
156 try {
157 input.close();
158 } catch (IOException e) {
159 e.printStackTrace();
160 }
161 }
162
163 }
164 }
165
166 }
+0
-56
faraday_plugins/plugins/repo/zap/java/Messages.properties less more
0 # An example ZAP extension which adds a top level menu item.
1 #
2 # This file defines the default (English) variants of all of the
3
4 faraday.extension.name = Faraday Extension
5 faraday.extension.author = Jorge Luis Gonzàlez Iznaga
6
7 faraday.menu.tools.label = Faraday configuration options
8 faraday.config.dialog.title = Faraday configuration
9 faraday.config.dialog.tabs.auth = Authorization
10 faraday.config.dialog.tabs.conf = Configuration
11 faraday.config.dialog.auth.user = Faraday user
12 faraday.config.dialog.auth.pass = Faraday password
13 faraday.config.dialog.server = Faraday server
14 faraday.config.dialog.auth.login = Login
15 faraday.config.dialog.auth.logout = Logout
16 faraday.config.dialog.import.current = Import current vulnerabilities
17 faraday.config.dialog.import.new = Import new vulnerabilities
18 faraday.config.dialog.restore = Restore configuration
19 faraday.config.dialog.refresh = Refresh
20 faraday.config.dialog.save = Save configuration
21 faraday.config.dialog.workspace = Select faraday workspace
22 faraday.config.dialog.default = Set this configuration as default
23
24 faraday.config.dialog.tab.auth = Authorization
25 faraday.config.dialog.tab.conf = Configuration
26
27 faraday.dialog.enter.user = Please enter your user
28
29
30 faraday.button.send.alert = Send alert to Faraday
31 faraday.button.send.request = Send request to Faraday
32
33 faraday.message.invalid.check.credentials = Please, check your credentials
34 faraday.message.invalid.credentials = Invalid credentials
35 faraday.dialog.login.title = Faraday login
36 faraday.dialog.logout.title = Faraday logout
37 faraday.dialog.logout.success = You're logout successfully !
38 faraday.dialog.logout.error = We can't complete logout operation
39
40 faraday.dialog.button.close = Close
41
42 faraday.save.config.success = Configuration saved successfully
43 faraday.save.config.error = We can't save your configuration, please check home ZAP directory
44 faraday.restore.config.error = You haven't a configuration saved with this user
45 faraday.refresh.workspace.done = Your workspaces are up to date
46 faraday.restore.config.error.login = Unable to restore this configuration
47 faraday.set.default.config.error = We can't set your configuration
48
49 faraday.send.alert.permissions.error = You should check your current workspace and your permissions
50 faraday.send.alert.conflict = This alert already exists in Faraday
51 faraday.send.request.conflict = This request already exists in Faraday
52 faraday.send.alert.success = Alert added successfully
53 faraday.send.request.success = Request added successfully
54
55 faraday.tool.command.name = OWASP
+0
-149
faraday_plugins/plugins/repo/zap/java/PopupMenuItemSendAlert.java less more
0 package org.zaproxy.zap.extension.faraday;
1
2 import org.apache.log4j.Logger;
3 import org.parosproxy.paros.Constant;
4 import org.parosproxy.paros.core.scanner.Alert;
5 import org.parosproxy.paros.view.View;
6 import org.zaproxy.zap.extension.alert.AlertNode;
7 import org.zaproxy.zap.extension.alert.PopupMenuItemAlert;
8
9 import javax.swing.*;
10 import java.awt.*;
11 import java.util.ResourceBundle;
12
13 public class PopupMenuItemSendAlert extends PopupMenuItemAlert {
14 private static final Logger logger = Logger.getLogger(PopupMenuItemSendAlert.class);
15 private FaradayClient faradayClient;
16 private ResourceBundle messages = null;
17 private int selectionCount = 0;
18 private int totalSelectionCount = 0;
19 private boolean treeAlertParentSelected = false;
20
21 public PopupMenuItemSendAlert(String label) {
22 super(label, true);
23 Configuration configuration = Configuration.getSingleton();
24 faradayClient = new FaradayClient(configuration.getServer());
25 messages = ResourceBundle.getBundle(
26 this.getClass().getPackage().getName() +
27 ".Messages", Constant.getLocale());
28 }
29
30 @Override
31 protected void performAction(Alert alert) {
32 Configuration configuration = Configuration.getSingleton();
33 String workspace = configuration.getWorkspace();
34 String session = configuration.getSession();
35 if (workspace != null && session != null && !workspace.equals("") && !session.equals("")) {
36 int responseCode = faradayClient.AddVulnerability(alert, configuration.getWorkspace(), session);
37 String message;
38 int iconMessage = 1;
39 switch (responseCode) {
40 case 200:
41 case 201:
42 case 409:
43 message = messages.getString("faraday.send.alert.success");
44 break;
45 case 403:
46 message = messages.getString("faraday.send.alert.permissions.error");
47 iconMessage = JOptionPane.WARNING_MESSAGE;
48 break;
49 // case 409:
50 // message = messages.getString("faraday.send.alert.conflict");
51 // iconMessage = JOptionPane.WARNING_MESSAGE;
52 // break;
53 case 400:
54 case 500:
55 message = "Unable to send " + alert.getName() + " to Faraday";
56 iconMessage = JOptionPane.ERROR_MESSAGE;
57 break;
58
59 default:
60 message = "Unable to send " + alert.getName() + " to Faraday";
61 iconMessage = JOptionPane.ERROR_MESSAGE;
62 break;
63 }
64
65 if (canShowMessageDialog()/*this.selectionCount == 1 && !treeAlertParentSelected*/) {
66 JOptionPane.showMessageDialog(
67 this,
68 message,
69 messages.getString("faraday.button.send.alert"),
70 iconMessage);
71 }
72
73
74 logger.error(message);
75 if (View.isInitialised()) {
76 // Report info to the Output tab
77 View.getSingleton().getOutputPanel().append(message + "\n");
78 }
79
80
81 } else {
82 if (canShowMessageDialog()) {
83 JOptionPane.showMessageDialog(
84 this,
85 messages.getString("faraday.send.alert.permissions.error"),
86 messages.getString("faraday.button.send.alert"),
87 JOptionPane.ERROR_MESSAGE);
88 logger.error(messages.getString("faraday.send.alert.permissions.error"));
89 }
90
91
92 if (View.isInitialised()) {
93 // Report info to the Output tab
94 View.getSingleton().getOutputPanel().append(messages.getString("faraday.send.alert.permissions.error") + "\n");
95 }
96 }
97
98 }
99
100 @Override
101 public boolean isEnableForComponent(Component invoker) {
102 logger.info(invoker.getName());
103 this.totalSelectionCount = 0;
104 try {
105 if (Configuration.getSingleton().getSession() == null || Configuration.getSingleton().getSession().equals("")) {
106 return false;
107 }
108 treeAlertParentSelected = ((JTree) invoker).isRowSelected(0);
109 if (super.isEnableForComponent(invoker) || treeAlertParentSelected) {
110 this.selectionCount = ((JTree) invoker).getSelectionCount();
111 for (int i = 0; i < ((JTree) invoker).getSelectionPaths().length; i++) {
112 AlertNode nodeTemp = (AlertNode) ((JTree) invoker).getSelectionPaths()[i].getLastPathComponent();
113 this.totalSelectionCount += getTotalAlertsToProcess(nodeTemp);
114 }
115
116 setEnabled(true);
117 return true;
118 }
119 return false;
120 } catch (Exception e) {
121 return false;
122 }
123 }
124
125
126 private int getTotalAlertsToProcess(AlertNode node) {
127 if (node.getChildCount() > 0) {
128 int total = 0;
129 for (int i = 0; i < node.getChildCount(); i++) {
130 total += getTotalAlertsToProcess(node.getChildAt(i));
131 }
132 return total;
133 } else {
134 return 1;
135 }
136
137 }
138
139 private boolean canShowMessageDialog() {
140 this.totalSelectionCount--;
141 if (this.treeAlertParentSelected) {
142 this.totalSelectionCount = 1;
143 this.treeAlertParentSelected = false;
144 }
145
146 return this.totalSelectionCount == 0;
147 }
148 }
+0
-137
faraday_plugins/plugins/repo/zap/java/PopupMenuItemSendRequest.java less more
0 package org.zaproxy.zap.extension.faraday;
1
2 import org.apache.log4j.Logger;
3 import org.parosproxy.paros.Constant;
4 import org.parosproxy.paros.core.scanner.Alert;
5 import org.parosproxy.paros.db.DatabaseException;
6 import org.parosproxy.paros.db.RecordAlert;
7 import org.parosproxy.paros.model.HistoryReference;
8 import org.parosproxy.paros.network.HttpMalformedHeaderException;
9 import org.parosproxy.paros.view.View;
10 import org.zaproxy.zap.extension.alert.PopupMenuAlert;
11 import org.zaproxy.zap.view.messagecontainer.http.HttpMessageContainer;
12 import org.zaproxy.zap.view.popup.PopupMenuItemHistoryReferenceContainer;
13
14 import javax.swing.*;
15 import java.awt.*;
16 import java.util.Iterator;
17 import java.util.List;
18 import java.util.ResourceBundle;
19
20
21 public class PopupMenuItemSendRequest extends PopupMenuItemHistoryReferenceContainer {
22 private FaradayClient faradayClient;
23 private ResourceBundle messages = null;
24 private int selectionCount = 0;
25 private static final Logger logger = Logger.getLogger(PopupMenuItemSendRequest.class);
26
27
28 public PopupMenuItemSendRequest(String label) {
29 super(label, true);
30 Configuration configuration = Configuration.getSingleton();
31 faradayClient = new FaradayClient(configuration.getServer());
32 messages = ResourceBundle.getBundle(
33 this.getClass().getPackage().getName() +
34 ".Messages", Constant.getLocale());
35 }
36
37 @Override
38 public void performAction(HistoryReference href) {
39 try {
40 Alert alert = new Alert(new RecordAlert(), href);
41 alert.setName(href.getSiteNode().getName());
42 alert.setUri(href.getURI().toString());
43 alert.setMessage(href.getHttpMessage());
44 alert.setDescription("");
45 alert.setRiskConfidence(0, 0);
46
47 Configuration configuration = Configuration.getSingleton();
48 String workspace = configuration.getWorkspace();
49 String session = configuration.getSession();
50 if (workspace != null && session != null && !workspace.equals("") && !session.equals("")) {
51 int responseCode = faradayClient.AddVulnerability(alert, configuration.getWorkspace(), session);
52 String message = "";
53 int iconMessage = 1;
54 switch (responseCode) {
55 case 403:
56 message = messages.getString("faraday.send.alert.permissions.error");
57 iconMessage = JOptionPane.WARNING_MESSAGE;
58 break;
59 case 409:
60 message = messages.getString("faraday.send.request.conflict");
61 iconMessage = JOptionPane.WARNING_MESSAGE;
62 break;
63 case 500:
64 message = "Unable to send " + alert.getName() + " to Faraday";
65 iconMessage = JOptionPane.ERROR_MESSAGE;
66 break;
67 case 201:
68 message = messages.getString("faraday.send.request.success");
69 break;
70 }
71
72 if (this.selectionCount == 1) {
73 JOptionPane.showMessageDialog(
74 this,
75 message,
76 messages.getString("faraday.button.send.alert"),
77 iconMessage);
78 }
79
80 logger.error(message);
81 if (View.isInitialised()) {
82 // Report info to the Output tab
83 View.getSingleton().getOutputPanel().append(message + "\n");
84 }
85
86
87 } else {
88 JOptionPane.showMessageDialog(
89 this,
90 messages.getString("faraday.send.alert.permissions.error"),
91 messages.getString("faraday.button.send.request"),
92 JOptionPane.ERROR_MESSAGE);
93
94 logger.error(messages.getString("faraday.send.alert.permissions.error"));
95 if (View.isInitialised()) {
96 // Report info to the Output tab
97 View.getSingleton().getOutputPanel().append(messages.getString("faraday.send.alert.permissions.error") + "\n");
98 }
99 }
100
101
102 } catch (HttpMalformedHeaderException e) {
103 e.printStackTrace();
104 } catch (DatabaseException e) {
105 e.printStackTrace();
106 }
107 }
108
109
110 @Override
111 public void performHistoryReferenceActions(List<HistoryReference> hrefs) {
112 this.selectionCount = hrefs.size();
113
114 for (HistoryReference href : hrefs) {
115 this.performAction(href);
116 }
117 }
118
119 @Override
120 public boolean isEnableForInvoker(Invoker invoker, HttpMessageContainer httpMessageContainer) {
121 if (Configuration.getSingleton().getSession() == null || Configuration.getSingleton().getSession().equals("") ||
122 invoker.name().equals("ALERTS_PANEL")) {
123 return false;
124 }
125 return super.isEnableForInvoker(invoker, httpMessageContainer);
126 }
127
128 @Override
129 public boolean isButtonEnabledForHistoryReference(HistoryReference href) {
130 if (Configuration.getSingleton().getSession() == null || Configuration.getSingleton().getSession().equals("")) {
131 return false;
132 }
133
134 return href.getSiteNode() != null && super.isButtonEnabledForHistoryReference(href);
135 }
136 }
+0
-14
faraday_plugins/plugins/repo/zap/java/ZapAddOn.xml less more
0 <zapaddon>
1 <name>Faraday</name>
2 <version>1</version>
3 <status>release</status>
4 <description>This extension integrates ZAP with the Faraday Integrated Penetration-Test Environment</description>
5 <author>Jorge Luis González Iznaga</author>
6 <extensions>
7 <extension>org.zaproxy.zap.extension.faraday.FaradayExtension</extension>
8 </extensions>
9 <ascanrules/>
10 <pscanrules/>
11 <not-before-version>2.7.0</not-before-version>
12 <not-from-version/>
13 </zapaddon>
33 See the file 'doc/LICENSE' for the license information
44 """
55 import re
6 import xml.etree.ElementTree as ET
67 from urllib.parse import urlparse
8
79 from faraday_plugins.plugins.plugin import PluginXMLFormat
810 from faraday_plugins.plugins.plugins_utils import resolve_hostname
9
10 try:
11 import xml.etree.cElementTree as ET
12 ETREE_VERSION = ET.VERSION
13 except ImportError:
14 import xml.etree.ElementTree as ET
15 ETREE_VERSION = ET.VERSION
16
17 ETREE_VERSION = [int(i) for i in ETREE_VERSION.split(".")]
18
1911
2012 __author__ = "Francisco Amato"
2113 __copyright__ = "Copyright (c) 2013, Infobyte LLC"
2719 __status__ = "Development"
2820
2921
30
3122 class ZapXmlParser:
3223 """
3324 The objective of this class is to parse an xml
5142 else:
5243 self.sites = []
5344
54 def parse_xml(self, xml_output):
45 @staticmethod
46 def parse_xml(xml_output):
5547 """
5648 Open and parse an xml file.
5749
7163
7264 return tree
7365
74 def get_items(self, tree):
66 @staticmethod
67 def get_items(tree):
7568 """
7669 @return items A list of Host instances
7770 """
8578
8679 @return An attribute value
8780 """
88 global ETREE_VERSION
89 node = None
90
91 if ETREE_VERSION[0] <= 1 and ETREE_VERSION[1] < 3:
92
93 match_obj = re.search(
94 "([^\@]+?)\[\@([^=]*?)=\'([^\']*?)\'",
95 subnode_xpath_expr)
96
97 if match_obj is not None:
98
99 node_to_find = match_obj.group(1)
100 xpath_attrib = match_obj.group(2)
101 xpath_value = match_obj.group(3)
102
103 for node_found in xml_node.findall(node_to_find):
104
105 if node_found.attrib[xpath_attrib] == xpath_value:
106 node = node_found
107 break
108 else:
109 node = xml_node.find(subnode_xpath_expr)
110
111 else:
112 node = xml_node.find(subnode_xpath_expr)
81
82 node = xml_node.find(subnode_xpath_expr)
11383
11484 if node is not None:
11585 return node.get(attrib_name)
11686
11787 return None
88
89
90 def strip_tags(data):
91 """
92 Remove html tags from a string
93 @return Stripped string
94 """
95 clean = re.compile('<.*?>')
96 return re.sub(clean, '', data)
11897
11998
12099 class Site:
126105 self.host = self.node.get('host')
127106 self.ip = resolve_hostname(self.host)
128107 self.port = self.node.get('port')
108 self.ssl = self.node.get('ssl')
129109
130110 self.items = []
131111 for alert in self.node.findall('alerts/alertitem'):
141121 if sub_node is not None:
142122 return sub_node.text
143123 return None
144
145124
146125
147126 class Item:
159138 self.name = self.get_text_from_subnode('alert')
160139 self.severity = self.get_text_from_subnode('riskcode')
161140 self.desc = self.get_text_from_subnode('desc')
162
163141 if self.get_text_from_subnode('solution'):
164142 self.resolution = self.get_text_from_subnode('solution')
165143 else:
166144 self.resolution = ''
167145
146 self.ref = []
168147 if self.get_text_from_subnode('reference'):
169 self.desc += '\nReference: ' + \
170 self.get_text_from_subnode('reference')
171
172 self.ref = []
148 links = self.get_text_from_subnode('reference')
149 for link in links.split("</p>"):
150 link = link.strip().replace("\n", "")
151 if link != "":
152 self.ref.append(strip_tags(link))
153
173154 if self.get_text_from_subnode('cweid'):
174 self.ref.append("CWE-" + self.get_text_from_subnode('cweid'))
155 self.ref.append("CWE:" + self.get_text_from_subnode('cweid'))
156
157 if self.get_text_from_subnode('wascid'):
158 self.ref.append("WASC:" + self.get_text_from_subnode('wascid'))
175159
176160 self.items = []
177161
182166
183167 for elem in arr:
184168 uri = elem.find('uri').text
185 method_element = elem.find('method')
186 if method_element:
187 method = elem.find('method').text
169 method = elem.findtext('method', "")
170 item = self.parse_uri(uri, method)
171
172 param = elem.findtext("param", "")
173 attack = elem.findtext("attack", "")
174 if attack and param:
175 item["data"] = f"URL:\n {uri}\n Payload:\n {param} = {attack}"
188176 else:
189 method = ""
190 self.parse_uri(uri, method)
191
192 def parse_uri(self, uri, method):
177 item["data"] = f"URL:\n {uri}\n Parameter:\n {param}"
178
179 evidence = elem.findtext("evidence", "")
180 if evidence:
181 item["data"] = f"URL:\n {uri}\n Parameter:\n {param}\n Evidence:\n {evidence}"
182 else:
183 item["data"] = f"URL:\n {uri}\n"
184
185 item["pname"] = elem.findtext("param", "")
186
187 self.items.append(item)
188
189 def parse_uri(self, uri, method) -> dict:
193190
194191 parsed_url = urlparse(uri)
195192 protocol = parsed_url.scheme
196193 host = parsed_url.netloc
197194 port = parsed_url.port
198
199 try:
200 params = [i.split('=')[0]
201 for i in uri.split('?')[1].split('&')]
202 except Exception as e:
203 params = ''
204
205 item = {
195 params = self.extract_params_from_uri(uri)
196
197 return {
206198 'uri': uri,
207199 'params': ', '.join(params),
208200 'host': host,
211203 'port': port,
212204 'method': method,
213205 'path': parsed_url.path,
214 'query': parsed_url.query
206 'query': parsed_url.query,
207 'data': ""
215208 }
216 self.items.append(item)
209
210 @staticmethod
211 def extract_params_from_uri(uri):
212 params = re.findall("(\w+)=", uri)
213 return params if params else ''
217214
218215 def get_text_from_subnode(self, subnode_xpath_expr):
219216 """
238235 self.identifier_tag = "OWASPZAPReport"
239236 self.id = "Zap"
240237 self.name = "Zap XML Output Plugin"
241 self.plugin_version = "0.0.3"
242 self.version = "2.4.3"
238 self.plugin_version = "0.0.4"
239 self.version = "2.10.0"
243240 self.framework_version = "1.0.0"
244241 self.options = None
245
246242
247243 def parseOutputString(self, output):
248244 """
258254 if site.host != site.ip:
259255 host = [site.host]
260256
257 if site.ssl == "true":
258 service = "https"
259 else:
260 service = "http"
261
261262 h_id = self.createAndAddHost(site.ip, hostnames=host)
262263
263 s_id = self.createAndAddServiceToHost(h_id, "http", "tcp", ports=[site.port], status='open')
264 s_id = self.createAndAddServiceToHost(h_id, service, "tcp", ports=[site.port], status='open')
264265
265266 for item in site.items:
266267 for instance in item.items:
268269 h_id,
269270 s_id,
270271 item.name,
271 item.desc,
272 strip_tags(item.desc),
272273 website=instance['website'],
273274 query=instance['query'],
274275 severity=item.severity,
276277 params=instance['params'],
277278 method=instance['method'],
278279 ref=item.ref,
279 resolution=item.resolution
280 resolution=strip_tags(item.resolution),
281 data=instance["data"],
282 pname=instance["pname"],
283 external_id="ZAP-" + str(item.id)
280284 )
281285
282286 del parser
283
284
285 def setHost(self):
286 pass
287287
288288
289289 def createPlugin(ignore_info=False):
+0
-166
faraday_plugins/plugins/repo/zap/report.xml less more
0 <?xml version="1.0" encoding="UTF-8"?><report>
1 Report generated at Tue, 12 Jul 2011 08:32:22.
2 <alertitem>
3 <pluginid>40000</pluginid>
4 <alert>Cookie set without HttpOnly flag</alert>
5 <riskcode>1</riskcode>
6 <reliability>2</reliability>
7 <riskdesc>Low (Warning)</riskdesc>
8 <desc>A cookie has been set without the HttpOnly flag, which means that the cookie can be accessed by JavaScript. If a malicious script can be run on this page then the cookie will be accessible and can be transmitted to another site. If this is a session cookie then session hijacking may be possible.
9 </desc>
10 <uri>http://192.168.1.100/</uri>
11 <param>ASPSESSIONIDQSDRBCRQ=EEFHJOACLHOKLJHFNAFBBECK; path=/</param>
12 <otherinfo/>
13 <uri>http://www.web3.com.ar/ServFotoPorNoticia.asp</uri>
14 <param>ASPSESSIONIDCQATADBB=LMFPHGLBHIIEDFILGFJEJNGE; path=/</param>
15 <otherinfo/>
16 <uri>http://www.web1.com.ar/acceso/include/valida.asp</uri>
17 <param>ASPSESSIONIDSCBABSTB=MNPOKADDPAIDCDNBPGFDHGBF; path=/</param>
18 <otherinfo/>
19 <uri>http://www.web3.com.ar/files/</uri>
20 <param>ASPSESSIONIDCSCTCABB=HFCNOPJBMNJEAHDHMCKAHOBN; path=/</param>
21 <otherinfo/>
22 <uri>http://www.web2.com.ar/acceso/include/valida.asp</uri>
23 <param>ASPSESSIONIDQAASDACB=HADJFCIBOIANGBGNAOIDBGIL; path=/</param>
24 <otherinfo/>
25 <uri>http://www.web3.com.ar/</uri>
26 <param>ASPSESSIONIDSABQACDB=PAJBMJHBLOFELCIKBNLAAKKJ; path=/</param>
27 <otherinfo/>
28 <solution>Ensure that the HttpOnly flag is set for all cookies.
29 </solution>
30 <reference>www.owasp.org/index.php/HttpOnly
31 </reference>
32 </alertitem>
33 <alertitem>
34 <pluginid>40001</pluginid>
35 <alert>Password Autocomplete in browser</alert>
36 <riskcode>1</riskcode>
37 <reliability>2</reliability>
38 <riskdesc>Low (Warning)</riskdesc>
39 <desc>AUTOCOMPLETE attribute is not disabled in HTML FORM/INPUT element containing password type input. Passwords may be stored in browsers and retrieved.
40 </desc>
41 <uri>http://192.168.1.100/</uri>
42 <param>input</param>
43 <otherinfo/>
44 <uri>http://www.web3.com.ar/</uri>
45 <param>input</param>
46 <otherinfo/>
47 <uri>http://www.web3.com.ar/default.asp?errsession=1</uri>
48 <param>input</param>
49 <otherinfo/>
50 <uri>http://www.web3.com.ar/</uri>
51 <param>input</param>
52 <otherinfo/>
53 <uri>http://www.web3.com.ar/</uri>
54 <param>input</param>
55 <otherinfo/>
56 <uri>http://www.web2.com.ar/dealers.htm</uri>
57 <param>input</param>
58 <otherinfo/>
59 <uri>http://www.web3.com.ar/</uri>
60 <param>input</param>
61 <otherinfo/>
62 <solution>Turn off AUTOCOMPLETE attribute in form or individual input elements containing password by using AUTOCOMPLETE='OFF'
63 </solution>
64 <reference>http://msdn.microsoft.com/library/default.asp?url=/workshop/author/forms/autocomplete_ovr.asp
65 </reference>
66 </alertitem>
67 <alertitem>
68 <pluginid>40003</pluginid>
69 <alert>Cross site scripting</alert>
70 <riskcode>3</riskcode>
71 <reliability>2</reliability>
72 <riskdesc>High (Warning)</riskdesc>
73 <desc>Cross-site scripting or HTML injection is possible. Malicious script may be injected into the browser which appeared to be genuine content from the original site. These scripts can be used to execute arbitrary code or steal customer sensitive information such as user password or cookies.
74 Very often this is in the form of a hyperlink with the injected script embeded in the query strings. However, XSS is possible via FORM POST data, cookies, user data sent from another user or shared data retrieved from database.
75 Currently this check does not verify XSS from cookie or database. They should be checked manually if the application retrieve database records from another user's input.
76 </desc>
77 <uri>http://www.web3.com.ar/Mes.asp?hhFrm=frm&amp;hhDia=DiaF&amp;hhMes=MesF&amp;hhAnno=%3CSCRIPT%3Ealert(%22OWASP%20ZAP%22);%3C/SCRIPT%3E</uri>
78 <param>hhAnno=&lt;SCRIPT&gt;alert("OWASP ZAP");&lt;/SCRIPT&gt;</param>
79 <otherinfo/>
80 <uri>http://www.web3.com.ar/Mes.asp?hhFrm=frm&amp;hhDia=DiaF&amp;hhMes=%3CSCRIPT%3Ealert(%22OWASP%20ZAP%22);%3C/SCRIPT%3E&amp;hhAnno=AnnoF</uri>
81 <param>hhMes=&lt;SCRIPT&gt;alert("OWASP ZAP");&lt;/SCRIPT&gt;</param>
82 <otherinfo/>
83 <uri>http://www.web3.com.ar/Mes.asp?hhFrm=frm&amp;hhDia=%3CSCRIPT%3Ealert(%22OWASP%20ZAP%22);%3C/SCRIPT%3E&amp;hhMes=MesF&amp;hhAnno=AnnoF</uri>
84 <param>hhDia=&lt;SCRIPT&gt;alert("OWASP ZAP");&lt;/SCRIPT&gt;</param>
85 <otherinfo/>
86 <uri>http://www.web3.com.ar/Mes.asp?hhFrm=%3CSCRIPT%3Ealert(%22OWASP%20ZAP%22);%3C/SCRIPT%3E&amp;hhDia=DiaF&amp;hhMes=MesF&amp;hhAnno=AnnoF</uri>
87 <param>hhFrm=&lt;SCRIPT&gt;alert("OWASP ZAP");&lt;/SCRIPT&gt;</param>
88 <otherinfo/>
89 <solution>Do not trust client side input even if there is client side validation. Sanitize potentially danger characters in the server side. Very often filtering the &lt;, &gt;, " characters prevented injected script to be executed in most cases. However, sometimes other danger meta-characters such as ' , (, ), /, &amp;, ; etc are also needed.
90 In addition (or if these characters are needed), HTML encode meta-characters in the response. For example, encode &lt; as &amp;lt;
91
92 </solution>
93 <reference>The OWASP guide at http://www.owasp.org/documentation/guide
94 http://www.technicalinfo.net/papers/CSS.html
95 http://www.cgisecurity.org/articles/xss-faq.shtml
96 http://www.cert.org/tech_tips/malicious_code_FAQ.html
97 http://sandsprite.com/Sleuth/papers/RealWorld_XSS_1.html
98
99 </reference>
100 </alertitem>
101 <alertitem>
102 <pluginid>40004</pluginid>
103 <alert>Cross site scripting without brackets</alert>
104 <riskcode>3</riskcode>
105 <reliability>1</reliability>
106 <riskdesc>High (Suspicious)</riskdesc>
107 <desc>Cross-site scripting or HTML injection is possible without '&lt;' and '&gt;'. Malicious script may be injected into the browser which appeared to be genuine content from the original site. These scripts can be used to execute arbitrary code or steal customer sensitive information such as user password or cookies.
108 Very often this is in the form of a hyperlink with the injected script embeded in the query strings. However, XSS is possible via FORM POST data, cookies, user data sent from another user or shared data retrieved from database.
109 Currently this check does not verify XSS from cookie or database. They should be checked manually if the application retrieve database records from another user's input.
110 </desc>
111 <uri>http://www.web3.com.ar/Mes.asp?hhFrm=frm&amp;hhDia=DiaF&amp;hhMes=MesF&amp;hhAnno=paros%22%20style=%22background:url(javascript:alert('OWASP%20ZAP'))</uri>
112 <param>hhAnno=paros" style="background:url(javascript:alert('OWASP ZAP'))</param>
113 <otherinfo/>
114 <uri>http://www.web3.com.ar/Mes.asp?hhFrm=frm&amp;hhDia=DiaF&amp;hhMes=paros%22%20style=%22background:url(javascript:alert('OWASP%20ZAP'))&amp;hhAnno=%3CSCRIPT%3Ealert(%22OWASP%20ZAP%22);%3C/SCRIPT%3E</uri>
115 <param>hhMes=paros" style="background:url(javascript:alert('OWASP ZAP'))</param>
116 <otherinfo/>
117 <uri>http://www.web3.com.ar/Mes.asp?hhFrm=frm&amp;hhDia=paros%22%20style=%22background:url(javascript:alert('OWASP%20ZAP'))&amp;hhMes=MesF&amp;hhAnno=%3CSCRIPT%3Ealert(%22OWASP%20ZAP%22);%3C/SCRIPT%3E</uri>
118 <param>hhDia=paros" style="background:url(javascript:alert('OWASP ZAP'))</param>
119 <otherinfo/>
120 <uri>http://www.web3.com.ar/Mes.asp?hhFrm=paros%22%20style=%22background:url(javascript:alert('OWASP%20ZAP'))&amp;hhDia=DiaF&amp;hhMes=MesF&amp;hhAnno=%3CSCRIPT%3Ealert(%22OWASP%20ZAP%22);%3C/SCRIPT%3E</uri>
121 <param>hhFrm=paros" style="background:url(javascript:alert('OWASP ZAP'))</param>
122 <otherinfo/>
123 <solution>Do not trust client side input even if there is client side validation. Sanitize potentially danger characters in the server side. Very often filtering the &lt;, &gt;, " characters prevented injected script to be executed in most cases. However, sometimes other danger meta-characters such as ' , (, ), /, &amp;, ; etc are also needed.
124 In addition (or if these characters are needed), HTML encode meta-characters in the response. For example, encode &lt; as &amp;lt;
125
126 </solution>
127 <reference>The OWASP guide at http://www.owasp.org/documentation/guide
128 http://www.technicalinfo.net/papers/CSS.html
129 http://www.cgisecurity.org/articles/xss-faq.shtml
130 http://www.cert.org/tech_tips/malicious_code_FAQ.html
131 http://sandsprite.com/Sleuth/papers/RealWorld_XSS_1.html
132
133 </reference>
134 </alertitem>
135 <alertitem>
136 <pluginid>40030</pluginid>
137 <alert>SQL Injection</alert>
138 <riskcode>3</riskcode>
139 <reliability>2</reliability>
140 <riskdesc>High (Warning)</riskdesc>
141 <desc>SQL injection is possible. User parameters submitted will be formulated into a SQL query for database processing. If the query is built by simple 'string concatenation', it is possible to modify the meaning of the query by carefully crafting the parameters. Depending on the access right and type of database used, tampered query can be used to retrieve sensitive information from the database or execute arbitrary code. MS SQL and PostGreSQL, which supports multiple statements, may be exploited if the database access right is more powerful.
142 This can occur in URL query strings, POST paramters or even cookies. Currently check on cookie is not supported by Paros. You should check SQL injection manually as well as some blind SQL injection areas cannot be discovered by this check.
143 </desc>
144 <uri>http://www.web3.com.ar/buscador.asp</uri>
145 <param>hId=&amp;hAreturn=&amp;hAccion=OK&amp;txtBuscar=test&amp;x=0&amp;y=0%27+AND+%271%27%3D%271</param>
146 <otherinfo/>
147 <uri>http://www.web3.com.ar/buscador.asp</uri>
148 <param>hId=&amp;hAreturn=&amp;hAccion=OK%22+OR+%221%22%3D%221&amp;txtBuscar=test&amp;x=0&amp;y=0</param>
149 <otherinfo/>
150 <solution>Do not trust client side input even if there is client side validation. In general, If the input string is numeric, type check it.
151 If the application used JDBC, use PreparedStatement or CallableStatement with parameters passed by '?'
152 If the application used ASP, use ADO Command Objects with strong type checking and parameterized query.
153 If stored procedure or bind variables can be used, use it for parameter passing into query. Do not just concatenate string into query in the stored procedure!
154 Do not create dynamic SQL query by simple string concatentation.
155 Use minimum database user privilege for the application. This does not eliminate SQL injection but minimize its damage. Eg if the application require reading one table only, grant such access to the application. Avoid using 'sa' or 'db-owner'.
156
157 </solution>
158 <reference>The OWASP guide at http://www.owasp.org/documentation/guide
159 http://www.sqlsecurity.com/DesktopDefault.aspx?tabid=23
160 http://www.spidynamics.com/whitepapers/WhitepaperSQLInjection.pdf
161 For Oracle database, refer to http://www.integrigy.com/info/IntegrigyIntrotoSQLInjectionAttacks.pdf
162
163 </reference>
164 </alertitem>
165 </report>
faraday_plugins/plugins/repo/zap/zap-plugin.zap less more
Binary diff not shown
0 Metadata-Version: 1.0
1 Name: faraday-plugins
2 Version: 1.4.6
3 Summary: Faraday plugins package
4 Home-page: UNKNOWN
5 Author: Faradaysec
6 Author-email: [email protected]
7 License: GNU General Public License v3
8 Description: UNKNOWN
9 Platform: UNKNOWN
0 MANIFEST.in
1 README.md
2 setup.py
3 faraday_plugins/__init__.py
4 faraday_plugins/__main__.py
5 faraday_plugins/commands.py
6 faraday_plugins.egg-info/PKG-INFO
7 faraday_plugins.egg-info/SOURCES.txt
8 faraday_plugins.egg-info/dependency_links.txt
9 faraday_plugins.egg-info/entry_points.txt
10 faraday_plugins.egg-info/requires.txt
11 faraday_plugins.egg-info/top_level.txt
12 faraday_plugins/plugins/__init__.py
13 faraday_plugins/plugins/manager.py
14 faraday_plugins/plugins/plugin.py
15 faraday_plugins/plugins/plugins_utils.py
16 faraday_plugins/plugins/port_mapper.txt
17 faraday_plugins/plugins/repo/__init__.py
18 faraday_plugins/plugins/repo/acunetix/__init__.py
19 faraday_plugins/plugins/repo/acunetix/plugin.py
20 faraday_plugins/plugins/repo/amap/__init__.py
21 faraday_plugins/plugins/repo/amap/plugin.py
22 faraday_plugins/plugins/repo/appscan/__init__.py
23 faraday_plugins/plugins/repo/appscan/plugin.py
24 faraday_plugins/plugins/repo/appspider/__init__.py
25 faraday_plugins/plugins/repo/appspider/plugin.py
26 faraday_plugins/plugins/repo/arachni/__init__.py
27 faraday_plugins/plugins/repo/arachni/plugin.py
28 faraday_plugins/plugins/repo/arp_scan/__init__.py
29 faraday_plugins/plugins/repo/arp_scan/plugin.py
30 faraday_plugins/plugins/repo/awsprowler/__init__.py
31 faraday_plugins/plugins/repo/awsprowler/plugin.py
32 faraday_plugins/plugins/repo/bandit/__init__.py
33 faraday_plugins/plugins/repo/bandit/plugin.py
34 faraday_plugins/plugins/repo/beef/__init__.py
35 faraday_plugins/plugins/repo/beef/plugin.py
36 faraday_plugins/plugins/repo/brutexss/__init__.py
37 faraday_plugins/plugins/repo/brutexss/plugin.py
38 faraday_plugins/plugins/repo/burp/__init__.py
39 faraday_plugins/plugins/repo/burp/plugin.py
40 faraday_plugins/plugins/repo/checkmarx/__init__.py
41 faraday_plugins/plugins/repo/checkmarx/plugin.py
42 faraday_plugins/plugins/repo/cobalt/__init__.py
43 faraday_plugins/plugins/repo/cobalt/plugin.py
44 faraday_plugins/plugins/repo/dig/__init__.py
45 faraday_plugins/plugins/repo/dig/plugin.py
46 faraday_plugins/plugins/repo/dirb/__init__.py
47 faraday_plugins/plugins/repo/dirb/plugin.py
48 faraday_plugins/plugins/repo/dirsearch/__init__.py
49 faraday_plugins/plugins/repo/dirsearch/plugin.py
50 faraday_plugins/plugins/repo/dnsenum/__init__.py
51 faraday_plugins/plugins/repo/dnsenum/plugin.py
52 faraday_plugins/plugins/repo/dnsmap/__init__.py
53 faraday_plugins/plugins/repo/dnsmap/plugin.py
54 faraday_plugins/plugins/repo/dnsrecon/__init__.py
55 faraday_plugins/plugins/repo/dnsrecon/plugin.py
56 faraday_plugins/plugins/repo/dnswalk/__init__.py
57 faraday_plugins/plugins/repo/dnswalk/plugin.py
58 faraday_plugins/plugins/repo/faraday_csv/__init__.py
59 faraday_plugins/plugins/repo/faraday_csv/plugin.py
60 faraday_plugins/plugins/repo/fierce/__init__.py
61 faraday_plugins/plugins/repo/fierce/plugin.py
62 faraday_plugins/plugins/repo/fortify/__init__.py
63 faraday_plugins/plugins/repo/fortify/plugin.py
64 faraday_plugins/plugins/repo/fruitywifi/__init__.py
65 faraday_plugins/plugins/repo/fruitywifi/fruitywifi.py
66 faraday_plugins/plugins/repo/fruitywifi/plugin.py
67 faraday_plugins/plugins/repo/ftp/__init__.py
68 faraday_plugins/plugins/repo/ftp/plugin.py
69 faraday_plugins/plugins/repo/goohost/__init__.py
70 faraday_plugins/plugins/repo/goohost/plugin.py
71 faraday_plugins/plugins/repo/hping3/__init__.py
72 faraday_plugins/plugins/repo/hping3/plugin.py
73 faraday_plugins/plugins/repo/hydra/__init__.py
74 faraday_plugins/plugins/repo/hydra/plugin.py
75 faraday_plugins/plugins/repo/impact/__init__.py
76 faraday_plugins/plugins/repo/impact/plugin.py
77 faraday_plugins/plugins/repo/ip360/__init__.py
78 faraday_plugins/plugins/repo/ip360/plugin.py
79 faraday_plugins/plugins/repo/junit/__init__.py
80 faraday_plugins/plugins/repo/junit/plugin.py
81 faraday_plugins/plugins/repo/lynis/__init__.py
82 faraday_plugins/plugins/repo/lynis/plugin.py
83 faraday_plugins/plugins/repo/maltego/__init__.py
84 faraday_plugins/plugins/repo/maltego/plugin.py
85 faraday_plugins/plugins/repo/mbsa/__init__.py
86 faraday_plugins/plugins/repo/mbsa/plugin.py
87 faraday_plugins/plugins/repo/medusa/__init__.py
88 faraday_plugins/plugins/repo/medusa/plugin.py
89 faraday_plugins/plugins/repo/metasploit/__init__.py
90 faraday_plugins/plugins/repo/metasploit/plugin.py
91 faraday_plugins/plugins/repo/naabu/__init__.py
92 faraday_plugins/plugins/repo/naabu/plugin.py
93 faraday_plugins/plugins/repo/ncrack/__init__.py
94 faraday_plugins/plugins/repo/ncrack/plugin.py
95 faraday_plugins/plugins/repo/ndiff/__init__.py
96 faraday_plugins/plugins/repo/ndiff/plugin.py
97 faraday_plugins/plugins/repo/nessus/DTO.py
98 faraday_plugins/plugins/repo/nessus/__init__.py
99 faraday_plugins/plugins/repo/nessus/plugin.py
100 faraday_plugins/plugins/repo/netdiscover/__init__.py
101 faraday_plugins/plugins/repo/netdiscover/plugin.py
102 faraday_plugins/plugins/repo/netsparker/__init__.py
103 faraday_plugins/plugins/repo/netsparker/plugin.py
104 faraday_plugins/plugins/repo/netsparkercloud/__init__.py
105 faraday_plugins/plugins/repo/netsparkercloud/plugin.py
106 faraday_plugins/plugins/repo/nexpose_full/__init__.py
107 faraday_plugins/plugins/repo/nexpose_full/plugin.py
108 faraday_plugins/plugins/repo/nextnet/__init__.py
109 faraday_plugins/plugins/repo/nextnet/plugin.py
110 faraday_plugins/plugins/repo/nikto/__init__.py
111 faraday_plugins/plugins/repo/nikto/plugin.py
112 faraday_plugins/plugins/repo/nmap/__init__.py
113 faraday_plugins/plugins/repo/nmap/plugin.py
114 faraday_plugins/plugins/repo/nuclei/__init__.py
115 faraday_plugins/plugins/repo/nuclei/plugin.py
116 faraday_plugins/plugins/repo/openscap/__init__.py
117 faraday_plugins/plugins/repo/openscap/plugin.py
118 faraday_plugins/plugins/repo/openvas/__init__.py
119 faraday_plugins/plugins/repo/openvas/plugin.py
120 faraday_plugins/plugins/repo/pasteanalyzer/__init__.py
121 faraday_plugins/plugins/repo/pasteanalyzer/plugin.py
122 faraday_plugins/plugins/repo/peepingtom/__init__.py
123 faraday_plugins/plugins/repo/peepingtom/plugin.py
124 faraday_plugins/plugins/repo/ping/__init__.py
125 faraday_plugins/plugins/repo/ping/plugin.py
126 faraday_plugins/plugins/repo/propecia/__init__.py
127 faraday_plugins/plugins/repo/propecia/plugin.py
128 faraday_plugins/plugins/repo/qualysguard/__init__.py
129 faraday_plugins/plugins/repo/qualysguard/plugin.py
130 faraday_plugins/plugins/repo/qualyswebapp/__init__.py
131 faraday_plugins/plugins/repo/qualyswebapp/plugin.py
132 faraday_plugins/plugins/repo/rdpscan/__init__.py
133 faraday_plugins/plugins/repo/rdpscan/plugin.py
134 faraday_plugins/plugins/repo/reconng/__init__.py
135 faraday_plugins/plugins/repo/reconng/plugin.py
136 faraday_plugins/plugins/repo/retina/__init__.py
137 faraday_plugins/plugins/repo/retina/plugin.py
138 faraday_plugins/plugins/repo/reverseraider/__init__.py
139 faraday_plugins/plugins/repo/reverseraider/plugin.py
140 faraday_plugins/plugins/repo/skipfish/__init__.py
141 faraday_plugins/plugins/repo/skipfish/plugin.py
142 faraday_plugins/plugins/repo/sonarqubeapi/__init__.py
143 faraday_plugins/plugins/repo/sonarqubeapi/plugin.py
144 faraday_plugins/plugins/repo/sourceclear/__init__.py
145 faraday_plugins/plugins/repo/sourceclear/plugin.py
146 faraday_plugins/plugins/repo/sshdefaultscan/__init__.py
147 faraday_plugins/plugins/repo/sshdefaultscan/plugin.py
148 faraday_plugins/plugins/repo/ssl_labs/__init__.py
149 faraday_plugins/plugins/repo/ssl_labs/plugin.py
150 faraday_plugins/plugins/repo/sslyze/__init__.py
151 faraday_plugins/plugins/repo/sslyze/plugin.py
152 faraday_plugins/plugins/repo/sslyzejson/__init__.py
153 faraday_plugins/plugins/repo/sslyzejson/plugin.py
154 faraday_plugins/plugins/repo/telnet/__init__.py
155 faraday_plugins/plugins/repo/telnet/plugin.py
156 faraday_plugins/plugins/repo/theharvester/__init__.py
157 faraday_plugins/plugins/repo/theharvester/plugin.py
158 faraday_plugins/plugins/repo/traceroute/__init__.py
159 faraday_plugins/plugins/repo/traceroute/plugin.py
160 faraday_plugins/plugins/repo/w3af/__init__.py
161 faraday_plugins/plugins/repo/w3af/plugin.py
162 faraday_plugins/plugins/repo/wapiti/__init__.py
163 faraday_plugins/plugins/repo/wapiti/plugin.py
164 faraday_plugins/plugins/repo/wcscan/__init__.py
165 faraday_plugins/plugins/repo/wcscan/plugin.py
166 faraday_plugins/plugins/repo/webfuzzer/__init__.py
167 faraday_plugins/plugins/repo/webfuzzer/plugin.py
168 faraday_plugins/plugins/repo/webinspect/__init__.py
169 faraday_plugins/plugins/repo/webinspect/plugin.py
170 faraday_plugins/plugins/repo/wfuzz/__init__.py
171 faraday_plugins/plugins/repo/wfuzz/plugin.py
172 faraday_plugins/plugins/repo/whatweb/__init__.py
173 faraday_plugins/plugins/repo/whatweb/plugin.py
174 faraday_plugins/plugins/repo/whitesource/__init__.py
175 faraday_plugins/plugins/repo/whitesource/plugin.py
176 faraday_plugins/plugins/repo/whois/__init__.py
177 faraday_plugins/plugins/repo/whois/plugin.py
178 faraday_plugins/plugins/repo/wpscan/__init__.py
179 faraday_plugins/plugins/repo/wpscan/plugin.py
180 faraday_plugins/plugins/repo/x1/__init__.py
181 faraday_plugins/plugins/repo/x1/plugin.py
182 faraday_plugins/plugins/repo/xsssniper/__init__.py
183 faraday_plugins/plugins/repo/xsssniper/plugin.py
184 faraday_plugins/plugins/repo/zap/__init__.py
185 faraday_plugins/plugins/repo/zap/plugin.py
0 [console_scripts]
1 faraday-plugins = faraday_plugins.commands:cli
2
0 Click
1 beautifulsoup4
2 colorama
3 html2text
4 lxml
5 python-dateutil
6 pytz
7 requests
8 simplejson
9 tabulate
0 [egg_info]
1 tag_build =
2 tag_date = 0
3
1313 'beautifulsoup4',
1414 'pytz',
1515 'python-dateutil',
16 'colorama'
16 'colorama',
17 'tabulate'
1718 ]
1819
1920
2223 version=version,
2324 packages=find_packages(include=['faraday_plugins', 'faraday_plugins.*']),
2425 url='',
25 license='',
26 license="GNU General Public License v3",
2627 author='Faradaysec',
2728 author_email='[email protected]',
2829 description='Faraday plugins package',
+0
-8
tests/commands.json less more
0 {
1 "commands": [
2 {"plugin_id": "ping", "command": "ping -c4 faradaysec.com"},
3 {"plugin_id": "whois", "command": "whois fradaysec.com"},
4 {"plugin_id": "nmap", "command": "nmap fradaysec.com"},
5 {"plugin_id": "skipfish", "command": "skipfish http://fradaysec.com"}
6 ]
7 }
+0
-21
tests/conftest.py less more
0 import pytest
1
2
3 def pytest_addoption(parser):
4 parser.addoption(
5 "--performance", action="store_true", default=False, help="run performance tests"
6 )
7
8
9 def pytest_configure(config):
10 config.addinivalue_line("markers", "performance: mark test as performance")
11
12
13 def pytest_collection_modifyitems(config, items):
14 if config.getoption("--performance"):
15 # --performance given in cli: do not skip performance tests
16 return
17 performance = pytest.mark.skip(reason="need --performance option to run")
18 for item in items:
19 if "performance" in item.keywords:
20 item.add_marker(performance)
+0
-90
tests/generate_reports_summary.py less more
0 #!/usr/bin/env python
1 import hashlib
2 import os
3 import shutil
4 import json
5 import click
6 import colorama
7 from faraday_plugins.plugins.manager import PluginsManager, ReportAnalyzer
8 from faraday_plugins.plugins.plugin import PluginBase
9
10 colorama.init(autoreset=True)
11
12 BLACK_LIST = [
13 'LICENSE',
14 'README.md',
15 '.gitignore',
16 '.gitkeep',
17 'faraday_plugins_tests',
18 ]
19
20 REPORT_COLLECTION_DIR = '../report-collection'
21 FARADAY_PLUGINS_TESTS_DIR = 'faraday_plugins_tests'
22 REPORTS_CHECKSUM = []
23
24 def list_report_files():
25 report_filenames = os.walk(os.path.join(REPORT_COLLECTION_DIR))
26 for root, directory, filenames in report_filenames:
27 if '.git' in directory or FARADAY_PLUGINS_TESTS_DIR in root:
28 continue
29 for filename in filenames:
30 if filename in BLACK_LIST:
31 continue
32 if '.git' in root:
33 continue
34 yield os.path.join(root, filename)
35
36
37 @click.command()
38 @click.option('--force', is_flag=True)
39 @click.option('--debug', is_flag=False)
40 def generate_reports_tests(force, debug):
41 generated_summaries = 0
42 analysed_reports = 0
43 click.echo(f"{colorama.Fore.GREEN}Generate Faraday Plugins Tests Summary")
44 plugins_manager = PluginsManager()
45 analyzer = ReportAnalyzer(plugins_manager)
46 for report_file_path in list_report_files():
47 if debug:
48 click.echo(f"File: {report_file_path}")
49 plugin: PluginBase = analyzer.get_plugin(report_file_path)
50 if not plugin:
51 click.echo(f"{colorama.Fore.YELLOW}Plugin for file: ({report_file_path}) not found")
52 else:
53 with open(report_file_path, 'rb') as f:
54 m = hashlib.md5(f.read())
55 file_checksum = m.hexdigest()
56 if file_checksum not in REPORTS_CHECKSUM:
57 REPORTS_CHECKSUM.append(file_checksum)
58 else:
59 click.echo(f"{colorama.Fore.YELLOW}Ignore duplicated file: ({report_file_path})")
60 continue
61 analysed_reports += 1
62 report_file_name = os.path.basename(report_file_path)
63 plugin_name = plugin.id
64 plugin_path = os.path.join(REPORT_COLLECTION_DIR, FARADAY_PLUGINS_TESTS_DIR, plugin_name)
65 if not os.path.isdir(plugin_path):
66 os.mkdir(plugin_path)
67 dst_report_file_path = os.path.join(plugin_path, report_file_name)
68 summary_needed = False
69 summary_file = f"{os.path.splitext(dst_report_file_path)[0]}_summary.json"
70 if not os.path.isfile(dst_report_file_path) or force:
71 summary_needed = True
72 shutil.copyfile(report_file_path, dst_report_file_path)
73 if not os.path.isfile(summary_file) or force:
74 summary_needed = True
75 if summary_needed:
76 try:
77 plugin.processReport(report_file_path)
78 click.echo(f"{colorama.Fore.GREEN}Generate Summary for: {dst_report_file_path} [{plugin}]")
79 summary = plugin.get_summary()
80 with open(summary_file, "w") as f:
81 json.dump(summary, f)
82 generated_summaries += 1
83 except Exception as e:
84 click.echo(f"{colorama.Fore.RED}Error generating summary for file: {report_file_path} [{plugin}]: [{e}]")
85 click.echo(f"Generated {generated_summaries} summaries of {analysed_reports} reports")
86
87
88 if __name__ == "__main__":
89 generate_reports_tests()
+0
-85
tests/test_cli.py less more
0 import json
1 import os
2 import re
3 from tempfile import NamedTemporaryFile
4 from click.testing import CliRunner
5 from faraday_plugins.commands import list_plugins, detect_command, process_command, detect_report, process_report
6
7
8 def test_list_plugins():
9 runner = CliRunner()
10 result = runner.invoke(list_plugins)
11 assert result.exit_code == 0
12 loaded_plugins = re.search(r'Loaded Plugins: (?P<loaded_plugins>\d+)', result.output)
13 assert loaded_plugins
14 assert int(loaded_plugins.groupdict().get('loaded_plugins', 0)) > 0
15
16
17 def test_detect_invalid_command():
18 runner = CliRunner()
19 result = runner.invoke(detect_command, args=['invalid_command'])
20 assert result.exit_code == 0
21 assert result.output.strip() == "Failed to detect command: invalid_command"
22
23
24 def test_detect_command():
25 runner = CliRunner()
26 result = runner.invoke(detect_command, args=['ping -c 1 www.google.com'])
27 assert result.exit_code == 0
28 assert result.output.strip() == "Faraday Plugin: ping"
29
30
31 def test_process_command():
32 runner = CliRunner()
33 result = runner.invoke(process_command, args=['ping -c 1 www.google.com', '--summary'])
34 assert result.exit_code == 0
35 summary = json.loads(result.output.strip())
36 assert summary['hosts'] == 1
37
38
39 def test_process_command_to_file():
40 runner = CliRunner()
41 with runner.isolated_filesystem() as file_system:
42 output_file = os.path.join(file_system, "test.json")
43 result = runner.invoke(process_command, args=['ping -c 1 www.google.com', '-o', output_file])
44 assert result.exit_code == 0
45 assert os.path.isfile(output_file)
46 with open(output_file) as f:
47 vuln_json = json.load(f)
48 assert len(vuln_json['hosts']) == 1
49
50
51 def test_detect_report():
52 report_file = os.path.join('./report-collection', 'faraday_plugins_tests', 'Nmap', 'nmap_5.21.xml')
53 runner = CliRunner()
54 result = runner.invoke(detect_report, args=[report_file])
55 assert result.exit_code == 0
56 assert "Faraday Plugin: Nmap" == result.output.strip()
57
58
59 def test_detect_report_dont_exists():
60 report_file = os.path.join('./report-collection', 'faraday_plugins_tests', 'Nmap', 'invalid_report.xml')
61 runner = CliRunner()
62 result = runner.invoke(detect_report, args=[report_file])
63 assert result.exit_code == 0
64 assert "Don't Exists" in result.output.strip()
65
66
67 def test_process_report_summary():
68 report_file = os.path.join('./report-collection', 'faraday_plugins_tests', 'Nmap', 'nmap_5.21.xml')
69 summary_file = os.path.join('./report-collection', 'faraday_plugins_tests', 'Nmap', 'nmap_5.21_summary.json')
70 runner = CliRunner()
71 result = runner.invoke(process_report, args=[report_file, '--summary'])
72 assert result.exit_code == 0
73 summary = json.loads(result.output.strip())
74 with open(summary_file) as f:
75 saved_summary = json.load(f)
76 vuln_hashes = set(summary['vuln_hashes'])
77 saved_vuln_hashes = set(saved_summary.get('vuln_hashes', []))
78 assert summary['hosts'] == saved_summary['hosts']
79 assert summary['services'] == saved_summary['services']
80 assert summary['hosts_vulns'] == saved_summary['hosts_vulns']
81 assert summary['services_vulns'] == saved_summary['services_vulns']
82 assert summary['severity_vulns'] == saved_summary['severity_vulns']
83 assert vuln_hashes == saved_vuln_hashes
84
+0
-26
tests/test_commands.py less more
0 import json
1 import pytest
2 from faraday_plugins.plugins.manager import PluginsManager, CommandAnalyzer
3 from faraday_plugins.plugins.plugin import PluginBase
4
5
6 plugins_manager = PluginsManager()
7 analyzer = CommandAnalyzer(plugins_manager)
8
9 COMMANDS_FILE = './tests/commands.json'
10
11 def list_commands():
12 with open(COMMANDS_FILE) as f:
13 commands_dict = json.load(f)
14 for command_data in commands_dict["commands"]:
15 yield command_data
16
17
18 @pytest.mark.parametrize("command_data", list_commands())
19 def test_autodetected_on_commands(command_data):
20 plugin_id = command_data["plugin_id"]
21 command_string = command_data["command"]
22 plugin: PluginBase = analyzer.get_plugin(command_string)
23 assert plugin, command_string
24 assert plugin.id.lower() == plugin_id.lower()
25
+0
-124
tests/test_engine_plugins.py less more
0 from faraday_plugins.plugins.plugin import PluginBase
1
2
3 def test_get_host_cache_id_with_same_host():
4 host_1 = {'ip': '127.0.0.1'}
5 host_2 = {'ip': '127.0.0.1', 'description': 'test desc'}
6 cache_id_1 = PluginBase.get_host_cache_id(host_1)
7 cache_id_2 = PluginBase.get_host_cache_id(host_2)
8
9 assert cache_id_1 == cache_id_2
10
11
12 def test_get_host_cache_id_with_diffent_ip():
13 host_1 = {'ip': '127.0.0.1'}
14 host_2 = {'ip': '192.168.0.1', 'description': 'test desc'}
15 cache_id_1 = PluginBase.get_host_cache_id(host_1)
16 cache_id_2 = PluginBase.get_host_cache_id(host_2)
17
18 assert cache_id_1 != cache_id_2
19
20
21 def test_get_host_service_cache_id_same_objects():
22 host_1 = {'ip': '127.0.0.1'}
23 host_cache_id_1 = PluginBase.get_host_cache_id(host_1)
24 service_1 = {'protocol': 'tcp', 'port': 80}
25 host_2 = {'ip': '127.0.0.1'}
26 host_cache_id_2 = PluginBase.get_host_cache_id(host_2)
27 service_2 = {'protocol': 'tcp', 'port': 80}
28
29 cache_1 = PluginBase.get_host_service_cache_id(host_cache_id_1, service_1)
30 cache_2 = PluginBase.get_host_service_cache_id(host_cache_id_2, service_2)
31
32 assert cache_1 == cache_2
33
34
35 def test_get_host_service_cache_id_different_host():
36 host_1 = {'ip': '127.0.0.1'}
37 host_cache_id_1 = PluginBase.get_host_cache_id(host_1)
38 service_1 = {'protocol': 'tcp', 'port': 80}
39 host_2 = {'ip': '192.168.0.1'}
40 host_cache_id_2 = PluginBase.get_host_cache_id(host_2)
41 service_2 = {'protocol': 'tcp', 'port': 80}
42
43 cache_1 = PluginBase.get_host_service_cache_id(host_cache_id_1, service_1)
44 cache_2 = PluginBase.get_host_service_cache_id(host_cache_id_2, service_2)
45
46 assert cache_1 != cache_2
47
48
49 def test_get_host_vuln_cache_id_severity_does_not_affect_duplicate():
50 host_1 = {'ip': '127.0.0.1'}
51 host_cache_id_1 = PluginBase.get_host_cache_id(host_1)
52 vuln_1 = {'name': 'test', 'desc': 'test', 'severity': 'low'}
53
54 host_2 = {'ip': '127.0.0.1'}
55 host_cache_id_2 = PluginBase.get_host_cache_id(host_2)
56 vuln_2 = {'name': 'test', 'desc': 'test', 'severity': 'high'}
57
58
59 cache_1 = PluginBase.get_host_vuln_cache_id(host_cache_id_1, vuln_1)
60 cache_2 = PluginBase.get_host_vuln_cache_id(host_cache_id_2, vuln_2)
61
62 assert cache_1 == cache_2
63
64
65 def test_get_host_vuln_cache_id_description_makes_different_cache_ids():
66 host_1 = {'ip': '127.0.0.1'}
67 host_cache_id_1 = PluginBase.get_host_cache_id(host_1)
68 vuln_1 = {'name': 'test', 'desc': 'test', 'severity': 'low'}
69
70 host_2 = {'ip': '127.0.0.1'}
71 host_cache_id_2 = PluginBase.get_host_cache_id(host_2)
72 vuln_2 = {'name': 'test', 'new desc': 'test', 'severity': 'high'}
73
74
75 cache_1 = PluginBase.get_host_vuln_cache_id(host_cache_id_1, vuln_1)
76 cache_2 = PluginBase.get_host_vuln_cache_id(host_cache_id_2, vuln_2)
77
78 assert cache_1 != cache_2
79
80
81 def test_get_service_vuln_cache_id_severity_does_not_affect_cache_id():
82 host_1 = {'ip': '127.0.0.1'}
83 host_cache_id_1 = PluginBase.get_host_cache_id(host_1)
84 service_1 = {'protocol': 'tcp', 'port': 80}
85
86 host_2 = {'ip': '127.0.0.1'}
87 host_cache_id_2 = PluginBase.get_host_cache_id(host_2)
88 host_2 = {'ip': '127.0.0.1'}
89 host_cache_id_2 = PluginBase.get_host_cache_id(host_2)
90 service_2 = {'protocol': 'tcp', 'port': 80}
91
92 service_cache_1 = PluginBase.get_host_service_cache_id(host_cache_id_1, service_1)
93 service_cache_2 = PluginBase.get_host_service_cache_id(host_cache_id_2, service_2)
94
95 vuln_2 = {'name': 'test', 'desc': 'test', 'severity': 'high', 'method': 'GET'}
96 vuln_1 = {'name': 'test', 'desc': 'test', 'severity': 'low', 'method': 'GET'}
97
98 cache_1 = PluginBase.get_service_vuln_cache_id(host_cache_id_1, service_cache_1, vuln_1)
99 cache_2 = PluginBase.get_service_vuln_cache_id(host_cache_id_2, service_cache_2, vuln_2)
100
101 assert cache_1 == cache_2
102
103 def test_get_service_vuln_cache_id_with_different_service_return_different_id():
104 host_1 = {'ip': '127.0.0.1'}
105 host_cache_id_1 = PluginBase.get_host_cache_id(host_1)
106 service_1 = {'protocol': 'tcp', 'port': 80}
107
108 host_2 = {'ip': '127.0.0.1'}
109 host_cache_id_2 = PluginBase.get_host_cache_id(host_2)
110 host_2 = {'ip': '127.0.0.1'}
111 host_cache_id_2 = PluginBase.get_host_cache_id(host_2)
112 service_2 = {'protocol': 'tcp', 'port': 22}
113
114 service_cache_1 = PluginBase.get_host_service_cache_id(host_cache_id_1, service_1)
115 service_cache_2 = PluginBase.get_host_service_cache_id(host_cache_id_2, service_2)
116
117 vuln_2 = {'name': 'test', 'desc': 'test', 'severity': 'high', 'method': 'GET'}
118 vuln_1 = {'name': 'test', 'desc': 'test', 'severity': 'low', 'method': 'GET'}
119
120 cache_1 = PluginBase.get_service_vuln_cache_id(host_cache_id_1, service_cache_1, vuln_1)
121 cache_2 = PluginBase.get_service_vuln_cache_id(host_cache_id_2, service_cache_2, vuln_2)
122
123 assert cache_1 != cache_2
+0
-158
tests/test_report_collection.py less more
0 import os
1 import socket
2 import json
3 import pytest
4 from faraday_plugins.plugins.manager import PluginsManager, ReportAnalyzer
5 from faraday_plugins.plugins.plugin import PluginBase
6 from faraday.server.api.modules.bulk_create import BulkCreateSchema
7
8 BLACK_LIST = [
9 'LICENSE',
10 'README.md',
11 '.gitignore',
12 '.gitkeep',
13 'faraday_plugins_tests',
14
15 ]
16
17 plugins_manager = PluginsManager()
18 analyzer = ReportAnalyzer(plugins_manager)
19
20 PLUGINS_CACHE = {}
21 REPORTS_JSON_CACHE = {}
22
23 SKIP_IP_PLUGINS = ['Fortify']
24
25 REPORTS_SUMMARY_DIR = './report-collection/faraday_plugins_tests'
26
27
28 def get_plugin_from_cache(report_file):
29 plugin = PLUGINS_CACHE.get(report_file)
30 if not plugin:
31 plugin: PluginBase = analyzer.get_plugin(report_file)
32 if plugin:
33 save_plugin_in_cache(report_file, plugin)
34 return plugin
35
36
37 def save_plugin_in_cache(report_file, plugin):
38 if report_file not in PLUGINS_CACHE:
39 PLUGINS_CACHE[report_file] = plugin
40
41
42 def get_report_json_from_cache(report_file):
43 plugin_json = REPORTS_JSON_CACHE.get(report_file)
44 if not plugin_json:
45 plugin = get_plugin_from_cache(report_file)
46 if plugin:
47 plugin.processReport(report_file)
48 plugin_json = json.loads(plugin.get_json())
49 REPORTS_JSON_CACHE[report_file] = plugin_json
50 else:
51 plugin = get_plugin_from_cache(report_file)
52 return plugin, plugin_json
53
54
55 def list_report_files():
56 report_filenames = os.walk(REPORTS_SUMMARY_DIR)
57 for root, directory, filenames in report_filenames:
58 if '.git' in directory or 'faraday_plugins_tests' in directory:
59 continue
60 for filename in filenames:
61 if filename in BLACK_LIST:
62 continue
63 if '.git' in root:
64 continue
65 if not filename.endswith('_summary.json'):
66 yield os.path.join(root, filename)
67
68
69 def is_valid_ipv4_address(address):
70 try:
71 socket.inet_pton(socket.AF_INET, address)
72 except AttributeError: # no inet_pton here, sorry
73 try:
74 socket.inet_aton(address)
75 except socket.error:
76 return False
77 return address.count('.') == 3
78 except socket.error: # not a valid address
79 return False
80 return True
81
82
83 def is_valid_ipv6_address(address):
84 try:
85 socket.inet_pton(socket.AF_INET6, address)
86 except socket.error: # not a valid address
87 return False
88 return True
89
90
91 def is_valid_ip_address(address):
92 return (is_valid_ipv4_address(address) or is_valid_ipv6_address(address))
93
94 def test_reports_collection_exists():
95 assert os.path.isdir(REPORTS_SUMMARY_DIR) is True, "Please clone the report-collection repo!"
96
97 @pytest.mark.parametrize("report_filename", list_report_files())
98 def test_autodetected_on_all_report_collection(report_filename):
99 plugin: PluginBase = get_plugin_from_cache(report_filename)
100 assert plugin, report_filename
101
102
103 @pytest.mark.parametrize("report_filename", list_report_files())
104 def test_schema_on_all_reports(report_filename):
105 plugin, plugin_json = get_report_json_from_cache(report_filename)
106 if plugin_json:
107 serializer = BulkCreateSchema()
108 res = serializer.loads(json.dumps(plugin_json))
109 assert set(res.keys()) == {'hosts', 'command'}
110
111
112
113
114 @pytest.mark.skip(reason="Skip validate ip format")
115 @pytest.mark.parametrize("report_filename", list_report_files())
116 def test_host_ips_all_reports(report_filename):
117 plugin, plugin_json = get_report_json_from_cache(report_filename)
118 if plugin_json:
119 if plugin.id not in SKIP_IP_PLUGINS:
120 for host in plugin_json['hosts']:
121 assert is_valid_ip_address(host['ip']) is True
122
123
124 @pytest.mark.parametrize("report_filename", list_report_files())
125 def test_summary_reports(report_filename):
126 plugin, plugin_json = get_report_json_from_cache(report_filename)
127 if plugin_json:
128 summary_file = f"{os.path.splitext(report_filename)[0]}_summary.json"
129 assert os.path.isfile(summary_file) is True
130 with open(summary_file) as f:
131 saved_summary = json.load(f)
132 summary = plugin.get_summary()
133 vuln_hashes = set(summary['vuln_hashes'])
134 saved_vuln_hashes = set(saved_summary.get('vuln_hashes', []))
135 assert summary['hosts'] == saved_summary['hosts']
136 assert summary['services'] == saved_summary['services']
137 assert summary['hosts_vulns'] == saved_summary['hosts_vulns']
138 assert summary['services_vulns'] == saved_summary['services_vulns']
139 assert summary['severity_vulns'] == saved_summary['severity_vulns']
140 assert vuln_hashes == saved_vuln_hashes
141
142
143 @pytest.mark.performance
144 @pytest.mark.parametrize("report_filename", list_report_files())
145 def test_detected_tools_on_all_report_collection(report_filename, benchmark):
146 plugins_manager = PluginsManager()
147 analyzer = ReportAnalyzer(plugins_manager)
148 plugin: PluginBase = analyzer.get_plugin(report_filename)
149 if not plugin:
150 return
151 assert plugin, report_filename
152 benchmark(plugin.processReport, report_filename)
153 plugin_json = json.loads(plugin.get_json())
154 assert "hosts" in plugin_json
155 assert "command" in plugin_json
156 assert os.path.isfile(report_filename) is True
157