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.

Files changed (48) hide show
  1. secator/cli.py +175 -66
  2. secator/config.py +1 -0
  3. secator/configs/workflows/host_recon.yaml +11 -2
  4. secator/configs/workflows/port_scan.yaml +39 -0
  5. secator/configs/workflows/url_dirsearch.yaml +5 -0
  6. secator/configs/workflows/url_params_fuzz.yaml +2 -0
  7. secator/decorators.py +39 -21
  8. secator/definitions.py +0 -4
  9. secator/installer.py +29 -15
  10. secator/runners/_base.py +2 -1
  11. secator/runners/_helpers.py +13 -2
  12. secator/runners/command.py +3 -1
  13. secator/tasks/_categories.py +2 -2
  14. secator/tasks/arjun.py +11 -2
  15. secator/tasks/bbot.py +30 -4
  16. secator/tasks/bup.py +2 -1
  17. secator/tasks/cariddi.py +15 -3
  18. secator/tasks/dalfox.py +2 -1
  19. secator/tasks/dirsearch.py +1 -1
  20. secator/tasks/dnsx.py +2 -1
  21. secator/tasks/dnsxbrute.py +2 -1
  22. secator/tasks/feroxbuster.py +3 -2
  23. secator/tasks/ffuf.py +2 -1
  24. secator/tasks/gau.py +2 -1
  25. secator/tasks/gitleaks.py +4 -3
  26. secator/tasks/gospider.py +3 -2
  27. secator/tasks/grype.py +1 -0
  28. secator/tasks/h8mail.py +2 -1
  29. secator/tasks/httpx.py +3 -2
  30. secator/tasks/katana.py +4 -3
  31. secator/tasks/maigret.py +1 -1
  32. secator/tasks/mapcidr.py +2 -1
  33. secator/tasks/msfconsole.py +4 -3
  34. secator/tasks/naabu.py +4 -2
  35. secator/tasks/nuclei.py +15 -9
  36. secator/tasks/searchsploit.py +3 -2
  37. secator/tasks/subfinder.py +2 -1
  38. secator/tasks/testssl.py +4 -3
  39. secator/tasks/trivy.py +2 -2
  40. secator/tasks/wafw00f.py +2 -1
  41. secator/tasks/wpprobe.py +2 -1
  42. secator/tasks/wpscan.py +6 -3
  43. secator/template.py +12 -0
  44. {secator-0.11.1.dist-info → secator-0.13.0.dist-info}/METADATA +1 -1
  45. {secator-0.11.1.dist-info → secator-0.13.0.dist-info}/RECORD +48 -47
  46. {secator-0.11.1.dist-info → secator-0.13.0.dist-info}/WHEEL +0 -0
  47. {secator-0.11.1.dist-info → secator-0.13.0.dist-info}/entry_points.txt +0 -0
  48. {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
- latest_release = cls.get_latest_release(github_handle)
227
- if not latest_release:
228
- return InstallerStatus.GITHUB_LATEST_RELEASE_NOT_FOUND
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(latest_release['assets'], os_identifiers, arch_identifiers)
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.GITHUB_RELEASE_NOT_FOUND
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 get_latest_release(cls, github_handle):
243
- """Get latest release from GitHub.
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: Latest release JSON from GitHub releases.
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
- url = f"https://api.github.com/repos/{owner}/{repo}/releases/latest"
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.get_latest_release(github_handle)
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.filter_results(results)
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')
@@ -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
- inputs = ['<COMPUTED>'] if dry_run else deduplicate(values)
28
+ targets = ['<COMPUTED>'] if dry_run else deduplicate(values)
29
+ computed_inputs.extend(targets)
27
30
  else:
28
- opts[key] = ['<COMPUTED>'] if dry_run else deduplicate(values)
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
 
@@ -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.__name__,
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
 
@@ -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', 'default': 2},
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', 'default': 50},
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, HEADER, URL)
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
- install_cmd = 'pipx install arjun && pipx upgrade arjun'
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', 'default': '', 'help': ','.join(BBOT_MODULES)},
163
- 'presets': {'type': str, 'short': 'ps', 'default': 'kitchen-sink', 'help': ','.join(BBOT_PRESETS), 'shlex': False},
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
- install_cmd = 'pipx install bbot && pipx upgrade bbot'
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
- install_cmd = 'pipx install bypass-url-parser && pipx upgrade bypass-url-parser'
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 -info -s -err -e -ext 1'
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
- install_cmd = 'go install -v github.com/edoardottt/cariddi/cmd/cariddi@latest'
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
- install_cmd = 'go install -v github.com/hahwul/dalfox/v2@v2.9.3'
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
@@ -52,7 +52,7 @@ class dirsearch(HttpFuzzer):
52
52
  STATUS_CODE: 'status'
53
53
  }
54
54
  }
55
- install_cmd = 'pipx install --force git+https://github.com/maurosoria/dirsearch'
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
- install_cmd = 'go install -v github.com/projectdiscovery/dnsx/cmd/dnsx@latest'
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
 
@@ -34,6 +34,7 @@ class dnsxbrute(ReconDns):
34
34
  }
35
35
  }
36
36
  }
37
- install_cmd = 'go install -v github.com/projectdiscovery/dnsx/cmd/dnsx@latest'
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'
@@ -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, DEFAULT_FEROXBUSTER_FLAGS)
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 = f'feroxbuster {DEFAULT_FEROXBUSTER_FLAGS}'
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
- install_cmd = 'go install -v github.com/ffuf/ffuf@latest'
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
- install_cmd = 'go install -v github.com/lc/gau/v2/cmd/gau@latest'
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}/gitleaks || true &&'
40
- f'cd {CONFIG.dirs.share}/gitleaks && make build &&'
41
- f'mv {CONFIG.dirs.share}/gitleaks/gitleaks {CONFIG.dirs.bin}'
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 --js'
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
- install_cmd = 'go install -v github.com/jaeles-project/gospider@latest'
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
@@ -30,6 +30,7 @@ class grype(VulnCode):
30
30
  install_pre = {
31
31
  '*': ['curl']
32
32
  }
33
+ install_version = 'v0.91.2'
33
34
  install_cmd = (
34
35
  f'curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b {CONFIG.dirs.bin}'
35
36
  )
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
- install_cmd = 'pipx install h8mail && pipx upgrade h8mail'
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': True, 'help': 'Tech detection'},
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
- install_cmd = 'go install -v github.com/projectdiscovery/httpx/cmd/httpx@latest'
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': True, 'help': 'Enable endpoint parsing / crawling in javascript file'}, # noqa: E501
30
- 'jsluice': {'is_flag': True, 'short': 'jsl', 'default': True, 'help': 'Enable jsluice parsing in javascript file (memory intensive)'}, # noqa: E501
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
- install_cmd = 'go install -v github.com/projectdiscovery/katana/cmd/katana@latest'
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
- install_cmd = 'go install -v github.com/projectdiscovery/mapcidr/cmd/mapcidr@latest'
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]
@@ -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-framework || true && ' # noqa: E501
53
- f'cd {CONFIG.dirs.share}/metasploit-framework && '
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-framework/msfconsole {CONFIG.dirs.bin}/msfconsole'
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 -Pn'
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
- install_cmd = 'go install -v github.com/projectdiscovery/naabu/v2/cmd/naabu@v2.3.3'
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'}