secator 0.12.0__py3-none-any.whl → 0.14.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 (56) hide show
  1. secator/cli.py +199 -66
  2. secator/configs/profiles/aggressive.yaml +6 -5
  3. secator/configs/profiles/default.yaml +6 -7
  4. secator/configs/profiles/insane.yaml +8 -0
  5. secator/configs/profiles/paranoid.yaml +8 -0
  6. secator/configs/profiles/polite.yaml +8 -0
  7. secator/configs/profiles/sneaky.yaml +8 -0
  8. secator/configs/profiles/tor.yaml +5 -0
  9. secator/configs/workflows/host_recon.yaml +11 -2
  10. secator/configs/workflows/url_dirsearch.yaml +5 -0
  11. secator/decorators.py +1 -0
  12. secator/definitions.py +0 -4
  13. secator/installer.py +29 -15
  14. secator/report.py +2 -2
  15. secator/runners/_base.py +32 -1
  16. secator/runners/_helpers.py +13 -2
  17. secator/runners/command.py +2 -1
  18. secator/runners/scan.py +1 -0
  19. secator/runners/task.py +1 -0
  20. secator/tasks/_categories.py +2 -2
  21. secator/tasks/arjun.py +2 -1
  22. secator/tasks/bbot.py +30 -4
  23. secator/tasks/bup.py +2 -1
  24. secator/tasks/cariddi.py +15 -3
  25. secator/tasks/dalfox.py +2 -1
  26. secator/tasks/dirsearch.py +1 -1
  27. secator/tasks/dnsx.py +2 -1
  28. secator/tasks/dnsxbrute.py +2 -1
  29. secator/tasks/feroxbuster.py +3 -2
  30. secator/tasks/ffuf.py +2 -1
  31. secator/tasks/gau.py +2 -1
  32. secator/tasks/gitleaks.py +4 -3
  33. secator/tasks/gospider.py +3 -2
  34. secator/tasks/grype.py +1 -0
  35. secator/tasks/h8mail.py +2 -1
  36. secator/tasks/httpx.py +3 -2
  37. secator/tasks/katana.py +4 -3
  38. secator/tasks/maigret.py +1 -1
  39. secator/tasks/mapcidr.py +2 -1
  40. secator/tasks/msfconsole.py +4 -3
  41. secator/tasks/naabu.py +4 -2
  42. secator/tasks/nuclei.py +15 -9
  43. secator/tasks/searchsploit.py +3 -2
  44. secator/tasks/subfinder.py +2 -1
  45. secator/tasks/testssl.py +4 -3
  46. secator/tasks/trivy.py +2 -2
  47. secator/tasks/wafw00f.py +2 -1
  48. secator/tasks/wpprobe.py +2 -1
  49. secator/tasks/wpscan.py +6 -3
  50. secator/template.py +1 -1
  51. {secator-0.12.0.dist-info → secator-0.14.0.dist-info}/METADATA +1 -1
  52. {secator-0.12.0.dist-info → secator-0.14.0.dist-info}/RECORD +55 -51
  53. secator/configs/profiles/stealth.yaml +0 -7
  54. {secator-0.12.0.dist-info → secator-0.14.0.dist-info}/WHEEL +0 -0
  55. {secator-0.12.0.dist-info → secator-0.14.0.dist-info}/entry_points.txt +0 -0
  56. {secator-0.12.0.dist-info → secator-0.14.0.dist-info}/licenses/LICENSE +0 -0
secator/report.py CHANGED
@@ -55,7 +55,7 @@ class Report:
55
55
  f'{str(e)}[/]\n[dim]{traceback_as_string(e)}[/]',
56
56
  )
57
57
 
58
- def build(self, extractors=[], dedupe=False):
58
+ def build(self, extractors=[], dedupe=CONFIG.runners.remove_duplicates):
59
59
  # Trim options
60
60
  from secator.decorators import DEFAULT_CLI_OPTIONS
61
61
  opts = merge_opts(self.runner.config.options, self.runner.run_opts)
@@ -97,7 +97,7 @@ class Report:
97
97
  if items:
98
98
  if sort_by and all(sort_by):
99
99
  items = sorted(items, key=operator.attrgetter(*sort_by))
100
- if dedupe and CONFIG.runners.remove_duplicates:
100
+ if dedupe:
101
101
  items = remove_duplicates(items)
102
102
  # items = [item for item in items if not item._duplicate and item not in dedupe_from]
103
103
  for extractor in extractors:
secator/runners/_base.py CHANGED
@@ -130,13 +130,18 @@ 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')
137
138
  self.debug('Run opts', obj={k: v for k, v in self.run_opts.items() if v is not None}, sub='init')
138
139
  self.debug('Print opts', obj={k: v for k, v in self.print_opts.items() if v is not None}, sub='init')
139
140
 
141
+ # Load profiles
142
+ profiles_str = run_opts.get('profiles', [])
143
+ self.load_profiles(profiles_str)
144
+
140
145
  # Determine exporters
