secator 0.11.1__py3-none-any.whl → 0.13.0__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/cli.py +175 -66
- secator/config.py +1 -0
- secator/configs/workflows/host_recon.yaml +11 -2
- secator/configs/workflows/port_scan.yaml +39 -0
- secator/configs/workflows/url_dirsearch.yaml +5 -0
- secator/configs/workflows/url_params_fuzz.yaml +2 -0
- secator/decorators.py +39 -21
- secator/definitions.py +0 -4
- secator/installer.py +29 -15
- secator/runners/_base.py +2 -1
- secator/runners/_helpers.py +13 -2
- secator/runners/command.py +3 -1
- secator/tasks/_categories.py +2 -2
- secator/tasks/arjun.py +11 -2
- secator/tasks/bbot.py +30 -4
- secator/tasks/bup.py +2 -1
- secator/tasks/cariddi.py +15 -3
- secator/tasks/dalfox.py +2 -1
- secator/tasks/dirsearch.py +1 -1
- secator/tasks/dnsx.py +2 -1
- secator/tasks/dnsxbrute.py +2 -1
- secator/tasks/feroxbuster.py +3 -2
- secator/tasks/ffuf.py +2 -1
- secator/tasks/gau.py +2 -1
- secator/tasks/gitleaks.py +4 -3
- secator/tasks/gospider.py +3 -2
- secator/tasks/grype.py +1 -0
- secator/tasks/h8mail.py +2 -1
- secator/tasks/httpx.py +3 -2
- secator/tasks/katana.py +4 -3
- secator/tasks/maigret.py +1 -1
- secator/tasks/mapcidr.py +2 -1
- secator/tasks/msfconsole.py +4 -3
- secator/tasks/naabu.py +4 -2
- secator/tasks/nuclei.py +15 -9
- secator/tasks/searchsploit.py +3 -2
- secator/tasks/subfinder.py +2 -1
- secator/tasks/testssl.py +4 -3
- secator/tasks/trivy.py +2 -2
- secator/tasks/wafw00f.py +2 -1
- secator/tasks/wpprobe.py +2 -1
- secator/tasks/wpscan.py +6 -3
- secator/template.py +12 -0
- {secator-0.11.1.dist-info → secator-0.13.0.dist-info}/METADATA +1 -1
- {secator-0.11.1.dist-info → secator-0.13.0.dist-info}/RECORD +48 -47
- {secator-0.11.1.dist-info → secator-0.13.0.dist-info}/WHEEL +0 -0
- {secator-0.11.1.dist-info → secator-0.13.0.dist-info}/entry_points.txt +0 -0
- {secator-0.11.1.dist-info → secator-0.13.0.dist-info}/licenses/LICENSE +0 -0
secator/installer.py
CHANGED
|
@@ -31,8 +31,10 @@ class InstallerStatus(Enum):
|
|
|
31
31
|
INSTALL_FAILED = 'INSTALL_FAILED'
|
|
32
32
|
INSTALL_NOT_SUPPORTED = 'INSTALL_NOT_SUPPORTED'
|
|
33
33
|
INSTALL_SKIPPED_OK = 'INSTALL_SKIPPED_OK'
|
|
34
|
+
INSTALL_VERSION_NOT_SPECIFIED = 'INSTALL_VERSION_NOT_SPECIFIED'
|
|
34
35
|
GITHUB_LATEST_RELEASE_NOT_FOUND = 'GITHUB_LATEST_RELEASE_NOT_FOUND'
|
|
35
36
|
GITHUB_RELEASE_NOT_FOUND = 'RELEASE_NOT_FOUND'
|
|
37
|
+
GITHUB_RELEASE_UNMATCHED_DISTRIBUTION = 'RELEASE_UNMATCHED_DISTRIBUTION'
|
|
36
38
|
GITHUB_RELEASE_FAILED_DOWNLOAD = 'GITHUB_RELEASE_FAILED_DOWNLOAD'
|
|
37
39
|
GITHUB_BINARY_NOT_FOUND_IN_ARCHIVE = 'GITHUB_BINARY_NOT_FOUND_IN_ARCHIVE'
|
|
38
40
|
UNKNOWN_DISTRIBUTION = 'UNKNOWN_DISTRIBUTION'
|
|
@@ -83,12 +85,12 @@ class ToolInstaller:
|
|
|
83
85
|
# Install binaries from GH
|
|
84
86
|
gh_status = InstallerStatus.UNKNOWN
|
|
85
87
|
if tool_cls.install_github_handle and not CONFIG.security.force_source_install:
|
|
86
|
-
gh_status = GithubInstaller.install(tool_cls.install_github_handle)
|
|
88
|
+
gh_status = GithubInstaller.install(tool_cls.install_github_handle, version=tool_cls.install_version or 'latest')
|
|
87
89
|
status = gh_status
|
|
88
90
|
|
|
89
91
|
# Install from source
|
|
90
92
|
if tool_cls.install_cmd and not gh_status.is_ok():
|
|
91
|
-
status = SourceInstaller.install(tool_cls.install_cmd)
|
|
93
|
+
status = SourceInstaller.install(tool_cls.install_cmd, tool_cls.install_version)
|
|
92
94
|
if not status.is_ok():
|
|
93
95
|
cls.print_status(status, name)
|
|
94
96
|
return status
|
|
@@ -167,12 +169,14 @@ class SourceInstaller:
|
|
|
167
169
|
"""Install a tool from source."""
|
|
168
170
|
|
|
169
171
|
@classmethod
|
|
170
|
-
def install(cls, config, install_prereqs=True):
|
|
172
|
+
def install(cls, config, version=None, install_prereqs=True):
|
|
171
173
|
"""Install from source.
|
|
172
174
|
|
|
173
175
|
Args:
|
|
174
176
|
cls: ToolInstaller class.
|
|
175
177
|
config (dict): A dict of distros as keys and a command as value.
|
|
178
|
+
version (str, optional): Version to install.
|
|
179
|
+
install_prereqs (bool, optional): Install pre-requisites.
|
|
176
180
|
|
|
177
181
|
Returns:
|
|
178
182
|
Status: install status.
|
|
@@ -204,6 +208,11 @@ class SourceInstaller:
|
|
|
204
208
|
if not status.is_ok():
|
|
205
209
|
return status
|
|
206
210
|
|
|
211
|
+
# Handle version
|
|
212
|
+
if '[install_version]' in install_cmd:
|
|
213
|
+
version = version or 'latest'
|
|
214
|
+
install_cmd = install_cmd.replace('[install_version]', version)
|
|
215
|
+
|
|
207
216
|
# Run command
|
|
208
217
|
ret = Command.execute(install_cmd, cls_attributes={'shell': True}, quiet=False)
|
|
209
218
|
return InstallerStatus.SUCCESS if ret.return_code == 0 else InstallerStatus.INSTALL_FAILED
|
|
@@ -213,7 +222,7 @@ class GithubInstaller:
|
|
|
213
222
|
"""Install a tool from GitHub releases."""
|
|
214
223
|
|
|
215
224
|
@classmethod
|
|
216
|
-
def install(cls, github_handle):
|
|
225
|
+
def install(cls, github_handle, version='latest'):
|
|
217
226
|
"""Find and install a release from a GitHub handle {user}/{repo}.
|
|
218
227
|
|
|
219
228
|
Args:
|
|
@@ -223,35 +232,38 @@ class GithubInstaller:
|
|
|
223
232
|
InstallerStatus: status.
|
|
224
233
|
"""
|
|
225
234
|
_, repo = tuple(github_handle.split('/'))
|
|
226
|
-
|
|
227
|
-
if not
|
|
228
|
-
return InstallerStatus.
|
|
235
|
+
release = cls.get_release(github_handle, version=version)
|
|
236
|
+
if not release:
|
|
237
|
+
return InstallerStatus.GITHUB_RELEASE_NOT_FOUND
|
|
229
238
|
|
|
230
239
|
# Find the right asset to download
|
|
231
240
|
system, arch, os_identifiers, arch_identifiers = cls._get_platform_identifier()
|
|
232
|
-
download_url = cls._find_matching_asset(
|
|
241
|
+
download_url = cls._find_matching_asset(release['assets'], os_identifiers, arch_identifiers)
|
|
233
242
|
if not download_url:
|
|
234
243
|
console.print(Error(message=f'Could not find a GitHub release matching distribution (system: {system}, arch: {arch}).')) # noqa: E501
|
|
235
|
-
return InstallerStatus.
|
|
244
|
+
return InstallerStatus.GITHUB_RELEASE_UNMATCHED_DISTRIBUTION
|
|
236
245
|
|
|
237
246
|
# Download and unpack asset
|
|
238
247
|
console.print(Info(message=f'Found release URL: {download_url}'))
|
|
239
248
|
return cls._download_and_unpack(download_url, CONFIG.dirs.bin, repo)
|
|
240
249
|
|
|
241
250
|
@classmethod
|
|
242
|
-
def
|
|
243
|
-
"""Get
|
|
251
|
+
def get_release(cls, github_handle, version='latest'):
|
|
252
|
+
"""Get release from GitHub.
|
|
244
253
|
|
|
245
254
|
Args:
|
|
246
255
|
github_handle (str): A GitHub handle {user}/{repo}.
|
|
247
256
|
|
|
248
257
|
Returns:
|
|
249
|
-
dict:
|
|
258
|
+
dict: Release JSON from GitHub releases.
|
|
250
259
|
"""
|
|
251
260
|
if not github_handle:
|
|
252
261
|
return False
|
|
253
262
|
owner, repo = tuple(github_handle.split('/'))
|
|
254
|
-
|
|
263
|
+
if version == 'latest':
|
|
264
|
+
url = f"https://api.github.com/repos/{owner}/{repo}/releases/latest"
|
|
265
|
+
else:
|
|
266
|
+
url = f"https://api.github.com/repos/{owner}/{repo}/releases/tags/{version}"
|
|
255
267
|
headers = {}
|
|
256
268
|
if CONFIG.cli.github_token:
|
|
257
269
|
headers['Authorization'] = f'Bearer {CONFIG.cli.github_token}'
|
|
@@ -268,7 +280,7 @@ class GithubInstaller:
|
|
|
268
280
|
|
|
269
281
|
@classmethod
|
|
270
282
|
def get_latest_version(cls, github_handle):
|
|
271
|
-
latest_release = cls.
|
|
283
|
+
latest_release = cls.get_release(github_handle, version='latest')
|
|
272
284
|
if not latest_release:
|
|
273
285
|
return None
|
|
274
286
|
return latest_release['tag_name'].lstrip('v')
|
|
@@ -444,6 +456,7 @@ def get_version_info(name, version_flag=None, install_github_handle=None, instal
|
|
|
444
456
|
'latest_version': None,
|
|
445
457
|
'location': None,
|
|
446
458
|
'status': '',
|
|
459
|
+
'outdated': False,
|
|
447
460
|
'errors': []
|
|
448
461
|
}
|
|
449
462
|
|
|
@@ -504,6 +517,7 @@ def get_version_info(name, version_flag=None, install_github_handle=None, instal
|
|
|
504
517
|
if version and latest_version:
|
|
505
518
|
if parse_version(version) < parse_version(latest_version):
|
|
506
519
|
info['status'] = 'outdated'
|
|
520
|
+
info['outdated'] = True
|
|
507
521
|
else:
|
|
508
522
|
info['status'] = 'latest'
|
|
509
523
|
elif not version:
|
|
@@ -529,7 +543,7 @@ def get_distro_config():
|
|
|
529
543
|
distrib = system
|
|
530
544
|
|
|
531
545
|
if system == "Linux":
|
|
532
|
-
distrib = distro.id()
|
|
546
|
+
distrib = distro.id() or distro.like()
|
|
533
547
|
|
|
534
548
|
if distrib in ["ubuntu", "debian", "linuxmint", "popos", "kali"]:
|
|
535
549
|
installer = "apt install -y --no-install-recommends"
|
secator/runners/_base.py
CHANGED
|
@@ -130,7 +130,8 @@ class Runner:
|
|
|
130
130
|
|
|
131
131
|
# Determine inputs
|
|
132
132
|
self.inputs = [inputs] if not isinstance(inputs, list) else inputs
|
|
133
|
-
self.
|
|
133
|
+
targets = [Target(name=target) for target in self.inputs]
|
|
134
|
+
self.filter_results(results + targets)
|
|
134
135
|
|
|
135
136
|
# Debug
|
|
136
137
|
self.debug('Inputs', obj=self.inputs, sub='init')
|
secator/runners/_helpers.py
CHANGED
|
@@ -18,14 +18,25 @@ def run_extractors(results, opts, inputs=[], dry_run=False):
|
|
|
18
18
|
"""
|
|
19
19
|
extractors = {k: v for k, v in opts.items() if k.endswith('_')}
|
|
20
20
|
errors = []
|
|
21
|
+
computed_inputs = []
|
|
22
|
+
computed_opts = {}
|
|
21
23
|
for key, val in extractors.items():
|
|
22
24
|
key = key.rstrip('_')
|
|
23
25
|
values, err = extract_from_results(results, val)
|
|
24
26
|
errors.extend(err)
|
|
25
27
|
if key == 'targets':
|
|
26
|
-
|
|
28
|
+
targets = ['<COMPUTED>'] if dry_run else deduplicate(values)
|
|
29
|
+
computed_inputs.extend(targets)
|
|
27
30
|
else:
|
|
28
|
-
|
|
31
|
+
computed_opt = ['<COMPUTED>'] if dry_run else deduplicate(values)
|
|
32
|
+
if computed_opt:
|
|
33
|
+
computed_opts[key] = computed_opt
|
|
34
|
+
opts[key] = computed_opts[key]
|
|
35
|
+
if computed_inputs:
|
|
36
|
+
debug('computed_inputs', obj=computed_inputs, sub='extractors')
|
|
37
|
+
inputs = computed_inputs
|
|
38
|
+
if computed_opts:
|
|
39
|
+
debug('computed_opts', obj=computed_opts, sub='extractors')
|
|
29
40
|
return inputs, opts, errors
|
|
30
41
|
|
|
31
42
|
|
secator/runners/command.py
CHANGED
|
@@ -84,6 +84,7 @@ class Command(Runner):
|
|
|
84
84
|
install_post = None
|
|
85
85
|
install_cmd = None
|
|
86
86
|
install_github_handle = None
|
|
87
|
+
install_version = None
|
|
87
88
|
|
|
88
89
|
# Serializer
|
|
89
90
|
item_loader = None
|
|
@@ -246,7 +247,7 @@ class Command(Runner):
|
|
|
246
247
|
def get_version_info(cls):
|
|
247
248
|
from secator.installer import get_version_info
|
|
248
249
|
return get_version_info(
|
|
249
|
-
cls.
|
|
250
|
+
cls.cmd.split(' ')[0],
|
|
250
251
|
cls.get_version_flag(),
|
|
251
252
|
cls.install_github_handle,
|
|
252
253
|
cls.install_cmd
|
|
@@ -372,6 +373,7 @@ class Command(Runner):
|
|
|
372
373
|
|
|
373
374
|
# Abort if dry run
|
|
374
375
|
if self.dry_run:
|
|
376
|
+
self._print('')
|
|
375
377
|
self.print_command()
|
|
376
378
|
return
|
|
377
379
|
|
secator/tasks/_categories.py
CHANGED
|
@@ -27,7 +27,7 @@ USER_AGENTS = {
|
|
|
27
27
|
OPTS = {
|
|
28
28
|
HEADER: {'type': str, 'help': 'Custom header to add to each request in the form "KEY1:VALUE1; KEY2:VALUE2"', 'default': 'User-Agent: ' + USER_AGENTS['chrome_134.0_win10']}, # noqa: E501
|
|
29
29
|
DELAY: {'type': float, 'short': 'd', 'help': 'Delay to add between each requests'},
|
|
30
|
-
DEPTH: {'type': int, 'help': 'Scan depth'
|
|
30
|
+
DEPTH: {'type': int, 'help': 'Scan depth'},
|
|
31
31
|
FILTER_CODES: {'type': str, 'short': 'fc', 'help': 'Filter out responses with HTTP codes'},
|
|
32
32
|
FILTER_REGEX: {'type': str, 'short': 'fr', 'help': 'Filter out responses with regular expression'},
|
|
33
33
|
FILTER_SIZE: {'type': str, 'short': 'fs', 'help': 'Filter out responses with size'},
|
|
@@ -41,7 +41,7 @@ OPTS = {
|
|
|
41
41
|
PROXY: {'type': str, 'help': 'HTTP(s) / SOCKS5 proxy'},
|
|
42
42
|
RATE_LIMIT: {'type': int, 'short': 'rl', 'help': 'Rate limit, i.e max number of requests per second'},
|
|
43
43
|
RETRIES: {'type': int, 'help': 'Retries'},
|
|
44
|
-
THREADS: {'type': int, 'help': 'Number of threads to run'
|
|
44
|
+
THREADS: {'type': int, 'help': 'Number of threads to run'},
|
|
45
45
|
TIMEOUT: {'type': int, 'help': 'Request timeout'},
|
|
46
46
|
USER_AGENT: {'type': str, 'short': 'ua', 'help': 'User agent, e.g "Mozilla Firefox 1.0"'},
|
|
47
47
|
WORDLIST: {'type': str, 'short': 'w', 'default': 'http', 'process': process_wordlist, 'help': 'Wordlist to use'}
|
secator/tasks/arjun.py
CHANGED
|
@@ -2,7 +2,8 @@ import os
|
|
|
2
2
|
import yaml
|
|
3
3
|
|
|
4
4
|
from secator.decorators import task
|
|
5
|
-
from secator.definitions import (OUTPUT_PATH, RATE_LIMIT, THREADS, DELAY, TIMEOUT, METHOD, WORDLIST,
|
|
5
|
+
from secator.definitions import (OUTPUT_PATH, RATE_LIMIT, THREADS, DELAY, TIMEOUT, METHOD, WORDLIST,
|
|
6
|
+
HEADER, URL, FOLLOW_REDIRECT)
|
|
6
7
|
from secator.output_types import Info, Url, Warning, Error
|
|
7
8
|
from secator.runners import Command
|
|
8
9
|
from secator.tasks._categories import OPTS
|
|
@@ -31,6 +32,7 @@ class arjun(Command):
|
|
|
31
32
|
RATE_LIMIT: OPTS[RATE_LIMIT],
|
|
32
33
|
METHOD: OPTS[METHOD],
|
|
33
34
|
HEADER: OPTS[HEADER],
|
|
35
|
+
FOLLOW_REDIRECT: OPTS[FOLLOW_REDIRECT],
|
|
34
36
|
}
|
|
35
37
|
opt_key_map = {
|
|
36
38
|
THREADS: 't',
|
|
@@ -44,9 +46,11 @@ class arjun(Command):
|
|
|
44
46
|
'stable': '--stable',
|
|
45
47
|
'passive': '--passive',
|
|
46
48
|
'casing': '--casing',
|
|
49
|
+
'follow_redirect': '--follow-redirect',
|
|
47
50
|
}
|
|
48
51
|
output_types = [Url]
|
|
49
|
-
|
|
52
|
+
install_version = '2.2.7'
|
|
53
|
+
install_cmd = 'pipx install arjun==[install_version] --force'
|
|
50
54
|
install_github_handle = 's0md3v/Arjun'
|
|
51
55
|
|
|
52
56
|
@staticmethod
|
|
@@ -57,6 +61,11 @@ class arjun(Command):
|
|
|
57
61
|
|
|
58
62
|
@staticmethod
|
|
59
63
|
def on_cmd(self):
|
|
64
|
+
follow_redirect = self.get_opt_value(FOLLOW_REDIRECT)
|
|
65
|
+
self.cmd = self.cmd.replace(' --follow-redirect', '')
|
|
66
|
+
if not follow_redirect:
|
|
67
|
+
self.cmd += ' --disable-redirects'
|
|
68
|
+
|
|
60
69
|
self.output_path = self.get_opt_value(OUTPUT_PATH)
|
|
61
70
|
if not self.output_path:
|
|
62
71
|
self.output_path = f'{self.reports_folder}/.outputs/{self.unique_name}.json'
|
secator/tasks/bbot.py
CHANGED
|
@@ -121,6 +121,29 @@ BBOT_PRESETS = [
|
|
|
121
121
|
'web-screenshots',
|
|
122
122
|
'web-thorough'
|
|
123
123
|
]
|
|
124
|
+
BBOT_FLAGS = [
|
|
125
|
+
'active',
|
|
126
|
+
'affiliates',
|
|
127
|
+
'aggressive',
|
|
128
|
+
'baddns',
|
|
129
|
+
'cloud-enum,'
|
|
130
|
+
'code-enum,deadly',
|
|
131
|
+
'email-enum',
|
|
132
|
+
'iis-shortnames',
|
|
133
|
+
'passive',
|
|
134
|
+
'portscan',
|
|
135
|
+
'report',
|
|
136
|
+
'safe',
|
|
137
|
+
'service-enum',
|
|
138
|
+
'slow',
|
|
139
|
+
'social-enum',
|
|
140
|
+
'subdomain-enum',
|
|
141
|
+
'subdomain-hijack',
|
|
142
|
+
'web-basic',
|
|
143
|
+
'web-paramminer',
|
|
144
|
+
'web-screenshots',
|
|
145
|
+
'web-thorough'
|
|
146
|
+
]
|
|
124
147
|
BBOT_MODULES_STR = ' '.join(BBOT_MODULES)
|
|
125
148
|
BBOT_MAP_TYPES = {
|
|
126
149
|
'IP_ADDRESS': Ip,
|
|
@@ -159,12 +182,14 @@ class bbot(Command):
|
|
|
159
182
|
file_flag = None
|
|
160
183
|
version_flag = '--help'
|
|
161
184
|
opts = {
|
|
162
|
-
'modules': {'type': str, 'short': 'm', '
|
|
163
|
-
'presets': {'type': str, 'short': 'ps', '
|
|
185
|
+
'modules': {'type': str, 'short': 'm', 'help': ','.join(BBOT_MODULES)},
|
|
186
|
+
'presets': {'type': str, 'short': 'ps', 'help': ','.join(BBOT_PRESETS), 'shlex': False},
|
|
187
|
+
'flags': {'type': str, 'short': 'fl', 'help': ','.join(BBOT_FLAGS)}
|
|
164
188
|
}
|
|
165
189
|
opt_key_map = {
|
|
166
190
|
'modules': 'm',
|
|
167
|
-
'presets': 'p'
|
|
191
|
+
'presets': 'p',
|
|
192
|
+
'flags': 'f'
|
|
168
193
|
}
|
|
169
194
|
opt_value_map = {
|
|
170
195
|
'presets': lambda x: ' '.join(x.split(','))
|
|
@@ -222,7 +247,8 @@ class bbot(Command):
|
|
|
222
247
|
'apk': ['python3-dev', 'linux-headers', 'musl-dev', 'gcc', 'git', 'openssl', 'unzip', 'tar', 'chromium'],
|
|
223
248
|
'*': ['gcc', 'git', 'openssl', 'unzip', 'tar', 'chromium']
|
|
224
249
|
}
|
|
225
|
-
|
|
250
|
+
install_version = '2.4.2'
|
|
251
|
+
install_cmd = 'pipx install bbot==[install_version] --force'
|
|
226
252
|
install_post = {
|
|
227
253
|
'*': f'rm -fr {CONFIG.dirs.share}/pipx/venvs/bbot/lib/python3.12/site-packages/ansible_collections/*'
|
|
228
254
|
}
|
secator/tasks/bup.py
CHANGED
|
@@ -63,7 +63,8 @@ class bup(Http):
|
|
|
63
63
|
'stored_response_path': 'response_html_filename',
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
|
-
|
|
66
|
+
install_version = '0.4.4'
|
|
67
|
+
install_cmd = 'pipx install bypass-url-parser==[install_version] --force'
|
|
67
68
|
|
|
68
69
|
@staticmethod
|
|
69
70
|
def on_init(self):
|
secator/tasks/cariddi.py
CHANGED
|
@@ -13,12 +13,19 @@ from secator.tasks._categories import HttpCrawler
|
|
|
13
13
|
@task()
|
|
14
14
|
class cariddi(HttpCrawler):
|
|
15
15
|
"""Crawl endpoints, secrets, api keys, extensions, tokens..."""
|
|
16
|
-
cmd = 'cariddi
|
|
16
|
+
cmd = 'cariddi'
|
|
17
17
|
input_type = URL
|
|
18
18
|
input_flag = OPT_PIPE_INPUT
|
|
19
19
|
output_types = [Url, Tag]
|
|
20
20
|
file_flag = OPT_PIPE_INPUT
|
|
21
21
|
json_flag = '-json'
|
|
22
|
+
opts = {
|
|
23
|
+
'info': {'is_flag': True, 'short': 'info', 'help': 'Hunt for useful informations in websites.'},
|
|
24
|
+
'secrets': {'is_flag': True, 'short': 'secrets', 'help': 'Hunt for secrets.'},
|
|
25
|
+
'errors': {'is_flag': True, 'short': 'err', 'help': 'Hunt for errors in websites.'},
|
|
26
|
+
'juicy_extensions': {'type': int, 'short': 'jext', 'help': 'Hunt for juicy file extensions. Integer from 1(juicy) to 7(not juicy)'}, # noqa: E501
|
|
27
|
+
'juicy_endpoints': {'is_flag': True, 'short': 'jep', 'help': 'Hunt for juicy endpoints.'}
|
|
28
|
+
}
|
|
22
29
|
opt_key_map = {
|
|
23
30
|
HEADER: 'headers',
|
|
24
31
|
DELAY: 'd',
|
|
@@ -38,10 +45,15 @@ class cariddi(HttpCrawler):
|
|
|
38
45
|
RETRIES: OPT_NOT_SUPPORTED,
|
|
39
46
|
THREADS: 'c',
|
|
40
47
|
TIMEOUT: 't',
|
|
41
|
-
USER_AGENT: 'ua'
|
|
48
|
+
USER_AGENT: 'ua',
|
|
49
|
+
'secrets': 's',
|
|
50
|
+
'errors': 'err',
|
|
51
|
+
'juicy_endpoints': 'e',
|
|
52
|
+
'juicy_extensions': 'ext'
|
|
42
53
|
}
|
|
43
54
|
item_loaders = [JSONSerializer()]
|
|
44
|
-
|
|
55
|
+
install_version = 'v1.3.6'
|
|
56
|
+
install_cmd = 'go install -v github.com/edoardottt/cariddi/cmd/cariddi@[install_version]'
|
|
45
57
|
install_github_handle = 'edoardottt/cariddi'
|
|
46
58
|
encoding = 'ansi'
|
|
47
59
|
proxychains = False
|
secator/tasks/dalfox.py
CHANGED
|
@@ -55,7 +55,8 @@ class dalfox(VulnHttp):
|
|
|
55
55
|
SEVERITY: lambda x: x['severity'].lower()
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
|
-
|
|
58
|
+
install_version = 'v2.11.0'
|
|
59
|
+
install_cmd = 'go install -v github.com/hahwul/dalfox/v2@latest'
|
|
59
60
|
install_github_handle = 'hahwul/dalfox'
|
|
60
61
|
encoding = 'ansi'
|
|
61
62
|
proxychains = False
|
secator/tasks/dirsearch.py
CHANGED
|
@@ -52,7 +52,7 @@ class dirsearch(HttpFuzzer):
|
|
|
52
52
|
STATUS_CODE: 'status'
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
|
-
install_cmd = 'pipx install
|
|
55
|
+
install_cmd = 'pipx install git+https://github.com/maurosoria/dirsearch.git --force'
|
|
56
56
|
proxychains = True
|
|
57
57
|
proxy_socks5 = True
|
|
58
58
|
proxy_http = True
|
secator/tasks/dnsx.py
CHANGED
|
@@ -26,7 +26,8 @@ class dnsx(ReconDns):
|
|
|
26
26
|
'wildcard_domain': {'type': str, 'short': 'wd', 'help': 'Domain name for wildcard filtering'},
|
|
27
27
|
}
|
|
28
28
|
item_loaders = [JSONSerializer()]
|
|
29
|
-
|
|
29
|
+
install_version = 'v1.2.2'
|
|
30
|
+
install_cmd = 'go install -v github.com/projectdiscovery/dnsx/cmd/dnsx@[install_version]'
|
|
30
31
|
install_github_handle = 'projectdiscovery/dnsx'
|
|
31
32
|
profile = 'io'
|
|
32
33
|
|
secator/tasks/dnsxbrute.py
CHANGED
|
@@ -34,6 +34,7 @@ class dnsxbrute(ReconDns):
|
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
|
-
|
|
37
|
+
install_version = 'v1.2.2'
|
|
38
|
+
install_cmd = 'go install -v github.com/projectdiscovery/dnsx/cmd/dnsx@[install_version]'
|
|
38
39
|
install_github_handle = 'projectdiscovery/dnsx'
|
|
39
40
|
profile = 'io'
|
secator/tasks/feroxbuster.py
CHANGED
|
@@ -6,7 +6,7 @@ from secator.definitions import (CONTENT_TYPE, DELAY, DEPTH, FILTER_CODES,
|
|
|
6
6
|
MATCH_REGEX, MATCH_SIZE, MATCH_WORDS, METHOD,
|
|
7
7
|
OPT_NOT_SUPPORTED, OPT_PIPE_INPUT, PROXY,
|
|
8
8
|
RATE_LIMIT, RETRIES, STATUS_CODE,
|
|
9
|
-
THREADS, TIMEOUT, USER_AGENT, WORDLIST, WORDS
|
|
9
|
+
THREADS, TIMEOUT, USER_AGENT, WORDLIST, WORDS)
|
|
10
10
|
from secator.output_types import Url
|
|
11
11
|
from secator.serializers import JSONSerializer
|
|
12
12
|
from secator.tasks._categories import HttpFuzzer
|
|
@@ -15,7 +15,7 @@ from secator.tasks._categories import HttpFuzzer
|
|
|
15
15
|
@task()
|
|
16
16
|
class feroxbuster(HttpFuzzer):
|
|
17
17
|
"""Simple, fast, recursive content discovery tool written in Rust"""
|
|
18
|
-
cmd =
|
|
18
|
+
cmd = 'feroxbuster --auto-bail --no-state'
|
|
19
19
|
input_flag = '--url'
|
|
20
20
|
input_chunk_size = 1
|
|
21
21
|
file_flag = OPT_PIPE_INPUT
|
|
@@ -62,6 +62,7 @@ class feroxbuster(HttpFuzzer):
|
|
|
62
62
|
install_pre = {
|
|
63
63
|
'*': ['curl', 'bash']
|
|
64
64
|
}
|
|
65
|
+
install_version = 'v2.11.0'
|
|
65
66
|
install_cmd = (
|
|
66
67
|
f'cd /tmp && curl -sL https://raw.githubusercontent.com/epi052/feroxbuster/master/install-nix.sh | bash -s {CONFIG.dirs.bin}' # noqa: E501
|
|
67
68
|
)
|
secator/tasks/ffuf.py
CHANGED
|
@@ -71,7 +71,8 @@ class ffuf(HttpFuzzer):
|
|
|
71
71
|
},
|
|
72
72
|
}
|
|
73
73
|
encoding = 'ansi'
|
|
74
|
-
|
|
74
|
+
install_version = 'v2.1.0'
|
|
75
|
+
install_cmd = 'go install -v github.com/ffuf/ffuf/v2@[install_version]'
|
|
75
76
|
install_github_handle = 'ffuf/ffuf'
|
|
76
77
|
proxychains = False
|
|
77
78
|
proxy_socks5 = True
|
secator/tasks/gau.py
CHANGED
|
@@ -44,7 +44,8 @@ class gau(HttpCrawler):
|
|
|
44
44
|
install_pre = {
|
|
45
45
|
'apk': ['libc6-compat']
|
|
46
46
|
}
|
|
47
|
-
|
|
47
|
+
install_version = 'v2.2.4'
|
|
48
|
+
install_cmd = 'go install -v github.com/lc/gau/v2/cmd/gau@[install_version]'
|
|
48
49
|
install_github_handle = 'lc/gau'
|
|
49
50
|
proxychains = False
|
|
50
51
|
proxy_socks5 = True
|
secator/tasks/gitleaks.py
CHANGED
|
@@ -35,10 +35,11 @@ class gitleaks(Command):
|
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
install_pre = {'*': ['git', 'make']}
|
|
38
|
+
install_version = 'v8.24.3'
|
|
38
39
|
install_cmd = (
|
|
39
|
-
f'git clone https://github.com/gitleaks/gitleaks.git {CONFIG.dirs.share}/
|
|
40
|
-
f'cd {CONFIG.dirs.share}/
|
|
41
|
-
f'mv {CONFIG.dirs.share}/
|
|
40
|
+
f'git clone https://github.com/gitleaks/gitleaks.git {CONFIG.dirs.share}/gitleaks_[install_version] || true &&'
|
|
41
|
+
f'cd {CONFIG.dirs.share}/gitleaks_[install_version] && make build &&'
|
|
42
|
+
f'mv {CONFIG.dirs.share}/gitleaks_[install_version]/gitleaks {CONFIG.dirs.bin}'
|
|
42
43
|
)
|
|
43
44
|
install_github_handle = 'gitleaks/gitleaks'
|
|
44
45
|
|
secator/tasks/gospider.py
CHANGED
|
@@ -15,7 +15,7 @@ from secator.tasks._categories import HttpCrawler
|
|
|
15
15
|
@task()
|
|
16
16
|
class gospider(HttpCrawler):
|
|
17
17
|
"""Fast web spider written in Go."""
|
|
18
|
-
cmd = 'gospider
|
|
18
|
+
cmd = 'gospider'
|
|
19
19
|
file_flag = '-S'
|
|
20
20
|
input_flag = '-s'
|
|
21
21
|
json_flag = '--json'
|
|
@@ -53,7 +53,8 @@ class gospider(HttpCrawler):
|
|
|
53
53
|
CONTENT_LENGTH: 'length',
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
|
-
|
|
56
|
+
install_version = 'v1.1.6'
|
|
57
|
+
install_cmd = 'go install -v github.com/jaeles-project/gospider@[install_version]'
|
|
57
58
|
install_github_handle = 'jaeles-project/gospider'
|
|
58
59
|
proxychains = False
|
|
59
60
|
proxy_socks5 = True # with leaks... https://github.com/jaeles-project/gospider/issues/61
|
secator/tasks/grype.py
CHANGED
secator/tasks/h8mail.py
CHANGED
|
@@ -21,7 +21,8 @@ class h8mail(OSInt):
|
|
|
21
21
|
'config': {'type': str, 'help': 'Configuration file for API keys'},
|
|
22
22
|
'local_breach': {'type': str, 'short': 'lb', 'help': 'Local breach file'}
|
|
23
23
|
}
|
|
24
|
-
|
|
24
|
+
install_version = '2.5.6'
|
|
25
|
+
install_cmd = 'pipx install h8mail==[install_version] --force'
|
|
25
26
|
|
|
26
27
|
@staticmethod
|
|
27
28
|
def on_start(self):
|
secator/tasks/httpx.py
CHANGED
|
@@ -33,7 +33,7 @@ class httpx(Http):
|
|
|
33
33
|
'system_chrome': {'is_flag': True, 'default': False, 'help': 'Use local installed Chrome for screenshot'},
|
|
34
34
|
'headless_options': {'is_flag': False, 'short': 'ho', 'default': None, 'help': 'Headless Chrome additional options'},
|
|
35
35
|
'follow_host_redirects': {'is_flag': True, 'short': 'fhr', 'default': None, 'help': 'Follow redirects on the same host'}, # noqa: E501
|
|
36
|
-
'tech_detect': {'is_flag': True, 'short': 'td', 'default':
|
|
36
|
+
'tech_detect': {'is_flag': True, 'short': 'td', 'default': False, 'help': 'Tech detection'},
|
|
37
37
|
'tls_grab': {'is_flag': True, 'short': 'tlsg', 'default': False, 'help': 'Grab some informations from the tls certificate'}, # noqa: E501
|
|
38
38
|
'rstr': {'type': int, 'default': CONFIG.http.response_max_size_bytes, 'help': 'Max body size to read (bytes)'},
|
|
39
39
|
'rsts': {'type': int, 'default': CONFIG.http.response_max_size_bytes, 'help': 'Max body size to save (bytes)'}
|
|
@@ -68,7 +68,8 @@ class httpx(Http):
|
|
|
68
68
|
install_pre = {
|
|
69
69
|
'apk': ['chromium']
|
|
70
70
|
}
|
|
71
|
-
|
|
71
|
+
install_version = 'v1.7.0'
|
|
72
|
+
install_cmd = 'go install -v github.com/projectdiscovery/httpx/cmd/httpx@[install_version]'
|
|
72
73
|
install_github_handle = 'projectdiscovery/httpx'
|
|
73
74
|
proxychains = False
|
|
74
75
|
proxy_socks5 = True
|
secator/tasks/katana.py
CHANGED
|
@@ -26,8 +26,8 @@ class katana(HttpCrawler):
|
|
|
26
26
|
'form_extraction': {'is_flag': True, 'short': 'fx', 'help': 'Detect forms'},
|
|
27
27
|
'store_responses': {'is_flag': True, 'short': 'sr', 'default': CONFIG.http.store_responses, 'help': 'Store responses'}, # noqa: E501
|
|
28
28
|
'form_fill': {'is_flag': True, 'short': 'ff', 'help': 'Enable form filling'},
|
|
29
|
-
'js_crawl': {'is_flag': True, 'short': 'jc', 'default':
|
|
30
|
-
'jsluice': {'is_flag': True, 'short': 'jsl', 'default':
|
|
29
|
+
'js_crawl': {'is_flag': True, 'short': 'jc', 'default': False, 'help': 'Enable endpoint parsing / crawling in javascript file'}, # noqa: E501
|
|
30
|
+
'jsluice': {'is_flag': True, 'short': 'jsl', 'default': False, 'help': 'Enable jsluice parsing in javascript file (memory intensive)'}, # noqa: E501
|
|
31
31
|
'known_files': {'type': str, 'short': 'kf', 'default': 'all', 'help': 'Enable crawling of known files (all, robotstxt, sitemapxml)'}, # noqa: E501
|
|
32
32
|
'omit_raw': {'is_flag': True, 'short': 'or', 'default': True, 'help': 'Omit raw requests/responses from jsonl output'}, # noqa: E501
|
|
33
33
|
'omit_body': {'is_flag': True, 'short': 'ob', 'default': True, 'help': 'Omit response body from jsonl output'},
|
|
@@ -78,7 +78,8 @@ class katana(HttpCrawler):
|
|
|
78
78
|
install_pre = {
|
|
79
79
|
'apk': ['libc6-compat']
|
|
80
80
|
}
|
|
81
|
-
|
|
81
|
+
install_version = 'v1.1.3'
|
|
82
|
+
install_cmd = 'go install -v github.com/projectdiscovery/katana/cmd/katana@[install_version]'
|
|
82
83
|
install_github_handle = 'projectdiscovery/katana'
|
|
83
84
|
proxychains = False
|
|
84
85
|
proxy_socks5 = True
|
secator/tasks/maigret.py
CHANGED
|
@@ -41,7 +41,7 @@ class maigret(ReconUser):
|
|
|
41
41
|
EXTRA_DATA: lambda x: x['status'].get('ids', {})
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
|
-
install_cmd = 'pipx install git+https://github.com/soxoj/maigret'
|
|
44
|
+
install_cmd = 'pipx install git+https://github.com/soxoj/maigret --force'
|
|
45
45
|
socks5_proxy = True
|
|
46
46
|
profile = 'io'
|
|
47
47
|
|
secator/tasks/mapcidr.py
CHANGED
|
@@ -16,7 +16,8 @@ class mapcidr(ReconIp):
|
|
|
16
16
|
install_pre = {
|
|
17
17
|
'apk': ['libc6-compat']
|
|
18
18
|
}
|
|
19
|
-
|
|
19
|
+
install_version = 'v1.1.34'
|
|
20
|
+
install_cmd = 'go install -v github.com/projectdiscovery/mapcidr/cmd/mapcidr@[install_version]'
|
|
20
21
|
install_github_handle = 'projectdiscovery/mapcidr'
|
|
21
22
|
input_type = CIDR_RANGE
|
|
22
23
|
output_types = [Ip]
|
secator/tasks/msfconsole.py
CHANGED
|
@@ -48,14 +48,15 @@ class msfconsole(VulnMulti):
|
|
|
48
48
|
'pacman': ['ruby-erb', 'postgresql-libs', 'make'],
|
|
49
49
|
'yum|zypper': ['postgresql-devel', 'make'],
|
|
50
50
|
}
|
|
51
|
+
install_version = '6.4.59'
|
|
51
52
|
install_cmd = (
|
|
52
|
-
f'git clone --depth 1 --single-branch https://github.com/rapid7/metasploit-framework.git {CONFIG.dirs.share}/metasploit-
|
|
53
|
-
f'cd {CONFIG.dirs.share}/metasploit-
|
|
53
|
+
f'git clone --depth 1 --single-branch -b [install_version] https://github.com/rapid7/metasploit-framework.git {CONFIG.dirs.share}/metasploit-framework_[install_version] || true && ' # noqa: E501
|
|
54
|
+
f'cd {CONFIG.dirs.share}/metasploit-framework_[install_version] && '
|
|
54
55
|
f'gem install bundler --user-install -n {CONFIG.dirs.bin} && '
|
|
55
56
|
f'bundle config set --local path "{CONFIG.dirs.share}" && '
|
|
56
57
|
'bundle lock --normalize-platforms &&'
|
|
57
58
|
'bundle install && '
|
|
58
|
-
f'ln -sf $HOME/.local/share/metasploit-
|
|
59
|
+
f'ln -sf $HOME/.local/share/metasploit-framework_[install_version]/msfconsole {CONFIG.dirs.bin}/msfconsole'
|
|
59
60
|
)
|
|
60
61
|
|
|
61
62
|
@staticmethod
|
secator/tasks/naabu.py
CHANGED
|
@@ -10,7 +10,7 @@ from secator.tasks._categories import ReconPort
|
|
|
10
10
|
@task()
|
|
11
11
|
class naabu(ReconPort):
|
|
12
12
|
"""Port scanning tool written in Go."""
|
|
13
|
-
cmd = 'naabu
|
|
13
|
+
cmd = 'naabu'
|
|
14
14
|
input_flag = '-host'
|
|
15
15
|
file_flag = '-list'
|
|
16
16
|
json_flag = '-json'
|
|
@@ -18,6 +18,7 @@ class naabu(ReconPort):
|
|
|
18
18
|
PORTS: {'type': str, 'short': 'p', 'help': 'Ports'},
|
|
19
19
|
TOP_PORTS: {'type': str, 'short': 'tp', 'help': 'Top ports'},
|
|
20
20
|
'scan_type': {'type': str, 'short': 'st', 'help': 'Scan type (SYN (s)/CONNECT(c))'},
|
|
21
|
+
'skip_host_discovery': {'is_flag': True, 'short': 'Pn', 'default': False, 'help': 'Skip host discovery'},
|
|
21
22
|
# 'health_check': {'is_flag': True, 'short': 'hc', 'help': 'Health check'}
|
|
22
23
|
}
|
|
23
24
|
opt_key_map = {
|
|
@@ -47,7 +48,8 @@ class naabu(ReconPort):
|
|
|
47
48
|
}
|
|
48
49
|
}
|
|
49
50
|
output_types = [Port]
|
|
50
|
-
|
|
51
|
+
install_version = 'v2.3.3'
|
|
52
|
+
install_cmd = 'go install -v github.com/projectdiscovery/naabu/v2/cmd/naabu@[install_version]'
|
|
51
53
|
install_github_handle = 'projectdiscovery/naabu'
|
|
52
54
|
install_pre = {'apt': ['libpcap-dev'], 'apk': ['libpcap-dev', 'libc6-compat'], 'pacman|brew': ['libpcap']}
|
|
53
55
|
install_post = {'arch|alpine': 'sudo ln -sf /usr/lib/libpcap.so /usr/lib/libpcap.so.0.8'}
|