secator 0.10.1a7__tar.gz → 0.10.1a8__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.10.1a7 → secator-0.10.1a8}/PKG-INFO +1 -1
- {secator-0.10.1a7 → secator-0.10.1a8}/pyproject.toml +1 -1
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/celery.py +17 -31
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/celery_utils.py +2 -2
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/configs/workflows/cidr_recon.yaml +1 -1
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/configs/workflows/host_recon.yaml +14 -21
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/runners/_base.py +70 -41
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/runners/scan.py +2 -2
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/runners/task.py +11 -13
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/runners/workflow.py +16 -10
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/tasks/naabu.py +1 -1
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/tasks/nmap.py +71 -5
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/tasks/wpscan.py +1 -1
- {secator-0.10.1a7 → secator-0.10.1a8}/tests/integration/test_celery.py +5 -2
- {secator-0.10.1a7 → secator-0.10.1a8}/tests/integration/test_worker.py +2 -2
- {secator-0.10.1a7 → secator-0.10.1a8}/tests/unit/test_celery.py +11 -3
- secator-0.10.1a7/secator/configs/workflows/port_scan.yaml +0 -38
- {secator-0.10.1a7 → secator-0.10.1a8}/.docker/Dockerfile.alpine +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/.docker/Dockerfile.arch +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/.docker/Dockerfile.debian +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/.docker/Dockerfile.kali +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/.docker/Dockerfile.osx +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/.docker/Dockerfile.ubuntu +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/.docker/build_all.sh +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/.dockerignore +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/.flake8 +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/.gitignore +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/CHANGELOG.md +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/CONTRIBUTING.md +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/Dockerfile +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/LICENSE +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/README.md +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/SECURITY.md +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/cloudbuild.yaml +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/helm/.helmignore +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/helm/Chart.yaml +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/helm/templates/redis-service.yaml +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/helm/templates/redis.yaml +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/helm/templates/secator-manager.yaml +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/helm/templates/secator-worker.yaml +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/helm/values.yaml +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/scripts/download_cves.sh +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/scripts/install.sh +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/scripts/install_asciinema.sh +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/scripts/install_go.sh +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/scripts/install_ruby.sh +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/scripts/msf/exploit_cve.rc +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/scripts/msf/ftp_anonymous.rc +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/scripts/msf/ftp_version.rc +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/scripts/msf/ftp_vsftpd_234_backdoor.rc +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/scripts/msf/redis.rc +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/scripts/stories/STORY.md +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/scripts/stories/aliases.sh +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/scripts/stories/demo.sh +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/scripts/stories/fmt.sh +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/scripts/stories/input.sh +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/scripts/stories/pipe.sh +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/scripts/stories/short_demo.sh +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/.gitignore +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/__init__.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/celery_signals.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/cli.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/config.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/configs/__init__.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/configs/profiles/__init__.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/configs/profiles/aggressive.yaml +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/configs/profiles/default.yaml +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/configs/profiles/stealth.yaml +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/configs/scans/__init__.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/configs/scans/domain.yaml +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/configs/scans/host.yaml +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/configs/scans/network.yaml +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/configs/scans/subdomain.yaml +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/configs/scans/url.yaml +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/configs/workflows/__init__.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/configs/workflows/code_scan.yaml +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/configs/workflows/subdomain_recon.yaml +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/configs/workflows/url_bypass.yaml +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/configs/workflows/url_crawl.yaml +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/configs/workflows/url_dirsearch.yaml +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/configs/workflows/url_fuzz.yaml +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/configs/workflows/url_nuclei.yaml +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/configs/workflows/url_vuln.yaml +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/configs/workflows/user_hunt.yaml +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/configs/workflows/wordpress.yaml +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/decorators.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/definitions.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/exporters/__init__.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/exporters/_base.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/exporters/console.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/exporters/csv.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/exporters/gdrive.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/exporters/json.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/exporters/table.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/exporters/txt.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/hooks/__init__.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/hooks/gcs.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/hooks/mongodb.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/installer.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/output_types/__init__.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/output_types/_base.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/output_types/error.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/output_types/exploit.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/output_types/info.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/output_types/ip.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/output_types/port.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/output_types/progress.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/output_types/record.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/output_types/stat.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/output_types/state.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/output_types/subdomain.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/output_types/tag.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/output_types/target.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/output_types/url.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/output_types/user_account.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/output_types/vulnerability.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/output_types/warning.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/report.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/rich.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/runners/__init__.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/runners/_helpers.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/runners/celery.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/runners/command.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/scans/__init__.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/serializers/__init__.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/serializers/dataclass.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/serializers/json.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/serializers/regex.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/tasks/__init__.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/tasks/_categories.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/tasks/bbot.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/tasks/bup.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/tasks/cariddi.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/tasks/dalfox.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/tasks/dirsearch.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/tasks/dnsx.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/tasks/dnsxbrute.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/tasks/feroxbuster.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/tasks/ffuf.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/tasks/fping.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/tasks/gau.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/tasks/gf.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/tasks/gospider.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/tasks/grype.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/tasks/h8mail.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/tasks/httpx.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/tasks/katana.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/tasks/maigret.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/tasks/mapcidr.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/tasks/msfconsole.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/tasks/nuclei.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/tasks/searchsploit.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/tasks/subfinder.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/template.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/thread.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/utils.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/utils_test.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/secator/workflows/__init__.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/tests/__init__.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/tests/fixtures/h8mail_breach.txt +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/tests/fixtures/ls.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/tests/fixtures/msfconsole_input.rc +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/tests/fixtures/nmap_output.xml +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/tests/integration/__init__.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/tests/integration/inputs.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/tests/integration/outputs.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/tests/integration/setup.sh +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/tests/integration/teardown.sh +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/tests/integration/test_addons.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/tests/integration/test_scans.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/tests/integration/test_tasks.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/tests/integration/test_tasks_categories.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/tests/integration/test_workflows.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/tests/integration/wordlist.txt +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/tests/integration/wordlist_dns.txt +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/tests/integration/wordpress_toolbox/Dockerfile +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/tests/integration/wordpress_toolbox/Makefile +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/tests/performance/__init__.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/tests/performance/loadtester.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/tests/performance/test_worker.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/tests/unit/__init__.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/tests/unit/test_cli.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/tests/unit/test_config.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/tests/unit/test_offline.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/tests/unit/test_runners.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/tests/unit/test_scans.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/tests/unit/test_serializers.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/tests/unit/test_tasks.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/tests/unit/test_tasks_categories.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/tests/unit/test_template.py +0 -0
- {secator-0.10.1a7 → secator-0.10.1a8}/tests/unit/test_utils.py +0 -0
|
@@ -170,8 +170,8 @@ def run_scan(self, args=[], kwargs={}):
|
|
|
170
170
|
def run_command(self, results, name, targets, opts={}):
|
|
171
171
|
if IN_CELERY_WORKER_PROCESS:
|
|
172
172
|
opts.update({'print_item': True, 'print_line': True, 'print_cmd': True})
|
|
173
|
-
routing_key = self.request.delivery_info['routing_key']
|
|
174
|
-
console.print(Info(message=f'Task "{name}" running with routing key "{routing_key}"'))
|
|
173
|
+
# routing_key = self.request.delivery_info['routing_key']
|
|
174
|
+
# console.print(Info(message=f'Task "{name}" running with routing key "{routing_key}"'))
|
|
175
175
|
|
|
176
176
|
# Flatten + dedupe + filter results
|
|
177
177
|
results = forward_results(results)
|
|
@@ -188,8 +188,7 @@ def run_command(self, results, name, targets, opts={}):
|
|
|
188
188
|
sync = not IN_CELERY_WORKER_PROCESS
|
|
189
189
|
task_cls = Task.get_task_class(name)
|
|
190
190
|
task = task_cls(targets, **opts)
|
|
191
|
-
task.
|
|
192
|
-
task.run_hooks('on_start')
|
|
191
|
+
task.mark_started()
|
|
193
192
|
update_state(self, task, force=True)
|
|
194
193
|
|
|
195
194
|
# Chunk task if needed
|
|
@@ -220,56 +219,43 @@ def forward_results(results):
|
|
|
220
219
|
results = results['results']
|
|
221
220
|
results = flatten(results)
|
|
222
221
|
results = deduplicate(results, attr='_uuid')
|
|
223
|
-
if IN_CELERY_WORKER_PROCESS:
|
|
224
|
-
console.print(Info(message=f'Forwarding {len(results)} results ...'))
|
|
225
222
|
return results
|
|
226
223
|
|
|
227
224
|
|
|
228
225
|
@app.task
|
|
229
|
-
def mark_runner_started(runner):
|
|
226
|
+
def mark_runner_started(runner, enable_hooks=True):
|
|
230
227
|
"""Mark a runner as started and run on_start hooks.
|
|
231
228
|
|
|
232
229
|
Args:
|
|
233
|
-
runner (Runner): Secator runner instance
|
|
230
|
+
runner (Runner): Secator runner instance.
|
|
231
|
+
enable_hooks (bool): Enable hooks.
|
|
234
232
|
|
|
235
233
|
Returns:
|
|
236
234
|
list: Runner results
|
|
237
235
|
"""
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
runner.
|
|
241
|
-
|
|
242
|
-
runner.run_hooks('on_start')
|
|
243
|
-
return runner.results
|
|
236
|
+
debug(f'Runner {runner.unique_name} has started, running mark_started', sub='celery')
|
|
237
|
+
runner.enable_hooks = enable_hooks
|
|
238
|
+
runner.mark_started()
|
|
239
|
+
return forward_results(runner.results)
|
|
244
240
|
|
|
245
241
|
|
|
246
242
|
@app.task
|
|
247
|
-
def
|
|
243
|
+
def mark_runner_completed(results, runner, enable_hooks=True):
|
|
248
244
|
"""Mark a runner as completed and run on_end hooks.
|
|
249
245
|
|
|
250
246
|
Args:
|
|
251
247
|
results (list): Task results
|
|
252
248
|
runner (Runner): Secator runner instance
|
|
249
|
+
enable_hooks (bool): Enable hooks.
|
|
253
250
|
|
|
254
251
|
Returns:
|
|
255
252
|
list: Final results
|
|
256
253
|
"""
|
|
257
|
-
|
|
258
|
-
console.print(Info(message=f'Marking runner {runner.unique_name} as completed'))
|
|
254
|
+
debug(f'Runner {runner.unique_name} has finished, running mark_completed', sub='celery')
|
|
259
255
|
results = forward_results(results)
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
if IN_CELERY_WORKER_PROCESS:
|
|
264
|
-
console.print(Info(message=f'Runner {runner.unique_name} is in sync mode, skipping final processing'))
|
|
265
|
-
return results
|
|
266
|
-
|
|
267
|
-
# Run final processing
|
|
268
|
-
runner.results = results
|
|
269
|
-
# if not runner.no_process:
|
|
270
|
-
# runner.mark_duplicates()
|
|
271
|
-
runner.log_results()
|
|
272
|
-
runner.run_hooks('on_end')
|
|
256
|
+
runner.enable_hooks = enable_hooks
|
|
257
|
+
[runner.add_result(item) for item in results]
|
|
258
|
+
runner.mark_completed()
|
|
273
259
|
return runner.results
|
|
274
260
|
|
|
275
261
|
|
|
@@ -331,6 +317,6 @@ def break_task(task, task_opts, results=[]):
|
|
|
331
317
|
# Build Celery workflow
|
|
332
318
|
workflow = chord(
|
|
333
319
|
tuple(sigs),
|
|
334
|
-
|
|
320
|
+
mark_runner_completed.s(runner=task).set(queue='results')
|
|
335
321
|
)
|
|
336
322
|
return workflow
|
|
@@ -144,7 +144,7 @@ class CeleryData(object):
|
|
|
144
144
|
_source='celery'
|
|
145
145
|
)
|
|
146
146
|
debug(f"Main task state: {result.id} - {result.state}", sub='celery.poll', verbose=True)
|
|
147
|
-
yield {'id': result.id, 'results': [main_task]}
|
|
147
|
+
yield {'id': result.id, 'state': result.state, 'results': [main_task]}
|
|
148
148
|
yield from CeleryData.get_all_data(result, ids_map)
|
|
149
149
|
|
|
150
150
|
if result.ready():
|
|
@@ -155,7 +155,7 @@ class CeleryData(object):
|
|
|
155
155
|
_source='celery'
|
|
156
156
|
)
|
|
157
157
|
debug(f"Final main task state: {result.id} - {result.state}", sub='celery.poll', verbose=True)
|
|
158
|
-
yield {'id': result.id, 'results': [main_task]}
|
|
158
|
+
yield {'id': result.id, 'state': result.state, 'results': [main_task]}
|
|
159
159
|
yield from CeleryData.get_all_data(result, ids_map)
|
|
160
160
|
break
|
|
161
161
|
except (KeyboardInterrupt, GreenletExit):
|
|
@@ -7,21 +7,23 @@ input_types:
|
|
|
7
7
|
- host
|
|
8
8
|
- cidr_range
|
|
9
9
|
tasks:
|
|
10
|
-
naabu:
|
|
11
|
-
description: Find open ports
|
|
12
10
|
nmap:
|
|
13
11
|
description: Search for vulnerabilities on open ports
|
|
14
12
|
skip_host_discovery: True
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
13
|
+
ports: "-" # scan all ports
|
|
14
|
+
_group/1:
|
|
15
|
+
httpx:
|
|
16
|
+
description: Probe HTTP services on open ports
|
|
17
|
+
targets_:
|
|
18
|
+
- type: port
|
|
19
|
+
field: '{host}:{port}'
|
|
20
|
+
searchsploit:
|
|
21
|
+
description: Search for related exploits
|
|
22
|
+
targets_:
|
|
23
|
+
- type: port
|
|
24
|
+
field: service_name
|
|
25
|
+
condition: len(item.service_name.split('/')) > 1
|
|
26
|
+
_group/2:
|
|
25
27
|
nuclei/network:
|
|
26
28
|
description: Scan network and SSL vulnerabilities
|
|
27
29
|
tags: [network, ssl]
|
|
@@ -32,12 +34,3 @@ tasks:
|
|
|
32
34
|
- type: url
|
|
33
35
|
field: url
|
|
34
36
|
condition: item.status_code != 0
|
|
35
|
-
results:
|
|
36
|
-
- type: port
|
|
37
|
-
condition: item._source.startswith('nmap')
|
|
38
|
-
|
|
39
|
-
- type: vulnerability
|
|
40
|
-
# condition: item.confidence == 'high'
|
|
41
|
-
|
|
42
|
-
- type: url
|
|
43
|
-
condition: item.status_code != 0
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import logging
|
|
3
|
-
import os
|
|
4
3
|
import sys
|
|
5
4
|
import uuid
|
|
6
5
|
from datetime import datetime
|
|
@@ -65,9 +64,6 @@ class Runner:
|
|
|
65
64
|
# Run hooks
|
|
66
65
|
enable_hooks = True
|
|
67
66
|
|
|
68
|
-
# Reports folder
|
|
69
|
-
reports_folder = None
|
|
70
|
-
|
|
71
67
|
def __init__(self, config, inputs=[], results=[], run_opts={}, hooks={}, validators={}, context={}):
|
|
72
68
|
self.uuids = []
|
|
73
69
|
self.results = []
|
|
@@ -98,6 +94,8 @@ class Runner:
|
|
|
98
94
|
self.no_poll = self.run_opts.get('no_poll', False)
|
|
99
95
|
self.quiet = self.run_opts.get('quiet', False)
|
|
100
96
|
self.started = False
|
|
97
|
+
self.enable_reports = self.run_opts.get('enable_reports', not self.sync)
|
|
98
|
+
self._reports_folder = self.run_opts.get('reports_folder', None)
|
|
101
99
|
|
|
102
100
|
# Runner process options
|
|
103
101
|
self.no_process = self.run_opts.get('no_process', False)
|
|
@@ -135,7 +133,7 @@ class Runner:
|
|
|
135
133
|
inputs, run_opts, errors = run_extractors(self.results, run_opts, inputs)
|
|
136
134
|
for error in errors:
|
|
137
135
|
self.add_result(error, print=True)
|
|
138
|
-
self.inputs = inputs
|
|
136
|
+
self.inputs = list(set(inputs))
|
|
139
137
|
|
|
140
138
|
# Debug
|
|
141
139
|
self.debug('Inputs', obj=self.inputs, sub='init')
|
|
@@ -146,16 +144,6 @@ class Runner:
|
|
|
146
144
|
exporters_str = self.run_opts.get('output') or self.default_exporters
|
|
147
145
|
self.exporters = self.resolve_exporters(exporters_str)
|
|
148
146
|
|
|
149
|
-
# Determine report folder
|
|
150
|
-
default_reports_folder_base = f'{CONFIG.dirs.reports}/{self.workspace_name}/{self.config.type}s'
|
|
151
|
-
_id = get_task_folder_id(default_reports_folder_base)
|
|
152
|
-
self.reports_folder = f'{default_reports_folder_base}/{_id}'
|
|
153
|
-
|
|
154
|
-
# Make reports folders
|
|
155
|
-
os.makedirs(self.reports_folder, exist_ok=True)
|
|
156
|
-
os.makedirs(f'{self.reports_folder}/.inputs', exist_ok=True)
|
|
157
|
-
os.makedirs(f'{self.reports_folder}/.outputs', exist_ok=True)
|
|
158
|
-
|
|
159
147
|
# Profiler
|
|
160
148
|
self.enable_profiler = self.run_opts.get('enable_profiler', False) and ADDONS_ENABLED['trace']
|
|
161
149
|
if self.enable_profiler:
|
|
@@ -260,6 +248,23 @@ class Runner:
|
|
|
260
248
|
'descr': self.config.description or '',
|
|
261
249
|
}
|
|
262
250
|
|
|
251
|
+
@property
|
|
252
|
+
def reports_folder(self):
|
|
253
|
+
if self._reports_folder and Path(self._reports_folder).exists():
|
|
254
|
+
return self._reports_folder
|
|
255
|
+
_base = f'{CONFIG.dirs.reports}/{self.workspace_name}/{self.config.type}s'
|
|
256
|
+
_id = get_task_folder_id(_base)
|
|
257
|
+
path = Path(f'{_base}/{_id}')
|
|
258
|
+
path_inputs = path / '.inputs'
|
|
259
|
+
path_outputs = path / '.outputs'
|
|
260
|
+
if not path.exists():
|
|
261
|
+
self.debug(f'Creating reports folder {path}')
|
|
262
|
+
path.mkdir(parents=True, exist_ok=True)
|
|
263
|
+
path_inputs.mkdir(exist_ok=True)
|
|
264
|
+
path_outputs.mkdir(exist_ok=True)
|
|
265
|
+
self._reports_folder = path.resolve()
|
|
266
|
+
return self._reports_folder
|
|
267
|
+
|
|
263
268
|
def run(self):
|
|
264
269
|
"""Run method.
|
|
265
270
|
|
|
@@ -275,16 +280,14 @@ class Runner:
|
|
|
275
280
|
OutputType: runner result.
|
|
276
281
|
"""
|
|
277
282
|
try:
|
|
278
|
-
|
|
279
|
-
self.
|
|
283
|
+
# If sync mode, set started
|
|
284
|
+
if self.sync:
|
|
285
|
+
self.mark_started()
|
|
280
286
|
|
|
281
|
-
# If any errors happened during
|
|
287
|
+
# If any errors happened during validation, exit
|
|
282
288
|
if self.errors:
|
|
283
289
|
yield from self.errors
|
|
284
|
-
|
|
285
|
-
return
|
|
286
|
-
self.log_results()
|
|
287
|
-
self.run_hooks('on_end')
|
|
290
|
+
self.mark_completed()
|
|
288
291
|
return
|
|
289
292
|
|
|
290
293
|
# Loop and process items
|
|
@@ -304,13 +307,13 @@ class Runner:
|
|
|
304
307
|
self.stop_celery_tasks()
|
|
305
308
|
yield from self.join_threads()
|
|
306
309
|
yield error
|
|
310
|
+
self.mark_completed()
|
|
307
311
|
|
|
308
312
|
finally:
|
|
309
|
-
if self.
|
|
310
|
-
|
|
311
|
-
self.
|
|
312
|
-
|
|
313
|
-
self.run_hooks('on_end')
|
|
313
|
+
if self.sync:
|
|
314
|
+
self.mark_completed()
|
|
315
|
+
if self.enable_reports:
|
|
316
|
+
self.export_reports()
|
|
314
317
|
|
|
315
318
|
def join_threads(self):
|
|
316
319
|
"""Wait for all running threads to complete."""
|
|
@@ -496,7 +499,6 @@ class Runner:
|
|
|
496
499
|
# Run workflow and get results
|
|
497
500
|
if self.sync:
|
|
498
501
|
self.print_item = False
|
|
499
|
-
self.started = True
|
|
500
502
|
results = workflow.apply().get()
|
|
501
503
|
yield from results
|
|
502
504
|
else:
|
|
@@ -508,6 +510,7 @@ class Runner:
|
|
|
508
510
|
)
|
|
509
511
|
if self.no_poll:
|
|
510
512
|
self.enable_hooks = False
|
|
513
|
+
self.enable_reports = False
|
|
511
514
|
self.no_process = True
|
|
512
515
|
return
|
|
513
516
|
results = CeleryData.iter_results(
|
|
@@ -677,30 +680,53 @@ class Runner:
|
|
|
677
680
|
self.debug('', obj={name + ' [dim yellow]->[/] ' + fun: 'registered (user)'}, sub='validators')
|
|
678
681
|
self.validators[key].extend(user_validators)
|
|
679
682
|
|
|
683
|
+
def mark_started(self):
|
|
684
|
+
"""Mark runner as started."""
|
|
685
|
+
if self.started:
|
|
686
|
+
return
|
|
687
|
+
self.started = True
|
|
688
|
+
self.start_time = datetime.fromtimestamp(time())
|
|
689
|
+
self.debug(f'started (sync: {self.sync}, hooks: {self.enable_hooks})')
|
|
690
|
+
self.log_start()
|
|
691
|
+
self.run_hooks('on_start')
|
|
692
|
+
|
|
693
|
+
def mark_completed(self):
|
|
694
|
+
"""Mark runner as completed."""
|
|
695
|
+
if self.done:
|
|
696
|
+
return
|
|
697
|
+
self.started = True
|
|
698
|
+
self.done = True
|
|
699
|
+
self.progress = 100
|
|
700
|
+
self.end_time = datetime.fromtimestamp(time())
|
|
701
|
+
self.debug(f'completed (sync: {self.sync}, reports: {self.enable_reports}, hooks: {self.enable_hooks})')
|
|
702
|
+
self.mark_duplicates()
|
|
703
|
+
self.run_hooks('on_end')
|
|
704
|
+
self.export_profiler()
|
|
705
|
+
self.log_results()
|
|
706
|
+
|
|
680
707
|
def log_start(self):
|
|
681
708
|
"""Log runner start."""
|
|
682
709
|
if not self.print_remote_info:
|
|
683
710
|
return
|
|
684
711
|
remote_str = 'starting' if self.sync else 'sent to Celery worker'
|
|
685
|
-
|
|
686
|
-
info = Info(message=f'{runner_name} {self.config.name} {remote_str}...', _source=self.unique_name)
|
|
712
|
+
info = Info(message=f'{self.config.type.capitalize()} {self.unique_name} {remote_str}...', _source=self.unique_name)
|
|
687
713
|
self._print_item(info)
|
|
688
714
|
|
|
689
715
|
def log_results(self):
|
|
690
716
|
"""Log runner results."""
|
|
691
|
-
self.
|
|
692
|
-
self.
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
else:
|
|
698
|
-
self.debug('', obj={self.__class__.__name__: self.status}, sub='status')
|
|
699
|
-
if self.exporters and not self.no_process:
|
|
717
|
+
info = Info(message=f'{self.config.type.capitalize()} {self.unique_name} finished with status {self.status} and found {len(self.self_findings)} findings', _source=self.unique_name) # noqa: E501
|
|
718
|
+
self._print_item(info)
|
|
719
|
+
|
|
720
|
+
def export_reports(self):
|
|
721
|
+
"""Export reports."""
|
|
722
|
+
if self.enable_reports and self.exporters and not self.no_process:
|
|
700
723
|
report = Report(self, exporters=self.exporters)
|
|
701
724
|
report.build()
|
|
702
725
|
report.send()
|
|
703
726
|
self.report = report
|
|
727
|
+
|
|
728
|
+
def export_profiler(self):
|
|
729
|
+
"""Export profiler."""
|
|
704
730
|
if self.enable_profiler:
|
|
705
731
|
self.profiler.stop()
|
|
706
732
|
profile_path = Path(self.reports_folder) / f'{self.unique_name}_profile.html'
|
|
@@ -858,13 +884,16 @@ class Runner:
|
|
|
858
884
|
|
|
859
885
|
# Check for state updates
|
|
860
886
|
if isinstance(item, State) and self.celery_result and item.task_id == self.celery_result.id:
|
|
861
|
-
self.debug(f'
|
|
887
|
+
self.debug(f'Sync runner state from remote: {item.state}')
|
|
862
888
|
if item.state in ['FAILURE', 'SUCCESS', 'REVOKED']:
|
|
863
889
|
self.started = True
|
|
864
890
|
self.done = True
|
|
891
|
+
self.progress = 100
|
|
892
|
+
self.end_time = datetime.fromtimestamp(time())
|
|
865
893
|
elif item.state in ['RUNNING']:
|
|
866
894
|
self.started = True
|
|
867
|
-
|
|
895
|
+
self.start_time = datetime.fromtimestamp(time())
|
|
896
|
+
self.end_time = None
|
|
868
897
|
self.last_updated_celery = item._timestamp
|
|
869
898
|
return
|
|
870
899
|
|
|
@@ -24,7 +24,7 @@ class Scan(Runner):
|
|
|
24
24
|
celery.Signature: Celery task signature.
|
|
25
25
|
"""
|
|
26
26
|
from celery import chain
|
|
27
|
-
from secator.celery import mark_runner_started,
|
|
27
|
+
from secator.celery import mark_runner_started, mark_runner_completed
|
|
28
28
|
from secator.template import TemplateLoader
|
|
29
29
|
|
|
30
30
|
scan_opts = self.config.options
|
|
@@ -52,5 +52,5 @@ class Scan(Runner):
|
|
|
52
52
|
return chain(
|
|
53
53
|
mark_runner_started.si(self).set(queue='results'),
|
|
54
54
|
*sigs,
|
|
55
|
-
|
|
55
|
+
mark_runner_completed.s(self).set(queue='results'),
|
|
56
56
|
)
|
|
@@ -24,7 +24,7 @@ class Task(Runner):
|
|
|
24
24
|
Returns:
|
|
25
25
|
celery.Signature: Celery task signature.
|
|
26
26
|
"""
|
|
27
|
-
from secator.celery import run_command
|
|
27
|
+
from secator.celery import run_command
|
|
28
28
|
|
|
29
29
|
# Get task class
|
|
30
30
|
task_cls = Task.get_task_class(self.config.name)
|
|
@@ -34,27 +34,25 @@ class Task(Runner):
|
|
|
34
34
|
opts.pop('output', None)
|
|
35
35
|
opts.pop('no_poll', False)
|
|
36
36
|
|
|
37
|
-
# Set
|
|
37
|
+
# Set output types
|
|
38
38
|
self.output_types = task_cls.output_types
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
|
|
40
|
+
# Set hooks and reports
|
|
41
|
+
self.enable_hooks = False # Celery will handle hooks
|
|
42
|
+
self.enable_reports = True # Task will handle reports
|
|
41
43
|
|
|
42
44
|
# Get hooks
|
|
43
45
|
hooks = self._hooks.get(Task, {})
|
|
44
46
|
opts['hooks'] = hooks
|
|
45
|
-
opts['context'] = self.context
|
|
47
|
+
opts['context'] = self.context.copy()
|
|
48
|
+
opts['reports_folder'] = str(self.reports_folder)
|
|
49
|
+
opts['enable_reports'] = False # Task will handle reports
|
|
46
50
|
|
|
47
51
|
# Create task signature
|
|
48
52
|
task_id = str(uuid.uuid4())
|
|
49
|
-
sig = run_command.
|
|
53
|
+
sig = run_command.si(self.results, self.config.name, self.inputs, opts).set(queue=task_cls.profile, task_id=task_id)
|
|
50
54
|
self.add_subtask(task_id, self.config.name, self.config.description or '')
|
|
51
|
-
|
|
52
|
-
# Build signature chain with lifecycle management
|
|
53
|
-
return chain(
|
|
54
|
-
mark_runner_started.si(self).set(queue='results'),
|
|
55
|
-
sig,
|
|
56
|
-
mark_runner_complete.s(self).set(queue='results'),
|
|
57
|
-
)
|
|
55
|
+
return chain(sig)
|
|
58
56
|
|
|
59
57
|
@staticmethod
|
|
60
58
|
def get_task_class(name):
|
|
@@ -27,13 +27,25 @@ class Workflow(Runner):
|
|
|
27
27
|
celery.Signature: Celery task signature.
|
|
28
28
|
"""
|
|
29
29
|
from celery import chain
|
|
30
|
-
from secator.celery import mark_runner_started,
|
|
30
|
+
from secator.celery import mark_runner_started, mark_runner_completed
|
|
31
31
|
|
|
32
32
|
# Prepare run options
|
|
33
33
|
opts = self.run_opts.copy()
|
|
34
|
-
opts
|
|
34
|
+
opts.pop('output', None)
|
|
35
35
|
opts.pop('no_poll', False)
|
|
36
36
|
|
|
37
|
+
# Set hooks and reports
|
|
38
|
+
self.enable_reports = True # Workflow will handle reports
|
|
39
|
+
self.enable_hooks = False # Celery will handle hooks
|
|
40
|
+
# Get hooks
|
|
41
|
+
hooks = self._hooks.get(Task, {})
|
|
42
|
+
opts['hooks'] = hooks
|
|
43
|
+
opts['context'] = self.context.copy()
|
|
44
|
+
opts['reports_folder'] = str(self.reports_folder)
|
|
45
|
+
opts['enable_reports'] = False # Workflow will handle reports
|
|
46
|
+
opts['has_parent'] = True
|
|
47
|
+
opts['skip_if_no_inputs'] = True
|
|
48
|
+
|
|
37
49
|
# Build task signatures
|
|
38
50
|
sigs = self.get_tasks(
|
|
39
51
|
self.config.tasks.toDict(),
|
|
@@ -43,9 +55,9 @@ class Workflow(Runner):
|
|
|
43
55
|
|
|
44
56
|
# Build workflow chain with lifecycle management
|
|
45
57
|
return chain(
|
|
46
|
-
mark_runner_started.si(self).set(queue='results'),
|
|
58
|
+
mark_runner_started.si(self, enable_hooks=True).set(queue='results'),
|
|
47
59
|
*sigs,
|
|
48
|
-
|
|
60
|
+
mark_runner_completed.s(self, enable_hooks=True).set(queue='results'),
|
|
49
61
|
)
|
|
50
62
|
|
|
51
63
|
def get_tasks(self, config, inputs, workflow_opts, run_opts):
|
|
@@ -91,13 +103,7 @@ class Workflow(Runner):
|
|
|
91
103
|
|
|
92
104
|
# Merge task options (order of priority with overrides)
|
|
93
105
|
opts = merge_opts(workflow_opts, task_opts, run_opts)
|
|
94
|
-
|
|
95
|
-
# Add task context and hooks to options
|
|
96
|
-
opts['hooks'] = {task: self._hooks.get(Task, {})}
|
|
97
|
-
opts['context'] = self.context.copy()
|
|
98
106
|
opts['name'] = task_name
|
|
99
|
-
opts['has_parent'] = True
|
|
100
|
-
opts['skip_if_no_inputs'] = True
|
|
101
107
|
|
|
102
108
|
# Create task signature
|
|
103
109
|
task_id = str(uuid.uuid4())
|
|
@@ -48,7 +48,7 @@ class naabu(ReconPort):
|
|
|
48
48
|
}
|
|
49
49
|
output_types = [Port]
|
|
50
50
|
install_cmd = 'go install -v github.com/projectdiscovery/naabu/v2/cmd/naabu@v2.3.3'
|
|
51
|
-
|
|
51
|
+
install_github_handle = 'projectdiscovery/naabu'
|
|
52
52
|
install_pre = {'apt': ['libpcap-dev'], 'apk': ['libpcap-dev', 'libc6-compat'], 'pacman|brew': ['libpcap']}
|
|
53
53
|
install_post = {'arch|alpine': 'sudo ln -sf /usr/lib/libpcap.so /usr/lib/libpcap.so.0.8'}
|
|
54
54
|
proxychains = False
|
|
@@ -30,14 +30,55 @@ class nmap(VulnMulti):
|
|
|
30
30
|
opt_prefix = '--'
|
|
31
31
|
output_types = [Port, Vulnerability, Exploit]
|
|
32
32
|
opts = {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
# Port specification and scan order
|
|
34
|
+
PORTS: {'type': str, 'short': 'p', 'help': 'Ports to scan (- to scan all)'},
|
|
35
|
+
TOP_PORTS: {'type': int, 'short': 'tp', 'help': 'Top ports to scan [100, 1000, full]'},
|
|
36
|
+
|
|
37
|
+
# Script scanning
|
|
38
|
+
SCRIPT: {'type': str, 'default': None, 'help': 'NSE scripts'},
|
|
39
|
+
'script_args': {'type': str, 'default': None, 'help': 'NSE script arguments (n1=v1,n2=v2,...)'},
|
|
40
|
+
|
|
41
|
+
# Host discovery
|
|
36
42
|
'skip_host_discovery': {'is_flag': True, 'short': 'Pn', 'default': False, 'help': 'Skip host discovery (no ping)'},
|
|
37
|
-
|
|
43
|
+
|
|
44
|
+
# Service and version detection
|
|
45
|
+
'version_detection': {'is_flag': True, 'short': 'sV', 'default': False, 'help': 'Enable version detection (slow)'},
|
|
46
|
+
'detect_all': {'is_flag': True, 'short': 'A', 'default': False, 'help': 'Enable OS detection, version detection, script scanning, and traceroute on open ports'}, # noqa: E501
|
|
47
|
+
'detect_os': {'is_flag': True, 'short': 'O', 'default': False, 'help': 'Enable OS detection'},
|
|
48
|
+
|
|
49
|
+
# Scan techniques
|
|
38
50
|
'tcp_syn_stealth': {'is_flag': True, 'short': 'sS', 'default': False, 'help': 'TCP SYN Stealth'},
|
|
39
51
|
'tcp_connect': {'is_flag': True, 'short': 'sT', 'default': False, 'help': 'TCP Connect scan'},
|
|
40
52
|
'udp_scan': {'is_flag': True, 'short': 'sU', 'default': False, 'help': 'UDP scan'},
|
|
53
|
+
'tcp_null_scan': {'is_flag': True, 'short': 'sN', 'default': False, 'help': 'TCP Null scan'},
|
|
54
|
+
'tcp_fin_scan': {'is_flag': True, 'short': 'sF', 'default': False, 'help': 'TCP FIN scan'},
|
|
55
|
+
'tcp_xmas_scan': {'is_flag': True, 'short': 'sX', 'default': False, 'help': 'TCP Xmas scan'},
|
|
56
|
+
'tcp_ack_scan': {'is_flag': True, 'short': 'sA', 'default': False, 'help': 'TCP ACK scan'},
|
|
57
|
+
'tcp_window_scan': {'is_flag': True, 'short': 'sW', 'default': False, 'help': 'TCP Window scan'},
|
|
58
|
+
'tcp_maimon_scan': {'is_flag': True, 'short': 'sM', 'default': False, 'help': 'TCP Maimon scan'},
|
|
59
|
+
'sctp_init_scan': {'is_flag': True, 'short': 'sY', 'default': False, 'help': 'SCTP Init scan'},
|
|
60
|
+
'sctp_cookie_echo_scan': {'is_flag': True, 'short': 'sZ', 'default': False, 'help': 'SCTP Cookie Echo scan'},
|
|
61
|
+
'ping_scan': {'is_flag': True, 'short': 'sn', 'default': False, 'help': 'Ping scan (disable port scan)'},
|
|
62
|
+
'ip_protocol_scan': {'type': str, 'short': 'sO', 'default': None, 'help': 'IP protocol scan'},
|
|
63
|
+
'script_scan': {'is_flag': True, 'short': 'sC', 'default': False, 'help': 'Enable default scanning'},
|
|
64
|
+
'zombie_host': {'type': str, 'short': 'sI', 'default': None, 'help': 'Use a zombie host for idle scan'},
|
|
65
|
+
'ftp_relay_host': {'type': str, 'short': 'sB', 'default': None, 'help': 'FTP bounce scan relay host'},
|
|
66
|
+
|
|
67
|
+
# Firewall / IDS evasion and spoofing
|
|
68
|
+
'spoof_source_port': {'type': int, 'short': 'g', 'default': None, 'help': 'Send packets from a specific port'},
|
|
69
|
+
'spoof_source_ip': {'type': str, 'short': 'S', 'default': None, 'help': 'Spoof source IP address'},
|
|
70
|
+
'spoof_source_mac': {'type': str, 'short': 'spoofmac', 'default': None, 'help': 'Spoof MAC address'},
|
|
71
|
+
'fragment': {'is_flag': True, 'short': 'fragment', 'default': False, 'help': 'Fragment packets'},
|
|
72
|
+
'mtu': {'type': int, 'short': 'mtu', 'default': None, 'help': 'Fragment packets with given MTU'},
|
|
73
|
+
'ttl': {'type': int, 'short': 'ttl', 'default': None, 'help': 'Set TTL'},
|
|
74
|
+
'badsum': {'is_flag': True, 'short': 'badsum', 'default': False, 'help': 'Create a bad checksum in the TCP header'},
|
|
75
|
+
'ipv6': {'is_flag': True, 'short': 'ipv6', 'default': False, 'help': 'Enable IPv6 scanning'},
|
|
76
|
+
|
|
77
|
+
# Host discovery
|
|
78
|
+
'traceroute': {'is_flag': True, 'short': 'traceroute', 'default': False, 'help': 'Traceroute'},
|
|
79
|
+
'disable_arp_ping': {'is_flag': True, 'short': 'disable-arp-ping', 'default': False, 'help': 'Disable ARP ping'},
|
|
80
|
+
|
|
81
|
+
# Misc
|
|
41
82
|
'output_path': {'type': str, 'short': 'oX', 'default': None, 'help': 'Output XML file path'},
|
|
42
83
|
}
|
|
43
84
|
opt_key_map = {
|
|
@@ -55,9 +96,34 @@ class nmap(VulnMulti):
|
|
|
55
96
|
PORTS: '-p',
|
|
56
97
|
'skip_host_discovery': '-Pn',
|
|
57
98
|
'version_detection': '-sV',
|
|
58
|
-
'
|
|
99
|
+
'detect_all': '-A',
|
|
100
|
+
'detect_os': '-O',
|
|
59
101
|
'tcp_syn_stealth': '-sS',
|
|
102
|
+
'tcp_connect': '-sT',
|
|
103
|
+
'tcp_window_scan': '-sW',
|
|
104
|
+
'tcp_maimon_scan': '-sM',
|
|
60
105
|
'udp_scan': '-sU',
|
|
106
|
+
'tcp_null_scan': '-sN',
|
|
107
|
+
'tcp_fin_scan': '-sF',
|
|
108
|
+
'tcp_xmas_scan': '-sX',
|
|
109
|
+
'tcp_ack_scan': '-sA',
|
|
110
|
+
'sctp_init_scan': '-sY',
|
|
111
|
+
'sctp_cookie_echo_scan': '-sZ',
|
|
112
|
+
'ping_scan': '-sn',
|
|
113
|
+
'ip_protocol_scan': '-sO',
|
|
114
|
+
'script_scan': '-sC',
|
|
115
|
+
'zombie_host': '-sI',
|
|
116
|
+
'ftp_relay_host': '-b',
|
|
117
|
+
'spoof_source_port': '-g',
|
|
118
|
+
'spoof_source_ip': '-S',
|
|
119
|
+
'spoof_source_mac': '--spoof-mac',
|
|
120
|
+
'fragmentation': '-f',
|
|
121
|
+
'mtu': '--mtu',
|
|
122
|
+
'ttl': '--ttl',
|
|
123
|
+
'badsum': '--badsum',
|
|
124
|
+
'ipv6': '-6',
|
|
125
|
+
'traceroute': '--traceroute',
|
|
126
|
+
'disable_arp_ping': '--disable-arp-ping',
|
|
61
127
|
'output_path': '-oX',
|
|
62
128
|
}
|
|
63
129
|
opt_value_map = {
|
|
@@ -16,7 +16,7 @@ from secator.tasks._categories import VulnHttp
|
|
|
16
16
|
@task()
|
|
17
17
|
class wpscan(VulnHttp):
|
|
18
18
|
"""Wordpress security scanner."""
|
|
19
|
-
cmd = 'wpscan --random-user-agent --force --verbose'
|
|
19
|
+
cmd = 'wpscan --random-user-agent --force --verbose --disable-tls-checks --ignore-main-redirect'
|
|
20
20
|
file_flag = None
|
|
21
21
|
input_flag = '--url'
|
|
22
22
|
input_type = URL
|
|
@@ -150,12 +150,15 @@ class TestCelery(unittest.TestCase):
|
|
|
150
150
|
return
|
|
151
151
|
|
|
152
152
|
size = CONFIG.runners.input_chunk_size + 1
|
|
153
|
-
|
|
153
|
+
import uuid
|
|
154
|
+
targets = []
|
|
155
|
+
for _ in range(size):
|
|
156
|
+
targets.append(URL_TARGETS[0] + '?id=' + str(uuid.uuid4()))
|
|
154
157
|
result = httpx.delay(targets)
|
|
155
158
|
results = result.get()
|
|
156
159
|
urls = [r.url for r in results if r._type == 'url']
|
|
157
160
|
infos = [r.message for r in results if r._type == 'info']
|
|
158
|
-
self.assertEqual(len(urls),
|
|
161
|
+
self.assertEqual(len(urls), size) # same URL, but twice because 2 chunks and same input
|
|
159
162
|
# self.assertEqual(len(infos), 2) # one chunk message for each chunk
|
|
160
163
|
# for message in infos:
|
|
161
164
|
# self.assertIn('Celery chunked task created', message)
|