secator 0.12.0__tar.gz → 0.13.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.12.0 → secator-0.13.0}/.docker/Dockerfile.alpine +2 -0
- {secator-0.12.0 → secator-0.13.0}/.docker/Dockerfile.arch +2 -2
- {secator-0.12.0 → secator-0.13.0}/.docker/Dockerfile.debian +2 -2
- {secator-0.12.0 → secator-0.13.0}/.docker/Dockerfile.kali +2 -2
- {secator-0.12.0 → secator-0.13.0}/.docker/Dockerfile.osx +2 -2
- {secator-0.12.0 → secator-0.13.0}/.docker/Dockerfile.ubuntu +2 -2
- {secator-0.12.0 → secator-0.13.0}/CHANGELOG.md +12 -0
- {secator-0.12.0 → secator-0.13.0}/PKG-INFO +1 -1
- {secator-0.12.0 → secator-0.13.0}/pyproject.toml +1 -1
- {secator-0.12.0 → secator-0.13.0}/secator/cli.py +174 -65
- {secator-0.12.0 → secator-0.13.0}/secator/configs/workflows/host_recon.yaml +11 -2
- secator-0.13.0/secator/configs/workflows/port_scan.yaml +39 -0
- {secator-0.12.0 → secator-0.13.0}/secator/configs/workflows/url_dirsearch.yaml +5 -0
- {secator-0.12.0 → secator-0.13.0}/secator/definitions.py +0 -4
- {secator-0.12.0 → secator-0.13.0}/secator/installer.py +29 -15
- {secator-0.12.0 → secator-0.13.0}/secator/runners/_base.py +2 -1
- {secator-0.12.0 → secator-0.13.0}/secator/runners/_helpers.py +13 -2
- {secator-0.12.0 → secator-0.13.0}/secator/runners/command.py +2 -1
- {secator-0.12.0 → secator-0.13.0}/secator/tasks/_categories.py +2 -2
- {secator-0.12.0 → secator-0.13.0}/secator/tasks/arjun.py +2 -1
- {secator-0.12.0 → secator-0.13.0}/secator/tasks/bbot.py +30 -4
- {secator-0.12.0 → secator-0.13.0}/secator/tasks/bup.py +2 -1
- {secator-0.12.0 → secator-0.13.0}/secator/tasks/cariddi.py +15 -3
- {secator-0.12.0 → secator-0.13.0}/secator/tasks/dalfox.py +2 -1
- {secator-0.12.0 → secator-0.13.0}/secator/tasks/dirsearch.py +1 -1
- {secator-0.12.0 → secator-0.13.0}/secator/tasks/dnsx.py +2 -1
- {secator-0.12.0 → secator-0.13.0}/secator/tasks/dnsxbrute.py +2 -1
- {secator-0.12.0 → secator-0.13.0}/secator/tasks/feroxbuster.py +3 -2
- {secator-0.12.0 → secator-0.13.0}/secator/tasks/ffuf.py +2 -1
- {secator-0.12.0 → secator-0.13.0}/secator/tasks/gau.py +2 -1
- {secator-0.12.0 → secator-0.13.0}/secator/tasks/gitleaks.py +4 -3
- {secator-0.12.0 → secator-0.13.0}/secator/tasks/gospider.py +3 -2
- {secator-0.12.0 → secator-0.13.0}/secator/tasks/grype.py +1 -0
- {secator-0.12.0 → secator-0.13.0}/secator/tasks/h8mail.py +2 -1
- {secator-0.12.0 → secator-0.13.0}/secator/tasks/httpx.py +3 -2
- {secator-0.12.0 → secator-0.13.0}/secator/tasks/katana.py +4 -3
- {secator-0.12.0 → secator-0.13.0}/secator/tasks/maigret.py +1 -1
- {secator-0.12.0 → secator-0.13.0}/secator/tasks/mapcidr.py +2 -1
- {secator-0.12.0 → secator-0.13.0}/secator/tasks/msfconsole.py +4 -3
- {secator-0.12.0 → secator-0.13.0}/secator/tasks/naabu.py +4 -2
- {secator-0.12.0 → secator-0.13.0}/secator/tasks/nuclei.py +15 -9
- {secator-0.12.0 → secator-0.13.0}/secator/tasks/searchsploit.py +3 -2
- {secator-0.12.0 → secator-0.13.0}/secator/tasks/subfinder.py +2 -1
- {secator-0.12.0 → secator-0.13.0}/secator/tasks/testssl.py +4 -3
- {secator-0.12.0 → secator-0.13.0}/secator/tasks/trivy.py +2 -2
- {secator-0.12.0 → secator-0.13.0}/secator/tasks/wafw00f.py +2 -1
- {secator-0.12.0 → secator-0.13.0}/secator/tasks/wpprobe.py +2 -1
- {secator-0.12.0 → secator-0.13.0}/secator/tasks/wpscan.py +6 -3
- {secator-0.12.0 → secator-0.13.0}/tests/integration/test_tasks.py +8 -1
- {secator-0.12.0 → secator-0.13.0}/.docker/build_all.sh +0 -0
- {secator-0.12.0 → secator-0.13.0}/.dockerignore +0 -0
- {secator-0.12.0 → secator-0.13.0}/.flake8 +0 -0
- {secator-0.12.0 → secator-0.13.0}/.gitignore +0 -0
- {secator-0.12.0 → secator-0.13.0}/CONTRIBUTING.md +0 -0
- {secator-0.12.0 → secator-0.13.0}/Dockerfile +0 -0
- {secator-0.12.0 → secator-0.13.0}/LICENSE +0 -0
- {secator-0.12.0 → secator-0.13.0}/README.md +0 -0
- {secator-0.12.0 → secator-0.13.0}/SECURITY.md +0 -0
- {secator-0.12.0 → secator-0.13.0}/cloudbuild.yaml +0 -0
- {secator-0.12.0 → secator-0.13.0}/helm/.helmignore +0 -0
- {secator-0.12.0 → secator-0.13.0}/helm/Chart.yaml +0 -0
- {secator-0.12.0 → secator-0.13.0}/helm/templates/redis-service.yaml +0 -0
- {secator-0.12.0 → secator-0.13.0}/helm/templates/redis.yaml +0 -0
- {secator-0.12.0 → secator-0.13.0}/helm/templates/secator-manager.yaml +0 -0
- {secator-0.12.0 → secator-0.13.0}/helm/templates/secator-worker.yaml +0 -0
- {secator-0.12.0 → secator-0.13.0}/helm/values.yaml +0 -0
- {secator-0.12.0 → secator-0.13.0}/scripts/download_cves.sh +0 -0
- {secator-0.12.0 → secator-0.13.0}/scripts/install.sh +0 -0
- {secator-0.12.0 → secator-0.13.0}/scripts/install_asciinema.sh +0 -0
- {secator-0.12.0 → secator-0.13.0}/scripts/install_go.sh +0 -0
- {secator-0.12.0 → secator-0.13.0}/scripts/install_ruby.sh +0 -0
- {secator-0.12.0 → secator-0.13.0}/scripts/msf/exploit_cve.rc +0 -0
- {secator-0.12.0 → secator-0.13.0}/scripts/msf/ftp_anonymous.rc +0 -0
- {secator-0.12.0 → secator-0.13.0}/scripts/msf/ftp_version.rc +0 -0
- {secator-0.12.0 → secator-0.13.0}/scripts/msf/ftp_vsftpd_234_backdoor.rc +0 -0
- {secator-0.12.0 → secator-0.13.0}/scripts/msf/redis.rc +0 -0
- {secator-0.12.0 → secator-0.13.0}/scripts/stories/STORY.md +0 -0
- {secator-0.12.0 → secator-0.13.0}/scripts/stories/aliases.sh +0 -0
- {secator-0.12.0 → secator-0.13.0}/scripts/stories/demo.sh +0 -0
- {secator-0.12.0 → secator-0.13.0}/scripts/stories/fmt.sh +0 -0
- {secator-0.12.0 → secator-0.13.0}/scripts/stories/input.sh +0 -0
- {secator-0.12.0 → secator-0.13.0}/scripts/stories/pipe.sh +0 -0
- {secator-0.12.0 → secator-0.13.0}/scripts/stories/short_demo.sh +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/.gitignore +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/__init__.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/celery.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/celery_signals.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/celery_utils.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/config.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/configs/__init__.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/configs/profiles/__init__.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/configs/profiles/aggressive.yaml +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/configs/profiles/default.yaml +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/configs/profiles/stealth.yaml +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/configs/scans/__init__.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/configs/scans/domain.yaml +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/configs/scans/host.yaml +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/configs/scans/network.yaml +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/configs/scans/subdomain.yaml +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/configs/scans/url.yaml +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/configs/workflows/__init__.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/configs/workflows/cidr_recon.yaml +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/configs/workflows/code_scan.yaml +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/configs/workflows/subdomain_recon.yaml +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/configs/workflows/url_bypass.yaml +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/configs/workflows/url_crawl.yaml +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/configs/workflows/url_fuzz.yaml +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/configs/workflows/url_nuclei.yaml +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/configs/workflows/url_params_fuzz.yaml +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/configs/workflows/url_vuln.yaml +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/configs/workflows/user_hunt.yaml +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/configs/workflows/wordpress.yaml +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/decorators.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/exporters/__init__.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/exporters/_base.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/exporters/console.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/exporters/csv.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/exporters/gdrive.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/exporters/json.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/exporters/table.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/exporters/txt.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/hooks/__init__.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/hooks/gcs.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/hooks/mongodb.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/output_types/__init__.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/output_types/_base.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/output_types/certificate.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/output_types/error.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/output_types/exploit.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/output_types/info.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/output_types/ip.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/output_types/port.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/output_types/progress.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/output_types/record.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/output_types/stat.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/output_types/state.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/output_types/subdomain.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/output_types/tag.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/output_types/target.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/output_types/url.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/output_types/user_account.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/output_types/vulnerability.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/output_types/warning.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/report.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/rich.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/runners/__init__.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/runners/celery.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/runners/scan.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/runners/task.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/runners/workflow.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/scans/__init__.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/serializers/__init__.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/serializers/dataclass.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/serializers/json.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/serializers/regex.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/tasks/__init__.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/tasks/fping.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/tasks/gf.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/tasks/nmap.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/template.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/thread.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/utils.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/utils_test.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/secator/workflows/__init__.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/tests/__init__.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/tests/fixtures/h8mail_breach.txt +0 -0
- {secator-0.12.0 → secator-0.13.0}/tests/fixtures/ls.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/tests/fixtures/msfconsole_input.rc +0 -0
- {secator-0.12.0 → secator-0.13.0}/tests/fixtures/nmap_output.xml +0 -0
- {secator-0.12.0 → secator-0.13.0}/tests/integration/__init__.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/tests/integration/inputs.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/tests/integration/outputs.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/tests/integration/setup.sh +0 -0
- {secator-0.12.0 → secator-0.13.0}/tests/integration/teardown.sh +0 -0
- {secator-0.12.0 → secator-0.13.0}/tests/integration/test_addons.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/tests/integration/test_celery.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/tests/integration/test_helpers.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/tests/integration/test_scans.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/tests/integration/test_worker.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/tests/integration/test_workflows.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/tests/integration/wordlist.txt +0 -0
- {secator-0.12.0 → secator-0.13.0}/tests/integration/wordlist_dns.txt +0 -0
- {secator-0.12.0 → secator-0.13.0}/tests/integration/wordpress_toolbox/Dockerfile +0 -0
- {secator-0.12.0 → secator-0.13.0}/tests/integration/wordpress_toolbox/Makefile +0 -0
- {secator-0.12.0 → secator-0.13.0}/tests/performance/__init__.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/tests/performance/loadtester.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/tests/performance/test_worker.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/tests/unit/__init__.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/tests/unit/test_celery.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/tests/unit/test_cli.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/tests/unit/test_command.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/tests/unit/test_config.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/tests/unit/test_offline.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/tests/unit/test_runners.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/tests/unit/test_scans.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/tests/unit/test_serializers.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/tests/unit/test_tasks.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/tests/unit/test_tasks_categories.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/tests/unit/test_template.py +0 -0
- {secator-0.12.0 → secator-0.13.0}/tests/unit/test_utils.py +0 -0
|
@@ -21,6 +21,7 @@ RUN pipx install --pip-args="--no-cache-dir" . && \
|
|
|
21
21
|
|
|
22
22
|
FROM python:3.12-alpine
|
|
23
23
|
ARG flavor=full
|
|
24
|
+
ARG build_from_source=false
|
|
24
25
|
ENV TERM="xterm-256color"
|
|
25
26
|
ENV PATH="${PATH}:/root/.local/bin"
|
|
26
27
|
ENV GOBIN="/root/.local/bin"
|
|
@@ -29,5 +30,6 @@ RUN apk add --no-cache \
|
|
|
29
30
|
flock \
|
|
30
31
|
pipx \
|
|
31
32
|
sudo
|
|
33
|
+
RUN if [ "$build_from_source" = "true" ]; then secator config set security.force_source_install 1; fi
|
|
32
34
|
RUN if [ "$flavor" != "lite" ]; then secator install tools --cleanup --fail-fast; fi
|
|
33
35
|
ENTRYPOINT ["secator"]
|
|
@@ -31,6 +31,6 @@ RUN pipx install . && \
|
|
|
31
31
|
secator install addons mongodb && \
|
|
32
32
|
secator install addons redis && \
|
|
33
33
|
secator install addons dev
|
|
34
|
-
RUN secator config set security.force_source_install
|
|
35
|
-
RUN secator install tools --cleanup --fail-fast
|
|
34
|
+
RUN if [ "$build_from_source" = "true" ]; then secator config set security.force_source_install 1; fi
|
|
35
|
+
RUN if [ "$flavor" != "lite" ]; then secator install tools --cleanup --fail-fast; fi
|
|
36
36
|
ENTRYPOINT ["secator"]
|
|
@@ -33,6 +33,6 @@ RUN pipx install . && \
|
|
|
33
33
|
secator install addons redis && \
|
|
34
34
|
secator install addons dev
|
|
35
35
|
RUN secator install langs go
|
|
36
|
-
RUN secator config set security.force_source_install
|
|
37
|
-
RUN secator install tools --cleanup --fail-fast
|
|
36
|
+
RUN if [ "$build_from_source" = "true" ]; then secator config set security.force_source_install 1; fi
|
|
37
|
+
RUN if [ "$flavor" != "lite" ]; then secator install tools --cleanup --fail-fast; fi
|
|
38
38
|
ENTRYPOINT ["secator"]
|
|
@@ -32,6 +32,6 @@ RUN pipx install . && \
|
|
|
32
32
|
secator install addons mongodb && \
|
|
33
33
|
secator install addons redis && \
|
|
34
34
|
secator install addons dev
|
|
35
|
-
RUN secator config set security.force_source_install
|
|
36
|
-
RUN secator install tools --cleanup --fail-fast
|
|
35
|
+
RUN if [ "$build_from_source" = "true" ]; then secator config set security.force_source_install 1; fi
|
|
36
|
+
RUN if [ "$flavor" != "lite" ]; then secator install tools --cleanup --fail-fast; fi
|
|
37
37
|
ENTRYPOINT ["secator"]
|
|
@@ -35,6 +35,6 @@ RUN pipx install . && \
|
|
|
35
35
|
secator install addons mongodb && \
|
|
36
36
|
secator install addons redis && \
|
|
37
37
|
secator install addons dev
|
|
38
|
-
RUN secator config set security.force_source_install
|
|
39
|
-
RUN secator install tools --cleanup --fail-fast
|
|
38
|
+
RUN if [ "$build_from_source" = "true" ]; then secator config set security.force_source_install 1; fi
|
|
39
|
+
RUN if [ "$flavor" != "lite" ]; then secator install tools --cleanup --fail-fast; fi
|
|
40
40
|
ENTRYPOINT ["secator"]
|
|
@@ -32,6 +32,6 @@ RUN pipx install . && \
|
|
|
32
32
|
secator install addons mongodb && \
|
|
33
33
|
secator install addons redis && \
|
|
34
34
|
secator install addons dev
|
|
35
|
-
RUN secator config set security.force_source_install
|
|
36
|
-
RUN secator install tools --cleanup --fail-fast
|
|
35
|
+
RUN if [ "$build_from_source" = "true" ]; then secator config set security.force_source_install 1; fi
|
|
36
|
+
RUN if [ "$flavor" != "lite" ]; then secator install tools --cleanup --fail-fast; fi
|
|
37
37
|
ENTRYPOINT ["secator"]
|
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.13.0](https://github.com/freelabz/secator/compare/v0.12.0...v0.13.0) (2025-04-29)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **core:** restore default task opts, improve workflows ([#560](https://github.com/freelabz/secator/issues/560)) ([4849d44](https://github.com/freelabz/secator/commit/4849d44448f52529380a6d9163a1b4db54114958))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* use distro.like() instead of distro.id() ([#604](https://github.com/freelabz/secator/issues/604)) ([15157d4](https://github.com/freelabz/secator/commit/15157d433a0c60292ed91bb26f513a10f15924c2))
|
|
14
|
+
|
|
3
15
|
## [0.12.0](https://github.com/freelabz/secator/compare/v0.11.1...v0.12.0) (2025-04-24)
|
|
4
16
|
|
|
5
17
|
|
|
@@ -37,7 +37,7 @@ 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
39
|
FINDING_TYPES_LOWER = [c.__name__.lower() for c in FINDING_TYPES]
|
|
40
|
-
CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help'])
|
|
40
|
+
CONTEXT_SETTINGS = dict(help_option_names=['-h', '-help', '--help'])
|
|
41
41
|
|
|
42
42
|
|
|
43
43
|
#-----#
|
|
@@ -46,15 +46,16 @@ CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help'])
|
|
|
46
46
|
|
|
47
47
|
|
|
48
48
|
@click.group(cls=OrderedGroup, invoke_without_command=True, context_settings=CONTEXT_SETTINGS)
|
|
49
|
-
@click.option('--version', '-version', is_flag=True, default=False)
|
|
49
|
+
@click.option('--version', '-version', '-v', is_flag=True, default=False)
|
|
50
|
+
@click.option('--quiet', '-quiet', '-q', is_flag=True, default=False)
|
|
50
51
|
@click.pass_context
|
|
51
|
-
def cli(ctx, version):
|
|
52
|
+
def cli(ctx, version, quiet):
|
|
52
53
|
"""Secator CLI."""
|
|
53
54
|
ctx.obj = {
|
|
54
55
|
'piped_input': S_ISFIFO(os.fstat(0).st_mode),
|
|
55
56
|
'piped_output': not sys.stdout.isatty()
|
|
56
57
|
}
|
|
57
|
-
if not ctx.obj['piped_output']:
|
|
58
|
+
if not ctx.obj['piped_output'] and not quiet:
|
|
58
59
|
console.print(ASCII, highlight=False)
|
|
59
60
|
if ctx.invoked_subcommand is None:
|
|
60
61
|
if version:
|
|
@@ -67,11 +68,16 @@ def cli(ctx, version):
|
|
|
67
68
|
# TASK #
|
|
68
69
|
#------#
|
|
69
70
|
|
|
70
|
-
@cli.group(aliases=['x', 't'])
|
|
71
|
+
@cli.group(aliases=['x', 't'], invoke_without_command=True)
|
|
72
|
+
@click.option('--list', '-list', is_flag=True, default=False)
|
|
71
73
|
@click.pass_context
|
|
72
|
-
def task(ctx):
|
|
74
|
+
def task(ctx, list=False):
|
|
73
75
|
"""Run a task."""
|
|
74
|
-
|
|
76
|
+
if list:
|
|
77
|
+
print("\n".join(sorted([t.__name__ for t in ALL_TASKS])))
|
|
78
|
+
return
|
|
79
|
+
if ctx.invoked_subcommand is None:
|
|
80
|
+
ctx.get_help()
|
|
75
81
|
|
|
76
82
|
|
|
77
83
|
for cls in ALL_TASKS:
|
|
@@ -83,11 +89,16 @@ for cls in ALL_TASKS:
|
|
|
83
89
|
#----------#
|
|
84
90
|
|
|
85
91
|
|
|
86
|
-
@cli.group(cls=OrderedGroup, aliases=['w'])
|
|
92
|
+
@cli.group(cls=OrderedGroup, aliases=['w'], invoke_without_command=True)
|
|
93
|
+
@click.option('--list', '-list', is_flag=True, default=False)
|
|
87
94
|
@click.pass_context
|
|
88
|
-
def workflow(ctx):
|
|
95
|
+
def workflow(ctx, list=False):
|
|
89
96
|
"""Run a workflow."""
|
|
90
|
-
|
|
97
|
+
if list:
|
|
98
|
+
print("\n".join(sorted([t.name for t in ALL_WORKFLOWS])))
|
|
99
|
+
return
|
|
100
|
+
if ctx.invoked_subcommand is None:
|
|
101
|
+
ctx.get_help()
|
|
91
102
|
|
|
92
103
|
|
|
93
104
|
for config in sorted(ALL_WORKFLOWS, key=lambda x: x['name']):
|
|
@@ -98,11 +109,16 @@ for config in sorted(ALL_WORKFLOWS, key=lambda x: x['name']):
|
|
|
98
109
|
# SCAN #
|
|
99
110
|
#------#
|
|
100
111
|
|
|
101
|
-
@cli.group(cls=OrderedGroup, aliases=['s'])
|
|
112
|
+
@cli.group(cls=OrderedGroup, aliases=['s'], invoke_without_command=True)
|
|
113
|
+
@click.option('--list', '-list', is_flag=True, default=False)
|
|
102
114
|
@click.pass_context
|
|
103
|
-
def scan(ctx):
|
|
115
|
+
def scan(ctx, list=False):
|
|
104
116
|
"""Run a scan."""
|
|
105
|
-
|
|
117
|
+
if list:
|
|
118
|
+
print("\n".join(sorted([t.name for t in ALL_SCANS])))
|
|
119
|
+
return
|
|
120
|
+
if ctx.invoked_subcommand is None:
|
|
121
|
+
ctx.get_help()
|
|
106
122
|
|
|
107
123
|
|
|
108
124
|
for config in sorted(ALL_SCANS, key=lambda x: x['name']):
|
|
@@ -860,13 +876,21 @@ def health(json, debug, strict):
|
|
|
860
876
|
import json as _json
|
|
861
877
|
print(_json.dumps(status))
|
|
862
878
|
|
|
879
|
+
# Print errors and warnings
|
|
880
|
+
error = False
|
|
881
|
+
for tool, info in status['tools'].items():
|
|
882
|
+
if not info['installed']:
|
|
883
|
+
console.print(Warning(message=f'{tool} is not installed.'))
|
|
884
|
+
error = True
|
|
885
|
+
elif info['outdated']:
|
|
886
|
+
message = (
|
|
887
|
+
f'{tool} is outdated (current:{info["version"]}, latest:{info["latest_version"]}).'
|
|
888
|
+
f' Run `secator install tools {tool}` to update it.'
|
|
889
|
+
)
|
|
890
|
+
console.print(Warning(message=message))
|
|
891
|
+
|
|
863
892
|
# Strict mode
|
|
864
893
|
if strict:
|
|
865
|
-
error = False
|
|
866
|
-
for tool, info in status['tools'].items():
|
|
867
|
-
if not info['installed']:
|
|
868
|
-
console.print(Error(message=f'{tool} is not installed.'))
|
|
869
|
-
error = True
|
|
870
894
|
if error:
|
|
871
895
|
sys.exit(1)
|
|
872
896
|
console.print(Info(message='Strict healthcheck passed !'))
|
|
@@ -1061,16 +1085,27 @@ def install_tools(cmds, cleanup, fail_fast):
|
|
|
1061
1085
|
if CONFIG.offline_mode:
|
|
1062
1086
|
console.print(Error(message='Cannot run this command in offline mode.'))
|
|
1063
1087
|
return
|
|
1088
|
+
tools = []
|
|
1064
1089
|
if cmds is not None:
|
|
1065
1090
|
cmds = cmds.split(',')
|
|
1066
|
-
|
|
1091
|
+
for cmd in cmds:
|
|
1092
|
+
if '==' in cmd:
|
|
1093
|
+
cmd, version = tuple(cmd.split('=='))
|
|
1094
|
+
else:
|
|
1095
|
+
cmd, version = cmd, None
|
|
1096
|
+
cls = next((cls for cls in ALL_TASKS if cls.__name__ == cmd), None)
|
|
1097
|
+
if cls:
|
|
1098
|
+
if version:
|
|
1099
|
+
cls.install_version = version
|
|
1100
|
+
tools.append(cls)
|
|
1101
|
+
else:
|
|
1102
|
+
console.print(Warning(message=f'Tool {cmd} is not supported or inexistent.'))
|
|
1067
1103
|
else:
|
|
1068
1104
|
tools = ALL_TASKS
|
|
1069
1105
|
tools.sort(key=lambda x: x.__name__)
|
|
1070
1106
|
return_code = 0
|
|
1071
1107
|
if not tools:
|
|
1072
|
-
|
|
1073
|
-
console.print(Error(message=f'No tools found for {cmd_str}.'))
|
|
1108
|
+
console.print(Error(message='No tools found for installing.'))
|
|
1074
1109
|
return
|
|
1075
1110
|
for ix, cls in enumerate(tools):
|
|
1076
1111
|
# with console.status(f'[bold yellow][{ix + 1}/{len(tools)}] Installing {cls.__name__} ...'):
|
|
@@ -1140,7 +1175,7 @@ def update(all):
|
|
|
1140
1175
|
cmd = cls.cmd.split(' ')[0]
|
|
1141
1176
|
version_flag = cls.get_version_flag()
|
|
1142
1177
|
info = get_version_info(cmd, version_flag, cls.install_github_handle)
|
|
1143
|
-
if not info['installed'] or info['
|
|
1178
|
+
if not info['installed'] or info['outdated'] or not info['latest_version']:
|
|
1144
1179
|
# with console.status(f'[bold yellow]Installing {cls.__name__} ...'):
|
|
1145
1180
|
status = ToolInstaller.install(cls)
|
|
1146
1181
|
if not status.is_ok():
|
|
@@ -1375,73 +1410,147 @@ def performance(tasks, workflows, scans, test):
|
|
|
1375
1410
|
@test.command()
|
|
1376
1411
|
@click.argument('name', type=str)
|
|
1377
1412
|
@click.option('--verbose', '-v', is_flag=True, default=False, help='Print verbose output')
|
|
1378
|
-
|
|
1379
|
-
|
|
1413
|
+
@click.option('--check', '-c', is_flag=True, default=False, help='Check task semantics only (no unit + integration tests)') # noqa: E501
|
|
1414
|
+
def task(name, verbose, check):
|
|
1415
|
+
"""Test a single task for semantics errors, and run unit + integration tests."""
|
|
1416
|
+
console.print(f'[bold gold3]:wrench: Testing task {name} ...[/]')
|
|
1380
1417
|
task = [task for task in ALL_TASKS if task.__name__ == name]
|
|
1381
1418
|
warnings = []
|
|
1419
|
+
errors = []
|
|
1382
1420
|
exit_code = 0
|
|
1383
1421
|
|
|
1384
1422
|
# Check if task is correctly registered
|
|
1385
|
-
check_error(task, 'Check task is registered', 'Task is not registered. Make sure there is no syntax errors in the task class definition.', warnings) # noqa: E501
|
|
1386
1423
|
task = task[0]
|
|
1387
1424
|
task_name = task.__name__
|
|
1388
1425
|
|
|
1389
1426
|
# Run install
|
|
1390
|
-
console.print(f'\n[bold gold3]:wrench: Running install tests for task {name} ...[/]') if verbose else None
|
|
1391
1427
|
cmd = f'secator install tools {task_name}'
|
|
1392
1428
|
ret_code = Command.execute(cmd, name='install', quiet=not verbose, cwd=ROOT_FOLDER)
|
|
1393
1429
|
version_info = task.get_version_info()
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1430
|
+
if verbose:
|
|
1431
|
+
console.print(f'Version info:\n{version_info}')
|
|
1432
|
+
status = version_info['status']
|
|
1433
|
+
check_test(
|
|
1434
|
+
version_info['installed'],
|
|
1435
|
+
'Check task is installed',
|
|
1436
|
+
'Failed to install command. Fix your installation command.',
|
|
1437
|
+
errors
|
|
1438
|
+
)
|
|
1439
|
+
check_test(
|
|
1440
|
+
any(cmd for cmd in [task.install_cmd, task.install_github_handle]),
|
|
1441
|
+
'Check task installation command is defined',
|
|
1442
|
+
'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
|
+
errors
|
|
1444
|
+
)
|
|
1445
|
+
check_test(
|
|
1446
|
+
version_info['version'],
|
|
1447
|
+
'Check task version can be fetched',
|
|
1448
|
+
'Failed to detect current version. Consider updating your `version_flag` class attribute.',
|
|
1449
|
+
warnings,
|
|
1450
|
+
warn=True
|
|
1451
|
+
)
|
|
1452
|
+
check_test(
|
|
1453
|
+
status != 'latest unknown',
|
|
1454
|
+
'Check latest version',
|
|
1455
|
+
'Failed to detect latest version.',
|
|
1456
|
+
warnings,
|
|
1457
|
+
warn=True
|
|
1458
|
+
)
|
|
1459
|
+
check_test(
|
|
1460
|
+
not version_info['outdated'],
|
|
1461
|
+
'Check task version is up to date',
|
|
1462
|
+
f'Task is not up to date (current version: {version_info["version"]}, latest: {version_info["latest_version"]}). Consider updating your `install_version` class attribute.', # noqa: E501
|
|
1463
|
+
warnings,
|
|
1464
|
+
warn=True
|
|
1465
|
+
)
|
|
1397
1466
|
|
|
1398
1467
|
# Run task-specific tests
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1468
|
+
check_test(
|
|
1469
|
+
task.__doc__,
|
|
1470
|
+
'Check task description is set (cls.__doc__)',
|
|
1471
|
+
'Task has no description (class docstring).',
|
|
1472
|
+
errors
|
|
1473
|
+
)
|
|
1474
|
+
check_test(
|
|
1475
|
+
task.cmd,
|
|
1476
|
+
'Check task command is set (cls.cmd)',
|
|
1477
|
+
'Task has no cmd attribute.',
|
|
1478
|
+
errors
|
|
1479
|
+
)
|
|
1480
|
+
check_test(
|
|
1481
|
+
task.input_type,
|
|
1482
|
+
'Check task input type is set (cls.input_type)',
|
|
1483
|
+
'Task has no input_type attribute.',
|
|
1484
|
+
warnings,
|
|
1485
|
+
warn=True
|
|
1486
|
+
)
|
|
1487
|
+
check_test(
|
|
1488
|
+
task.output_types,
|
|
1489
|
+
'Check task output types is set (cls.output_types)',
|
|
1490
|
+
'Task has no output_types attribute. Consider setting some so that secator can load your task outputs.',
|
|
1491
|
+
warnings,
|
|
1492
|
+
warn=True
|
|
1493
|
+
)
|
|
1494
|
+
check_test(
|
|
1495
|
+
task.install_version,
|
|
1496
|
+
'Check task install_version is set (cls.install_version)',
|
|
1497
|
+
'Task has no install_version attribute. Consider setting it to pin the tool version and ensure it does not break in the future.', # noqa: E501
|
|
1498
|
+
warnings,
|
|
1499
|
+
warn=True
|
|
1500
|
+
)
|
|
1501
|
+
|
|
1502
|
+
if not check:
|
|
1503
|
+
|
|
1504
|
+
# Run unit tests
|
|
1505
|
+
cmd = f'secator test unit --tasks {name}'
|
|
1506
|
+
ret_code = run_test(cmd, exit=False, verbose=verbose)
|
|
1507
|
+
check_test(
|
|
1508
|
+
ret_code == 0,
|
|
1509
|
+
'Check unit tests pass',
|
|
1510
|
+
'Unit tests failed.',
|
|
1511
|
+
errors
|
|
1512
|
+
)
|
|
1513
|
+
|
|
1514
|
+
# Run integration tests
|
|
1515
|
+
cmd = f'secator test integration --tasks {name}'
|
|
1516
|
+
ret_code = run_test(cmd, exit=False, verbose=verbose)
|
|
1517
|
+
check_test(
|
|
1518
|
+
ret_code == 0,
|
|
1519
|
+
'Check integration tests pass',
|
|
1520
|
+
'Integration tests failed.',
|
|
1521
|
+
errors
|
|
1522
|
+
)
|
|
1428
1523
|
|
|
1429
1524
|
# Exit with exit code
|
|
1430
|
-
exit_code = 1 if len(
|
|
1525
|
+
exit_code = 1 if len(errors) > 0 else 0
|
|
1431
1526
|
if exit_code == 0:
|
|
1432
|
-
console.print(f':tada: Task {name} tests passed !
|
|
1527
|
+
console.print(f':tada: Task {name} tests passed !', style='bold green')
|
|
1433
1528
|
else:
|
|
1434
|
-
console.print(
|
|
1529
|
+
console.print('\n[bold gold3]Errors:[/]')
|
|
1530
|
+
for error in errors:
|
|
1531
|
+
console.print(error)
|
|
1532
|
+
console.print(Error(message=f'Task {name} tests failed. Please fix the issues above.'))
|
|
1435
1533
|
|
|
1534
|
+
if warnings:
|
|
1535
|
+
console.print('\n[bold gold3]Warnings:[/]')
|
|
1536
|
+
for warning in warnings:
|
|
1537
|
+
console.print(warning)
|
|
1538
|
+
|
|
1539
|
+
console.print("\n")
|
|
1436
1540
|
sys.exit(exit_code)
|
|
1437
1541
|
|
|
1438
1542
|
|
|
1439
|
-
def
|
|
1543
|
+
def check_test(condition, message, fail_message, results=[], warn=False):
|
|
1440
1544
|
console.print(f'[bold magenta]:zap: {message} ...[/]', end='')
|
|
1441
1545
|
if not condition:
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1546
|
+
if not warn:
|
|
1547
|
+
error = Error(message=fail_message)
|
|
1548
|
+
console.print(' [bold red]FAILED[/]', style='dim')
|
|
1549
|
+
results.append(error)
|
|
1550
|
+
else:
|
|
1551
|
+
warning = Warning(message=fail_message)
|
|
1552
|
+
console.print(' [bold yellow]WARNING[/]', style='dim')
|
|
1553
|
+
results.append(warning)
|
|
1445
1554
|
else:
|
|
1446
1555
|
console.print(' [bold green]OK[/]', style='dim')
|
|
1447
1556
|
return True
|
|
@@ -7,10 +7,19 @@ input_types:
|
|
|
7
7
|
- host
|
|
8
8
|
- cidr_range
|
|
9
9
|
tasks:
|
|
10
|
+
naabu:
|
|
11
|
+
description: Find open ports
|
|
12
|
+
ports: "-" # scan all ports
|
|
10
13
|
nmap:
|
|
11
14
|
description: Search for vulnerabilities on open ports
|
|
12
|
-
|
|
13
|
-
|
|
15
|
+
version_detection: True
|
|
16
|
+
script: vulners
|
|
17
|
+
targets_:
|
|
18
|
+
- port.host
|
|
19
|
+
- target.name
|
|
20
|
+
ports_:
|
|
21
|
+
- port.port
|
|
22
|
+
ports: "-" # default if no port found by naabu
|
|
14
23
|
_group/1:
|
|
15
24
|
httpx:
|
|
16
25
|
description: Probe HTTP services on open ports
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
type: workflow
|
|
2
|
+
name: port_scan
|
|
3
|
+
alias: pscan
|
|
4
|
+
description: Port scan
|
|
5
|
+
tags: [recon, network, http, vuln]
|
|
6
|
+
input_types:
|
|
7
|
+
- host
|
|
8
|
+
- cidr_range
|
|
9
|
+
tasks:
|
|
10
|
+
naabu:
|
|
11
|
+
description: Find open ports
|
|
12
|
+
skip_host_discovery: True
|
|
13
|
+
ports: "-" # scan all ports
|
|
14
|
+
nmap:
|
|
15
|
+
description: Search for vulnerabilities on open ports
|
|
16
|
+
skip_host_discovery: True
|
|
17
|
+
version_detection: True
|
|
18
|
+
targets_: port.host
|
|
19
|
+
ports_: port.port
|
|
20
|
+
_group:
|
|
21
|
+
searchsploit:
|
|
22
|
+
description: Search for related exploits
|
|
23
|
+
targets_:
|
|
24
|
+
- type: port
|
|
25
|
+
field: '{host}~{service_name}'
|
|
26
|
+
condition: item._source.startswith('nmap') and len(item.service_name.split('/')) > 1
|
|
27
|
+
httpx:
|
|
28
|
+
description: Probe HTTP services on open ports
|
|
29
|
+
targets_:
|
|
30
|
+
- type: port
|
|
31
|
+
field: '{host}:{port}'
|
|
32
|
+
condition: item._source.startswith('nmap')
|
|
33
|
+
results:
|
|
34
|
+
- type: port
|
|
35
|
+
|
|
36
|
+
- type: url
|
|
37
|
+
condition: item.status_code != 0
|
|
38
|
+
|
|
39
|
+
- type: vulnerability
|
|
@@ -23,10 +23,6 @@ ASCII = rf"""
|
|
|
23
23
|
DEBUG = CONFIG.debug.level
|
|
24
24
|
DEBUG_COMPONENT = CONFIG.debug.component.split(',')
|
|
25
25
|
|
|
26
|
-
# Default tasks settings
|
|
27
|
-
DEFAULT_NUCLEI_FLAGS = os.environ.get('DEFAULT_NUCLEI_FLAGS', '-stats -sj -si 20 -hm -or')
|
|
28
|
-
DEFAULT_FEROXBUSTER_FLAGS = os.environ.get('DEFAULT_FEROXBUSTER_FLAGS', '--auto-bail --no-state')
|
|
29
|
-
|
|
30
26
|
# Constants
|
|
31
27
|
OPT_NOT_SUPPORTED = -1
|
|
32
28
|
OPT_PIPE_INPUT = -1
|