secator 0.10.1a12__py3-none-any.whl → 0.11.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of secator might be problematic. Click here for more details.

Files changed (40) hide show
  1. secator/celery.py +10 -5
  2. secator/celery_signals.py +2 -11
  3. secator/cli.py +153 -46
  4. secator/config.py +2 -2
  5. secator/configs/workflows/url_params_fuzz.yaml +23 -0
  6. secator/configs/workflows/wordpress.yaml +4 -1
  7. secator/decorators.py +10 -5
  8. secator/definitions.py +3 -0
  9. secator/installer.py +46 -32
  10. secator/output_types/__init__.py +2 -1
  11. secator/output_types/certificate.py +78 -0
  12. secator/output_types/user_account.py +1 -1
  13. secator/rich.py +1 -1
  14. secator/runners/_base.py +14 -6
  15. secator/runners/_helpers.py +4 -3
  16. secator/runners/command.py +81 -21
  17. secator/runners/scan.py +5 -3
  18. secator/runners/workflow.py +22 -4
  19. secator/tasks/_categories.py +12 -4
  20. secator/tasks/arjun.py +82 -0
  21. secator/tasks/ffuf.py +2 -1
  22. secator/tasks/fping.py +1 -0
  23. secator/tasks/gitleaks.py +76 -0
  24. secator/tasks/grype.py +1 -1
  25. secator/tasks/mapcidr.py +1 -1
  26. secator/tasks/naabu.py +7 -1
  27. secator/tasks/nmap.py +29 -29
  28. secator/tasks/subfinder.py +1 -1
  29. secator/tasks/testssl.py +274 -0
  30. secator/tasks/trivy.py +95 -0
  31. secator/tasks/wafw00f.py +83 -0
  32. secator/tasks/wpprobe.py +94 -0
  33. secator/template.py +49 -67
  34. secator/utils.py +16 -7
  35. secator/utils_test.py +26 -8
  36. {secator-0.10.1a12.dist-info → secator-0.11.1.dist-info}/METADATA +1 -1
  37. {secator-0.10.1a12.dist-info → secator-0.11.1.dist-info}/RECORD +40 -32
  38. {secator-0.10.1a12.dist-info → secator-0.11.1.dist-info}/WHEEL +0 -0
  39. {secator-0.10.1a12.dist-info → secator-0.11.1.dist-info}/entry_points.txt +0 -0
  40. {secator-0.10.1a12.dist-info → secator-0.11.1.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,83 @@
1
+ import os
2
+ import yaml
3
+
4
+ from secator.decorators import task
5
+ from secator.runners import Command
6
+ from secator.definitions import (OUTPUT_PATH, HEADER, PROXY, URL, TIMEOUT)
7
+ from secator.output_types import Tag, Info, Error
8
+ from secator.tasks._categories import OPTS
9
+
10
+
11
+ @task()
12
+ class wafw00f(Command):
13
+ """Web Application Firewall Fingerprinting tool."""
14
+ cmd = 'wafw00f'
15
+ input_type = URL
16
+ input_flag = None
17
+ file_flag = '-i'
18
+ json_flag = '-f json'
19
+ encoding = 'ansi'
20
+ opt_prefix = '--'
21
+ meta_opts = {
22
+ PROXY: OPTS[PROXY],
23
+ HEADER: OPTS[HEADER],
24
+ TIMEOUT: OPTS[TIMEOUT]
25
+ }
26
+ opts = {
27
+ 'list': {'is_flag': True, 'default': False, 'help': 'List all WAFs that WAFW00F is able to detect'},
28
+ 'waf_type': {'type': str, 'short': 'wt', 'help': 'Test for one specific WAF'},
29
+ 'find_all': {'is_flag': True, 'short': 'ta', 'default': False, 'help': 'Find all WAFs which match the signatures, do not stop testing on the first one'}, # noqa: E501
30
+ 'no_follow_redirects': {'is_flag': True, 'short': 'nfr', 'default': False, 'help': 'Do not follow redirections given by 3xx responses'}, # noqa: E501
31
+ }
32
+ opt_key_map = {
33
+ HEADER: 'headers',
34
+ PROXY: 'proxy',
35
+ 'waf_type': 'test',
36
+ 'find_all': 'findall',
37
+ 'no_follow_redirects': 'noredirect',
38
+ }
39
+ output_types = [Tag]
40
+ install_cmd = 'pipx install git+https://github.com/EnableSecurity/wafw00f.git && pipx upgrade wafw00f'
41
+ install_github_handle = 'EnableSecurity/wafw00f'
42
+ proxy_http = True
43
+
44
+ @staticmethod
45
+ def on_cmd(self):
46
+ self.output_path = self.get_opt_value(OUTPUT_PATH)
47
+ if not self.output_path:
48
+ self.output_path = f'{self.reports_folder}/.outputs/{self.unique_name}.json'
49
+ self.cmd += f' -o {self.output_path}'
50
+
51
+ self.headers = self.get_opt_value(HEADER)
52
+ if self.headers:
53
+ header_file = f'{self.reports_folder}/.inputs/headers.txt'
54
+ with open(header_file, 'w') as f:
55
+ for header in self.headers.split(';;'):
56
+ f.write(f'{header}\n')
57
+ self.cmd = self.cmd.replace(self.headers, header_file)
58
+
59
+ @staticmethod
60
+ def on_cmd_done(self):
61
+ # Skip parsing if list mode
62
+ list_mode = self.get_opt_value('list')
63
+ if list_mode:
64
+ return
65
+
66
+ if not os.path.exists(self.output_path):
67
+ yield Error(message=f'Could not find JSON results in {self.output_path}')
68
+ return
69
+
70
+ yield Info(message=f'JSON results saved to {self.output_path}')
71
+ with open(self.output_path, 'r') as f:
72
+ results = yaml.safe_load(f.read())
73
+
74
+ if len(results) > 0 and results[0]['detected']:
75
+ waf_name = results[0]['firewall']
76
+ url = results[0]['url']
77
+ match = results[0]['trigger_url']
78
+ manufacter = results[0]['manufacturer']
79
+ yield Tag(
80
+ name=waf_name + ' WAF',
81
+ match=url,
82
+ extra_data={'waf_name': waf_name, 'manufacter': manufacter, 'trigger_url': match}
83
+ )
@@ -0,0 +1,94 @@
1
+ import click
2
+ import yaml
3
+
4
+ from secator.decorators import task
5
+ from secator.runners import Command
6
+ from secator.definitions import OUTPUT_PATH, THREADS, URL
7
+ from secator.output_types import Vulnerability, Tag, Info, Warning
8
+ from secator.tasks._categories import OPTS
9
+
10
+
11
+ @task()
12
+ class wpprobe(Command):
13
+ """Fast wordpress plugin enumeration tool."""
14
+ cmd = 'wpprobe'
15
+ file_flag = '-f'
16
+ input_flag = '-u'
17
+ input_type = URL
18
+ opt_prefix = '-'
19
+ opts = {
20
+ 'mode': {'type': click.Choice(['scan', 'update', 'update-db']), 'default': 'scan', 'help': 'WPProbe mode', 'required': True, 'internal': True}, # noqa: E501
21
+ 'output_path': {'type': str, 'default': None, 'help': 'Output JSON file path', 'internal': True, 'display': False}, # noqa: E501
22
+ }
23
+ meta_opts = {
24
+ THREADS: OPTS[THREADS]
25
+ }
26
+ opt_key_map = {
27
+ THREADS: 't'
28
+ }
29
+ output_types = [Vulnerability, Tag]
30
+ install_cmd = 'go install github.com/Chocapikk/wpprobe@latest'
31
+ install_github_handle = 'Chocapikk/wpprobe'
32
+ install_post = {
33
+ '*': 'wpprobe update && wpprobe update-db'
34
+ }
35
+
36
+ @staticmethod
37
+ def on_cmd(self):
38
+ mode = self.get_opt_value('mode')
39
+ if mode == 'update' or mode == 'update-db':
40
+ self.cmd = f'{wpprobe.cmd} {mode}'
41
+ return
42
+ self.cmd = self.cmd.replace(wpprobe.cmd, f'{wpprobe.cmd} {mode}')
43
+ output_path = self.get_opt_value(OUTPUT_PATH)
44
+ if not output_path:
45
+ output_path = f'{self.reports_folder}/.outputs/{self.unique_name}.json'
46
+ self.output_path = output_path
47
+ self.cmd += f' -o {self.output_path}'
48
+
49
+ @staticmethod
50
+ def on_cmd_done(self):
51
+ if not self.get_opt_value('mode') == 'scan':
52
+ return
53
+ yield Info(message=f'JSON results saved to {self.output_path}')
54
+ with open(self.output_path, 'r') as f:
55
+ results = yaml.safe_load(f.read())
56
+ if not results or 'url' not in results:
57
+ yield Warning(message='No results found !')
58
+ return
59
+ url = results['url']
60
+ for plugin_name, plugin_data in results['plugins'].items():
61
+ for plugin_data_version in plugin_data:
62
+ plugin_version = plugin_data_version['version']
63
+ yield Tag(
64
+ name=f'Wordpress plugin - {plugin_name} {plugin_version}',
65
+ match=url,
66
+ extra_data={
67
+ 'name': plugin_name,
68
+ 'version': plugin_version
69
+ }
70
+ )
71
+ severities = plugin_data_version.get('severities', {})
72
+ for severity, severity_data in severities.items():
73
+ if severity == 'None':
74
+ severity = 'unknown'
75
+ for item in severity_data:
76
+ for vuln in item['vulnerabilities']:
77
+ auth_type = item.get('auth_type')
78
+ extra_data = {
79
+ 'plugin_name': plugin_name,
80
+ 'plugin_version': plugin_version,
81
+ }
82
+ if auth_type:
83
+ extra_data['auth_type'] = auth_type
84
+ yield Vulnerability(
85
+ name=vuln['title'],
86
+ id=vuln['cve'],
87
+ severity=severity,
88
+ cvss_score=vuln['cvss_score'],
89
+ tags=[plugin_name],
90
+ reference=vuln['cve_link'],
91
+ extra_data=extra_data,
92
+ matched_at=url,
93
+ confidence='high'
94
+ )
secator/template.py CHANGED
@@ -8,85 +8,44 @@ from dotmap import DotMap
8
8
 
9
9
  from secator.config import CONFIG, CONFIGS_FOLDER
10
10
  from secator.rich import console
11
- from secator.utils import convert_functions_to_strings
11
+ from secator.utils import convert_functions_to_strings, debug
12
+ from secator.output_types import Error
12
13
 
13
-
14
- TEMPLATES_DIR_KEYS = ['workflow', 'scan', 'profile']
15
-
16
-
17
- def load_template(name):
18
- """Load a config by name.
19
-
20
- Args:
21
- name: Name of the config, for instances profiles/aggressive or workflows/domain_scan.
22
-
23
- Returns:
24
- dict: Loaded config.
25
- """
26
- path = CONFIGS_FOLDER / f'{name}.yaml'
27
- if not path.exists():
28
- console.log(f'Config "{name}" could not be loaded.')
29
- return
30
- with path.open('r') as f:
31
- return yaml.load(f.read(), Loader=yaml.Loader)
32
-
33
-
34
- def find_templates():
35
- results = {'scan': [], 'workflow': [], 'profile': []}
36
- dirs_type = [CONFIGS_FOLDER]
37
- if CONFIG.dirs.templates:
38
- dirs_type.append(CONFIG.dirs.templates)
39
- paths = []
40
- for dir in dirs_type:
41
- dir_paths = [
42
- Path(path)
43
- for path in glob.glob(str(dir).rstrip('/') + '/**/*.y*ml', recursive=True)
44
- ]
45
- paths.extend(dir_paths)
46
- for path in paths:
47
- with path.open('r') as f:
48
- try:
49
- config = yaml.load(f.read(), yaml.Loader)
50
- type = config.get('type')
51
- if type:
52
- results[type].append(path)
53
- except yaml.YAMLError as exc:
54
- console.log(f'Unable to load config at {path}')
55
- console.log(str(exc))
56
- return results
14
+ TEMPLATES = []
57
15
 
58
16
 
59
17
  class TemplateLoader(DotMap):
60
18
 
61
19
  def __init__(self, input={}, name=None, **kwargs):
62
20
  if name:
63
- name = name.replace('-', '_') # so that workflows have a nice '-' in CLI
64
- config = self._load_from_name(name)
65
- elif isinstance(input, str) or isinstance(input, Path):
66
- config = self._load_from_file(input)
67
- else:
21
+ if '/' not in name:
22
+ console.print(Error(message=f'Cannot load {name}: you should specify a type for the template when loading by name (e.g. workflow/<workflow_name>)')) # noqa: E501
23
+ return
24
+ _type, name = name.split('/')
25
+ config = next((p for p in TEMPLATES if p['type'] == _type and p['name'] == name in str(p)), None)
26
+ if not config:
27
+ console.print(Error(message=f'Template {name} not found in loaded templates'))
28
+ config = {}
29
+ elif isinstance(input, dict):
68
30
  config = input
69
- super().__init__(config)
31
+ elif isinstance(input, Path) or Path(input).exists():
32
+ config = self._load_from_path(input)
33
+ elif isinstance(input, str):
34
+ config = self._load(input)
35
+ super().__init__(config, **kwargs)
36
+
37
+ def add_to_templates(self):
38
+ TEMPLATES.append(self)
70
39
 
71
- def _load_from_file(self, path):
72
- if isinstance(path, str):
73
- path = Path(path)
40
+ def _load_from_path(self, path):
74
41
  if not path.exists():
75
- console.log(f'Config path {path} does not exists', style='bold red')
42
+ console.print(Error(message=f'Config path {path} does not exists'))
76
43
  return
77
44
  with path.open('r') as f:
78
- return yaml.load(f.read(), Loader=yaml.Loader)
45
+ return self._load(f.read())
79
46
 
80
- def _load_from_name(self, name):
81
- return load_template(name)
82
-
83
- @classmethod
84
- def load_all(cls):
85
- configs = find_templates()
86
- return TemplateLoader({
87
- key: [TemplateLoader(path) for path in configs[key]]
88
- for key in TEMPLATES_DIR_KEYS
89
- })
47
+ def _load(self, input):
48
+ return yaml.load(input, Loader=yaml.Loader)
90
49
 
91
50
  @property
92
51
  def supported_opts(self):
@@ -141,7 +100,7 @@ class TemplateLoader(DotMap):
141
100
  # For each workflow in the scan, load it and incorporate it with a unique prefix
142
101
  for wf_name, _ in self.workflows.items():
143
102
  name = wf_name.split('/')[0]
144
- config = TemplateLoader(name=f'workflows/{name}')
103
+ config = TemplateLoader(name=f'workflow/{name}')
145
104
  wf_tasks = config.flat_tasks
146
105
  # Prefix tasks from this workflow with its name to prevent collision
147
106
  for task_key, task_val in wf_tasks.items():
@@ -153,3 +112,26 @@ class TemplateLoader(DotMap):
153
112
  parse_config(self.tasks)
154
113
 
155
114
  return dict(tasks)
115
+
116
+
117
+ def find_templates():
118
+ results = []
119
+ dirs = [CONFIGS_FOLDER]
120
+ if CONFIG.dirs.templates:
121
+ dirs.append(CONFIG.dirs.templates)
122
+ paths = []
123
+ for dir in dirs:
124
+ config_paths = [
125
+ Path(path)
126
+ for path in glob.glob(str(dir).rstrip('/') + '/**/*.y*ml', recursive=True)
127
+ ]
128
+ debug(f'Found {len(config_paths)} templates in {dir}', sub='template')
129
+ paths.extend(config_paths)
130
+ for path in paths:
131
+ config = TemplateLoader(input=path)
132
+ debug(f'Loaded template from {path}', sub='template')
133
+ results.append(config)
134
+ return results
135
+
136
+
137
+ TEMPLATES = find_templates()
secator/utils.py CHANGED
@@ -373,11 +373,15 @@ def rich_to_ansi(text):
373
373
  Returns:
374
374
  str: Converted text (ANSI).
375
375
  """
376
- from rich.console import Console
377
- tmp_console = Console(file=None, highlight=False)
378
- with tmp_console.capture() as capture:
379
- tmp_console.print(text, end='', soft_wrap=True)
380
- return capture.get()
376
+ try:
377
+ from rich.console import Console
378
+ tmp_console = Console(file=None, highlight=False)
379
+ with tmp_console.capture() as capture:
380
+ tmp_console.print(text, end='', soft_wrap=True)
381
+ return capture.get()
382
+ except Exception:
383
+ console.print(f'[bold red]Could not convert rich text to ansi: {text}[/]', highlight=False, markup=False)
384
+ return text
381
385
 
382
386
 
383
387
  def rich_escape(obj):
@@ -459,6 +463,10 @@ def escape_mongodb_url(url):
459
463
  return url
460
464
 
461
465
 
466
+ def caml_to_snake(s):
467
+ return re.sub(r'(?<!^)(?=[A-Z])', '_', s).lower()
468
+
469
+
462
470
  def print_version():
463
471
  """Print secator version information."""
464
472
  from secator.installer import get_version_info
@@ -773,8 +781,9 @@ def process_wordlist(val):
773
781
  val = default_wordlist
774
782
  template_wordlist = getattr(CONFIG.wordlists.templates, val)
775
783
  if template_wordlist:
776
- return template_wordlist
777
- elif Path(val).exists():
784
+ val = template_wordlist
785
+
786
+ if Path(val).exists():
778
787
  return val
779
788
  else:
780
789
  return download_file(
secator/utils_test.py CHANGED
@@ -14,7 +14,7 @@ from secator.cli import ALL_WORKFLOWS, ALL_TASKS, ALL_SCANS
14
14
  from secator.output_types import EXECUTION_TYPES, STAT_TYPES
15
15
  from secator.runners import Command
16
16
  from secator.rich import console
17
- from secator.utils import load_fixture
17
+ from secator.utils import load_fixture, debug
18
18
 
19
19
  #---------#
20
20
  # GLOBALS #
@@ -60,7 +60,8 @@ INPUTS_TASKS = {
60
60
  USERNAME: 'test',
61
61
  IP: '192.168.1.23',
62
62
  CIDR_RANGE: '192.168.1.0/24',
63
- EMAIL: 'fake@fake.com'
63
+ EMAIL: 'fake@fake.com',
64
+ 'folder': '.'
64
65
  }
65
66
 
66
67
  #---------------------#
@@ -97,11 +98,18 @@ META_OPTS = {
97
98
  'nmap.skip_host_discovery': True,
98
99
  'msfconsole.resource': load_fixture('msfconsole_input', FIXTURES_DIR, only_path=True),
99
100
  'dirsearch.output_path': load_fixture('dirsearch_output', FIXTURES_DIR, only_path=True),
101
+ 'gitleaks_output_path': load_fixture('gitleaks_output', FIXTURES_DIR, only_path=True),
100
102
  'maigret.output_path': load_fixture('maigret_output', FIXTURES_DIR, only_path=True),
101
103
  'nuclei.template_id': 'prometheus-metrics',
102
104
  'wpscan.output_path': load_fixture('wpscan_output', FIXTURES_DIR, only_path=True),
103
105
  'h8mail.output_path': load_fixture('h8mail_output', FIXTURES_DIR, only_path=True),
104
- 'h8mail.local_breach': load_fixture('h8mail_breach', FIXTURES_DIR, only_path=True)
106
+ 'h8mail.local_breach': load_fixture('h8mail_breach', FIXTURES_DIR, only_path=True),
107
+ 'wpprobe.output_path': load_fixture('wpprobe_output', FIXTURES_DIR, only_path=True),
108
+ 'arjun.output_path': load_fixture('arjun_output', FIXTURES_DIR, only_path=True),
109
+ 'arjun.wordlist': False,
110
+ 'trivy.output_path': load_fixture('trivy_output', FIXTURES_DIR, only_path=True),
111
+ 'wafw00f.output_path': load_fixture('wafw00f_output', FIXTURES_DIR, only_path=True),
112
+ 'testssl.output_path': load_fixture('testssl_output', FIXTURES_DIR, only_path=True),
105
113
  }
106
114
 
107
115
 
@@ -158,17 +166,20 @@ class CommandOutputTester: # Mixin for unittest.TestCase
158
166
  empty_results_allowed=False):
159
167
 
160
168
  console.print(f'[dim]Testing {runner.config.type} {runner.name} ...[/]', end='')
169
+ debug('', sub='unittest')
161
170
 
162
171
  if not runner.inputs:
163
172
  console.print('[dim gold3] skipped (no inputs defined).[/]')
164
173
  return
165
174
 
166
- if not expected_results and not expected_output_keys:
175
+ if not expected_results and not expected_output_keys and not expected_output_types:
167
176
  console.print('[dim gold3] (no outputs defined).[/]', end='')
168
177
 
169
178
  try:
170
179
  # Run runner
171
180
  results = runner.run()
181
+ for result in results:
182
+ debug(result.toDict(), sub='unittest')
172
183
 
173
184
  # Add execution types to allowed output types
174
185
  expected_output_types.extend(EXECUTION_TYPES + STAT_TYPES)
@@ -176,32 +187,39 @@ class CommandOutputTester: # Mixin for unittest.TestCase
176
187
  # Check return code
177
188
  if isinstance(runner, Command):
178
189
  if not runner.ignore_return_code:
179
- self.assertEqual(runner.return_code, 0, f'{runner.name} should have a 0 return code')
190
+ debug(f'{runner.name} should have a 0 return code', sub='unittest')
191
+ self.assertEqual(runner.return_code, 0, f'{runner.name} should have a 0 return code. Runner return code: {runner.return_code}') # noqa: E501
180
192
 
181
193
  # Check results not empty
182
194
  if not empty_results_allowed:
195
+ debug(f'{runner.name} should return at least 1 result', sub='unittest')
183
196
  self.assertGreater(len(results), 0, f'{runner.name} should return at least 1 result')
184
197
 
185
198
  # Check status
186
- self.assertEqual(runner.status, expected_status, f'{runner.name} should have the status {expected_status}')
199
+ debug(f'{runner.name} should have the status {expected_status}.', sub='unittest')
200
+ self.assertEqual(runner.status, expected_status, f'{runner.name} should have the status {expected_status}. Errors: {runner.errors}') # noqa: E501
187
201
 
188
202
  # Check results
189
203
  for item in results:
204
+ debug(f'{runner.name} yielded {repr(item)}', sub='unittest')
190
205
 
191
206
  if expected_output_types:
207
+ debug(f'{runner.name} item should have an output type in {[_._type for _ in expected_output_types]}', sub='unittest') # noqa: E501
192
208
  self.assertIn(type(item), expected_output_types, f'{runner.name}: item has an unexpected output type "{type(item)}"') # noqa: E501
193
209
 
194
210
  if expected_output_keys:
195
211
  keys = [k for k in list(item.keys()) if not k.startswith('_')]
212
+ debug(f'{runner.name} item should have output keys {keys}', sub='unittest')
196
213
  self.assertEqual(
197
214
  set(keys).difference(set(expected_output_keys)),
198
215
  set(),
199
- f'{runner.name}: item is missing expected keys {set(expected_output_keys)}')
216
+ f'{runner.name}: item is missing expected keys {set(expected_output_keys)}. Item keys: {keys}') # noqa: E501
200
217
 
201
218
  # Check if runner results in expected results
202
219
  if expected_results:
203
220
  for result in expected_results:
204
- self.assertIn(result, results, f'{runner.name}: {result} should be in runner results')
221
+ debug(f'{runner.name} item should be in expected results {result}.', sub='unittest')
222
+ self.assertIn(result, results, f'{runner.name}: {result} should be in runner results.') # noqa: E501
205
223
 
206
224
  except Exception:
207
225
  console.print('[dim red] failed[/]')
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: secator
3
- Version: 0.10.1a12
3
+ Version: 0.11.1
4
4
  Summary: The pentester's swiss knife.
5
5
  Project-URL: Homepage, https://github.com/freelabz/secator
6
6
  Project-URL: Issues, https://github.com/freelabz/secator/issues
@@ -1,19 +1,19 @@
1
1
  secator/.gitignore,sha256=da8MUc3hdb6Mo0WjZu2upn5uZMbXcBGvhdhTQ1L89HI,3093
2
2
  secator/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- secator/celery.py,sha256=o-8s9TNaApVVeYanok0SzvmGD_zsSMzf55DgERjnUgs,9635
4
- secator/celery_signals.py,sha256=iumfx7tTeoavAbHijBtij0JzeIqElxQldNZtuZmFY_U,4456
3
+ secator/celery.py,sha256=Xg8e0zpQu4_-jlsZeC65NZtkopHGsGIyQ3SiW5fyH4E,9771
4
+ secator/celery_signals.py,sha256=hG62Gr34xKJYZTgZFn_wZcsAlMgKuTazQhx55FC5cDA,4259
5
5
  secator/celery_utils.py,sha256=_wcUC42VPUotPhh9YYqbuq0dkARI8_RoCklDlhQL9Jg,8903
6
- secator/cli.py,sha256=KweGQaeGaZ53lGsrdmbrHqqHpFrGh8m4KQgARucHHG4,44022
7
- secator/config.py,sha256=CdVBh6d4k13SpkQKyHQfMFHgkLypUH07kAKLmCJJO1w,19688
8
- secator/decorators.py,sha256=3kYadCz6haIZtnjkFHSRfenTdc6Yu7bHd-0IVjhD72w,13902
9
- secator/definitions.py,sha256=gFtLT9fjNtX_1qkiCjNfQyCvYq07IhScsQzX4o20_SE,3084
10
- secator/installer.py,sha256=Q5qmGbxGmuhysEA9YovTpy-YY2TxxFskhrzSX44c42E,17971
6
+ secator/cli.py,sha256=f_ySIOXyHmFwH3cSElxdXlnDGAYH72VXPFDhx0q9pnY,48866
7
+ secator/config.py,sha256=Nuwhkd9jh-5TTq6e7M9SmfZWyBjblbjMsNz1Mba32zg,19692
8
+ secator/decorators.py,sha256=Ac926Sxt7HvR5JTvpy5uqa4oxKWBXzx5VpeAOHJevJ4,14197
9
+ secator/definitions.py,sha256=f8Otl2MLo2XAVcl-CqbZ1PP4fAi-WXCTq5YfDhOzCR8,3201
10
+ secator/installer.py,sha256=mxtt-TK1rr6uuw7nECZgrw3031rac5P2wWtXBUeuD4c,18937
11
11
  secator/report.py,sha256=55xKvYY0MKNPaEgTrx66mj-Siohx3drLbTX2LpEx6zs,3627
12
- secator/rich.py,sha256=owmuLcTTUt8xYBTE3_SqWTkPeAomcU_8bPdW_V-U8VM,3264
13
- secator/template.py,sha256=Sb6PjCTGIkZ7I0OGWFp5CaXmjt-6VPe_xpcRhWhjGpU,4409
12
+ secator/rich.py,sha256=0P6TECNePsfivc5h1JsJoAqKmpFnME5m8k29ZJjvbwM,3277
13
+ secator/template.py,sha256=8EVsRRDAzNeALqTMzO9cNtxiXSbpSi0Nw7uSBb2Hbs0,4167
14
14
  secator/thread.py,sha256=rgRgEtcMgs2wyfLWVlCTUCLWeg6jsMo5iKpyyrON5rY,655
15
- secator/utils.py,sha256=6PfR0uixpLszVLWVJIHVNhkV4YZDU-r5cP6kz7THYoU,21830
16
- secator/utils_test.py,sha256=ArHwkWW89t0IDqxO4HjJWd_tm7tp1illP4pu3nLq5yo,6559
15
+ secator/utils.py,sha256=kaBqWgBmUZohlvn6nFY805tG26viIu_LdJysNfZWMY4,22055
16
+ secator/utils_test.py,sha256=jiCvgL4JMhIC1-ZGe6j9umNRZreSDp6nlkMgEJhf5ho,7996
17
17
  secator/configs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
18
  secator/configs/profiles/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
19
  secator/configs/profiles/aggressive.yaml,sha256=JilVySABlSCYEFMjH7V0Oc3dAVlkfHOh1odTGhtm7BQ,108
@@ -35,9 +35,10 @@ secator/configs/workflows/url_crawl.yaml,sha256=h74dvDBNLuY1EHc9FMby3ydr34VH1qFJ
35
35
  secator/configs/workflows/url_dirsearch.yaml,sha256=wiiVY3RK0s8DYxg7UWcxLjkxMdIIINWefG1mhps2E-0,627
36
36
  secator/configs/workflows/url_fuzz.yaml,sha256=K1RkplXrgc7q2YJVv5A6B5MMkAzIIv31HInhRCKMpyI,774
37
37
  secator/configs/workflows/url_nuclei.yaml,sha256=Qigz-hJzM7GeNA_UD46dThVIoqbWlBgiYb_i5fSyJiI,265
38
+ secator/configs/workflows/url_params_fuzz.yaml,sha256=ooOMxQDtuYq3jR2GOU6e-69H4bLvsq-CzemGFvmktjY,647
38
39
  secator/configs/workflows/url_vuln.yaml,sha256=_nX_D96NbD8fHU4wXov7ZHD1cmiFgKc86Mh0enWGS7s,1354
39
40
  secator/configs/workflows/user_hunt.yaml,sha256=e5b-CkkjhOPE8Yh5LUh0K60GKmxTgn4s-Joo7m9jKrk,180
40
- secator/configs/workflows/wordpress.yaml,sha256=QgBUNi8Gav_efbmczUGfzlByWsmogTmGtu1MwAlvQts,279
41
+ secator/configs/workflows/wordpress.yaml,sha256=m80JdK2G9O5TGxk_BTiRjzhrXrLJQz0a1foIOQTKp3U,341
41
42
  secator/exporters/__init__.py,sha256=PnT9Ra4ArHt9VQTK5Cpc4CPY89XRwLLUGtZ8nUcknm0,415
42
43
  secator/exporters/_base.py,sha256=-RrrwO_qp0ETLLHSta4T-zKtMbWdiEmz1Cw5mNo6USU,77
43
44
  secator/exporters/console.py,sha256=idVotf9B0LnYZ4JQJHrgMtVfE26XkRDuvbCyJvCY2hU,249
@@ -49,8 +50,9 @@ secator/exporters/txt.py,sha256=oMtr22di6cqyE_5yJoiWP-KElrI5QgvK1cOUrj7H7js,730
49
50
  secator/hooks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
50
51
  secator/hooks/gcs.py,sha256=MIhntyWYz9BZdTXhWl5JznaczSq1_7fl3TVqPufuTSo,1490
51
52
  secator/hooks/mongodb.py,sha256=XKbm_SrcSbQ2koILWvhzSg4tqdvHXgX5aU5x46Edu1s,7716
52
- secator/output_types/__init__.py,sha256=L3q9NXPaW0TGeidx5YH-6dWhOXD1GizztAcL2lqIA8Q,1221
53
+ secator/output_types/__init__.py,sha256=CJcYy2_Ek-opKiBz4wFlDHQBTm3t0JVwZ4w_2Jxoeuw,1291
53
54
  secator/output_types/_base.py,sha256=OgS6ICt66TzPsqo1JZwRIIwbng2HRX1i_u5qbUECgNk,2820
55
+ secator/output_types/certificate.py,sha256=G2Z39UIT037oSujf8BwwgXXBIEVWSI-Oc-PorhyYT38,3346
54
56
  secator/output_types/error.py,sha256=39gpEJfKM2EuyOhD9lSkjjna2QicMvnLdFav6kHmhlg,1529
55
57
  secator/output_types/exploit.py,sha256=-BKTqPBg94rVgjw8YSmcYuBCI2x-73WwMd9ITP9qr3Y,1750
56
58
  secator/output_types/info.py,sha256=R8xeiD3ocNOsvkJPhrQgsx6q-Ea1G0eTAqyuh5JrAR0,843
@@ -64,24 +66,25 @@ secator/output_types/subdomain.py,sha256=ivJ_2kmrJ8hdB8wmvRJYlKV1BcE3Cds_vAI_5wL
64
66
  secator/output_types/tag.py,sha256=_XEqWAvAvmi7nd2ldfEE71zQx97jTSph2iDHkeqGTyk,1470
65
67
  secator/output_types/target.py,sha256=lmPw2aFOGIOFG4XXo6vNVZBBAZlnApJjyDVepDY54TU,871
66
68
  secator/output_types/url.py,sha256=gTGShwXIA2mA9cBLP7_I4qA5XUP-EYB1xnPRLtUDAi8,2912
67
- secator/output_types/user_account.py,sha256=rm10somxyu30JHjj629IkR15Nhahylud_fVO8j2pdR0,1417
69
+ secator/output_types/user_account.py,sha256=EvF3Ebg9eXS_-iDguU1dSHZ9wAsJimEJznDvpSt_RSY,1417
68
70
  secator/output_types/vulnerability.py,sha256=nF7OT9zGez8sZvLrkhjBOORjVi8hCqfCYUFq3eZ_ywo,2870
69
71
  secator/output_types/warning.py,sha256=47GtmG083GqGPb_R5JDFmARJ9Mqrme58UxwJhgdGPuI,853
70
72
  secator/runners/__init__.py,sha256=EBbOk37vkBy9p8Hhrbi-2VtM_rTwQ3b-0ggTyiD22cE,290
71
- secator/runners/_base.py,sha256=C50WhU1WC8y69kLVqlR-to_ijwzh0Lgkf2j8bVTFy0M,31416
72
- secator/runners/_helpers.py,sha256=QhJmdmFdu5XSx3LBFf4Q4Hy2EXS6bLGnJUq8G7C6f68,2410
73
+ secator/runners/_base.py,sha256=bd_k3xn1DMxt7RaWhiaSI9zN_qbN_sTUrmwh7j2_xmk,31657
74
+ secator/runners/_helpers.py,sha256=_2pyPgDK0obqlOEYJRDrqJgvDntz_zL483spFLtGSXs,2514
73
75
  secator/runners/celery.py,sha256=bqvDTTdoHiGRCt0FRvlgFHQ_nsjKMP5P0PzGbwfCj_0,425
74
- secator/runners/command.py,sha256=0iabT_5kXClU7WSD30qT-bAFMJqA2NjRgaT52TZxJO0,25479
75
- secator/runners/scan.py,sha256=L-6YfdgeVXjTEHiSriwNVFyBmSCNhHTj-6A7R9lka6c,1532
76
+ secator/runners/command.py,sha256=rb1g7Sj-GfA5T4klz1ClgQWSY0Ut_wBqBFbLSwVq158,26847
77
+ secator/runners/scan.py,sha256=n8RL9vXPmNqukdB2a5wcPhSmxsZB4KFaqtZt0wfa8dU,1622
76
78
  secator/runners/task.py,sha256=LIgcBqORVPG5Kfx6g6RnEni1kgWchMfa3Oo2JEZri1Y,2037
77
- secator/runners/workflow.py,sha256=AchWBPVKKqmuVGU7ihEzB6kZeVso309YHl7ayeKSbDM,3302
79
+ secator/runners/workflow.py,sha256=sO3B9GcndQLgGPnDz-A6XKnBmYO_ABAU_UXpW-q1K1A,3890
78
80
  secator/scans/__init__.py,sha256=s4Ojsk5CWwyWqHu_A4zaXUL5Hm5L5nCmCHZn7wdD3Io,623
79
81
  secator/serializers/__init__.py,sha256=OP5cmFl77ovgSCW_IDcZ21St2mUt5UK4QHfrsK2KvH8,248
80
82
  secator/serializers/dataclass.py,sha256=RqICpfsYWGjHAACAA2h2jZ_69CFHim4VZwcBqowGMcQ,1010
81
83
  secator/serializers/json.py,sha256=UJwAymRzjF-yBKOgz1MTOyBhQcdQg7fOKRXgmHIu8fo,411
82
84
  secator/serializers/regex.py,sha256=fh-fE0RGvKSGKByFtwmKsWriRpZR9PXZQsY9JybHBWI,489
83
85
  secator/tasks/__init__.py,sha256=yRIZf9E47aS7o6rpgAJLgJUpX2cug1ofZeq8QsxgyjU,192
84
- secator/tasks/_categories.py,sha256=IWyBprIUBZxflh7QfvK27Ix18M_bnquzlERqfTZohVs,13821
86
+ secator/tasks/_categories.py,sha256=kpFyTsFlcFlf4Veqa5CfLvODODGKP8VKsYgCfFg5iUI,14387
87
+ secator/tasks/arjun.py,sha256=viuFJtSk1-UBLQF_5Yl5dJEcx_-JDKs2eHAcn8NdBrg,2581
85
88
  secator/tasks/bbot.py,sha256=pvA435toxYBxP-Nr6DB70fe38FGl9tKg2S9dDWUW4Vo,7527
86
89
  secator/tasks/bup.py,sha256=4PM123Km3uOkMUwfdLY6J7pyCqIsbwMvOLYx7XYCAZc,3030
87
90
  secator/tasks/cariddi.py,sha256=7S92pp7tvihoz9fAiMpmcfPzEvxEJKMlk-IqAvVDISA,2906
@@ -90,27 +93,32 @@ secator/tasks/dirsearch.py,sha256=DF-yXHANHb3ARgMOUbqpRuHc8-mE3bteHwTkFpXQtKc,22
90
93
  secator/tasks/dnsx.py,sha256=nK14_DeyX0QTpAMdIP0LSSEOEu5_tQemyFW0XPjA2f8,2266
91
94
  secator/tasks/dnsxbrute.py,sha256=5VnSpd5ken7vWxFX1bcsGcUN8LpaVhcjafnuETzkMGs,1422
92
95
  secator/tasks/feroxbuster.py,sha256=3bKolPIdDBhdJ2fu4BP3w1cOlxDyI8WmtM-_2pDQ0AM,2773
93
- secator/tasks/ffuf.py,sha256=VGrtjFgSX6Q1I8h1wjPO5XwBFCfZXmn0DQsn9gxEUXc,2468
94
- secator/tasks/fping.py,sha256=9nMIahBMizRwsos9py-ltXMEffIiyx1reVytj9sTyKU,1089
96
+ secator/tasks/ffuf.py,sha256=YmMBttdInDLsOGNeDM17c0POQLNxILHdYkLiGeKO9wY,2551
97
+ secator/tasks/fping.py,sha256=OFF_uR3YzXhQJcb-ObdY178cHHjnJBPXtjMjdzVSlGI,1116
95
98
  secator/tasks/gau.py,sha256=1Qt0I_FqTh-QyJ0YR8I7i_T80HehWSvem_SS-TQKVm0,1648
96
99
  secator/tasks/gf.py,sha256=y8Fc0sRLGqNuwUjTBgLk3HEw3ZOnh09nB_GTufGErNA,962
100
+ secator/tasks/gitleaks.py,sha256=Y8q3rOTvuvfmZ4tG3awng2vG7NJLxkLZBzE0mLFat6o,2500
97
101
  secator/tasks/gospider.py,sha256=mpoBq2VQXUqgwWPLz41fzdW85hJeo8mn9FUUJj_DrUw,2275
98
- secator/tasks/grype.py,sha256=xoOuldnHCrS0O1Y4IzjbSVvoX5eX-fLSZ74THdRC2so,2447
102
+ secator/tasks/grype.py,sha256=ay85FlOyWeYGwQR-O0_qMTatHmfjrdzub1WeLFDnRng,2456
99
103
  secator/tasks/h8mail.py,sha256=wNukV-aB-bXPZNq7WL8n1nFgH5b5tGh6vOF80Yna33I,1934
100
104
  secator/tasks/httpx.py,sha256=ONfCdAOV7ARCM9tSnlucIAM3UQeWcMUm8QZX8F7u9Pg,5895
101
105
  secator/tasks/katana.py,sha256=J0HKPT4QIrDj4uW2gZe7ByW6iEwPortSszqaHDvziwY,5355
102
106
  secator/tasks/maigret.py,sha256=6anhBzB4lEM90Lk23cAD_ku7I_ghTpj0W0i3h6HARD8,2088
103
- secator/tasks/mapcidr.py,sha256=56ocbaDmB5_C_ns-773CgZXGOKOtkI9q9xJs2Rlfqio,990
107
+ secator/tasks/mapcidr.py,sha256=bw5NMLfNj3k48MaoDGFu30fJh0pHASgPXEO2LqlzMA8,982
104
108
  secator/tasks/msfconsole.py,sha256=TXVrvzSWw9Ncv2h9QJtaEinTMbps_z0zX1PFirERVho,6430
105
- secator/tasks/naabu.py,sha256=LjtyX3RTsME6RegVWm3VshzREmufRfFQ9Pn0WC4hqeE,2089
106
- secator/tasks/nmap.py,sha256=191jBXlZ3jpGMfJxEsTOG9lGaMB7EQCWA630JSiMx_E,16144
109
+ secator/tasks/naabu.py,sha256=anIGoaPlfmiaZ_HqVs9GTVzm3yYgYMKEcIQ5k5HYCPI,2214
110
+ secator/tasks/nmap.py,sha256=ZQJnlratjEqASHXb05QYknX2J1gWaZAN3-O4Y1Dw3UA,16970
107
111
  secator/tasks/nuclei.py,sha256=bMXCRU5VWyrwI7Cv6BCj84NTpfjuALFumPqUSZ4Y6Ug,4243
108
112
  secator/tasks/searchsploit.py,sha256=gvtLZbL2hzAZ07Cf0cSj2Qs0GvWK94XyHvoPFsetXu8,3321
109
- secator/tasks/subfinder.py,sha256=C6W5NnXT92OUB1aSS9IYseqdI3wDMAz70TOEl8X-o3U,1213
113
+ secator/tasks/subfinder.py,sha256=dfn_Cd2rqDqeh8aJde0gFwLMNc8-UcEK276iTU7wM4Q,1205
114
+ secator/tasks/testssl.py,sha256=xjv0cUW_K9KT3Yeon71v8OrdJUJSE4JWmbumViPgNes,11460
115
+ secator/tasks/trivy.py,sha256=vf68wXnhM_7N-RAcyyA1MnKl3cb75zc-i0E9ibXudv8,3204
116
+ secator/tasks/wafw00f.py,sha256=sjjaDSch5gfo6vRFJ0j4ccdGHGda9YodHwuIHBEIWY8,2717
117
+ secator/tasks/wpprobe.py,sha256=wDwpbA4OvLB-APDyRMSsLZbfgOZ60c0BiYj5f7zHQg8,3983
110
118
  secator/tasks/wpscan.py,sha256=cSRwRfJEsZlqt1pVP3jWQ-7XhFfwR3i7FuL1PDRyWBQ,5594
111
119
  secator/workflows/__init__.py,sha256=R_TTyjg9f2Ph2_LYiF0lL07IjTrfRE_zqJzy-N7_WCk,675
112
- secator-0.10.1a12.dist-info/METADATA,sha256=f6diMPN0-xfjMEASdER9XSOhvfVhEa-2gIHTuK5wliA,14727
113
- secator-0.10.1a12.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
114
- secator-0.10.1a12.dist-info/entry_points.txt,sha256=lPgsqqUXWgiuGSfKy-se5gHdQlAXIwS_A46NYq7Acic,44
115
- secator-0.10.1a12.dist-info/licenses/LICENSE,sha256=19W5Jsy4WTctNkqmZIqLRV1gTDOp01S3LDj9iSgWaJ0,2867
116
- secator-0.10.1a12.dist-info/RECORD,,
120
+ secator-0.11.1.dist-info/METADATA,sha256=eAUM8aG26_2gLv0BqVvSq7lk823S6QGdWxmctEin_DM,14724
121
+ secator-0.11.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
122
+ secator-0.11.1.dist-info/entry_points.txt,sha256=lPgsqqUXWgiuGSfKy-se5gHdQlAXIwS_A46NYq7Acic,44
123
+ secator-0.11.1.dist-info/licenses/LICENSE,sha256=19W5Jsy4WTctNkqmZIqLRV1gTDOp01S3LDj9iSgWaJ0,2867
124
+ secator-0.11.1.dist-info/RECORD,,