141
146
  exporters_str = self.run_opts.get('output') or self.default_exporters
142
147
  self.exporters = self.resolve_exporters(exporters_str)
@@ -952,6 +957,32 @@ class Runner:
952
957
  ]
953
958
  return [cls for cls in classes if cls]
954
959
 
960
+ def load_profiles(self, profiles):
961
+ """Load profiles and update run options.
962
+
963
+ Args:
964
+ profiles (list[str]): List of profile names to resolve.
965
+
966
+ Returns:
967
+ list: List of profiles.
968
+ """
969
+ from secator.cli import ALL_PROFILES
970
+ if isinstance(profiles, str):
971
+ profiles = profiles.split(',')
972
+ templates = []
973
+ for pname in profiles:
974
+ matches = [p for p in ALL_PROFILES if p.name == pname]
975
+ if not matches:
976
+ self._print(Warning(message=f'Profile "{pname}" was not found'), rich=True)
977
+ else:
978
+ templates.append(matches[0])
979
+ opts = {}
980
+ for profile in templates:
981
+ self._print(Info(message=f'Loaded profile {profile.name} ({profile.description})'), rich=True)
982
+ opts.update(profile.opts)
983
+ opts = {k: v for k, v in opts.items() if k not in self.run_opts}
984
+ self.run_opts.update(opts)
985
+
955
986
  @classmethod
956
987
  def get_func_path(cls, func):
