secator 0.13.0__tar.gz → 0.15.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of secator might be problematic. Click here for more details.
- {secator-0.13.0 → secator-0.15.0}/CHANGELOG.md +24 -0
- {secator-0.13.0 → secator-0.15.0}/PKG-INFO +10 -3
- {secator-0.13.0 → secator-0.15.0}/README.md +9 -2
- {secator-0.13.0 → secator-0.15.0}/pyproject.toml +1 -1
- {secator-0.13.0 → secator-0.15.0}/secator/cli.py +34 -10
- secator-0.15.0/secator/configs/profiles/aggressive.yaml +8 -0
- secator-0.15.0/secator/configs/profiles/default.yaml +8 -0
- secator-0.15.0/secator/configs/profiles/insane.yaml +8 -0
- secator-0.15.0/secator/configs/profiles/paranoid.yaml +8 -0
- secator-0.15.0/secator/configs/profiles/polite.yaml +8 -0
- secator-0.15.0/secator/configs/profiles/sneaky.yaml +8 -0
- secator-0.15.0/secator/configs/profiles/tor.yaml +5 -0
- {secator-0.13.0 → secator-0.15.0}/secator/decorators.py +17 -10
- {secator-0.13.0 → secator-0.15.0}/secator/definitions.py +5 -0
- {secator-0.13.0 → secator-0.15.0}/secator/installer.py +10 -3
- {secator-0.13.0 → secator-0.15.0}/secator/output_types/stat.py +3 -0
- {secator-0.13.0 → secator-0.15.0}/secator/report.py +2 -2
- {secator-0.13.0 → secator-0.15.0}/secator/runners/_base.py +32 -2
- {secator-0.13.0 → secator-0.15.0}/secator/runners/command.py +2 -0
- {secator-0.13.0 → secator-0.15.0}/secator/runners/scan.py +1 -0
- {secator-0.13.0 → secator-0.15.0}/secator/runners/task.py +1 -0
- {secator-0.13.0 → secator-0.15.0}/secator/tasks/_categories.py +11 -11
- {secator-0.13.0 → secator-0.15.0}/secator/tasks/arjun.py +2 -1
- {secator-0.13.0 → secator-0.15.0}/secator/tasks/bbot.py +3 -0
- {secator-0.13.0 → secator-0.15.0}/secator/tasks/bup.py +2 -1
- {secator-0.13.0 → secator-0.15.0}/secator/tasks/cariddi.py +2 -1
- {secator-0.13.0 → secator-0.15.0}/secator/tasks/dalfox.py +2 -1
- {secator-0.13.0 → secator-0.15.0}/secator/tasks/dirsearch.py +3 -1
- {secator-0.13.0 → secator-0.15.0}/secator/tasks/dnsx.py +3 -1
- {secator-0.13.0 → secator-0.15.0}/secator/tasks/dnsxbrute.py +2 -0
- {secator-0.13.0 → secator-0.15.0}/secator/tasks/feroxbuster.py +3 -1
- {secator-0.13.0 → secator-0.15.0}/secator/tasks/ffuf.py +3 -1
- {secator-0.13.0 → secator-0.15.0}/secator/tasks/fping.py +3 -1
- {secator-0.13.0 → secator-0.15.0}/secator/tasks/gau.py +3 -1
- {secator-0.13.0 → secator-0.15.0}/secator/tasks/gf.py +2 -1
- {secator-0.13.0 → secator-0.15.0}/secator/tasks/gitleaks.py +3 -1
- {secator-0.13.0 → secator-0.15.0}/secator/tasks/gospider.py +2 -0
- {secator-0.13.0 → secator-0.15.0}/secator/tasks/grype.py +3 -1
- {secator-0.13.0 → secator-0.15.0}/secator/tasks/h8mail.py +2 -1
- {secator-0.13.0 → secator-0.15.0}/secator/tasks/httpx.py +3 -1
- {secator-0.13.0 → secator-0.15.0}/secator/tasks/katana.py +2 -0
- {secator-0.13.0 → secator-0.15.0}/secator/tasks/maigret.py +3 -1
- {secator-0.13.0 → secator-0.15.0}/secator/tasks/mapcidr.py +2 -1
- {secator-0.13.0 → secator-0.15.0}/secator/tasks/msfconsole.py +4 -3
- {secator-0.13.0 → secator-0.15.0}/secator/tasks/naabu.py +3 -1
- {secator-0.13.0 → secator-0.15.0}/secator/tasks/nmap.py +2 -0
- {secator-0.13.0 → secator-0.15.0}/secator/tasks/nuclei.py +3 -1
- {secator-0.13.0 → secator-0.15.0}/secator/tasks/searchsploit.py +3 -1
- {secator-0.13.0 → secator-0.15.0}/secator/tasks/subfinder.py +3 -1
- {secator-0.13.0 → secator-0.15.0}/secator/tasks/testssl.py +2 -1
- {secator-0.13.0 → secator-0.15.0}/secator/tasks/trivy.py +4 -1
- {secator-0.13.0 → secator-0.15.0}/secator/tasks/wafw00f.py +2 -1
- {secator-0.13.0 → secator-0.15.0}/secator/tasks/wpprobe.py +2 -1
- {secator-0.13.0 → secator-0.15.0}/secator/tasks/wpscan.py +2 -1
- {secator-0.13.0 → secator-0.15.0}/secator/template.py +1 -1
- {secator-0.13.0 → secator-0.15.0}/secator/utils.py +15 -11
- {secator-0.13.0 → secator-0.15.0}/secator/utils_test.py +9 -3
- {secator-0.13.0 → secator-0.15.0}/tests/integration/inputs.py +2 -0
- {secator-0.13.0 → secator-0.15.0}/tests/integration/test_tasks.py +7 -2
- {secator-0.13.0 → secator-0.15.0}/tests/unit/test_tasks.py +3 -3
- secator-0.13.0/secator/configs/profiles/aggressive.yaml +0 -7
- secator-0.13.0/secator/configs/profiles/default.yaml +0 -9
- secator-0.13.0/secator/configs/profiles/stealth.yaml +0 -7
- secator-0.13.0/secator/configs/workflows/port_scan.yaml +0 -39
- {secator-0.13.0 → secator-0.15.0}/.docker/Dockerfile.alpine +0 -0
- {secator-0.13.0 → secator-0.15.0}/.docker/Dockerfile.arch +0 -0
- {secator-0.13.0 → secator-0.15.0}/.docker/Dockerfile.debian +0 -0
- {secator-0.13.0 → secator-0.15.0}/.docker/Dockerfile.kali +0 -0
- {secator-0.13.0 → secator-0.15.0}/.docker/Dockerfile.osx +0 -0
- {secator-0.13.0 → secator-0.15.0}/.docker/Dockerfile.ubuntu +0 -0
- {secator-0.13.0 → secator-0.15.0}/.docker/build_all.sh +0 -0
- {secator-0.13.0 → secator-0.15.0}/.dockerignore +0 -0
- {secator-0.13.0 → secator-0.15.0}/.flake8 +0 -0
- {secator-0.13.0 → secator-0.15.0}/.gitignore +0 -0
- {secator-0.13.0 → secator-0.15.0}/CONTRIBUTING.md +0 -0
- {secator-0.13.0 → secator-0.15.0}/Dockerfile +0 -0
- {secator-0.13.0 → secator-0.15.0}/LICENSE +0 -0
- {secator-0.13.0 → secator-0.15.0}/SECURITY.md +0 -0
- {secator-0.13.0 → secator-0.15.0}/cloudbuild.yaml +0 -0
- {secator-0.13.0 → secator-0.15.0}/helm/.helmignore +0 -0
- {secator-0.13.0 → secator-0.15.0}/helm/Chart.yaml +0 -0
- {secator-0.13.0 → secator-0.15.0}/helm/templates/redis-service.yaml +0 -0
- {secator-0.13.0 → secator-0.15.0}/helm/templates/redis.yaml +0 -0
- {secator-0.13.0 → secator-0.15.0}/helm/templates/secator-manager.yaml +0 -0
- {secator-0.13.0 → secator-0.15.0}/helm/templates/secator-worker.yaml +0 -0
- {secator-0.13.0 → secator-0.15.0}/helm/values.yaml +0 -0
- {secator-0.13.0 → secator-0.15.0}/scripts/download_cves.sh +0 -0
- {secator-0.13.0 → secator-0.15.0}/scripts/install.sh +0 -0
- {secator-0.13.0 → secator-0.15.0}/scripts/install_asciinema.sh +0 -0
- {secator-0.13.0 → secator-0.15.0}/scripts/install_go.sh +0 -0
- {secator-0.13.0 → secator-0.15.0}/scripts/install_ruby.sh +0 -0
- {secator-0.13.0 → secator-0.15.0}/scripts/msf/exploit_cve.rc +0 -0
- {secator-0.13.0 → secator-0.15.0}/scripts/msf/ftp_anonymous.rc +0 -0
- {secator-0.13.0 → secator-0.15.0}/scripts/msf/ftp_version.rc +0 -0
- {secator-0.13.0 → secator-0.15.0}/scripts/msf/ftp_vsftpd_234_backdoor.rc +0 -0
- {secator-0.13.0 → secator-0.15.0}/scripts/msf/redis.rc +0 -0
- {secator-0.13.0 → secator-0.15.0}/scripts/stories/STORY.md +0 -0
- {secator-0.13.0 → secator-0.15.0}/scripts/stories/aliases.sh +0 -0
- {secator-0.13.0 → secator-0.15.0}/scripts/stories/demo.sh +0 -0
- {secator-0.13.0 → secator-0.15.0}/scripts/stories/fmt.sh +0 -0
- {secator-0.13.0 → secator-0.15.0}/scripts/stories/input.sh +0 -0
- {secator-0.13.0 → secator-0.15.0}/scripts/stories/pipe.sh +0 -0
- {secator-0.13.0 → secator-0.15.0}/scripts/stories/short_demo.sh +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/.gitignore +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/__init__.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/celery.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/celery_signals.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/celery_utils.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/config.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/configs/__init__.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/configs/profiles/__init__.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/configs/scans/__init__.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/configs/scans/domain.yaml +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/configs/scans/host.yaml +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/configs/scans/network.yaml +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/configs/scans/subdomain.yaml +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/configs/scans/url.yaml +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/configs/workflows/__init__.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/configs/workflows/cidr_recon.yaml +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/configs/workflows/code_scan.yaml +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/configs/workflows/host_recon.yaml +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/configs/workflows/subdomain_recon.yaml +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/configs/workflows/url_bypass.yaml +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/configs/workflows/url_crawl.yaml +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/configs/workflows/url_dirsearch.yaml +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/configs/workflows/url_fuzz.yaml +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/configs/workflows/url_nuclei.yaml +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/configs/workflows/url_params_fuzz.yaml +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/configs/workflows/url_vuln.yaml +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/configs/workflows/user_hunt.yaml +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/configs/workflows/wordpress.yaml +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/exporters/__init__.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/exporters/_base.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/exporters/console.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/exporters/csv.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/exporters/gdrive.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/exporters/json.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/exporters/table.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/exporters/txt.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/hooks/__init__.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/hooks/gcs.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/hooks/mongodb.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/output_types/__init__.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/output_types/_base.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/output_types/certificate.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/output_types/error.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/output_types/exploit.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/output_types/info.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/output_types/ip.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/output_types/port.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/output_types/progress.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/output_types/record.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/output_types/state.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/output_types/subdomain.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/output_types/tag.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/output_types/target.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/output_types/url.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/output_types/user_account.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/output_types/vulnerability.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/output_types/warning.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/rich.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/runners/__init__.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/runners/_helpers.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/runners/celery.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/runners/workflow.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/scans/__init__.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/serializers/__init__.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/serializers/dataclass.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/serializers/json.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/serializers/regex.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/tasks/__init__.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/thread.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/secator/workflows/__init__.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/tests/__init__.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/tests/fixtures/h8mail_breach.txt +0 -0
- {secator-0.13.0 → secator-0.15.0}/tests/fixtures/ls.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/tests/fixtures/msfconsole_input.rc +0 -0
- {secator-0.13.0 → secator-0.15.0}/tests/fixtures/nmap_output.xml +0 -0
- {secator-0.13.0 → secator-0.15.0}/tests/integration/__init__.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/tests/integration/outputs.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/tests/integration/setup.sh +0 -0
- {secator-0.13.0 → secator-0.15.0}/tests/integration/teardown.sh +0 -0
- {secator-0.13.0 → secator-0.15.0}/tests/integration/test_addons.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/tests/integration/test_celery.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/tests/integration/test_helpers.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/tests/integration/test_scans.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/tests/integration/test_worker.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/tests/integration/test_workflows.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/tests/integration/wordlist.txt +0 -0
- {secator-0.13.0 → secator-0.15.0}/tests/integration/wordlist_dns.txt +0 -0
- {secator-0.13.0 → secator-0.15.0}/tests/integration/wordpress_toolbox/Dockerfile +0 -0
- {secator-0.13.0 → secator-0.15.0}/tests/integration/wordpress_toolbox/Makefile +0 -0
- {secator-0.13.0 → secator-0.15.0}/tests/performance/__init__.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/tests/performance/loadtester.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/tests/performance/test_worker.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/tests/unit/__init__.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/tests/unit/test_celery.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/tests/unit/test_cli.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/tests/unit/test_command.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/tests/unit/test_config.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/tests/unit/test_offline.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/tests/unit/test_runners.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/tests/unit/test_scans.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/tests/unit/test_serializers.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/tests/unit/test_tasks_categories.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/tests/unit/test_template.py +0 -0
- {secator-0.13.0 → secator-0.15.0}/tests/unit/test_utils.py +0 -0
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.15.0](https://github.com/freelabz/secator/compare/v0.14.0...v0.15.0) (2025-05-04)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* improve cli usage and add multi input types ([#609](https://github.com/freelabz/secator/issues/609)) ([b850914](https://github.com/freelabz/secator/commit/b8509141e62dfd72e0b4f15c2b9b5466089e9818))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* installer issue on non-standard distribs ([#613](https://github.com/freelabz/secator/issues/613)) ([194e911](https://github.com/freelabz/secator/commit/194e911b420fcbb0feec3b563a098a3f36cc09cd))
|
|
14
|
+
|
|
15
|
+
## [0.14.0](https://github.com/freelabz/secator/compare/v0.13.0...v0.14.0) (2025-04-30)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Features
|
|
19
|
+
|
|
20
|
+
* add support for profiles ([#532](https://github.com/freelabz/secator/issues/532)) ([6f499b7](https://github.com/freelabz/secator/commit/6f499b72ec18dddde717e00318be4e2b53cc0478))
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
### Bug Fixes
|
|
24
|
+
|
|
25
|
+
* **cli:** restore --unified option, delete port_scan workflow ([#606](https://github.com/freelabz/secator/issues/606)) ([6dc647d](https://github.com/freelabz/secator/commit/6dc647d7205d15faa1c675485af441549d798118))
|
|
26
|
+
|
|
3
27
|
## [0.13.0](https://github.com/freelabz/secator/compare/v0.12.0...v0.13.0) (2025-04-29)
|
|
4
28
|
|
|
5
29
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: secator
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.15.0
|
|
4
4
|
Summary: The pentester's swiss knife.
|
|
5
5
|
Project-URL: Homepage, https://github.com/freelabz/secator
|
|
6
6
|
Project-URL: Issues, https://github.com/freelabz/secator/issues
|
|
@@ -82,7 +82,7 @@ Description-Content-Type: text/markdown
|
|
|
82
82
|
<a href="https://pypi.org/project/secator/"><img src="https://img.shields.io/pypi/dm/secator"></a>
|
|
83
83
|
<a href="https://twitter.com/freelabz"><img src="https://img.shields.io/twitter/follow/freelabz.svg?logo=twitter"></a>
|
|
84
84
|
<a href="https://youtube.com/@FreeLabz"><img src="https://img.shields.io/youtube/channel/subscribers/UCu-F6SpU0h2NP18zBBP04cw?style=social&label=Subscribe%20%40FreeLabz"></a>
|
|
85
|
-
|
|
85
|
+
<a href="https://discord.gg/nyHjC2aTrq"><img src="https://img.shields.io/discord/695645237418131507.svg?logo=discord"></a>
|
|
86
86
|
</p>
|
|
87
87
|
|
|
88
88
|
|
|
@@ -91,7 +91,8 @@ Description-Content-Type: text/markdown
|
|
|
91
91
|
<a href="#supported-commands">Supported commands</a> •
|
|
92
92
|
<a href="#install-secator">Installation</a> •
|
|
93
93
|
<a href="#usage">Usage</a> •
|
|
94
|
-
<a href="https://docs.freelabz.com">Documentation</a>
|
|
94
|
+
<a href="https://docs.freelabz.com">Documentation</a> •
|
|
95
|
+
<a href="https://discord.gg/nyHjC2aTrq">Join us on Discord !</a>
|
|
95
96
|
</p>
|
|
96
97
|
|
|
97
98
|
`secator` is a task and workflow runner used for security assessments. It supports dozens of well-known security tools
|
|
@@ -122,6 +123,11 @@ and it is designed to improve productivity for pentesters and security researche
|
|
|
122
123
|
|
|
123
124
|
| Name | Description | Category |
|
|
124
125
|
|---------------------------------------------------------------|--------------------------------------------------------------------------------|-----------------|
|
|
126
|
+
| [arjun](https://github.com/s0md3v/Arjun) | HTTP Parameter Discovery Suite. | |
|
|
127
|
+
| [gitleaks](https://github.com/gitleaks/gitleaks) | Tool for detecting secrets like passwords, API keys, tokens, etc. | |
|
|
128
|
+
| [testssl](https://github.com/testssl/testssl.sh) | SSL/TLS security scanner, including ciphers, protocols and cryptographic flaws.| |
|
|
129
|
+
| [wafw00f](https://github.com/EnableSecurity/wafw00f) | Web Application Firewall Fingerprinting tool. | |
|
|
130
|
+
| [wpprobe](https://github.com/Chocapikk/wpprobe) | Fast wordpress plugin enumeration tool. | |
|
|
125
131
|
| [httpx](https://github.com/projectdiscovery/httpx) | Fast HTTP prober. | `http` |
|
|
126
132
|
| [cariddi](https://github.com/edoardottt/cariddi) | Fast crawler and endpoint secrets / api keys / tokens matcher. | `http/crawler` |
|
|
127
133
|
| [gau](https://github.com/lc/gau) | Offline URL crawler (Alien Vault, The Wayback Machine, Common Crawl, URLScan). | `http/crawler` |
|
|
@@ -139,6 +145,7 @@ and it is designed to improve productivity for pentesters and security researche
|
|
|
139
145
|
| [naabu](https://github.com/projectdiscovery/naabu) | Fast port discovery tool. | `recon/port` |
|
|
140
146
|
| [maigret](https://github.com/soxoj/maigret) | Hunt for user accounts across many websites. | `recon/user` |
|
|
141
147
|
| [gf](https://github.com/tomnomnom/gf) | A wrapper around grep to avoid typing common patterns. | `tagger` |
|
|
148
|
+
| [trivy](https://github.com/aquasecurity/trivy) | Comprehensive and versatile security scanner. | `vuln` |
|
|
142
149
|
| [grype](https://github.com/anchore/grype) | A vulnerability scanner for container images and filesystems. | `vuln/code` |
|
|
143
150
|
| [dalfox](https://github.com/hahwul/dalfox) | Powerful XSS scanning tool and parameter analyzer. | `vuln/http` |
|
|
144
151
|
| [msfconsole](https://docs.rapid7.com/metasploit/msf-overview) | CLI to access and work with the Metasploit Framework. | `vuln/http` |
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
<a href="https://pypi.org/project/secator/"><img src="https://img.shields.io/pypi/dm/secator"></a>
|
|
13
13
|
<a href="https://twitter.com/freelabz"><img src="https://img.shields.io/twitter/follow/freelabz.svg?logo=twitter"></a>
|
|
14
14
|
<a href="https://youtube.com/@FreeLabz"><img src="https://img.shields.io/youtube/channel/subscribers/UCu-F6SpU0h2NP18zBBP04cw?style=social&label=Subscribe%20%40FreeLabz"></a>
|
|
15
|
-
|
|
15
|
+
<a href="https://discord.gg/nyHjC2aTrq"><img src="https://img.shields.io/discord/695645237418131507.svg?logo=discord"></a>
|
|
16
16
|
</p>
|
|
17
17
|
|
|
18
18
|
|
|
@@ -21,7 +21,8 @@
|
|
|
21
21
|
<a href="#supported-commands">Supported commands</a> •
|
|
22
22
|
<a href="#install-secator">Installation</a> •
|
|
23
23
|
<a href="#usage">Usage</a> •
|
|
24
|
-
<a href="https://docs.freelabz.com">Documentation</a>
|
|
24
|
+
<a href="https://docs.freelabz.com">Documentation</a> •
|
|
25
|
+
<a href="https://discord.gg/nyHjC2aTrq">Join us on Discord !</a>
|
|
25
26
|
</p>
|
|
26
27
|
|
|
27
28
|
`secator` is a task and workflow runner used for security assessments. It supports dozens of well-known security tools
|
|
@@ -52,6 +53,11 @@ and it is designed to improve productivity for pentesters and security researche
|
|
|
52
53
|
|
|
53
54
|
| Name | Description | Category |
|
|
54
55
|
|---------------------------------------------------------------|--------------------------------------------------------------------------------|-----------------|
|
|
56
|
+
| [arjun](https://github.com/s0md3v/Arjun) | HTTP Parameter Discovery Suite. | |
|
|
57
|
+
| [gitleaks](https://github.com/gitleaks/gitleaks) | Tool for detecting secrets like passwords, API keys, tokens, etc. | |
|
|
58
|
+
| [testssl](https://github.com/testssl/testssl.sh) | SSL/TLS security scanner, including ciphers, protocols and cryptographic flaws.| |
|
|
59
|
+
| [wafw00f](https://github.com/EnableSecurity/wafw00f) | Web Application Firewall Fingerprinting tool. | |
|
|
60
|
+
| [wpprobe](https://github.com/Chocapikk/wpprobe) | Fast wordpress plugin enumeration tool. | |
|
|
55
61
|
| [httpx](https://github.com/projectdiscovery/httpx) | Fast HTTP prober. | `http` |
|
|
56
62
|
| [cariddi](https://github.com/edoardottt/cariddi) | Fast crawler and endpoint secrets / api keys / tokens matcher. | `http/crawler` |
|
|
57
63
|
| [gau](https://github.com/lc/gau) | Offline URL crawler (Alien Vault, The Wayback Machine, Common Crawl, URLScan). | `http/crawler` |
|
|
@@ -69,6 +75,7 @@ and it is designed to improve productivity for pentesters and security researche
|
|
|
69
75
|
| [naabu](https://github.com/projectdiscovery/naabu) | Fast port discovery tool. | `recon/port` |
|
|
70
76
|
| [maigret](https://github.com/soxoj/maigret) | Hunt for user accounts across many websites. | `recon/user` |
|
|
71
77
|
| [gf](https://github.com/tomnomnom/gf) | A wrapper around grep to avoid typing common patterns. | `tagger` |
|
|
78
|
+
| [trivy](https://github.com/aquasecurity/trivy) | Comprehensive and versatile security scanner. | `vuln` |
|
|
72
79
|
| [grype](https://github.com/anchore/grype) | A vulnerability scanner for container images and filesystems. | `vuln/code` |
|
|
73
80
|
| [dalfox](https://github.com/hahwul/dalfox) | Powerful XSS scanning tool and parameter analyzer. | `vuln/http` |
|
|
74
81
|
| [msfconsole](https://docs.rapid7.com/metasploit/msf-overview) | CLI to access and work with the Metasploit Framework. | `vuln/http` |
|
|
@@ -36,6 +36,7 @@ click.rich_click.USE_RICH_MARKUP = True
|
|
|
36
36
|
ALL_TASKS = discover_tasks()
|
|
37
37
|
ALL_WORKFLOWS = [t for t in TEMPLATES if t.type == 'workflow']
|
|
38
38
|
ALL_SCANS = [t for t in TEMPLATES if t.type == 'scan']
|
|
39
|
+
ALL_PROFILES = [t for t in TEMPLATES if t.type == 'profile']
|
|
39
40
|
FINDING_TYPES_LOWER = [c.__name__.lower() for c in FINDING_TYPES]
|
|
40
41
|
CONTEXT_SETTINGS = dict(help_option_names=['-h', '-help', '--help'])
|
|
41
42
|
|
|
@@ -125,6 +126,25 @@ for config in sorted(ALL_SCANS, key=lambda x: x['name']):
|
|
|
125
126
|
register_runner(scan, config)
|
|
126
127
|
|
|
127
128
|
|
|
129
|
+
@cli.group(aliases=['p'])
|
|
130
|
+
@click.pass_context
|
|
131
|
+
def profile(ctx):
|
|
132
|
+
"""Show profiles"""
|
|
133
|
+
pass
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
@profile.command('list')
|
|
137
|
+
def profile_list():
|
|
138
|
+
table = Table()
|
|
139
|
+
table.add_column("Profile name", style="bold gold3")
|
|
140
|
+
table.add_column("Description", overflow='fold')
|
|
141
|
+
table.add_column("Options", overflow='fold')
|
|
142
|
+
for profile in ALL_PROFILES:
|
|
143
|
+
opts_str = ','.join(f'{k}={v}' for k, v in profile.opts.items())
|
|
144
|
+
table.add_row(profile.name, profile.description, opts_str)
|
|
145
|
+
console.print(table)
|
|
146
|
+
|
|
147
|
+
|
|
128
148
|
#--------#
|
|
129
149
|
# WORKER #
|
|
130
150
|
#--------#
|
|
@@ -685,7 +705,7 @@ def report_show(report_query, output, runner_type, time_delta, type, query, work
|
|
|
685
705
|
all_results.extend(runner.results)
|
|
686
706
|
continue
|
|
687
707
|
report = Report(runner, title=f"Consolidated report - {current}", exporters=exporters)
|
|
688
|
-
report.build(extractors=extractors if not unified else [])
|
|
708
|
+
report.build(extractors=extractors if not unified else [], dedupe=unified)
|
|
689
709
|
file_date = get_file_date(path)
|
|
690
710
|
runner_name = data['info']['name']
|
|
691
711
|
console.print(
|
|
@@ -763,7 +783,7 @@ def report_list(workspace, runner_type, time_delta):
|
|
|
763
783
|
@report.command('export')
|
|
764
784
|
@click.argument('json_path', type=str)
|
|
765
785
|
@click.option('--output-folder', '-of', type=str)
|
|
766
|
-
@click.option('-output', '-o', type=str)
|
|
786
|
+
@click.option('-output', '-o', type=str, required=True)
|
|
767
787
|
def report_export(json_path, output_folder, output):
|
|
768
788
|
with open(json_path, 'r') as f:
|
|
769
789
|
data = loads_dataclass(f.read())
|
|
@@ -1423,6 +1443,16 @@ def task(name, verbose, check):
|
|
|
1423
1443
|
task = task[0]
|
|
1424
1444
|
task_name = task.__name__
|
|
1425
1445
|
|
|
1446
|
+
# Check task command is set
|
|
1447
|
+
check_test(
|
|
1448
|
+
task.cmd,
|
|
1449
|
+
'Check task command is set (cls.cmd)',
|
|
1450
|
+
'Task has no cmd attribute.',
|
|
1451
|
+
errors
|
|
1452
|
+
)
|
|
1453
|
+
if errors:
|
|
1454
|
+
sys.exit(0)
|
|
1455
|
+
|
|
1426
1456
|
# Run install
|
|
1427
1457
|
cmd = f'secator install tools {task_name}'
|
|
1428
1458
|
ret_code = Command.execute(cmd, name='install', quiet=not verbose, cwd=ROOT_FOLDER)
|
|
@@ -1437,7 +1467,7 @@ def task(name, verbose, check):
|
|
|
1437
1467
|
errors
|
|
1438
1468
|
)
|
|
1439
1469
|
check_test(
|
|
1440
|
-
any(cmd for cmd in [task.install_cmd, task.install_github_handle]),
|
|
1470
|
+
any(cmd for cmd in [task.install_pre, task.install_cmd, task.install_github_handle]),
|
|
1441
1471
|
'Check task installation command is defined',
|
|
1442
1472
|
'Task has no installation command. Please define one or more of the following class attributes: `install_pre`, `install_cmd`, `install_post`, `install_github_handle`.', # noqa: E501
|
|
1443
1473
|
errors
|
|
@@ -1472,13 +1502,7 @@ def task(name, verbose, check):
|
|
|
1472
1502
|
errors
|
|
1473
1503
|
)
|
|
1474
1504
|
check_test(
|
|
1475
|
-
task.
|
|
1476
|
-
'Check task command is set (cls.cmd)',
|
|
1477
|
-
'Task has no cmd attribute.',
|
|
1478
|
-
errors
|
|
1479
|
-
)
|
|
1480
|
-
check_test(
|
|
1481
|
-
task.input_type,
|
|
1505
|
+
task.input_types,
|
|
1482
1506
|
'Check task input type is set (cls.input_type)',
|
|
1483
1507
|
'Task has no input_type attribute.',
|
|
1484
1508
|
warnings,
|
|
@@ -13,6 +13,7 @@ from secator.utils import (deduplicate, expand_input, get_command_category)
|
|
|
13
13
|
|
|
14
14
|
RUNNER_OPTS = {
|
|
15
15
|
'output': {'type': str, 'default': None, 'help': 'Output options (-o table,json,csv,gdrive)', 'short': 'o'},
|
|
16
|
+
'profiles': {'type': str, 'default': 'default', 'help': 'Profiles', 'short': 'pf'},
|
|
16
17
|
'workspace': {'type': str, 'default': 'default', 'help': 'Workspace', 'short': 'ws'},
|
|
17
18
|
'print_json': {'is_flag': True, 'short': 'json', 'default': False, 'help': 'Print items as JSON lines'},
|
|
18
19
|
'print_raw': {'is_flag': True, 'short': 'raw', 'default': False, 'help': 'Print items in raw format'},
|
|
@@ -270,7 +271,6 @@ def generate_cli_subcommand(cli_endpoint, func, **opts):
|
|
|
270
271
|
def register_runner(cli_endpoint, config):
|
|
271
272
|
name = config.name
|
|
272
273
|
input_required = True
|
|
273
|
-
input_type = 'targets'
|
|
274
274
|
command_opts = {
|
|
275
275
|
'no_args_is_help': True,
|
|
276
276
|
'context_settings': {
|
|
@@ -281,37 +281,44 @@ def register_runner(cli_endpoint, config):
|
|
|
281
281
|
|
|
282
282
|
if cli_endpoint.name == 'scan':
|
|
283
283
|
runner_cls = Scan
|
|
284
|
+
input_required = False # allow targets from stdin
|
|
284
285
|
short_help = config.description or ''
|
|
285
286
|
short_help += f' [dim]alias: {config.alias}' if config.alias else ''
|
|
286
287
|
command_opts.update({
|
|
287
288
|
'name': name,
|
|
288
|
-
'short_help': short_help
|
|
289
|
+
'short_help': short_help,
|
|
290
|
+
'no_args_is_help': False
|
|
289
291
|
})
|
|
292
|
+
input_types = config.input_types
|
|
290
293
|
|
|
291
294
|
elif cli_endpoint.name == 'workflow':
|
|
292
295
|
runner_cls = Workflow
|
|
296
|
+
input_required = False # allow targets from stdin
|
|
293
297
|
short_help = config.description or ''
|
|
294
298
|
short_help = f'{short_help:<55} [dim](alias)[/][bold cyan] {config.alias}' if config.alias else ''
|
|
295
299
|
command_opts.update({
|
|
296
300
|
'name': name,
|
|
297
|
-
'short_help': short_help
|
|
301
|
+
'short_help': short_help,
|
|
302
|
+
'no_args_is_help': False
|
|
298
303
|
})
|
|
304
|
+
input_types = config.input_types
|
|
299
305
|
|
|
300
306
|
elif cli_endpoint.name == 'task':
|
|
301
307
|
runner_cls = Task
|
|
302
308
|
input_required = False # allow targets from stdin
|
|
303
309
|
task_cls = Task.get_task_class(config.name)
|
|
304
310
|
task_category = get_command_category(task_cls)
|
|
305
|
-
|
|
306
|
-
short_help = f'[magenta]{task_category:<15}[/]{task_cls.__doc__}'
|
|
311
|
+
short_help = f'[magenta]{task_category:<25}[/] {task_cls.__doc__}'
|
|
307
312
|
command_opts.update({
|
|
308
313
|
'name': name,
|
|
309
314
|
'short_help': short_help,
|
|
310
315
|
'no_args_is_help': False
|
|
311
316
|
})
|
|
317
|
+
input_types = task_cls.input_types
|
|
312
318
|
|
|
313
319
|
else:
|
|
314
320
|
raise ValueError(f"Unrecognized runner endpoint name {cli_endpoint.name}")
|
|
321
|
+
input_types_str = '|'.join(input_types) if input_types else 'targets'
|
|
315
322
|
options = get_command_options(config)
|
|
316
323
|
|
|
317
324
|
# TODO: maybe allow this in the future
|
|
@@ -323,7 +330,7 @@ def register_runner(cli_endpoint, config):
|
|
|
323
330
|
# for i in range(0, len(ctx.args), 2)
|
|
324
331
|
# }
|
|
325
332
|
|
|
326
|
-
@click.argument(
|
|
333
|
+
@click.argument(input_types_str, required=input_required)
|
|
327
334
|
@decorate_command_options(options)
|
|
328
335
|
@click.pass_context
|
|
329
336
|
def func(ctx, **opts):
|
|
@@ -352,7 +359,7 @@ def register_runner(cli_endpoint, config):
|
|
|
352
359
|
# opts.update(unknown_opts)
|
|
353
360
|
|
|
354
361
|
# Expand input
|
|
355
|
-
inputs = opts.pop(
|
|
362
|
+
inputs = opts.pop(input_types_str)
|
|
356
363
|
inputs = expand_input(inputs, ctx)
|
|
357
364
|
|
|
358
365
|
# Build hooks from driver name
|
|
@@ -419,10 +426,10 @@ def register_runner(cli_endpoint, config):
|
|
|
419
426
|
runner.run()
|
|
420
427
|
|
|
421
428
|
generate_cli_subcommand(cli_endpoint, func, **command_opts)
|
|
422
|
-
generate_rich_click_opt_groups(cli_endpoint, name,
|
|
429
|
+
generate_rich_click_opt_groups(cli_endpoint, name, input_types, options)
|
|
423
430
|
|
|
424
431
|
|
|
425
|
-
def generate_rich_click_opt_groups(cli_endpoint, name,
|
|
432
|
+
def generate_rich_click_opt_groups(cli_endpoint, name, input_types, options):
|
|
426
433
|
sortorder = {
|
|
427
434
|
'Execution': 0,
|
|
428
435
|
'Output': 1,
|
|
@@ -433,7 +440,7 @@ def generate_rich_click_opt_groups(cli_endpoint, name, input_type, options):
|
|
|
433
440
|
opt_group = [
|
|
434
441
|
{
|
|
435
442
|
'name': 'Targets',
|
|
436
|
-
'options':
|
|
443
|
+
'options': input_types,
|
|
437
444
|
},
|
|
438
445
|
]
|
|
439
446
|
for prefix in prefixes:
|
|
@@ -40,6 +40,9 @@ AUTO_CALIBRATION = 'auto_calibration'
|
|
|
40
40
|
CONTENT_TYPE = 'content_type'
|
|
41
41
|
CONTENT_LENGTH = 'content_length'
|
|
42
42
|
CIDR_RANGE = 'cidr_range'
|
|
43
|
+
DOCKER_IMAGE = 'docker_image'
|
|
44
|
+
FILENAME = 'filename'
|
|
45
|
+
GIT_REPOSITORY = 'git_repository'
|
|
43
46
|
CPES = 'cpes'
|
|
44
47
|
CVES = 'cves'
|
|
45
48
|
DELAY = 'delay'
|
|
@@ -62,6 +65,7 @@ MATCH_CODES = 'match_codes'
|
|
|
62
65
|
MATCH_REGEX = 'match_regex'
|
|
63
66
|
MATCH_SIZE = 'match_size'
|
|
64
67
|
MATCH_WORDS = 'match_words'
|
|
68
|
+
ORG_NAME = 'org_name'
|
|
65
69
|
OUTPUT_PATH = 'output_path'
|
|
66
70
|
PATH = 'path'
|
|
67
71
|
PERCENT = 'percent'
|
|
@@ -100,6 +104,7 @@ REFERENCE = 'reference'
|
|
|
100
104
|
REFERENCES = 'references'
|
|
101
105
|
SEVERITY = 'severity'
|
|
102
106
|
TAGS = 'tags'
|
|
107
|
+
TECHNOLOGY = 'technology'
|
|
103
108
|
WEBSERVER = 'webserver'
|
|
104
109
|
WORDLIST = 'wordlist'
|
|
105
110
|
WORDS = 'words'
|
|
@@ -47,6 +47,7 @@ class InstallerStatus(Enum):
|
|
|
47
47
|
@dataclass
|
|
48
48
|
class Distribution:
|
|
49
49
|
name: str
|
|
50
|
+
system: str
|
|
50
51
|
pm_name: str
|
|
51
52
|
pm_installer: str
|
|
52
53
|
pm_finalizer: str
|
|
@@ -186,6 +187,8 @@ class SourceInstaller:
|
|
|
186
187
|
install_cmd = config
|
|
187
188
|
else:
|
|
188
189
|
distribution = get_distro_config()
|
|
190
|
+
if not distribution.pm_installer:
|
|
191
|
+
return InstallerStatus.UNKNOWN_DISTRIBUTION
|
|
189
192
|
for distros, command in config.items():
|
|
190
193
|
if distribution.name in distros.split("|") or distros == '*':
|
|
191
194
|
install_cmd = command
|
|
@@ -543,7 +546,7 @@ def get_distro_config():
|
|
|
543
546
|
distrib = system
|
|
544
547
|
|
|
545
548
|
if system == "Linux":
|
|
546
|
-
distrib = distro.
|
|
549
|
+
distrib = distro.like() or distro.id()
|
|
547
550
|
|
|
548
551
|
if distrib in ["ubuntu", "debian", "linuxmint", "popos", "kali"]:
|
|
549
552
|
installer = "apt install -y --no-install-recommends"
|
|
@@ -573,12 +576,16 @@ def get_distro_config():
|
|
|
573
576
|
else:
|
|
574
577
|
installer = "scoop" # Alternative package manager for Windows
|
|
575
578
|
|
|
576
|
-
|
|
579
|
+
if not installer:
|
|
580
|
+
console.print(Error(message=f'Could not find installer for your distribution (system: {system}, distrib: {distrib})')) # noqa: E501
|
|
581
|
+
|
|
582
|
+
manager = installer.split(' ')[0] if installer else ''
|
|
577
583
|
config = Distribution(
|
|
578
584
|
pm_installer=installer,
|
|
579
585
|
pm_finalizer=finalizer,
|
|
580
586
|
pm_name=manager,
|
|
581
|
-
name=distrib
|
|
587
|
+
name=distrib,
|
|
588
|
+
system=system
|
|
582
589
|
)
|
|
583
590
|
return config
|
|
584
591
|
|
|
@@ -25,6 +25,9 @@ class Stat(OutputType):
|
|
|
25
25
|
_table_fields = ['name', 'pid', 'cpu', 'memory']
|
|
26
26
|
_sort_by = ('name', 'pid')
|
|
27
27
|
|
|
28
|
+
def __str__(self) -> str:
|
|
29
|
+
return f'{self.name} [pid={self.pid}] [cpu={self.cpu:.2f}%] [memory={self.memory:.2f}%]'
|
|
30
|
+
|
|
28
31
|
def __repr__(self) -> str:
|
|
29
32
|
s = rf'[dim yellow3]📊 {self.name} \[pid={self.pid}] \[cpu={self.cpu:.2f}%] \[memory={self.memory:.2f}%]'
|
|
30
33
|
if self.net_conns:
|
|
@@ -55,7 +55,7 @@ class Report:
|
|
|
55
55
|
f'{str(e)}[/]\n[dim]{traceback_as_string(e)}[/]',
|
|
56
56
|
)
|
|
57
57
|
|
|
58
|
-
def build(self, extractors=[], dedupe=
|
|
58
|
+
def build(self, extractors=[], dedupe=CONFIG.runners.remove_duplicates):
|
|
59
59
|
# Trim options
|
|
60
60
|
from secator.decorators import DEFAULT_CLI_OPTIONS
|
|
61
61
|
opts = merge_opts(self.runner.config.options, self.runner.run_opts)
|
|
@@ -97,7 +97,7 @@ class Report:
|
|
|
97
97
|
if items:
|
|
98
98
|
if sort_by and all(sort_by):
|
|
99
99
|
items = sorted(items, key=operator.attrgetter(*sort_by))
|
|
100
|
-
if dedupe
|
|
100
|
+
if dedupe:
|
|
101
101
|
items = remove_duplicates(items)
|
|
102
102
|
# items = [item for item in items if not item._duplicate and item not in dedupe_from]
|
|
103
103
|
for extractor in extractors:
|
|
@@ -53,7 +53,7 @@ class Runner:
|
|
|
53
53
|
"""
|
|
54
54
|
|
|
55
55
|
# Input field (mostly for tests and CLI)
|
|
56
|
-
|
|
56
|
+
input_types = []
|
|
57
57
|
|
|
58
58
|
# Output types
|
|
59
59
|
output_types = []
|
|
@@ -138,6 +138,10 @@ class Runner:
|
|
|
138
138
|
self.debug('Run opts', obj={k: v for k, v in self.run_opts.items() if v is not None}, sub='init')
|
|
139
139
|
self.debug('Print opts', obj={k: v for k, v in self.print_opts.items() if v is not None}, sub='init')
|
|
140
140
|
|
|
141
|
+
# Load profiles
|
|
142
|
+
profiles_str = run_opts.get('profiles', [])
|
|
143
|
+
self.load_profiles(profiles_str)
|
|
144
|
+
|
|
141
145
|
# Determine exporters
|
|
142
146
|
exporters_str = self.run_opts.get('output') or self.default_exporters
|
|
143
147
|
self.exporters = self.resolve_exporters(exporters_str)
|
|
@@ -827,7 +831,7 @@ class Runner:
|
|
|
827
831
|
if isinstance(data, (OutputType, dict)):
|
|
828
832
|
if getattr(data, 'toDict', None):
|
|
829
833
|
data = data.toDict()
|
|
830
|
-
data = json.dumps(data)
|
|
834
|
+
data = json.dumps(data, default=str)
|
|
831
835
|
print(data, file=out)
|
|
832
836
|
|
|
833
837
|
def _get_findings_count(self):
|
|
@@ -953,6 +957,32 @@ class Runner:
|
|
|
953
957
|
]
|
|
954
958
|
return [cls for cls in classes if cls]
|
|
955
959
|
|
|
960
|
+
def load_profiles(self, profiles):
|
|
961
|
+
"""Load profiles and update run options.
|
|
962
|
+
|
|
963
|
+
Args:
|
|
964
|
+
profiles (list[str]): List of profile names to resolve.
|
|
965
|
+
|
|
966
|
+
Returns:
|
|
967
|
+
list: List of profiles.
|
|
968
|
+
"""
|
|
969
|
+
from secator.cli import ALL_PROFILES
|
|
970
|
+
if isinstance(profiles, str):
|
|
971
|
+
profiles = profiles.split(',')
|
|
972
|
+
templates = []
|
|
973
|
+
for pname in profiles:
|
|
974
|
+
matches = [p for p in ALL_PROFILES if p.name == pname]
|
|
975
|
+
if not matches:
|
|
976
|
+
self._print(Warning(message=f'Profile "{pname}" was not found'), rich=True)
|
|
977
|
+
else:
|
|
978
|
+
templates.append(matches[0])
|
|
979
|
+
opts = {}
|
|
980
|
+
for profile in templates:
|
|
981
|
+
self._print(Info(message=f'Loaded profile {profile.name} ({profile.description})'), rich=True)
|
|
982
|
+
opts.update(profile.opts)
|
|
983
|
+
opts = {k: v for k, v in opts.items() if k not in self.run_opts}
|
|
984
|
+
self.run_opts.update(opts)
|
|
985
|
+
|
|
956
986
|
@classmethod
|
|
957
987
|
def get_func_path(cls, func):
|
|
958
988
|
"""Get the full symbolic path of a function or method, including staticmethods, using function and method
|
|
@@ -33,6 +33,7 @@ class Scan(Runner):
|
|
|
33
33
|
sigs = []
|
|
34
34
|
for name, workflow_opts in self.config.workflows.items():
|
|
35
35
|
run_opts = self.run_opts.copy()
|
|
36
|
+
run_opts.pop('profiles', None)
|
|
36
37
|
run_opts['no_poll'] = True
|
|
37
38
|
run_opts['caller'] = 'Scan'
|
|
38
39
|
opts = merge_opts(scan_opts, workflow_opts, run_opts)
|
|
@@ -73,19 +73,19 @@ OPTS_VULN = [
|
|
|
73
73
|
|
|
74
74
|
class Http(Command):
|
|
75
75
|
meta_opts = {k: OPTS[k] for k in OPTS_HTTP_CRAWLERS}
|
|
76
|
-
|
|
76
|
+
input_types = [URL]
|
|
77
77
|
output_types = [Url]
|
|
78
78
|
|
|
79
79
|
|
|
80
80
|
class HttpCrawler(Command):
|
|
81
81
|
meta_opts = {k: OPTS[k] for k in OPTS_HTTP_CRAWLERS}
|
|
82
|
-
|
|
82
|
+
input_types = [URL]
|
|
83
83
|
output_types = [Url]
|
|
84
84
|
|
|
85
85
|
|
|
86
86
|
class HttpFuzzer(Command):
|
|
87
87
|
meta_opts = {k: OPTS[k] for k in OPTS_HTTP_FUZZERS}
|
|
88
|
-
|
|
88
|
+
input_types = [URL]
|
|
89
89
|
output_types = [Url]
|
|
90
90
|
|
|
91
91
|
|
|
@@ -99,22 +99,22 @@ class Recon(Command):
|
|
|
99
99
|
|
|
100
100
|
|
|
101
101
|
class ReconDns(Recon):
|
|
102
|
-
|
|
102
|
+
input_types = [HOST]
|
|
103
103
|
output_types = [Subdomain]
|
|
104
104
|
|
|
105
105
|
|
|
106
106
|
class ReconUser(Recon):
|
|
107
|
-
|
|
107
|
+
input_types = [USERNAME]
|
|
108
108
|
output_types = [UserAccount]
|
|
109
109
|
|
|
110
110
|
|
|
111
111
|
class ReconIp(Recon):
|
|
112
|
-
|
|
112
|
+
input_types = [CIDR_RANGE]
|
|
113
113
|
output_types = [Ip]
|
|
114
114
|
|
|
115
115
|
|
|
116
116
|
class ReconPort(Recon):
|
|
117
|
-
|
|
117
|
+
input_types = [IP]
|
|
118
118
|
output_types = [Port]
|
|
119
119
|
|
|
120
120
|
|
|
@@ -434,15 +434,15 @@ class Vuln(Command):
|
|
|
434
434
|
|
|
435
435
|
|
|
436
436
|
class VulnHttp(Vuln):
|
|
437
|
-
|
|
437
|
+
input_types = [HOST]
|
|
438
438
|
|
|
439
439
|
|
|
440
440
|
class VulnCode(Vuln):
|
|
441
|
-
|
|
441
|
+
input_types = [PATH]
|
|
442
442
|
|
|
443
443
|
|
|
444
444
|
class VulnMulti(Vuln):
|
|
445
|
-
|
|
445
|
+
input_types = [HOST]
|
|
446
446
|
output_types = [Vulnerability]
|
|
447
447
|
|
|
448
448
|
|
|
@@ -451,7 +451,7 @@ class VulnMulti(Vuln):
|
|
|
451
451
|
#--------------#
|
|
452
452
|
|
|
453
453
|
class Tagger(Command):
|
|
454
|
-
|
|
454
|
+
input_types = [URL]
|
|
455
455
|
output_types = [Tag]
|
|
456
456
|
|
|
457
457
|
#----------------#
|