secator 0.15.1__py3-none-any.whl → 0.16.1__py3-none-any.whl
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/celery.py +40 -24
- secator/celery_signals.py +71 -68
- secator/celery_utils.py +43 -27
- secator/cli.py +520 -280
- secator/cli_helper.py +394 -0
- secator/click.py +87 -0
- secator/config.py +67 -39
- secator/configs/profiles/http_headless.yaml +6 -0
- secator/configs/profiles/http_record.yaml +6 -0
- secator/configs/profiles/tor.yaml +1 -1
- secator/configs/scans/domain.yaml +4 -2
- secator/configs/scans/host.yaml +1 -1
- secator/configs/scans/network.yaml +1 -4
- secator/configs/scans/subdomain.yaml +13 -1
- secator/configs/scans/url.yaml +1 -2
- secator/configs/workflows/cidr_recon.yaml +6 -4
- secator/configs/workflows/code_scan.yaml +1 -1
- secator/configs/workflows/host_recon.yaml +29 -3
- secator/configs/workflows/subdomain_recon.yaml +67 -16
- secator/configs/workflows/url_crawl.yaml +44 -15
- secator/configs/workflows/url_dirsearch.yaml +4 -4
- secator/configs/workflows/url_fuzz.yaml +25 -17
- secator/configs/workflows/url_params_fuzz.yaml +7 -0
- secator/configs/workflows/url_vuln.yaml +33 -8
- secator/configs/workflows/user_hunt.yaml +4 -2
- secator/configs/workflows/wordpress.yaml +5 -3
- secator/cve.py +718 -0
- secator/decorators.py +0 -454
- secator/definitions.py +49 -30
- secator/exporters/_base.py +2 -2
- secator/exporters/console.py +2 -2
- secator/exporters/table.py +4 -3
- secator/exporters/txt.py +1 -1
- secator/hooks/mongodb.py +2 -4
- secator/installer.py +77 -49
- secator/loader.py +116 -0
- secator/output_types/_base.py +3 -0
- secator/output_types/certificate.py +63 -63
- secator/output_types/error.py +4 -5
- secator/output_types/info.py +2 -2
- secator/output_types/ip.py +3 -1
- secator/output_types/progress.py +5 -9
- secator/output_types/state.py +17 -17
- secator/output_types/tag.py +3 -0
- secator/output_types/target.py +10 -2
- secator/output_types/url.py +19 -7
- secator/output_types/vulnerability.py +11 -7
- secator/output_types/warning.py +2 -2
- secator/report.py +27 -15
- secator/rich.py +18 -10
- secator/runners/_base.py +446 -233
- secator/runners/_helpers.py +133 -24
- secator/runners/command.py +182 -102
- secator/runners/scan.py +33 -5
- secator/runners/task.py +13 -7
- secator/runners/workflow.py +105 -72
- secator/scans/__init__.py +2 -2
- secator/serializers/dataclass.py +20 -20
- secator/tasks/__init__.py +4 -4
- secator/tasks/_categories.py +39 -27
- secator/tasks/arjun.py +9 -5
- secator/tasks/bbot.py +53 -21
- secator/tasks/bup.py +19 -5
- secator/tasks/cariddi.py +24 -3
- secator/tasks/dalfox.py +26 -7
- secator/tasks/dirsearch.py +10 -4
- secator/tasks/dnsx.py +70 -25
- secator/tasks/feroxbuster.py +11 -3
- secator/tasks/ffuf.py +42 -6
- secator/tasks/fping.py +20 -8
- secator/tasks/gau.py +3 -1
- secator/tasks/gf.py +3 -3
- secator/tasks/gitleaks.py +2 -2
- secator/tasks/gospider.py +7 -1
- secator/tasks/grype.py +5 -4
- secator/tasks/h8mail.py +2 -1
- secator/tasks/httpx.py +18 -5
- secator/tasks/katana.py +35 -15
- secator/tasks/maigret.py +4 -4
- secator/tasks/mapcidr.py +3 -3
- secator/tasks/msfconsole.py +4 -4
- secator/tasks/naabu.py +2 -2
- secator/tasks/nmap.py +12 -14
- secator/tasks/nuclei.py +3 -3
- secator/tasks/searchsploit.py +4 -5
- secator/tasks/subfinder.py +2 -2
- secator/tasks/testssl.py +264 -263
- secator/tasks/trivy.py +5 -5
- secator/tasks/wafw00f.py +21 -3
- secator/tasks/wpprobe.py +90 -83
- secator/tasks/wpscan.py +6 -5
- secator/template.py +218 -104
- secator/thread.py +15 -15
- secator/tree.py +196 -0
- secator/utils.py +131 -123
- secator/utils_test.py +60 -19
- secator/workflows/__init__.py +2 -2
- {secator-0.15.1.dist-info → secator-0.16.1.dist-info}/METADATA +36 -36
- secator-0.16.1.dist-info/RECORD +132 -0
- secator/configs/profiles/default.yaml +0 -8
- secator/configs/workflows/url_nuclei.yaml +0 -11
- secator/tasks/dnsxbrute.py +0 -42
- secator-0.15.1.dist-info/RECORD +0 -128
- {secator-0.15.1.dist-info → secator-0.16.1.dist-info}/WHEEL +0 -0
- {secator-0.15.1.dist-info → secator-0.16.1.dist-info}/entry_points.txt +0 -0
- {secator-0.15.1.dist-info → secator-0.16.1.dist-info}/licenses/LICENSE +0 -0
secator/tasks/trivy.py
CHANGED
|
@@ -5,8 +5,7 @@ import yaml
|
|
|
5
5
|
from secator.config import CONFIG
|
|
6
6
|
from secator.decorators import task
|
|
7
7
|
from secator.definitions import (THREADS, OUTPUT_PATH, OPT_NOT_SUPPORTED, HEADER, DELAY, FOLLOW_REDIRECT,
|
|
8
|
-
|
|
9
|
-
USER_AGENT)
|
|
8
|
+
PATH, PROXY, RATE_LIMIT, RETRIES, TIMEOUT, USER_AGENT, STRING, URL)
|
|
10
9
|
from secator.tasks._categories import Vuln
|
|
11
10
|
from secator.output_types import Vulnerability, Tag, Info, Error
|
|
12
11
|
|
|
@@ -15,10 +14,12 @@ from secator.output_types import Vulnerability, Tag, Info, Error
|
|
|
15
14
|
class trivy(Vuln):
|
|
16
15
|
"""Comprehensive and versatile security scanner."""
|
|
17
16
|
cmd = 'trivy'
|
|
17
|
+
input_types = [PATH, URL, STRING]
|
|
18
|
+
output_types = [Tag, Vulnerability]
|
|
18
19
|
tags = ['vuln', 'scan']
|
|
19
|
-
|
|
20
|
-
input_types = [DOCKER_IMAGE, PATH, GIT_REPOSITORY]
|
|
20
|
+
input_chunk_size = 1
|
|
21
21
|
json_flag = '-f json'
|
|
22
|
+
version_flag = '--version'
|
|
22
23
|
opts = {
|
|
23
24
|
"mode": {"type": click.Choice(['image', 'fs', 'repo']), 'default': 'image', 'help': 'Trivy mode', 'required': True} # noqa: E501
|
|
24
25
|
}
|
|
@@ -33,7 +34,6 @@ class trivy(Vuln):
|
|
|
33
34
|
TIMEOUT: OPT_NOT_SUPPORTED,
|
|
34
35
|
USER_AGENT: OPT_NOT_SUPPORTED
|
|
35
36
|
}
|
|
36
|
-
output_types = [Tag, Vulnerability]
|
|
37
37
|
install_version = 'v0.61.1'
|
|
38
38
|
install_cmd = (
|
|
39
39
|
'curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh |'
|
secator/tasks/wafw00f.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import os
|
|
2
|
+
import tempfile
|
|
2
3
|
import yaml
|
|
3
4
|
|
|
4
5
|
from secator.decorators import task
|
|
@@ -12,8 +13,9 @@ from secator.tasks._categories import OPTS
|
|
|
12
13
|
class wafw00f(Command):
|
|
13
14
|
"""Web Application Firewall Fingerprinting tool."""
|
|
14
15
|
cmd = 'wafw00f'
|
|
15
|
-
tags = ['waf', 'scan']
|
|
16
16
|
input_types = [URL]
|
|
17
|
+
output_types = [Tag]
|
|
18
|
+
tags = ['waf', 'scan']
|
|
17
19
|
input_flag = None
|
|
18
20
|
file_flag = '-i'
|
|
19
21
|
json_flag = '-f json'
|
|
@@ -30,6 +32,9 @@ class wafw00f(Command):
|
|
|
30
32
|
'find_all': {'is_flag': True, 'short': 'ta', 'default': False, 'help': 'Find all WAFs which match the signatures, do not stop testing on the first one'}, # noqa: E501
|
|
31
33
|
'no_follow_redirects': {'is_flag': True, 'short': 'nfr', 'default': False, 'help': 'Do not follow redirections given by 3xx responses'}, # noqa: E501
|
|
32
34
|
}
|
|
35
|
+
opt_value_map = {
|
|
36
|
+
HEADER: lambda x: wafw00f.headers_to_file(x)
|
|
37
|
+
}
|
|
33
38
|
opt_key_map = {
|
|
34
39
|
HEADER: 'headers',
|
|
35
40
|
PROXY: 'proxy',
|
|
@@ -37,7 +42,6 @@ class wafw00f(Command):
|
|
|
37
42
|
'find_all': 'findall',
|
|
38
43
|
'no_follow_redirects': 'noredirect',
|
|
39
44
|
}
|
|
40
|
-
output_types = [Tag]
|
|
41
45
|
install_version = 'v2.3.1'
|
|
42
46
|
install_cmd = 'pipx install git+https://github.com/EnableSecurity/wafw00f.git@[install_version] --force'
|
|
43
47
|
install_github_handle = 'EnableSecurity/wafw00f'
|
|
@@ -81,5 +85,19 @@ class wafw00f(Command):
|
|
|
81
85
|
yield Tag(
|
|
82
86
|
name=waf_name + ' WAF',
|
|
83
87
|
match=url,
|
|
84
|
-
extra_data={
|
|
88
|
+
extra_data={
|
|
89
|
+
'waf_name': waf_name,
|
|
90
|
+
'manufacter': manufacter,
|
|
91
|
+
'trigger_url': match,
|
|
92
|
+
'headers': self.get_opt_value('header', preprocess=True)
|
|
93
|
+
}
|
|
85
94
|
)
|
|
95
|
+
|
|
96
|
+
@staticmethod
|
|
97
|
+
def headers_to_file(headers):
|
|
98
|
+
temp_dir = tempfile.gettempdir()
|
|
99
|
+
header_file = f'{temp_dir}/headers.txt'
|
|
100
|
+
with open(header_file, 'w') as f:
|
|
101
|
+
for header in headers.split(';;'):
|
|
102
|
+
f.write(f'{header}\n')
|
|
103
|
+
return header_file
|
secator/tasks/wpprobe.py
CHANGED
|
@@ -1,96 +1,103 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import re
|
|
1
3
|
import click
|
|
2
4
|
import yaml
|
|
3
5
|
|
|
4
6
|
from secator.decorators import task
|
|
5
7
|
from secator.runners import Command
|
|
6
8
|
from secator.definitions import OUTPUT_PATH, THREADS, URL
|
|
7
|
-
from secator.output_types import Vulnerability, Tag, Info, Warning
|
|
9
|
+
from secator.output_types import Vulnerability, Tag, Info, Warning, Error
|
|
8
10
|
from secator.tasks._categories import OPTS
|
|
9
11
|
|
|
10
12
|
|
|
11
13
|
@task()
|
|
12
14
|
class wpprobe(Command):
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
15
|
+
"""Fast wordpress plugin enumeration tool."""
|
|
16
|
+
cmd = 'wpprobe'
|
|
17
|
+
input_types = [URL]
|
|
18
|
+
output_types = [Vulnerability, Tag]
|
|
19
|
+
tags = ['vuln', 'scan', 'wordpress']
|
|
20
|
+
file_flag = '-f'
|
|
21
|
+
input_flag = '-u'
|
|
22
|
+
opt_prefix = '-'
|
|
23
|
+
opts = {
|
|
24
|
+
'mode': {'type': click.Choice(['scan', 'update', 'update-db']), 'default': 'scan', 'help': 'WPProbe mode', 'required': True, 'internal': True}, # noqa: E501
|
|
25
|
+
'output_path': {'type': str, 'default': None, 'help': 'Output JSON file path', 'internal': True, 'display': False}, # noqa: E501
|
|
26
|
+
}
|
|
27
|
+
meta_opts = {
|
|
28
|
+
THREADS: OPTS[THREADS]
|
|
29
|
+
}
|
|
30
|
+
opt_key_map = {
|
|
31
|
+
THREADS: 't'
|
|
32
|
+
}
|
|
33
|
+
install_version = 'v0.5.6'
|
|
34
|
+
install_cmd = 'go install github.com/Chocapikk/wpprobe@[install_version]'
|
|
35
|
+
install_github_handle = 'Chocapikk/wpprobe'
|
|
36
|
+
install_post = {
|
|
37
|
+
'*': 'wpprobe update && wpprobe update-db'
|
|
38
|
+
}
|
|
37
39
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
40
|
+
@staticmethod
|
|
41
|
+
def on_cmd(self):
|
|
42
|
+
mode = self.get_opt_value('mode')
|
|
43
|
+
if mode == 'update' or mode == 'update-db':
|
|
44
|
+
self.cmd = f'{wpprobe.cmd} {mode}'
|
|
45
|
+
return
|
|
46
|
+
self.cmd = re.sub(wpprobe.cmd, f'{wpprobe.cmd} {mode}', self.cmd, 1)
|
|
47
|
+
output_path = self.get_opt_value(OUTPUT_PATH)
|
|
48
|
+
if not output_path:
|
|
49
|
+
output_path = f'{self.reports_folder}/.outputs/{self.unique_name}.json'
|
|
50
|
+
self.output_path = output_path
|
|
51
|
+
self.cmd += f' -o {self.output_path}'
|
|
50
52
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
53
|
+
@staticmethod
|
|
54
|
+
def on_cmd_done(self):
|
|
55
|
+
if not self.get_opt_value('mode') == 'scan':
|
|
56
|
+
return
|
|
57
|
+
|
|
58
|
+
if not os.path.exists(self.output_path):
|
|
59
|
+
yield Error(message=f'Could not find JSON results in {self.output_path}')
|
|
60
|
+
return
|
|
61
|
+
|
|
62
|
+
yield Info(message=f'JSON results saved to {self.output_path}')
|
|
63
|
+
with open(self.output_path, 'r') as f:
|
|
64
|
+
results = yaml.safe_load(f.read())
|
|
65
|
+
if not results or 'url' not in results:
|
|
66
|
+
yield Warning(message='No results found !')
|
|
67
|
+
return
|
|
68
|
+
url = results['url']
|
|
69
|
+
for plugin_name, plugin_data in results['plugins'].items():
|
|
70
|
+
for plugin_data_version in plugin_data:
|
|
71
|
+
plugin_version = plugin_data_version['version']
|
|
72
|
+
yield Tag(
|
|
73
|
+
name=f'Wordpress plugin - {plugin_name} {plugin_version}',
|
|
74
|
+
match=url,
|
|
75
|
+
extra_data={
|
|
76
|
+
'name': plugin_name,
|
|
77
|
+
'version': plugin_version
|
|
78
|
+
}
|
|
79
|
+
)
|
|
80
|
+
severities = plugin_data_version.get('severities', {})
|
|
81
|
+
for severity, severity_data in severities.items():
|
|
82
|
+
if severity == 'None':
|
|
83
|
+
severity = 'unknown'
|
|
84
|
+
for item in severity_data:
|
|
85
|
+
for vuln in item['vulnerabilities']:
|
|
86
|
+
auth_type = item.get('auth_type')
|
|
87
|
+
extra_data = {
|
|
88
|
+
'plugin_name': plugin_name,
|
|
89
|
+
'plugin_version': plugin_version,
|
|
90
|
+
}
|
|
91
|
+
if auth_type:
|
|
92
|
+
extra_data['auth_type'] = auth_type
|
|
93
|
+
yield Vulnerability(
|
|
94
|
+
name=vuln['title'],
|
|
95
|
+
id=vuln['cve'],
|
|
96
|
+
severity=severity,
|
|
97
|
+
cvss_score=vuln['cvss_score'],
|
|
98
|
+
tags=[plugin_name],
|
|
99
|
+
reference=vuln['cve_link'],
|
|
100
|
+
extra_data=extra_data,
|
|
101
|
+
matched_at=url,
|
|
102
|
+
confidence='high'
|
|
103
|
+
)
|
secator/tasks/wpscan.py
CHANGED
|
@@ -17,10 +17,11 @@ from secator.tasks._categories import VulnHttp
|
|
|
17
17
|
class wpscan(VulnHttp):
|
|
18
18
|
"""Wordpress security scanner."""
|
|
19
19
|
cmd = 'wpscan --force --verbose'
|
|
20
|
+
input_types = [URL]
|
|
21
|
+
output_types = [Vulnerability, Tag]
|
|
20
22
|
tags = ['vuln', 'scan', 'wordpress']
|
|
21
|
-
file_flag = None
|
|
22
23
|
input_flag = '--url'
|
|
23
|
-
|
|
24
|
+
input_chunk_size = 1
|
|
24
25
|
json_flag = '-f json'
|
|
25
26
|
opt_prefix = '--'
|
|
26
27
|
opts = {
|
|
@@ -69,14 +70,14 @@ class wpscan(VulnHttp):
|
|
|
69
70
|
PROVIDER: 'wpscan',
|
|
70
71
|
},
|
|
71
72
|
}
|
|
72
|
-
output_types = [Vulnerability, Tag]
|
|
73
73
|
install_pre = {
|
|
74
74
|
'apt': ['make', 'kali:libcurl4t64', 'libffi-dev'],
|
|
75
75
|
'pacman': ['make', 'ruby-erb'],
|
|
76
76
|
'*': ['make']
|
|
77
77
|
}
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
install_github_handle = 'wpscanteam/wpscan'
|
|
79
|
+
install_version = 'v3.8.28'
|
|
80
|
+
install_cmd = f'gem install wpscan -v [install_version_strip] --user-install -n {CONFIG.dirs.bin}'
|
|
80
81
|
install_post = {
|
|
81
82
|
'kali': (
|
|
82
83
|
f'gem uninstall nokogiri --user-install -n {CONFIG.dirs.bin} --force --executables && '
|