Import upstream version 1.8.0
Kali Janitor
1 year, 6 months ago
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 | # 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 | .get_secrets: | |
1 | script: | |
2 | - export VAULT_TOKEN="$(vault write -field=token auth/jwt/login role=python-sast-readonly jwt=$CI_JOB_JWT)"; if [ -z "$VAULT_TOKEN" ]; then exit 1; fi | |
3 | - if [ -z "$DEVSECOPS_WORKSPACE" ]; then export DEVSECOPS_WORKSPACE="$(vault kv get -field=DEVSECOPS_WORKSPACE secrets/gitlab/SAST)"; fi; if [ -z "$DEVSECOPS_WORKSPACE" ]; then exit 1; fi | |
4 | - if [ -z "$FARADAY_PASSWORD" ]; then export FARADAY_PASSWORD="$(vault kv get -field=FARADAY_PASSWORD secrets/gitlab/SAST)"; fi; if [ -z "$FARADAY_PASSWORD" ]; then exit 1; fi | |
5 | - if [ -z "$FARADAY_URL" ]; then export FARADAY_URL="$(vault kv get -field=FARADAY_URL secrets/gitlab/SAST)"; fi; if [ -z "$FARADAY_URL" ]; then exit 1; fi | |
6 | - if [ -z "$FARADAY_USER" ]; then export FARADAY_USER="$(vault kv get -field=FARADAY_USER secrets/gitlab/SAST)"; fi; if [ -z "$FARADAY_USER" ]; then exit 1; fi |
0 | variables: | |
1 | VAULT_ROLE: 'python-sast-readonly' | |
2 | VAULT_ADDR: 'https://tluav-lb.faradaysec.com' | |
3 | VAULT_SECRET_PATH: 'gitlab/SAST' | |
4 | ||
5 | ||
6 | include: | |
7 | - local: .gitlab/ci/fetch-secrets.yml | |
8 | ||
9 | stages: | |
10 | - SAST | |
11 | - pre_testing | |
12 | - testing | |
13 | - post_testing | |
14 | - publish | |
15 | ||
16 | before_script: | |
17 | - apt-get update -qy | |
18 | - pip install pip -U | |
19 | ||
20 | workflow: | |
21 | rules: | |
22 | - if: $CI_MERGE_REQUEST_ID | |
23 | when: never | |
24 | - when: always | |
25 | ||
26 | .install_faraday_venv: &install_faraday_venv | |
27 | - pip3 install virtualenv | |
28 | - virtualenv -p python3 faraday_venv | |
29 | - source faraday_venv/bin/activate | |
30 | - pip3 install pytest pytest-xdist pytest-cov | |
31 | - git clone https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.com/faradaysec/faraday.git | |
32 | - cd faraday | |
33 | - pip3 install $PIP_FLAGS . | |
34 | - pip uninstall faraday-plugins -y # we need to install fardaysec for marshmallow schemas, we remove plugins from pypi | |
35 | - cd .. | |
36 | ||
37 | .clone_reports: &clone_reports | |
38 | - git clone https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.com/faradaysec/support/report-collection.git | |
39 | - cd report-collection | |
40 | - (git branch -a | grep $CI_COMMIT_BRANCH) && export REPORT_REF=$CI_COMMIT_BRANCH || export REPORT_REF=master | |
41 | - git checkout $REPORT_REF | |
42 | - cd .. | |
43 | ||
44 | bandit: | |
45 | stage: SAST | |
46 | image: python:3 | |
47 | tags: | |
48 | - faradaytests | |
49 | script: | |
50 | - pip3 install bandit | |
51 | - mkdir /results | |
52 | - "bandit -r ${CI_PROJECT_DIR} -o /results/output.xml -f xml --skip B410,B320,B310,B314,B404,B405,B324,B603,B104,B110,B112,B101" | |
53 | after_script: | |
54 | - curl -fsSL https://apt.releases.hashicorp.com/gpg | apt-key add - | |
55 | - apt update | |
56 | - apt-get install software-properties-common -y | |
57 | - apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com focal main" | |
58 | - apt update | |
59 | - apt install vault -y | |
60 | - setcap cap_ipc_lock= /usr/bin/vault | |
61 | - !reference [ .get_secrets, script ] | |
62 | - pip3 install faraday-cli | |
63 | - if [[ $(grep -c testcase /results/output.xml) -gt 0 ]]; then (faraday-cli auth -f $FARADAY_URL -u $FARADAY_USER -p $FARADAY_PASSWORD && faraday-cli tool report /results/output.xml -w $DEVSECOPS_WORKSPACE --tag-vuln $CI_PROJECT_NAME --tag-vuln $CI_COMMIT_REF_NAME); else (echo 'no vulns dettected' && exit 0); fi | |
64 | rules: | |
65 | - when: on_success | |
66 | ||
67 | flake8: | |
68 | image: python:3 | |
69 | stage: pre_testing | |
70 | before_script: | |
71 | - pip install flake8 | |
72 | # Help flake8 to find the Python files without .py extension. | |
73 | - find . -name '*.py' >> files.txt | |
74 | - sort -u files.txt | tee files.processed | |
75 | script: | |
76 | - python -m flake8 --statistics --count $(cat files.processed) --verbose | |
77 | after_script: | |
78 | - wc -l files.processed | |
79 | ||
80 | .test_base: | |
81 | stage: testing | |
82 | coverage: '/TOTAL\s+\d+\s+\d+\s+(\d+%)/' | |
83 | script: | |
84 | - *clone_reports | |
85 | - *install_faraday_venv | |
86 | - pip3 install $PIP_FLAGS . | |
87 | - pytest tests --capture=sys -v --cov=faraday_plugins --color=yes --disable-warnings $PYTEST_FLAGS | |
88 | ||
89 | tests: | |
90 | extends: .test_base | |
91 | image: python:3 | |
92 | ||
93 | test_performance: | |
94 | extends: .test_base | |
95 | image: python:3 | |
96 | stage: post_testing | |
97 | allow_failure: true | |
98 | variables: | |
99 | PYTEST_FLAGS: --performance | |
100 | rules: | |
101 | - if: '$CI_COMMIT_BRANCH == "dev"' | |
102 | when: on_success | |
103 | ||
104 | publish_pypi: | |
105 | image: python:3 | |
106 | stage: publish | |
107 | script: | |
108 | - apt-get update -qy | |
109 | - apt-get install twine -y | |
110 | - python setup.py sdist bdist_wheel | |
111 | - twine upload -u $PYPI_USER -p $PYPI_PASS dist/* --verbose | |
112 | rules: | |
113 | - if: '$CI_COMMIT_TAG' | |
114 | when: on_success | |
115 |
0 | add a default value to plugin_version⏎ |
0 | Add --output-file parameter to faraday-plugins process command⏎ |
0 | Bug fix: Arachni Plugin 'NoneType' object has no attribute 'find' |
0 | Bug fix: Openvas Plugin - Import xml from OpenVas doesnt work |
0 | Bug fix: QualysWebApp Plugin, error in get info OPERATING_SYSTEM |
0 | Fix Hydra plugin to resolve ip address⏎ |
0 | Update the fields of the nuclei output used to create a vuln⏎ |
0 | Add new plugin base class, for multi line json⏎ |
0 | Fix missing ip in some arachni reports⏎ |
0 | Change the way we detect json reports when they are lists of dictionaries⏎ |
0 | ADD microsoft baseline security analyzer plugin |
0 | Add Ignore information vulnerabilities option |
0 | Faraday CSV Plugin do not consider ignore_info |
0 | Use background for description and detail for data en Burp plugin. |
0 | - add attribute "command" for the pluggins of each command | |
1 | - adding test in test_command | |
2 | - change some regex in self._command_regex⏎ |
0 | [FIX] add hostnames if host is already cached |
0 | FIX unused import, innecesary list compression and unused variables⏎ |
0 | FIX metasploit report when the web-site-id is null⏎ |
0 | ADD cve, cvss3_base_score, cvss3_vector, exploit_available when import nessus and change the structure of external_id to NESSUS-XXX⏎ |
0 | ADD more data like attack, params, uri, method, WASC, CWE and format externail_id⏎ |
0 | Add vuln details for Certificate Mismatch and move unique details to data, now vulns can be grupped |
0 | ADD more data to plugins arachni and w3af⏎ |
0 | ADD cvss_base, cpe, threat, severity into references⏎ |
0 | cwe, capec, references, tags, impact, resolution, easeofresolution |
0 | [FIX] Fix improt of CSV with big fields |
0 | Adding support for running nuclei through command / faraday-cli |
0 | Add CVE to plugins | |
1 | - acunetix | |
2 | - appscan | |
3 | - burp | |
4 | - metasploit | |
5 | - nessus | |
6 | - netsparker | |
7 | - nexpose | |
8 | - nikto | |
9 | - nipper | |
10 | - nmap | |
11 | - openscap | |
12 | - qualysguard | |
13 | - retina | |
14 | - shodan |
0 | Fix errors while creating hosts with wrong regex⏎ |
0 | Add severity to shodan's plugins using cvss⏎ |
0 | Change qualysguard's plugin severity_dict to refer level 2 severities as low |
0 | Now Appscan plugin saves line and highlight of the vulns in desc and data |
0 | Now the faraday_csv custom_fields regex match any no whitespace character. |
0 | Now Openvas's plugin set severity to Critical when cvss >= 9.0 |
0 | Add hostname_resolution parameter within plugins |
0 | Change hostname_restolution to dont_resolve_hostname for process-report and now test dosent resovle hostname |
0 | Now QualysWebApp's plugin will diferenciate vulns from differents urlpaths |
0 | Now faraday_csv's plugin uses ignore_info parameter |
0 | Add cve and data fields to desc for avoid duplications |
0 | Add CWE to PluginBase. The plugins that have this implemented are the following: | |
1 | "Acunetix", | |
2 | "Acunetix_Json", | |
3 | "AppSpider", | |
4 | "Appscan", | |
5 | "Arachni", | |
6 | "Burp", | |
7 | "Checkmarx", | |
8 | "Metasploit", | |
9 | "Nessus", | |
10 | "Netsparker", | |
11 | "NetsparkerCloud", | |
12 | "Openvas", | |
13 | "QualysWebapp", | |
14 | "W3af", | |
15 | "Wapiti", | |
16 | "Zap", | |
17 | "Zap_Json", | |
18 | "nuclei", | |
19 | "nuclei_legacy" |
0 | Now the nexts pluggins extracts cvss from reports: | |
1 | ||
2 | - Acunetix | |
3 | - Acunetix_Json | |
4 | - Appscan | |
5 | - Nessus | |
6 | - Netsparker | |
7 | - NexposeFull | |
8 | - Nipper | |
9 | - Nmap | |
10 | - Openvas | |
11 | - QualysWebapp | |
12 | - Qualysguard | |
13 | - Retina | |
14 | - shodan | |
15 | - whitesource |
0 | Add command support for the wpscan plugin |
0 | [FIX] - Asset duplicated on same file with multiple entries for Appscan_csv plugin.⏎ |
0 | [FIX] Change import dateutil to from dateutil.parser import parse | |
1 | for compatibility issues with python 3.10 |
0 | [FIX] Add case for Netsparker plugins, when the url has a number inside a parenthesis. |
0 | fix bug when grype report has no arifact/metadata |
0 | Metadata-Version: 2.1 | |
1 | Name: faraday-plugins | |
2 | Version: 1.8.0 | |
3 | Summary: Faraday plugins package | |
4 | Home-page: | |
5 | Author: Faradaysec | |
6 | Author-email: [email protected] | |
7 | License: GNU General Public License v3 | |
8 | License-File: COPYING |
0 | 1.7.0 [Sep 5th, 2022]: | |
1 | --- | |
2 | * Add CWE to PluginBase. The plugins that have this implemented are the following: | |
3 | "Acunetix", | |
4 | "Acunetix_Json", | |
5 | "AppSpider", | |
6 | "Appscan", | |
7 | "Arachni", | |
8 | "Burp", | |
9 | "Checkmarx", | |
10 | "Metasploit", | |
11 | "Nessus", | |
12 | "Netsparker", | |
13 | "NetsparkerCloud", | |
14 | "Openvas", | |
15 | "QualysWebapp", | |
16 | "W3af", | |
17 | "Wapiti", | |
18 | "Zap", | |
19 | "Zap_Json", | |
20 | "nuclei", | |
21 | "nuclei_legacy" | |
22 | * Now the nexts pluggins extracts cvss from reports: | |
23 | ||
24 | - Acunetix | |
25 | - Acunetix_Json | |
26 | - Appscan | |
27 | - Nessus | |
28 | - Netsparker | |
29 | - NexposeFull | |
30 | - Nipper | |
31 | - Nmap | |
32 | - Openvas | |
33 | - QualysWebapp | |
34 | - Qualysguard | |
35 | - Retina | |
36 | - shodan | |
37 | - whitesource | |
38 | * Add arguments for add tags for vulns, services and host. | |
39 | ||
40 | Add test for tags and ignore_info | |
41 | * Add trivy's json plugin | |
42 | * Add command support for the wpscan plugin | |
43 | * [MOD] Now refs field is a list of dictionary with the format: | |
44 | {'name': string, 'type': string}, | |
45 | * Fix for acunetix_json when host is ip | |
46 | * [FIX] - Asset duplicated on same file with multiple entries for Appscan_csv plugin. | |
47 | * [FIX] Change import dateutil to from dateutil.parser import parse | |
48 | for compatibility issues with python 3.10 | |
49 | * [FIX] Add case for Netsparker plugins, when the url has a number inside a parenthesis. | |
50 | * Add *args **kwargs to syhunt plugin | |
51 | * fix bug when grype report has no arifact/metadata | |
52 | * [MOD] Now prowler plugin returns CAF Epic as policy violation and | |
53 | remove [check#] from tittle | |
54 | ||
55 | 1.6.8 [Jul 25th, 2022]: | |
56 | --- | |
57 | * Add appscan csv | |
58 | * Now faraday_csv's plugin uses ignore_info parameter | |
59 | * Add syhunt plugin | |
60 | * Add cve and data fields to desc for avoid duplications | |
61 | * Now nuclei resolve hostname if the field ip is None | |
62 | ||
63 | 1.6.7 [Jun 2nd, 2022]: | |
64 | --- | |
65 | * Change hostname_restolution to dont_resolve_hostname for process-report and now test dosent resovle hostname | |
66 | * Now QualysWebApp's plugin will diferenciate vulns from differents urlpaths | |
67 | ||
68 | 1.6.6 [May 20th, 2022]: | |
69 | --- | |
70 | * Add hostname_resolution parameter within plugins | |
71 | * Fix openvas external ID | |
72 | ||
73 | 1.6.5 [Apr 28th, 2022]: | |
74 | --- | |
75 | * Now Openvas's plugin set severity to Critical when cvss >= 9.0 | |
76 | ||
77 | 1.6.4 [Apr 21th, 2022]: | |
78 | --- | |
79 | * Add location as params in burp's plugin | |
80 | * Now the faraday_csv custom_fields regex match any no whitespace character. | |
81 | ||
82 | 1.6.3 [Apr 19th, 2022]: | |
83 | --- | |
84 | * Add Zap Json plugin. | |
85 | ||
86 | 1.6.2 [Apr 4th, 2022]: | |
87 | --- | |
88 | * Now Appscan plugin saves line and highlight of the vulns in desc and data | |
89 | ||
90 | 1.6.1 [Mar 18th, 2022]: | |
91 | --- | |
92 | * Add references tu burp plugin | |
93 | * Move item.detail from data to desc | |
94 | * update open status | |
95 | ||
96 | 1.6.0 [Feb 3rd, 2022]: | |
97 | --- | |
98 | * Add packaging to requierments in setup.py | |
99 | * Add severity to shodan's plugins using cvss | |
100 | * check if cve exist on cve-id field | |
101 | * Fix Fortify's plugin | |
102 | * Change qualysguard's plugin severity_dict to refer level 2 severities as low | |
103 | ||
104 | 1.5.10 [Jan 13th, 2022]: | |
105 | --- | |
106 | * support cve,cwe,cvss and metadata | |
107 | ||
108 | 1.5.9 [Dec 27th, 2021]: | |
109 | --- | |
110 | * Add cve in faraday_csv plugin | |
111 | * ADD Grype plugin | |
112 | ||
113 | 1.5.8 [Dec 13th, 2021]: | |
114 | --- | |
115 | * Add CVE to plugins | |
116 | - acunetix | |
117 | - appscan | |
118 | - burp | |
119 | - metasploit | |
120 | - nessus | |
121 | - netsparker | |
122 | - nexpose | |
123 | - nikto | |
124 | - nipper | |
125 | - nmap | |
126 | - openscap | |
127 | - qualysguard | |
128 | - retina | |
129 | - shodan | |
130 | * Add support for Sslyze 5.0 resports | |
131 | * Fix errors while creating hosts with wrong regex | |
132 | * ADD masscan support to nmap plugin | |
133 | * Fix bug in openvas plugin | |
134 | ||
135 | 1.5.7 [Nov 19th, 2021]: | |
136 | --- | |
137 | * FIX extrainfo of netsparker plugin | |
138 | * Add nuclei_legacy plugin | |
139 | ||
140 | 1.5.6 [Nov 10th, 2021]: | |
141 | --- | |
142 | * FIX issue with acunetix plugin | |
143 | ||
144 | * FIX typo in nikto plugin | |
145 | ||
146 | 1.5.5 [Oct 21st, 2021]: | |
147 | --- | |
148 | * Merge PR from github | |
149 | ||
150 | 1.5.4 [Oct 19th, 2021]: | |
151 | --- | |
152 | * Update nuclei parser | |
153 | ||
154 | 1.5.3 [Sep 7th, 2021]: | |
155 | --- | |
156 | * Adding support for running nuclei through command / faraday-cli | |
157 | * Fix missing references in nuclei | |
158 | ||
159 | 1.5.2 [Aug 9th, 2021]: | |
160 | --- | |
161 | * add new structure acunetix | |
162 | ||
163 | 1.5.1 [Jul 27th, 2021]: | |
164 | --- | |
165 | * cwe, capec, references, tags, impact, resolution, easeofresolution | |
166 | * add os openvas | |
167 | * [FIX] Fix improt of CSV with big fields | |
168 | * Fix sslyze json bug with port | |
169 | * Only show report name in command data | |
170 | ||
171 | 1.5.0 [Jun 28th, 2021]: | |
172 | --- | |
173 | * Add Nipper Plugin | |
174 | * add shodan plugin | |
175 | * fix acunetix url parser | |
176 | * FIX netsparker multi-host | |
177 | * Add vuln details for Certificate Mismatch and move unique details to data, now vulns can be grupped | |
178 | * ADD more data to plugins arachni and w3af | |
179 | * Use run_date in UTC | |
180 | * ADD cvss_base, cpe, threat, severity into references | |
181 | ||
182 | 1.4.6 [May 14th, 2021]: | |
183 | --- | |
184 | * - add attribute "command" for the pluggins of each command | |
185 | - adding test in test_command | |
186 | - change some regex in self._command_regex | |
187 | * [FIX] add hostnames if host is already cached | |
188 | * Add Naabu plugin | |
189 | * Add Sonarqube plugin | |
190 | * Add version and change list_plugins style | |
191 | * FIX unused import, innecesary list compression and unused variables | |
192 | * FIX metasploit report when the web-site-id is null | |
193 | * Fix port stats in nmap | |
194 | * fixup ssylze | |
195 | sacar unknown de version= | |
196 | * ADD remedy into resolution | |
197 | * Support for nuclei 2.3.0 | |
198 | * ADD cve, cvss3_base_score, cvss3_vector, exploit_available when import nessus and change the structure of external_id to NESSUS-XXX | |
199 | * ADD more data like attack, params, uri, method, WASC, CWE and format externail_id | |
200 | ||
201 | 1.4.5 [Apr 15th, 2021]: | |
202 | --- | |
203 | * Add Bandit plugin | |
204 | * Use background for description and detail for data en Burp plugin. | |
205 | * Rewrite Appscan Plugin | |
206 | * Parse Nmap vulners script data | |
207 | ||
208 | 1.4.4 [Mar 30th, 2021]: | |
209 | --- | |
210 | * Faraday CSV Plugin do not consider ignore_info | |
211 | ||
212 | 1.4.3 [Mar 17th, 2021]: | |
213 | --- | |
214 | * Add Ignore information vulnerabilities option | |
215 | ||
216 | 1.4.2 [Mar 10th, 2021]: | |
217 | --- | |
218 | * Fix bug with sslyze output file | |
219 | * FIX change id sslyze for JSON/XML | |
220 | ||
221 | 1.4.1 [Feb 26th, 2021]: | |
222 | --- | |
223 | * ADD microsoft baseline security analyzer plugin | |
224 | * ADD nextnet plugin | |
225 | * ADD openscap plugin | |
226 | * FIX old versions of Nessus plugins bugs | |
227 | ||
228 | 1.4.0 [Dec 23rd, 2020]: | |
229 | --- | |
230 | * Update the fields of the nuclei output used to create a vuln | |
231 | ||
232 | 1.4.0b2 [Dec 15th, 2020]: | |
233 | --- | |
234 | * Fix nuclei plugin bug when url is None | |
235 | ||
236 | 1.4.0b1 [Dec 14th, 2020]: | |
237 | --- | |
238 | * Add new plugin base class, for multi line json | |
239 | * New ncrack plugin | |
240 | * New nuclei plugin | |
241 | * New sslyze json plugin | |
242 | * New WhatWeb plugin | |
243 | * Fix missing ip in some arachni reports | |
244 | * Fix change name vuln in Netsparker plugin | |
245 | * Fix whois plugin, command whois IP not parse data | |
246 | * Change the way we detect json reports when they are lists of dictionaries | |
247 | ||
248 | 1.3.0 [Sep 2nd, 2020]: | |
249 | --- | |
250 | * ADD plugin AppSpider | |
251 | * Add tests to faraday-plugins cli | |
252 | * add a default value to plugin_version | |
253 | * Add --output-file parameter to faraday-plugins process command | |
254 | * Add plugins prowler | |
255 | * Add plugins ssl labs | |
256 | * Add support for tenable io | |
257 | * delete old deprecated methods | |
258 | * Bug fix: Arachni Plugin 'NoneType' object has no attribute 'find' | |
259 | * Bug fix: Openvas Plugin - Import xml from OpenVas doesnt work | |
260 | * Bug fix: QualysWebApp Plugin, error in get info OPERATING_SYSTEM | |
261 | * Fix Hydra plugin to resolve ip address | |
262 | * Fix Nessus mod severity HIGH for Low | |
263 | * Bug Fix: Detect plugins AWS Prowler | |
264 | * Fix broken xml on nmap plugin | |
265 | * Add new rdpscan plugin | |
266 | * UPDATE xml report to appscan | |
267 | * Update Readme | |
268 | * Fix how ZAP genereate vulns | |
269 |
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 | ## Write you own plugins | |
1 | ||
2 | > XML report plugin | |
3 | ||
4 | ```python | |
5 | class XXXPLugin(PluginXMLFormat): | |
6 | ||
7 | def __init__(self, *args, **kwargs): | |
8 | super().__init__(*args, **kwargs) | |
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, *args, **kwargs): | |
24 | super().__init__(*args, **kwargs) | |
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 | ``` |
427 | 427 | """ |
428 | 428 | refs = [] |
429 | 429 | if ref: |
430 | refs = [{'name': url, 'type': 'other'} for url in ref] | |
430 | for r in ref: | |
431 | if isinstance(r, dict): | |
432 | refs.append(r) | |
433 | else: | |
434 | refs.append({'name': r, 'type': 'other'}) | |
431 | 435 | return refs |
432 | 436 | |
433 | 437 | def createAndAddVulnToHost(self, host_id, name, desc="", ref=None, |
739 | 743 | if super().report_belongs_to(**kwargs): |
740 | 744 | if file_json_keys is None: |
741 | 745 | file_json_keys = set() |
742 | match = self.json_keys.issubset(file_json_keys) | |
743 | self.logger.debug(f"Json Keys Match: [{file_json_keys} =/in {self.json_keys}] -> {match}") | |
746 | if isinstance(self.json_keys, list): | |
747 | for jk in self.json_keys: | |
748 | match = jk.issubset(file_json_keys) | |
749 | self.logger.debug(f"Json Keys Match: [{file_json_keys} =/in {jk}] -> {match}") | |
750 | if match: | |
751 | break | |
752 | else: | |
753 | match = self.json_keys.issubset(file_json_keys) | |
754 | self.logger.debug(f"Json Keys Match: [{file_json_keys} =/in {self.json_keys}] -> {match}") | |
744 | 755 | return match |
745 | 756 | |
746 | 757 |
24 | 24 | self._command_regex = re.compile(r'^grype\s+.*') |
25 | 25 | self._use_temp_file = True |
26 | 26 | self._temp_file_extension = "json" |
27 | self.json_keys = {"source", "matches", "descriptor"} | |
27 | self.json_keys = [{"source", "matches", "descriptor"}, {"matches", "image"}] | |
28 | 28 | |
29 | 29 | def parseOutputString(self, output, debug=True): |
30 | 30 | grype_json = json.loads(output) |
31 | if "userInput" in grype_json["source"]["target"]: | |
31 | if "userInput" in grype_json.get("source", {"target": ""}).get("target"): | |
32 | 32 | name = grype_json["source"]["target"]["userInput"] |
33 | host_type = grype_json['source']['type'] | |
34 | elif "tags" in grype_json.get("image", {}): | |
35 | name = " ".join(grype_json["image"]["tags"]) | |
36 | host_type = "Docker Image" | |
33 | 37 | else: |
34 | 38 | name = grype_json["source"]["target"] |
35 | host_id = self.createAndAddHost(name, description=f"Type: {grype_json['source']['type']}") | |
39 | host_type = grype_json['source']['type'] | |
40 | host_id = self.createAndAddHost(name, description=f"Type: {host_type}") | |
36 | 41 | for match in grype_json['matches']: |
37 | 42 | name = match.get('vulnerability').get('id') |
38 | 43 | cve = name |
39 | 44 | references = [] |
40 | if match["relatedVulnerabilities"]: | |
45 | if match.get("relatedVulnerabilities"): | |
41 | 46 | description = match["relatedVulnerabilities"][0].get('description') |
42 | 47 | references.append(match["relatedVulnerabilities"][0]["dataSource"]) |
43 | 48 | related_vuln = match["relatedVulnerabilities"][0] |
44 | 49 | severity = related_vuln["severity"].lower().replace("negligible", "info") |
45 | for url in related_vuln["urls"]: | |
46 | references.append(url) | |
50 | if related_vuln.get("links"): | |
51 | for url in related_vuln["links"]: | |
52 | references.append(url) | |
53 | else: | |
54 | for url in related_vuln["urls"]: | |
55 | references.append(url) | |
47 | 56 | else: |
48 | description = match.get('vulnerability').get('description') | |
57 | description = match.get('vulnerability').get('description', "Issues provided no description") | |
49 | 58 | severity = match.get('vulnerability').get('severity').lower().replace("negligible", "info") |
50 | for url in match.get('vulnerability').get('urls'): | |
51 | references.append(url) | |
59 | if match.get('vulnerability').get("links"): | |
60 | for url in match.get('vulnerability')["links"]: | |
61 | references.append(url) | |
62 | else: | |
63 | for url in match.get('vulnerability')["urls"]: | |
64 | references.append(url) | |
52 | 65 | if not match['artifact'].get('metadata'): |
53 | 66 | data = f"Artifact: {match['artifact']['name']}" \ |
54 | 67 | f"Version: {match['artifact']['version']} " \ |
60 | 73 | f"Type: {match['artifact']['type']}" |
61 | 74 | elif "VirtualPath" in match['artifact']['metadata']: |
62 | 75 | data = f"Artifact: {match['artifact']['name']} [{match['artifact']['metadata']['VirtualPath']}] " \ |
76 | f"Version: {match['artifact']['version']} " \ | |
77 | f"Type: {match['artifact']['type']}" | |
78 | else: | |
79 | data = f"Artifact: {match['artifact']['name']}" \ | |
63 | 80 | f"Version: {match['artifact']['version']} " \ |
64 | 81 | f"Type: {match['artifact']['type']}" |
65 | 82 | self.createAndAddVulnToHost(host_id, |
0 | from typing import List | |
1 | ||
2 | ||
3 | class Cvss3: | |
4 | def __init__(self, node): | |
5 | self.node = node | |
6 | ||
7 | @property | |
8 | def vector(self) -> str: | |
9 | return self.node.find('vector').text | |
10 | ||
11 | ||
12 | class Reference: | |
13 | def __init__(self, node): | |
14 | self.node = node | |
15 | ||
16 | @property | |
17 | def owasp(self) -> str: | |
18 | return self.node.find('owasp').text | |
19 | ||
20 | @property | |
21 | def wasc(self) -> str: | |
22 | return self.node.find('wasc').text | |
23 | ||
24 | @property | |
25 | def cwe(self) -> str: | |
26 | return self.node.find('cwe').text | |
27 | ||
28 | @property | |
29 | def capec(self) -> str: | |
30 | return self.node.find('capec').text | |
31 | ||
32 | @property | |
33 | def pci32(self) -> str: | |
34 | return self.node.find('pci32').text | |
35 | ||
36 | @property | |
37 | def hipaa(self) -> str: | |
38 | return self.node.find('hipaa').text | |
39 | ||
40 | @property | |
41 | def owasppc(self) -> str: | |
42 | return self.node.find('owasppc').text | |
43 | ||
44 | @property | |
45 | def cvss3(self) -> Cvss3: | |
46 | return Cvss3(self.node.find("cvss31")) | |
47 | ||
48 | ||
49 | class Request: | |
50 | def __init__(self, node): | |
51 | self.node = node | |
52 | ||
53 | @property | |
54 | def method(self) -> str: | |
55 | return self.node.find("method").text | |
56 | ||
57 | @property | |
58 | def content(self) -> str: | |
59 | return self.node.find("content").text | |
60 | ||
61 | ||
62 | class Response: | |
63 | def __init__(self, node): | |
64 | self.node = node | |
65 | ||
66 | @property | |
67 | def content(self) -> str: | |
68 | return self.node.find("content").text | |
69 | ||
70 | ||
71 | class Vulnerability: | |
72 | def __init__(self, node): | |
73 | self.node = node | |
74 | ||
75 | @property | |
76 | def look_id(self) -> str: | |
77 | return self.node.find('LookupId').text | |
78 | ||
79 | @property | |
80 | def url(self) -> str: | |
81 | return self.node.find("url").text | |
82 | ||
83 | @property | |
84 | def name(self) -> str: | |
85 | return self.node.find('name').text | |
86 | ||
87 | @property | |
88 | def severity(self) -> str: | |
89 | return self.node.find('severity').text | |
90 | ||
91 | @property | |
92 | def confirmed(self) -> str: | |
93 | return self.node.find('confirmed').text | |
94 | ||
95 | @property | |
96 | def description(self) -> str: | |
97 | return self.node.find('description').text | |
98 | ||
99 | @property | |
100 | def http_request(self) -> Request: | |
101 | return Request(self.node.find("http-request")) | |
102 | ||
103 | @property | |
104 | def http_response(self) -> Response: | |
105 | return Response(self.node.find("http-response")) | |
106 | ||
107 | @property | |
108 | def impact(self) -> str: | |
109 | return self.node.find("impact").text | |
110 | ||
111 | @property | |
112 | def remedial_actions(self) -> str: | |
113 | return self.node.find("remedial-actions").text | |
114 | ||
115 | @property | |
116 | def remedial_procedure(self) -> str: | |
117 | return self.node.find("remedial-procedure").text | |
118 | ||
119 | @property | |
120 | def classification(self) -> Reference: | |
121 | return Reference(self.node.find("classification")) | |
122 | ||
123 | ||
124 | class Target: | |
125 | def __init__(self, node): | |
126 | self.node = node | |
127 | ||
128 | @property | |
129 | def scan_id(self) -> str: | |
130 | return self.node.find("scan-id").text | |
131 | ||
132 | @property | |
133 | def url(self) -> str: | |
134 | return self.node.find("url").text | |
135 | ||
136 | ||
137 | class Invicti: | |
138 | def __init__(self, node): | |
139 | self.node = node | |
140 | ||
141 | @property | |
142 | def target(self) -> Target: | |
143 | return Target(self.node.find('target')) | |
144 | ||
145 | @property | |
146 | def vulnerabilities(self) -> List[Vulnerability]: | |
147 | return [Vulnerability(i) for i in self.node.findall('vulnerabilities/vulnerability')] |
0 | """ | |
1 | Faraday Penetration Test IDE | |
2 | Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) | |
3 | See the file 'doc/LICENSE' for the license information | |
4 | ||
5 | """ | |
6 | from urllib.parse import urlsplit | |
7 | from bs4 import BeautifulSoup | |
8 | from lxml import etree | |
9 | ||
10 | from faraday_plugins.plugins.plugin import PluginXMLFormat | |
11 | from faraday_plugins.plugins.repo.invicti.DTO import Invicti | |
12 | ||
13 | __author__ = "Gonzalo Martinez" | |
14 | __copyright__ = "Copyright (c) 2013, Infobyte LLC" | |
15 | __credits__ = ["Gonzalo Martinez"] | |
16 | __version__ = "1.0.0" | |
17 | __maintainer__ = "Gonzalo Martinez" | |
18 | __email__ = "[email protected]" | |
19 | __status__ = "Development" | |
20 | ||
21 | ||
22 | class InvictiXmlParser: | |
23 | """ | |
24 | The objective of this class is to parse a xml file generated by | |
25 | the acunetix tool. | |
26 | ||
27 | @param invicti_xml_filepath A proper xml generated by acunetix | |
28 | """ | |
29 | ||
30 | def __init__(self, xml_output): | |
31 | ||
32 | tree = self.parse_xml(xml_output) | |
33 | self.invicti = Invicti(tree) | |
34 | ||
35 | @staticmethod | |
36 | def parse_xml(xml_output): | |
37 | """ | |
38 | Open and parse an xml file. | |
39 | ||
40 | TODO: Write custom parser to just read the nodes that we need instead | |
41 | of reading the whole file. | |
42 | ||
43 | @return xml_tree An xml tree instance. None if error. | |
44 | """ | |
45 | ||
46 | try: | |
47 | parser = etree.XMLParser(recover=True) | |
48 | tree = etree.fromstring(xml_output, parser=parser) | |
49 | except SyntaxError as err: | |
50 | print(f"SyntaxError: {err}. {xml_output}") | |
51 | return None | |
52 | ||
53 | return tree | |
54 | ||
55 | ||
56 | class InvictiPlugin(PluginXMLFormat): | |
57 | """ | |
58 | Example plugin to parse invicti output. | |
59 | """ | |
60 | ||
61 | def __init__(self, *arg, **kwargs): | |
62 | super().__init__(*arg, **kwargs) | |
63 | self.identifier_tag = "invicti-enterprise" | |
64 | self.id = "Invicti" | |
65 | self.name = "Invicti XML Output Plugin" | |
66 | self.plugin_version = "1.0.0" | |
67 | self.version = "9" | |
68 | self.framework_version = "1.0.0" | |
69 | self.options = None | |
70 | self._current_output = None | |
71 | self.target = None | |
72 | ||
73 | def parseOutputString(self, output): | |
74 | """ | |
75 | This method will discard the output the shell sends, it will read it | |
76 | from the xml where it expects it to be present. | |
77 | ||
78 | NOTE: if 'debug' is true then it is being run from a test case and the | |
79 | output being sent is valid. | |
80 | """ | |
81 | parser = InvictiXmlParser(output) | |
82 | url = urlsplit(parser.invicti.target.url) | |
83 | ip = self.resolve_hostname(url.netloc) | |
84 | h_id = self.createAndAddHost(ip) | |
85 | s_id = self.createAndAddServiceToHost(h_id, url.scheme, ports=433) | |
86 | for vulnerability in parser.invicti.vulnerabilities: | |
87 | vuln = {"name": vulnerability.name, "severity": vulnerability.severity, | |
88 | "confirmed": vulnerability.confirmed, | |
89 | "desc": BeautifulSoup(vulnerability.description, features="lxml").text, | |
90 | "path": vulnerability.url.replace(parser.invicti.target.url, ""), | |
91 | "external_id": vulnerability.look_id, | |
92 | "resolution": BeautifulSoup(vulnerability.remedial_procedure, features="lxml").text} | |
93 | if vulnerability.classification: | |
94 | references = [] | |
95 | if vulnerability.classification.owasp: | |
96 | references.append("OWASP" + vulnerability.classification.owasp) | |
97 | if vulnerability.classification.wasc: | |
98 | references.append("WASC" + vulnerability.classification.wasc) | |
99 | if vulnerability.classification.cwe: | |
100 | vuln["cwe"] = "CWE-" + vulnerability.classification.cwe | |
101 | if vulnerability.classification.capec: | |
102 | references.append("CAPEC" + vulnerability.classification.capec) | |
103 | if vulnerability.classification.pci32: | |
104 | references.append("PCI32" + vulnerability.classification.pci32) | |
105 | if vulnerability.classification.hipaa: | |
106 | references.append("HIPAA" + vulnerability.classification.hipaa) | |
107 | if vulnerability.classification.owasppc: | |
108 | references.append("OWASPPC" + vulnerability.classification.owasppc) | |
109 | if vulnerability.classification.cvss3.node is not None: | |
110 | vuln["cvss3"] = {"vector_string": vulnerability.classification.cvss3.vector} | |
111 | vuln["ref"] = references | |
112 | if vulnerability.http_response.node is not None: | |
113 | vuln["response"] = vulnerability.http_response.content | |
114 | if vulnerability.http_request.node is not None: | |
115 | vuln["request"] = vulnerability.http_request.content | |
116 | self.createAndAddVulnWebToService(h_id, s_id, **vuln) | |
117 | ||
118 | ||
119 | def createPlugin(*args, **kwargs): | |
120 | return InvictiPlugin(*args, **kwargs) |
0 | """ | |
1 | Faraday Penetration Test IDE | |
2 | Copyright (C) 2017 Infobyte LLC (http://www.infobytesec.com/) | |
3 | See the file 'doc/LICENSE' for the license information | |
4 | ||
5 | """ |
0 | """ | |
1 | Faraday Penetration Test IDE | |
2 | Copyright (C) 2013 Infobyte LLC (http://www.infobytesec.com/) | |
3 | See the file 'doc/LICENSE' for the license information | |
4 | ||
5 | """ | |
6 | ||
7 | from faraday_plugins.plugins.plugin import PluginCSVFormat | |
8 | import csv | |
9 | import io | |
10 | ||
11 | ||
12 | __author__ = "Gonzalo Martinez" | |
13 | __copyright__ = "Copyright (c) 2019, Infobyte LLC" | |
14 | __credits__ = ["Gonzalo Martinez"] | |
15 | __license__ = "" | |
16 | __version__ = "1.0.0" | |
17 | __maintainer__ = "Gonzalo Martinez" | |
18 | __email__ = "[email protected]" | |
19 | __status__ = "Development" | |
20 | ||
21 | ||
22 | class NessusScPlugin(PluginCSVFormat): | |
23 | """ | |
24 | Example plugin to parse Nessus Sc output. | |
25 | """ | |
26 | ||
27 | def __init__(self, *arg, **kwargs): | |
28 | super().__init__(*arg, **kwargs) | |
29 | self.csv_headers = [{'Plugin', 'Plugin Name'}] | |
30 | self.id = "Nessus_sc" | |
31 | self.name = "Nessus Sc Output Plugin" | |
32 | self.plugin_version = "1.0.0" | |
33 | self.version = "1.0.0" | |
34 | self.framework_version = "1.0.0" | |
35 | ||
36 | def parseOutputString(self, output): | |
37 | try: | |
38 | reader = csv.DictReader(io.StringIO(output)) | |
39 | except: | |
40 | print("Error parser output") | |
41 | return None | |
42 | ||
43 | for row in reader: | |
44 | ip = row['IP Address'] | |
45 | hostname = row['DNS Name'] | |
46 | h_id = self.createAndAddHost(name=ip, hostnames=hostname) | |
47 | protocol = row['Protocol'] | |
48 | port = row['Port'] | |
49 | s_id = self.createAndAddServiceToHost(h_id, name=port, protocol=protocol, ports=port, status="open") | |
50 | name = row['Plugin Name'] | |
51 | severity = row['Severity'] | |
52 | description = row['Description'] | |
53 | vuln = {"name": name, "severity": severity, "desc": description} | |
54 | solution = row['Solution'] | |
55 | if solution: | |
56 | vuln["resolution"] = solution | |
57 | cvss3_vector = row['CVSS V3 Vector'] | |
58 | if cvss3_vector: | |
59 | if not cvss3_vector.startswith("CVSS:3.0/"): | |
60 | cvss3_vector = "CVSS:3.0/"+cvss3_vector | |
61 | vuln["cvss3"] = {"vector_string": cvss3_vector} | |
62 | cvss2_vector = row['CVSS V2 Vector'] | |
63 | if cvss2_vector: | |
64 | vuln["cvss2"] = {"vector_string": cvss2_vector} | |
65 | external_ref = row["See Also"] | |
66 | cross_ref = row["Cross References"] | |
67 | references = [] | |
68 | if external_ref: | |
69 | references.append(external_ref) | |
70 | if cross_ref: | |
71 | references.append(cross_ref) | |
72 | vuln["ref"] = references | |
73 | cve = row['CVE'] | |
74 | if cve: | |
75 | vuln["cve"] = cve | |
76 | self.createAndAddVulnToService(h_id, s_id, **vuln) | |
77 | ||
78 | ||
79 | def createPlugin(*args, **kwargs): | |
80 | return NessusScPlugin(*args, **kwargs) |
140 | 140 | vuln = { |
141 | 141 | 'desc': "", |
142 | 142 | 'name': vulnDef.get('title'), |
143 | 'refs': ["vector: " + vector, vid], | |
143 | 'refs': [], | |
144 | 144 | 'resolution': "", |
145 | 145 | 'severity': "", |
146 | 146 | 'tags': list(), |
171 | 171 | vuln['refs'].append(nameMalware) |
172 | 172 | if item.tag == 'references': |
173 | 173 | for ref in list(item): |
174 | if ref.text: | |
175 | rf = ref.text.strip() | |
176 | check = CVE_regex.search(rf.upper()) | |
177 | if check: | |
178 | vuln["CVE"].append(check.group()) | |
179 | else: | |
180 | vuln['refs'].append(rf) | |
174 | if not ref.text: | |
175 | continue | |
176 | source = "" | |
177 | if "source" in ref.attrib: | |
178 | source = ref.attrib['source'] + ": " | |
179 | rf = ref.text.strip() | |
180 | check = CVE_regex.search(rf.upper()) | |
181 | if check: | |
182 | vuln["CVE"].append(check.group()) | |
183 | else: | |
184 | if rf.isnumeric(): | |
185 | rf = source + rf | |
186 | vuln['refs'].append(rf) | |
181 | 187 | if item.tag == 'solution': |
182 | 188 | for htmlType in list(item): |
183 | 189 | vuln['resolution'] += self.parse_html_type(htmlType) |
99 | 99 | self.node = item_node |
100 | 100 | |
101 | 101 | self.osvdbid = [ |
102 | "OSVDB-ID: " + self.node.get('osvdbid')] if self.node.get('osvdbid') != "0" else [] | |
102 | "OSVDB-ID: " + self.node.get('osvdbid')] if self.node.get('osvdbid', "0") != "0" else [] | |
103 | 103 | |
104 | 104 | self.namelink = self.get_text_from_subnode('namelink') |
105 | 105 | self.iplink = self.get_text_from_subnode('iplink') |
206 | 206 | |
207 | 207 | def __init__(self, *arg, **kwargs): |
208 | 208 | super().__init__(*arg, **kwargs) |
209 | self.identifier_tag = "niktoscan" | |
209 | self.identifier_tag = ["niktoscan", "niktoscans"] | |
210 | 210 | self.id = "Nikto" |
211 | 211 | self.name = "Nikto XML Output Plugin" |
212 | 212 | self.plugin_version = "0.0.2" |
0 | Metadata-Version: 2.1 | |
1 | Name: faraday-plugins | |
2 | Version: 1.8.0 | |
3 | Summary: Faraday plugins package | |
4 | Home-page: | |
5 | Author: Faradaysec | |
6 | Author-email: [email protected] | |
7 | License: GNU General Public License v3 | |
8 | License-File: COPYING |
0 | COPYING | |
1 | MANIFEST.in | |
2 | README.md | |
3 | setup.py | |
4 | faraday_plugins/__init__.py | |
5 | faraday_plugins/__main__.py | |
6 | faraday_plugins/commands.py | |
7 | faraday_plugins.egg-info/PKG-INFO | |
8 | faraday_plugins.egg-info/SOURCES.txt | |
9 | faraday_plugins.egg-info/dependency_links.txt | |
10 | faraday_plugins.egg-info/entry_points.txt | |
11 | faraday_plugins.egg-info/requires.txt | |
12 | faraday_plugins.egg-info/top_level.txt | |
13 | faraday_plugins/plugins/__init__.py | |
14 | faraday_plugins/plugins/manager.py | |
15 | faraday_plugins/plugins/plugin.py | |
16 | faraday_plugins/plugins/plugins_utils.py | |
17 | faraday_plugins/plugins/port_mapper.txt | |
18 | faraday_plugins/plugins/repo/__init__.py | |
19 | faraday_plugins/plugins/repo/acunetix/DTO.py | |
20 | faraday_plugins/plugins/repo/acunetix/__init__.py | |
21 | faraday_plugins/plugins/repo/acunetix/plugin.py | |
22 | faraday_plugins/plugins/repo/acunetix_json/DTO.py | |
23 | faraday_plugins/plugins/repo/acunetix_json/__init__.py | |
24 | faraday_plugins/plugins/repo/acunetix_json/plugin.py | |
25 | faraday_plugins/plugins/repo/amap/__init__.py | |
26 | faraday_plugins/plugins/repo/amap/plugin.py | |
27 | faraday_plugins/plugins/repo/appscan/__init__.py | |
28 | faraday_plugins/plugins/repo/appscan/plugin.py | |
29 | faraday_plugins/plugins/repo/appscan_csv/__init__.py | |
30 | faraday_plugins/plugins/repo/appscan_csv/plugin.py | |
31 | faraday_plugins/plugins/repo/appspider/__init__.py | |
32 | faraday_plugins/plugins/repo/appspider/plugin.py | |
33 | faraday_plugins/plugins/repo/arachni/__init__.py | |
34 | faraday_plugins/plugins/repo/arachni/plugin.py | |
35 | faraday_plugins/plugins/repo/arp_scan/__init__.py | |
36 | faraday_plugins/plugins/repo/arp_scan/plugin.py | |
37 | faraday_plugins/plugins/repo/bandit/__init__.py | |
38 | faraday_plugins/plugins/repo/bandit/plugin.py | |
39 | faraday_plugins/plugins/repo/beef/__init__.py | |
40 | faraday_plugins/plugins/repo/beef/plugin.py | |
41 | faraday_plugins/plugins/repo/brutexss/__init__.py | |
42 | faraday_plugins/plugins/repo/brutexss/plugin.py | |
43 | faraday_plugins/plugins/repo/burp/__init__.py | |
44 | faraday_plugins/plugins/repo/burp/plugin.py | |
45 | faraday_plugins/plugins/repo/checkmarx/__init__.py | |
46 | faraday_plugins/plugins/repo/checkmarx/plugin.py | |
47 | faraday_plugins/plugins/repo/cobalt/__init__.py | |
48 | faraday_plugins/plugins/repo/cobalt/plugin.py | |
49 | faraday_plugins/plugins/repo/dig/__init__.py | |
50 | faraday_plugins/plugins/repo/dig/plugin.py | |
51 | faraday_plugins/plugins/repo/dirb/__init__.py | |
52 | faraday_plugins/plugins/repo/dirb/plugin.py | |
53 | faraday_plugins/plugins/repo/dirsearch/__init__.py | |
54 | faraday_plugins/plugins/repo/dirsearch/plugin.py | |
55 | faraday_plugins/plugins/repo/dnsenum/__init__.py | |
56 | faraday_plugins/plugins/repo/dnsenum/plugin.py | |
57 | faraday_plugins/plugins/repo/dnsmap/__init__.py | |
58 | faraday_plugins/plugins/repo/dnsmap/plugin.py | |
59 | faraday_plugins/plugins/repo/dnsrecon/__init__.py | |
60 | faraday_plugins/plugins/repo/dnsrecon/plugin.py | |
61 | faraday_plugins/plugins/repo/dnswalk/__init__.py | |
62 | faraday_plugins/plugins/repo/dnswalk/plugin.py | |
63 | faraday_plugins/plugins/repo/faraday_csv/__init__.py | |
64 | faraday_plugins/plugins/repo/faraday_csv/plugin.py | |
65 | faraday_plugins/plugins/repo/fierce/__init__.py | |
66 | faraday_plugins/plugins/repo/fierce/plugin.py | |
67 | faraday_plugins/plugins/repo/fortify/__init__.py | |
68 | faraday_plugins/plugins/repo/fortify/plugin.py | |
69 | faraday_plugins/plugins/repo/ftp/__init__.py | |
70 | faraday_plugins/plugins/repo/ftp/plugin.py | |
71 | faraday_plugins/plugins/repo/goohost/__init__.py | |
72 | faraday_plugins/plugins/repo/goohost/plugin.py | |
73 | faraday_plugins/plugins/repo/grype/__init__.py | |
74 | faraday_plugins/plugins/repo/grype/plugin.py | |
75 | faraday_plugins/plugins/repo/hping3/__init__.py | |
76 | faraday_plugins/plugins/repo/hping3/plugin.py | |
77 | faraday_plugins/plugins/repo/hydra/__init__.py | |
78 | faraday_plugins/plugins/repo/hydra/plugin.py | |
79 | faraday_plugins/plugins/repo/impact/__init__.py | |
80 | faraday_plugins/plugins/repo/impact/plugin.py | |
81 | faraday_plugins/plugins/repo/invicti/DTO.py | |
82 | faraday_plugins/plugins/repo/invicti/__init__.py | |
83 | faraday_plugins/plugins/repo/invicti/plugin.py | |
84 | faraday_plugins/plugins/repo/ip360/__init__.py | |
85 | faraday_plugins/plugins/repo/ip360/plugin.py | |
86 | faraday_plugins/plugins/repo/junit/__init__.py | |
87 | faraday_plugins/plugins/repo/junit/plugin.py | |
88 | faraday_plugins/plugins/repo/lynis/__init__.py | |
89 | faraday_plugins/plugins/repo/lynis/plugin.py | |
90 | faraday_plugins/plugins/repo/maltego/__init__.py | |
91 | faraday_plugins/plugins/repo/maltego/plugin.py | |
92 | faraday_plugins/plugins/repo/mbsa/__init__.py | |
93 | faraday_plugins/plugins/repo/mbsa/plugin.py | |
94 | faraday_plugins/plugins/repo/medusa/__init__.py | |
95 | faraday_plugins/plugins/repo/medusa/plugin.py | |
96 | faraday_plugins/plugins/repo/metasploit/__init__.py | |
97 | faraday_plugins/plugins/repo/metasploit/plugin.py | |
98 | faraday_plugins/plugins/repo/naabu/__init__.py | |
99 | faraday_plugins/plugins/repo/naabu/plugin.py | |
100 | faraday_plugins/plugins/repo/ncrack/__init__.py | |
101 | faraday_plugins/plugins/repo/ncrack/plugin.py | |
102 | faraday_plugins/plugins/repo/ndiff/__init__.py | |
103 | faraday_plugins/plugins/repo/ndiff/plugin.py | |
104 | faraday_plugins/plugins/repo/nessus/DTO.py | |
105 | faraday_plugins/plugins/repo/nessus/__init__.py | |
106 | faraday_plugins/plugins/repo/nessus/plugin.py | |
107 | faraday_plugins/plugins/repo/nessus_sc/__init__.py | |
108 | faraday_plugins/plugins/repo/nessus_sc/plugin.py | |
109 | faraday_plugins/plugins/repo/netdiscover/__init__.py | |
110 | faraday_plugins/plugins/repo/netdiscover/plugin.py | |
111 | faraday_plugins/plugins/repo/netsparker/__init__.py | |
112 | faraday_plugins/plugins/repo/netsparker/plugin.py | |
113 | faraday_plugins/plugins/repo/netsparkercloud/__init__.py | |
114 | faraday_plugins/plugins/repo/netsparkercloud/plugin.py | |
115 | faraday_plugins/plugins/repo/nexpose_full/__init__.py | |
116 | faraday_plugins/plugins/repo/nexpose_full/plugin.py | |
117 | faraday_plugins/plugins/repo/nextnet/__init__.py | |
118 | faraday_plugins/plugins/repo/nextnet/plugin.py | |
119 | faraday_plugins/plugins/repo/nikto/__init__.py | |
120 | faraday_plugins/plugins/repo/nikto/plugin.py | |
121 | faraday_plugins/plugins/repo/nipper/__init__.py | |
122 | faraday_plugins/plugins/repo/nipper/plugin.py | |
123 | faraday_plugins/plugins/repo/nmap/__init__.py | |
124 | faraday_plugins/plugins/repo/nmap/plugin.py | |
125 | faraday_plugins/plugins/repo/nuclei/__init__.py | |
126 | faraday_plugins/plugins/repo/nuclei/plugin.py | |
127 | faraday_plugins/plugins/repo/nuclei_legacy/__init__.py | |
128 | faraday_plugins/plugins/repo/nuclei_legacy/plugin.py | |
129 | faraday_plugins/plugins/repo/openscap/__init__.py | |
130 | faraday_plugins/plugins/repo/openscap/plugin.py | |
131 | faraday_plugins/plugins/repo/openvas/__init__.py | |
132 | faraday_plugins/plugins/repo/openvas/plugin.py | |
133 | faraday_plugins/plugins/repo/pasteanalyzer/__init__.py | |
134 | faraday_plugins/plugins/repo/pasteanalyzer/plugin.py | |
135 | faraday_plugins/plugins/repo/peepingtom/__init__.py | |
136 | faraday_plugins/plugins/repo/peepingtom/plugin.py | |
137 | faraday_plugins/plugins/repo/ping/__init__.py | |
138 | faraday_plugins/plugins/repo/ping/plugin.py | |
139 | faraday_plugins/plugins/repo/propecia/__init__.py | |
140 | faraday_plugins/plugins/repo/propecia/plugin.py | |
141 | faraday_plugins/plugins/repo/prowler/__init__.py | |
142 | faraday_plugins/plugins/repo/prowler/plugin.py | |
143 | faraday_plugins/plugins/repo/qualysguard/__init__.py | |
144 | faraday_plugins/plugins/repo/qualysguard/plugin.py | |
145 | faraday_plugins/plugins/repo/qualyswebapp/__init__.py | |
146 | faraday_plugins/plugins/repo/qualyswebapp/plugin.py | |
147 | faraday_plugins/plugins/repo/rdpscan/__init__.py | |
148 | faraday_plugins/plugins/repo/rdpscan/plugin.py | |
149 | faraday_plugins/plugins/repo/reconng/__init__.py | |
150 | faraday_plugins/plugins/repo/reconng/plugin.py | |
151 | faraday_plugins/plugins/repo/retina/__init__.py | |
152 | faraday_plugins/plugins/repo/retina/plugin.py | |
153 | faraday_plugins/plugins/repo/reverseraider/__init__.py | |
154 | faraday_plugins/plugins/repo/reverseraider/plugin.py | |
155 | faraday_plugins/plugins/repo/shodan/__init__.py | |
156 | faraday_plugins/plugins/repo/shodan/plugin.py | |
157 | faraday_plugins/plugins/repo/skipfish/__init__.py | |
158 | faraday_plugins/plugins/repo/skipfish/plugin.py | |
159 | faraday_plugins/plugins/repo/sonarqubeapi/__init__.py | |
160 | faraday_plugins/plugins/repo/sonarqubeapi/plugin.py | |
161 | faraday_plugins/plugins/repo/sourceclear/__init__.py | |
162 | faraday_plugins/plugins/repo/sourceclear/plugin.py | |
163 | faraday_plugins/plugins/repo/sshdefaultscan/__init__.py | |
164 | faraday_plugins/plugins/repo/sshdefaultscan/plugin.py | |
165 | faraday_plugins/plugins/repo/ssl_labs/__init__.py | |
166 | faraday_plugins/plugins/repo/ssl_labs/plugin.py | |
167 | faraday_plugins/plugins/repo/sslyze/__init__.py | |
168 | faraday_plugins/plugins/repo/sslyze/plugin.py | |
169 | faraday_plugins/plugins/repo/sslyzejson/__init__.py | |
170 | faraday_plugins/plugins/repo/sslyzejson/plugin.py | |
171 | faraday_plugins/plugins/repo/syhunt/__init__.py | |
172 | faraday_plugins/plugins/repo/syhunt/plugin.py | |
173 | faraday_plugins/plugins/repo/telnet/__init__.py | |
174 | faraday_plugins/plugins/repo/telnet/plugin.py | |
175 | faraday_plugins/plugins/repo/theharvester/__init__.py | |
176 | faraday_plugins/plugins/repo/theharvester/plugin.py | |
177 | faraday_plugins/plugins/repo/traceroute/__init__.py | |
178 | faraday_plugins/plugins/repo/traceroute/plugin.py | |
179 | faraday_plugins/plugins/repo/trivy_json/DTO.py | |
180 | faraday_plugins/plugins/repo/trivy_json/__init__.py | |
181 | faraday_plugins/plugins/repo/trivy_json/plugin.py | |
182 | faraday_plugins/plugins/repo/w3af/__init__.py | |
183 | faraday_plugins/plugins/repo/w3af/plugin.py | |
184 | faraday_plugins/plugins/repo/wapiti/__init__.py | |
185 | faraday_plugins/plugins/repo/wapiti/plugin.py | |
186 | faraday_plugins/plugins/repo/wcscan/__init__.py | |
187 | faraday_plugins/plugins/repo/wcscan/plugin.py | |
188 | faraday_plugins/plugins/repo/webfuzzer/__init__.py | |
189 | faraday_plugins/plugins/repo/webfuzzer/plugin.py | |
190 | faraday_plugins/plugins/repo/webinspect/__init__.py | |
191 | faraday_plugins/plugins/repo/webinspect/plugin.py | |
192 | faraday_plugins/plugins/repo/wfuzz/__init__.py | |
193 | faraday_plugins/plugins/repo/wfuzz/plugin.py | |
194 | faraday_plugins/plugins/repo/whatweb/__init__.py | |
195 | faraday_plugins/plugins/repo/whatweb/plugin.py | |
196 | faraday_plugins/plugins/repo/whitesource/__init__.py | |
197 | faraday_plugins/plugins/repo/whitesource/plugin.py | |
198 | faraday_plugins/plugins/repo/whois/__init__.py | |
199 | faraday_plugins/plugins/repo/whois/plugin.py | |
200 | faraday_plugins/plugins/repo/wpscan/__init__.py | |
201 | faraday_plugins/plugins/repo/wpscan/plugin.py | |
202 | faraday_plugins/plugins/repo/x1/__init__.py | |
203 | faraday_plugins/plugins/repo/x1/plugin.py | |
204 | faraday_plugins/plugins/repo/xsssniper/__init__.py | |
205 | faraday_plugins/plugins/repo/xsssniper/plugin.py | |
206 | faraday_plugins/plugins/repo/zap/__init__.py | |
207 | faraday_plugins/plugins/repo/zap/plugin.py | |
208 | faraday_plugins/plugins/repo/zap_json/DTO.py | |
209 | faraday_plugins/plugins/repo/zap_json/__init__.py | |
210 | faraday_plugins/plugins/repo/zap_json/plugin.py⏎ |
0 | Click | |
1 | beautifulsoup4 | |
2 | colorama | |
3 | html2text | |
4 | lxml | |
5 | packaging | |
6 | python-dateutil | |
7 | pytz | |
8 | requests | |
9 | simplejson | |
10 | tabulate |
0 | faraday_plugins |
0 | { | |
1 | "commands": [ | |
2 | {"plugin_id": "ping", "command": "ping -c4 faradaysec.com", "command_result": "ping"}, | |
3 | {"plugin_id": "whois", "command": "whois fradaysec.com", "command_result": "whois"}, | |
4 | {"plugin_id": "nmap", "command": "nmap fradaysec.com", "command_result": "nmap"}, | |
5 | {"plugin_id": "skipfish", "command": "skipfish http://fradaysec.com", "command_result": "skipfish"}, | |
6 | {"plugin_id": "sslyze_json", "command": "sslyze www.google.com --json_out=x.json", "command_result": "sslyze"}, | |
7 | {"plugin_id": "Amap", "command": "amap www.google.com", "command_result": "amap"}, | |
8 | {"plugin_id": "arp-scan", "command": "arp-scan www.google.com", "command_result": "arp-scan"}, | |
9 | {"plugin_id": "Beef", "command": "beef www.google.com", "command_result": "beef"}, | |
10 | {"plugin_id": "brutexss", "command": "brutexss www.google.com", "command_result": "brutexss"}, | |
11 | {"plugin_id": "dig", "command": "dig www.google.com", "command_result": "dig"}, | |
12 | {"plugin_id": "dirsearch", "command": "python3 dirsearch.py -u https://target", "command_result": "python3 dirsearch.py"}, | |
13 | ||
14 | {"plugin_id": "Dnsenum", "command": "dnsenum www.google.com", "command_result": "Dnsenum"}, | |
15 | {"plugin_id": "Dnsmap", "command": "dnsmap www.google.com", "command_result": "Dnsmap"}, | |
16 | {"plugin_id": "Dnsrecon", "command": "dnsrecon www.google.com", "command_result": "Dnsrecon"}, | |
17 | {"plugin_id": "Dnswalk", "command": "dnswalk www.google.com", "command_result": "Dnswalk"}, | |
18 | {"plugin_id": "Fierce", "command": "fierce www.google.com", "command_result": "Fierce"}, | |
19 | {"plugin_id": "ftp", "command": "ftp www.google.com", "command_result": "ftp"}, | |
20 | {"plugin_id": "Goohost", "command": "goohost.sh www.google.com", "command_result": "goohost.sh"}, | |
21 | {"plugin_id": "Hping3", "command": "hping3 www.google.com", "command_result": "Hping3"}, | |
22 | {"plugin_id": "Hydra", "command": "hydra www.google.com", "command_result": "Hydra"}, | |
23 | {"plugin_id": "Lynis", "command": "lynis www.google.com", "command_result": "Lynis"}, | |
24 | {"plugin_id": "Medusa", "command": "medusa www.google.com", "command_result": "Medusa"}, | |
25 | {"plugin_id": "Ndiff", "command": "ndiff www.google.com", "command_result": "Ndiff"}, | |
26 | {"plugin_id": "Netdiscover", "command": "netdiscover www.google.com", "command_result": "Netdiscover"}, | |
27 | {"plugin_id": "nextnet", "command": "nextnet www.google.com", "command_result": "nextnet"}, | |
28 | {"plugin_id": "Nikto", "command": "nikto www.google.com", "command_result": "Nikto"}, | |
29 | {"plugin_id": "Nmap", "command": "nmap www.google.com", "command_result": "Nmap"}, | |
30 | {"plugin_id": "pasteAnalyzer", "command": "pasteAnalyzer www.google.com", "command_result": "pasteAnalyzer"}, | |
31 | {"plugin_id": "peepingtom", "command": "./peepingtom.py www.google.com", "command_result": "./peepingtom.py"}, | |
32 | {"plugin_id": "propecia", "command": "propecia www.google.com", "command_result": "propecia"}, | |
33 | {"plugin_id": "rdpscan", "command": "rdpscan www.google.com", "command_result": "rdpscan"}, | |
34 | {"plugin_id": "Reverseraider", "command": "./reverseraider www.google.com", "command_result": "./reverseraider"}, | |
35 | {"plugin_id": "Skipfish", "command": "skipfish www.google.com", "command_result": "Skipfish"}, | |
36 | {"plugin_id": "sshdefaultscan", "command": "./sshdefaultscan.py www.google.com", "command_result": "./sshdefaultscan.py"}, | |
37 | {"plugin_id": "Telnet", "command": "telnet www.google.com", "command_result": "telnet"}, | |
38 | {"plugin_id": "Theharvester", "command": "./theHarvester.py www.google.com", "command_result": "./theharvester.py"}, | |
39 | {"plugin_id": "Traceroute", "command": "traceroute www.google.com", "command_result": "Traceroute"}, | |
40 | {"plugin_id": "W3af", "command": "w3af www.google.com", "command_result": "W3af"}, | |
41 | {"plugin_id": "Wapiti", "command": "wapiti www.google.com", "command_result": "Wapiti"}, | |
42 | {"plugin_id": "Wcscan", "command": "wcscan www.google.com", "command_result": "Wcscan"}, | |
43 | {"plugin_id": "Webfuzzer", "command": "webfuzzer www.google.com", "command_result": "Webfuzzer"}, | |
44 | {"plugin_id": "Wfuzz", "command": "wfuzz www.google.com", "command_result": "Wfuzz"}, | |
45 | {"plugin_id": "whois", "command": "whois www.google.com", "command_result": "whois"}, | |
46 | {"plugin_id": "X1", "command": "./x1 www.google.com", "command_result": "./x1"}, | |
47 | {"plugin_id": "xsssniper", "command": "xsssniper www.google.com", "command_result": "xsssniper"}, | |
48 | {"plugin_id": "dirb", "command": "dirb google.com", "command_result": "dirb"}, | |
49 | {"plugin_id": "Arachni", "command": "arachni www.google.com", "command_result": "Arachni"} | |
50 | ] | |
51 | } |
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 | #!/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(hostname_resolution=False) | |
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 | import json | |
1 | import os | |
2 | import re | |
3 | import pytest | |
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 | @pytest.mark.skip(reason="issue with docker image") | |
25 | def test_detect_command(): | |
26 | runner = CliRunner() | |
27 | result = runner.invoke(detect_command, args=['ping -c 1 www.google.com']) | |
28 | assert result.exit_code == 0 | |
29 | assert result.output.strip() == "Faraday Plugin: ping" | |
30 | ||
31 | ||
32 | @pytest.mark.skip(reason="issue with docker image") | |
33 | def test_process_command(): | |
34 | runner = CliRunner() | |
35 | result = runner.invoke(process_command, args=['ping -c 1 www.google.com', '--summary']) | |
36 | assert result.exit_code == 0, result.output | |
37 | summary = json.loads(result.output.strip()) | |
38 | assert summary['hosts'] == 1 | |
39 | ||
40 | ||
41 | @pytest.mark.skip(reason="issue with docker image") | |
42 | def test_process_command_ping(): | |
43 | runner = CliRunner() | |
44 | result = runner.invoke(process_command, args=['ping -c 1 www.google.com']) | |
45 | assert result.exit_code == 0, result.output | |
46 | summary = json.loads(result.output.strip()) | |
47 | ||
48 | assert summary['command']["command"] == 'ping' | |
49 | ||
50 | ||
51 | @pytest.mark.skip(reason="issue with docker image") | |
52 | def test_process_command_to_file(): | |
53 | runner = CliRunner() | |
54 | with runner.isolated_filesystem() as file_system: | |
55 | output_file = os.path.join(file_system, "test.json") | |
56 | result = runner.invoke(process_command, args=['ping -c 1 www.google.com', '-o', output_file]) | |
57 | assert result.exit_code == 0, result.output | |
58 | assert os.path.isfile(output_file) | |
59 | with open(output_file) as f: | |
60 | vuln_json = json.load(f) | |
61 | assert len(vuln_json['hosts']) == 1 | |
62 | ||
63 | ||
64 | def test_detect_report(): | |
65 | report_file = os.path.join('./report-collection', 'faraday_plugins_tests', 'Nmap', 'nmap_5.21.xml') | |
66 | runner = CliRunner() | |
67 | result = runner.invoke(detect_report, args=[report_file]) | |
68 | assert result.exit_code == 0 | |
69 | assert "Faraday Plugin: Nmap" == result.output.strip() | |
70 | ||
71 | ||
72 | def test_detect_report_dont_exists(): | |
73 | report_file = os.path.join('./report-collection', 'faraday_plugins_tests', 'Nmap', 'invalid_report.xml') | |
74 | runner = CliRunner() | |
75 | result = runner.invoke(detect_report, args=[report_file]) | |
76 | assert result.exit_code == 0 | |
77 | assert "Don't Exists" in result.output.strip() | |
78 | ||
79 | ||
80 | def test_process_report_summary(): | |
81 | report_file = os.path.join('./report-collection', 'faraday_plugins_tests', 'Nmap', 'nmap_5.21.xml') | |
82 | summary_file = os.path.join('./report-collection', 'faraday_plugins_tests', 'Nmap', 'nmap_5.21_summary.json') | |
83 | runner = CliRunner() | |
84 | result = runner.invoke(process_report, args=[report_file, '--summary']) | |
85 | assert result.exit_code == 0 | |
86 | summary = json.loads(result.output.strip()) | |
87 | with open(summary_file) as f: | |
88 | saved_summary = json.load(f) | |
89 | vuln_hashes = set(summary['vuln_hashes']) | |
90 | saved_vuln_hashes = set(saved_summary.get('vuln_hashes', [])) | |
91 | assert summary['hosts'] == saved_summary['hosts'] | |
92 | assert summary['services'] == saved_summary['services'] | |
93 | assert summary['hosts_vulns'] == saved_summary['hosts_vulns'] | |
94 | assert summary['services_vulns'] == saved_summary['services_vulns'] | |
95 | assert summary['severity_vulns'] == saved_summary['severity_vulns'] | |
96 | assert vuln_hashes == saved_vuln_hashes | |
97 | ||
98 | ||
99 | def test_process_report_ignore_info(): | |
100 | report_file = os.path.join('./report-collection', 'faraday_plugins_tests', 'Nmap', 'nmap_5.21.xml') | |
101 | runner = CliRunner() | |
102 | result = runner.invoke(process_report, args=[report_file, '--summary', '--ignore-info']) | |
103 | assert result.exit_code == 0 | |
104 | summary = json.loads(result.output.strip()) | |
105 | assert summary['hosts'] == 256 | |
106 | assert summary['services'] == 69 | |
107 | assert summary['hosts_vulns'] == 0 | |
108 | assert summary['services_vulns'] == 0 | |
109 | ||
110 | ||
111 | def test_process_report_tags(): | |
112 | report_file = os.path.join('./report-collection', 'faraday_plugins_tests', 'Acunetix', 'acunetix_valid_dummy.xml') | |
113 | runner = CliRunner() | |
114 | args = [report_file, '--vuln-tag=vuln_tag', '--service-tag=service_tag', '--host-tag=host_tag'] | |
115 | result = runner.invoke(process_report, args=args) | |
116 | assert result.exit_code == 0 | |
117 | body = json.loads(result.output.strip()) | |
118 | assert body['hosts'][0]["tags"][0] == "host_tag" | |
119 | assert body['hosts'][0]["services"][0]["tags"][0] == "service_tag" | |
120 | assert body['hosts'][0]["services"][0]["vulnerabilities"][0]["tags"][0] == "vuln_tag" |
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 | command_result = command_data["command_result"] | |
23 | ||
24 | plugin: PluginBase = analyzer.get_plugin(command_string) | |
25 | assert plugin, command_string | |
26 | assert plugin.id.lower() == plugin_id.lower() | |
27 | assert plugin.command.lower() == command_result.lower() | |
28 |
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 | import os | |
1 | import socket | |
2 | import json | |
3 | import pytest | |
4 | from pathlib import Path | |
5 | from faraday_plugins.plugins.manager import PluginsManager, ReportAnalyzer | |
6 | from faraday_plugins.plugins.plugin import PluginBase | |
7 | from faraday.server.api.modules.bulk_create import BulkCreateSchema | |
8 | ||
9 | BLACK_LIST = [ | |
10 | 'LICENSE', | |
11 | 'README.md', | |
12 | '.gitignore', | |
13 | '.gitkeep', | |
14 | 'faraday_plugins_tests', | |
15 | ||
16 | ] | |
17 | ||
18 | plugins_manager = PluginsManager(hostname_resolution=False) | |
19 | analyzer = ReportAnalyzer(plugins_manager) | |
20 | ||
21 | PLUGINS_CACHE = {} | |
22 | REPORTS_JSON_CACHE = {} | |
23 | ||
24 | SKIP_IP_PLUGINS = ['Fortify'] | |
25 | ||
26 | REPORTS_SUMMARY_DIR = './report-collection/faraday_plugins_tests' | |
27 | ||
28 | ||
29 | def get_plugin_from_cache(report_file): | |
30 | plugin = PLUGINS_CACHE.get(report_file) | |
31 | if not plugin: | |
32 | plugin: PluginBase = analyzer.get_plugin(report_file) | |
33 | if plugin: | |
34 | save_plugin_in_cache(report_file, plugin) | |
35 | return plugin | |
36 | ||
37 | ||
38 | def save_plugin_in_cache(report_file, plugin): | |
39 | if report_file not in PLUGINS_CACHE: | |
40 | PLUGINS_CACHE[report_file] = plugin | |
41 | ||
42 | ||
43 | def get_report_json_from_cache(report_file): | |
44 | plugin_json = REPORTS_JSON_CACHE.get(report_file) | |
45 | if not plugin_json: | |
46 | plugin = get_plugin_from_cache(report_file) | |
47 | if plugin: | |
48 | plugin.processReport(Path(report_file)) | |
49 | plugin_json = json.loads(plugin.get_json()) | |
50 | REPORTS_JSON_CACHE[report_file] = plugin_json | |
51 | else: | |
52 | plugin = get_plugin_from_cache(report_file) | |
53 | return plugin, plugin_json | |
54 | ||
55 | ||
56 | def list_report_files(): | |
57 | report_filenames = os.walk(REPORTS_SUMMARY_DIR) | |
58 | for plugin_folder, directory, filenames in report_filenames: | |
59 | if '.git' in directory or 'faraday_plugins_tests' in directory: | |
60 | continue | |
61 | for filename in filenames: | |
62 | if filename in BLACK_LIST: | |
63 | continue | |
64 | if '.git' in plugin_folder: | |
65 | continue | |
66 | if not filename.endswith('_summary.json'): | |
67 | yield Path(plugin_folder).name, os.path.join(plugin_folder, filename) | |
68 | ||
69 | ||
70 | def is_valid_ipv4_address(address): | |
71 | try: | |
72 | socket.inet_pton(socket.AF_INET, address) | |
73 | except AttributeError: # no inet_pton here, sorry | |
74 | try: | |
75 | socket.inet_aton(address) | |
76 | except OSError: | |
77 | return False | |
78 | return address.count('.') == 3 | |
79 | except OSError: # not a valid address | |
80 | return False | |
81 | return True | |
82 | ||
83 | ||
84 | def is_valid_ipv6_address(address): | |
85 | try: | |
86 | socket.inet_pton(socket.AF_INET6, address) | |
87 | except OSError: # not a valid address | |
88 | return False | |
89 | return True | |
90 | ||
91 | ||
92 | def is_valid_ip_address(address): | |
93 | return (is_valid_ipv4_address(address) or is_valid_ipv6_address(address)) | |
94 | ||
95 | def test_reports_collection_exists(): | |
96 | assert os.path.isdir(REPORTS_SUMMARY_DIR) is True, "Please clone the report-collection repo!" | |
97 | ||
98 | @pytest.mark.parametrize("report_filename_and_folder", list_report_files()) | |
99 | def test_autodetected_on_all_report_collection(report_filename_and_folder): | |
100 | plugin_folder = report_filename_and_folder[0] | |
101 | report_filename = report_filename_and_folder[1] | |
102 | plugin: PluginBase = get_plugin_from_cache(report_filename) | |
103 | assert plugin, report_filename | |
104 | assert plugin.id == plugin_folder | |
105 | ||
106 | ||
107 | @pytest.mark.skip(reason="Fail until release") | |
108 | @pytest.mark.parametrize("report_filename_and_folder", list_report_files()) | |
109 | def test_schema_on_all_reports(report_filename_and_folder): | |
110 | report_filename = report_filename_and_folder[1] | |
111 | plugin, plugin_json = get_report_json_from_cache(report_filename) | |
112 | if plugin_json: | |
113 | serializer = BulkCreateSchema() | |
114 | res = serializer.loads(json.dumps(plugin_json)) | |
115 | assert set(res.keys()) == {'hosts', 'command'} | |
116 | ||
117 | ||
118 | ||
119 | ||
120 | @pytest.mark.skip(reason="Skip validate ip format") | |
121 | @pytest.mark.parametrize("report_filename_and_folder", list_report_files()) | |
122 | def test_host_ips_all_reports(report_filename_and_folder): | |
123 | report_filename = report_filename_and_folder[1] | |
124 | plugin, plugin_json = get_report_json_from_cache(report_filename) | |
125 | if plugin_json: | |
126 | if plugin.id not in SKIP_IP_PLUGINS: | |
127 | for host in plugin_json['hosts']: | |
128 | assert is_valid_ip_address(host['ip']) is True | |
129 | ||
130 | ||
131 | @pytest.mark.parametrize("report_filename_and_folder", list_report_files()) | |
132 | def test_summary_reports(report_filename_and_folder): | |
133 | report_filename = report_filename_and_folder[1] | |
134 | plugin, plugin_json = get_report_json_from_cache(report_filename) | |
135 | if plugin_json: | |
136 | summary_file = f"{os.path.splitext(report_filename)[0]}_summary.json" | |
137 | assert os.path.isfile(summary_file) is True | |
138 | with open(summary_file) as f: | |
139 | saved_summary = json.load(f) | |
140 | summary = plugin.get_summary() | |
141 | vuln_hashes = set(summary['vuln_hashes']) | |
142 | saved_vuln_hashes = set(saved_summary.get('vuln_hashes', [])) | |
143 | assert summary['hosts'] == saved_summary['hosts'] | |
144 | assert summary['services'] == saved_summary['services'] | |
145 | assert summary['hosts_vulns'] == saved_summary['hosts_vulns'] | |
146 | assert summary['services_vulns'] == saved_summary['services_vulns'] | |
147 | assert summary['severity_vulns'] == saved_summary['severity_vulns'] | |
148 | assert vuln_hashes == saved_vuln_hashes | |
149 | ||
150 | ||
151 | @pytest.mark.performance | |
152 | @pytest.mark.parametrize("report_filename_and_folder", list_report_files()) | |
153 | def test_detected_tools_on_all_report_collection(report_filename_and_folder, benchmark): | |
154 | report_filename = report_filename_and_folder[1] | |
155 | plugins_manager = PluginsManager() | |
156 | analyzer = ReportAnalyzer(plugins_manager) | |
157 | plugin: PluginBase = analyzer.get_plugin(report_filename) | |
158 | if not plugin: | |
159 | return | |
160 | assert plugin, report_filename | |
161 | benchmark(plugin.processReport, report_filename) | |
162 | plugin_json = json.loads(plugin.get_json()) | |
163 | assert "hosts" in plugin_json | |
164 | assert "command" in plugin_json | |
165 | assert os.path.isfile(report_filename) is True |