957
988
  """Get the full symbolic path of a function or method, including staticmethods, using function and method
@@ -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
secator/runners/scan.py CHANGED
@@ -33,6 +33,7 @@ class Scan(Runner):
33
33
  sigs = []
34
34
  for name, workflow_opts in self.config.workflows.items():
35
35
  run_opts = self.run_opts.copy()
36
+ run_opts.pop('profiles', None)
36
37
  run_opts['no_poll'] = True
37
38
  run_opts['caller'] = 'Scan'
38
39
  opts = merge_opts(scan_opts, workflow_opts, run_opts)
secator/runners/task.py CHANGED
@@ -32,6 +32,7 @@ class Task(Runner):
32
32
  # Run opts
33
33
  opts = self.run_opts.copy()
34
34
  opts.pop('output', None)
35
+ opts.pop('profiles', None)
35
36
  opts.pop('no_poll', False)
36
37
 
37
38
  # Set output types
@@ -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
@@ -49,7 +49,8 @@ class arjun(Command):
49
49
  'follow_redirect': '--follow-redirect',
50
50
  }
51
51
  output_types = [Url]
52
- install_cmd = 'pipx install arjun && pipx upgrade arjun'
52
+ install_version = '2.2.7'
53
+ install_cmd = 'pipx install arjun==[install_version] --force'
53
54
  install_github_handle = 's0md3v/Arjun'
54
55
 
55
56
  @staticmethod
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'}
secator/tasks/nuclei.py CHANGED
@@ -18,17 +18,22 @@ class nuclei(VulnMulti):
18
18
  input_flag = '-u'
19
19
  json_flag = '-jsonl'
20
20
  opts = {
21
- 'templates': {'type': str, 'short': 't', 'help': 'Templates'},
22
- 'tags': {'type': str, 'help': 'Tags'},
23
- 'exclude_tags': {'type': str, 'short': 'etags', 'help': 'Exclude tags'},
24
- 'exclude_severity': {'type': str, 'short': 'es', 'help': 'Exclude severity'},
25
- 'template_id': {'type': str, 'short': 'tid', 'help': 'Template id'},
21
+ 'bulk_size': {'type': int, 'short': 'bs', 'help': 'Maximum number of hosts to be analyzed in parallel per template'}, # noqa: E501
26
22
  'debug': {'type': str, 'help': 'Debug mode'},
23
+ 'exclude_severity': {'type': str, 'short': 'es', 'help': 'Exclude severity'},
24
+ 'exclude_tags': {'type': str, 'short': 'etags', 'help': 'Exclude tags'},
25
+ 'input_mode': {'type': str, 'short': 'im', 'help': 'Mode of input file (list, burp, jsonl, yaml, openapi, swagger)'},
26
+ 'hang_monitor': {'is_flag': True, 'short': 'hm', 'default': True, 'help': 'Enable nuclei hang monitoring'},
27
+ 'headless_bulk_size': {'type': int, 'short': 'hbs', 'help': 'Maximum number of headless hosts to be analzyed in parallel per template'}, # noqa: E501
28
+ 'new_templates': {'type': str, 'short': 'nt', 'help': 'Run only new templates added in latest nuclei-templates release'}, # noqa: E501
29
+ 'automatic_scan': {'is_flag': True, 'short': 'as', 'help': 'Automatic web scan using wappalyzer technology detection to tags mapping'}, # noqa: E501
30
+ 'omit_raw': {'is_flag': True, 'short': 'or', 'default': True, 'help': 'Omit requests/response pairs in the JSON, JSONL, and Markdown outputs (for findings only)'}, # noqa: E501
27
31
  'stats': {'is_flag': True, 'short': 'stats', 'default': True, 'help': 'Display statistics about the running scan'},
28
32
  'stats_json': {'is_flag': True, 'short': 'sj', 'default': True, 'help': 'Display statistics in JSONL(ines) format'},
29
- 'stats_interval': {'type': str, 'short': 'si', 'default': 20, 'help': 'Number of seconds to wait between showing a statistics update'}, # noqa: E501
30
- 'hang_monitor': {'is_flag': True, 'short': 'hm', 'default': True, 'help': 'Enable nuclei hang monitoring'},
31
- 'omit_raw': {'is_flag': True, 'short': 'or', 'default': True, 'help': 'Omit requests/response pairs in the JSON, JSONL, and Markdown outputs (for findings only)'} # noqa: E501
33
+ 'stats_interval': {'type': str, 'short': 'si', 'help': 'Number of seconds to wait between showing a statistics update'}, # noqa: E501
34
+ 'tags': {'type': str, 'help': 'Tags'},
35
+ 'templates': {'type': str, 'short': 't', 'help': 'Templates'},
36
+ 'template_id': {'type': str, 'short': 'tid', 'help': 'Template id'},
32
37
  }
33
38
  opt_key_map = {
34
39
  HEADER: 'header',
@@ -76,7 +81,8 @@ class nuclei(VulnMulti):
76
81
  install_pre = {
77
82
  '*': ['git']
78
83
  }
79
- install_cmd = 'go install -v github.com/projectdiscovery/nuclei/v2/cmd/nuclei@latest'
84
+ install_version = 'v3.4.2'
85
+ install_cmd = 'go install -v github.com/projectdiscovery/nuclei/v3/cmd/nuclei@[install_version]'
80
86
  install_github_handle = 'projectdiscovery/nuclei'
81
87
  install_post = {
82
88
  '*': 'nuclei -ut'
@@ -41,9 +41,10 @@ class searchsploit(Command):
41
41
  install_pre = {
42
42
  'apk': ['ncurses']
43
43
  }
44
+ install_version = '2025-04-23'
44
45
  install_cmd = (
45
- f'git clone --depth 1 --single-branch https://gitlab.com/exploit-database/exploitdb.git {CONFIG.dirs.share}/exploitdb || true && ' # noqa: E501
46
- f'ln -sf $HOME/.local/share/exploitdb/searchsploit {CONFIG.dirs.bin}/searchsploit'
46
+ f'git clone --depth 1 --single-branch -b [install_version] https://gitlab.com/exploit-database/exploitdb.git {CONFIG.dirs.share}/exploitdb_[install_version] || true && ' # noqa: E501
47
+ f'ln -sf $HOME/.local/share/exploitdb_[install_version]/searchsploit {CONFIG.dirs.bin}/searchsploit'
47
48
  )
48
49
  proxychains = False
49
50
  proxy_socks5 = False
@@ -31,7 +31,8 @@ class subfinder(ReconDns):
31
31
  }
32
32
  }
33
33
  output_types = [Subdomain]
34
- install_cmd = 'go install -v github.com/projectdiscovery/subfinder/v2/cmd/subfinder@latest'
34
+ install_version = 'v2.7.0'
35
+ install_cmd = 'go install -v github.com/projectdiscovery/subfinder/v2/cmd/subfinder@[install_version]'
35
36
  install_github_handle = 'projectdiscovery/subfinder'
36
37
  proxychains = False
37
38
  proxy_http = True
secator/tasks/testssl.py CHANGED
@@ -48,13 +48,14 @@ class testssl(Command):
48
48
  proxy_socks5 = False
49
49
  profile = 'io'
50
50
  install_pre = {
51
- 'apk': ['hexdump'],
51
+ 'apk': ['hexdump', 'coreutils', 'procps'],
52
52
  'pacman': ['util-linux'],
53
53
  '*': ['bsdmainutils']
54
54
  }
55
+ install_version = 'v3.2.0'
55
56
  install_cmd = (
56
- f'git clone --depth 1 https://github.com/drwetter/testssl.sh.git {CONFIG.dirs.share}/testssl.sh || true && '
57
- f'ln -sf {CONFIG.dirs.share}/testssl.sh/testssl.sh {CONFIG.dirs.bin}'
57
+ f'git clone --depth 1 --single-branch -b [install_version] https://github.com/drwetter/testssl.sh.git {CONFIG.dirs.share}/testssl.sh_[install_version] || true && ' # noqa: E501
58
+ f'ln -sf {CONFIG.dirs.share}/testssl.sh_[install_version]/testssl.sh {CONFIG.dirs.bin}'
58
59
  )
59
60
 
60
61
  @staticmethod