secator 0.3.6__py3-none-any.whl → 0.4.1__py3-none-any.whl

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

Potentially problematic release.


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

secator/tasks/nmap.py CHANGED
@@ -4,16 +4,19 @@ import re
4
4
 
5
5
  import xmltodict
6
6
 
7
+ from secator.config import CONFIG
7
8
  from secator.decorators import task
8
9
  from secator.definitions import (CONFIDENCE, CVSS_SCORE, DELAY,
9
10
  DESCRIPTION, EXTRA_DATA, FOLLOW_REDIRECT,
10
11
  HEADER, HOST, ID, IP, MATCHED_AT, NAME,
11
12
  OPT_NOT_SUPPORTED, OUTPUT_PATH, PORT, PORTS, PROVIDER,
12
13
  PROXY, RATE_LIMIT, REFERENCE, REFERENCES,
13
- RETRIES, SCRIPT, SERVICE_NAME, STATE, TAGS,
14
- THREADS, TIMEOUT, USER_AGENT)
14
+ RETRIES, SCRIPT, SERVICE_NAME, SEVERITY, STATE, TAGS,
15
+ THREADS, TIMEOUT, TOP_PORTS, USER_AGENT)
15
16
  from secator.output_types import Exploit, Port, Vulnerability
17
+ from secator.rich import console
16
18
  from secator.tasks._categories import VulnMulti
19
+ from secator.utils import debug
17
20
 
18
21
  logger = logging.getLogger(__name__)
19
22
 
@@ -28,11 +31,12 @@ class nmap(VulnMulti):
28
31
  opt_prefix = '--'
29
32
  output_types = [Port, Vulnerability, Exploit]
30
33
  opts = {
31
- PORTS: {'type': str, 'help': 'Ports to scan', 'short': 'p'},
34
+ PORTS: {'type': str, 'short': 'p', 'help': 'Ports to scan'},
35
+ TOP_PORTS: {'type': int, 'short': 'tp', 'help': 'Top ports to scan [full, 100, 1000]'},
32
36
  SCRIPT: {'type': str, 'default': 'vulners', 'help': 'NSE scripts'},
33
37
  # 'tcp_connect': {'type': bool, 'short': 'sT', 'default': False, 'help': 'TCP Connect scan'},
34
38
  'tcp_syn_stealth': {'is_flag': True, 'short': 'sS', 'default': False, 'help': 'TCP SYN Stealth'},
35
- 'output_path': {'type': str, 'short': 'oX', 'default': None, 'help': 'Output XML file path'}
39
+ 'output_path': {'type': str, 'short': 'oX', 'default': None, 'help': 'Output XML file path'},
36
40
  }
37
41
  opt_key_map = {
38
42
  HEADER: OPT_NOT_SUPPORTED,
@@ -114,20 +118,18 @@ class nmapData(dict):
114
118
 
115
119
  # Get extra data
116
120
  extra_data = self._get_extra_data(port)
121
+ service_name = extra_data['service_name']
122
+ version_exact = extra_data.get('version_exact', False)
123
+ conf = extra_data.get('confidence')
124
+ if not version_exact:
125
+ console.print(
126
+ f'[bold orange1]nmap could not identify an exact version for {service_name} '
127
+ f'(detection confidence is {conf}): do not blindy trust the results ![/]'
128
+ )
117
129
 
118
130
  # Grab CPEs
119
131
  cpes = extra_data.get('cpe', [])
120
132
 
121
- # Grab service name
122
- service_name = ''
123
- if 'product' in extra_data:
124
- service_name = extra_data['product']
125
- elif 'name' in extra_data:
126
- service_name = extra_data['name']
127
- if 'version' in extra_data:
128
- version = extra_data['version']
129
- service_name += f'/{version}'
130
-
131
133
  # Get script output
132
134
  scripts = self._get_scripts(port)
133
135
 
@@ -160,10 +162,17 @@ class nmapData(dict):
160
162
  EXTRA_DATA: extra_data,
161
163
  }
162
164
  if not func:
163
- # logger.debug(f'Script output parser for "{script_id}" is not supported YET.')
165
+ debug(f'Script output parser for "{script_id}" is not supported YET.', sub='cve')
164
166
  continue
165
167
  for vuln in func(output, cpes=cpes):
166
168
  vuln.update(metadata)
169
+ confidence = 'low'
170
+ if 'cpe-match' in vuln[TAGS]:
171
+ confidence = 'high' if version_exact else 'medium'
172
+ vuln[CONFIDENCE] = confidence
173
+ if (CONFIG.runners.skip_cve_low_confidence and vuln[CONFIDENCE] == 'low'):
174
+ debug(f'{vuln[ID]}: ignored (low confidence).', sub='cve')
175
+ continue
167
176
  yield vuln
168
177
 
169
178
  #---------------------#
@@ -198,40 +207,74 @@ class nmapData(dict):
198
207
  return host_cfg.get('address', {}).get('@addr', None)
199
208
 
200
209
  def _get_extra_data(self, port_cfg):
201
- extra_datas = {
210
+ extra_data = {
202
211
  k.lstrip('@'): v
203
212
  for k, v in port_cfg.get('service', {}).items()
204
213
  }
205
214
 
206
215
  # Strip product / version strings
207
- if 'product' in extra_datas:
208
- extra_datas['product'] = extra_datas['product'].lower()
209
-
210
- if 'version' in extra_datas:
211
- version_split = extra_datas['version'].split(' ')
212
- version = None
216
+ if 'product' in extra_data:
217
+ extra_data['product'] = extra_data['product'].lower()
218
+
219
+ # Get version and post-process it
220
+ version = None
221
+ if 'version' in extra_data:
222
+ vsplit = extra_data['version'].split(' ')
223
+ version_exact = True
213
224
  os = None
214
- if len(version_split) == 3:
215
- version, os, extra_version = tuple(version_split)
225
+ if len(vsplit) == 3:
226
+ version, os, extra_version = tuple(vsplit)
227
+ if os == 'or' and extra_version == 'later':
228
+ version_exact = False
229
+ os = None
216
230
  version = f'{version}-{extra_version}'
217
- elif len(version_split) == 2:
218
- version, os = tuple(version_split)
219
- elif len(version_split) == 1:
220
- version = version_split[0]
231
+ elif len(vsplit) == 2:
232
+ version, os = tuple(vsplit)
233
+ elif len(vsplit) == 1:
234
+ version = vsplit[0]
221
235
  else:
222
- version = extra_datas['version']
236
+ version = extra_data['version']
223
237
  if os:
224
- extra_datas['os'] = os
238
+ extra_data['os'] = os
239
+ if version:
240
+ extra_data['version'] = version
241
+ extra_data['version_exact'] = version_exact
242
+
243
+ # Grap service name
244
+ product = extra_data.get('name', None) or extra_data.get('product', None)
245
+ if product:
246
+ service_name = product
225
247
  if version:
226
- extra_datas['version'] = version
248
+ service_name += f'/{version}'
249
+ extra_data['service_name'] = service_name
227
250
 
228
251
  # Grab CPEs
229
- cpes = extra_datas.get('cpe', [])
252
+ cpes = extra_data.get('cpe', [])
230
253
  if not isinstance(cpes, list):
231
254
  cpes = [cpes]
232
- extra_datas['cpe'] = cpes
255
+ extra_data['cpe'] = cpes
256
+ debug(f'Found CPEs: {",".join(cpes)}', sub='cve')
257
+
258
+ # Grab confidence
259
+ conf = int(extra_data.get('conf', 0))
260
+ if conf > 7:
261
+ confidence = 'high'
262
+ elif conf > 4:
263
+ confidence = 'medium'
264
+ else:
265
+ confidence = 'low'
266
+ extra_data['confidence'] = confidence
267
+
268
+ # Build custom CPE
269
+ if product and version:
270
+ vsplit = version.split('-')
271
+ version_cpe = vsplit[0] if not version_exact else version
272
+ cpe = VulnMulti.create_cpe_string(product, version_cpe)
273
+ if cpe not in cpes:
274
+ cpes.append(cpe)
275
+ debug(f'Added new CPE from identified product and version: {cpe}', sub='cve')
233
276
 
234
- return extra_datas
277
+ return extra_data
235
278
 
236
279
  def _get_scripts(self, port_cfg):
237
280
  scripts = port_cfg.get('script', [])
@@ -276,23 +319,23 @@ class nmapData(dict):
276
319
  TAGS: [vuln_id, provider_name]
277
320
  }
278
321
  if provider_name == 'MITRE CVE':
279
- vuln_data = VulnMulti.lookup_cve(vuln['id'], cpes=cpes)
280
- if vuln_data:
281
- vuln.update(vuln_data)
322
+ data = VulnMulti.lookup_cve(vuln['id'], cpes=cpes)
323
+ if data:
324
+ vuln.update(data)
282
325
  yield vuln
283
326
  else:
284
- # logger.debug(f'Vulscan provider {provider_name} is not supported YET.')
327
+ debug(f'Vulscan provider {provider_name} is not supported YET.', sub='cve')
285
328
  continue
286
329
 
287
330
  def _parse_vulners_output(self, out, **kwargs):
288
- cpes = []
331
+ cpes = kwargs.get('cpes', [])
289
332
  provider_name = 'vulners'
290
333
  for line in out.splitlines():
291
334
  if not line:
292
335
  continue
293
336
  line = line.strip()
294
337
  if line.startswith('cpe:'):
295
- cpes.append(line)
338
+ cpes.append(line.rstrip(':'))
296
339
  continue
297
340
  elems = tuple(line.split('\t'))
298
341
  vuln = {}
@@ -307,7 +350,8 @@ class nmapData(dict):
307
350
  NAME: name,
308
351
  PROVIDER: provider_name,
309
352
  REFERENCE: reference_url,
310
- '_type': 'exploit'
353
+ '_type': 'exploit',
354
+ TAGS: [exploit_id, provider_name]
311
355
  # CVSS_SCORE: cvss_score,
312
356
  # CONFIDENCE: 'low'
313
357
  }
@@ -319,23 +363,26 @@ class nmapData(dict):
319
363
 
320
364
  elif len(elems) == 3: # vuln
321
365
  vuln_id, vuln_cvss, reference_url = tuple(line.split('\t'))
366
+ vuln_cvss = float(vuln_cvss)
367
+ vuln_id = vuln_id.split(':')[-1]
322
368
  vuln_type = vuln_id.split('-')[0]
323
369
  vuln = {
324
370
  ID: vuln_id,
325
371
  NAME: vuln_id,
326
372
  PROVIDER: provider_name,
327
373
  CVSS_SCORE: vuln_cvss,
374
+ SEVERITY: VulnMulti.cvss_to_severity(vuln_cvss),
328
375
  REFERENCES: [reference_url],
329
- TAGS: [],
376
+ TAGS: [vuln_id, provider_name],
330
377
  CONFIDENCE: 'low'
331
378
  }
332
- if vuln_type == 'CVE':
379
+ if vuln_type == 'CVE' or vuln_type == 'PRION:CVE':
333
380
  vuln[TAGS].append('cve')
334
- vuln_data = VulnMulti.lookup_cve(vuln_id, cpes=cpes)
335
- if vuln_data:
336
- vuln.update(vuln_data)
381
+ data = VulnMulti.lookup_cve(vuln_id, cpes=cpes)
382
+ if data:
383
+ vuln.update(data)
337
384
  yield vuln
338
385
  else:
339
- logger.debug(f'Vulners parser for "{vuln_type}" is not implemented YET.')
386
+ debug(f'Vulners parser for "{vuln_type}" is not implemented YET.', sub='cve')
340
387
  else:
341
- logger.error(f'Unrecognized vulners output: {elems}')
388
+ debug(f'Unrecognized vulners output: {elems}', sub='cve')
secator/tasks/nuclei.py CHANGED
@@ -85,8 +85,12 @@ class nuclei(VulnMulti):
85
85
  def extra_data_extractor(item):
86
86
  data = {}
87
87
  data['data'] = item.get('extracted-results', [])
88
+ data['type'] = item.get('type', '')
88
89
  data['template_id'] = item['template-id']
89
90
  data['template_url'] = item.get('template-url', '')
91
+ for k, v in item.get('meta', {}).items():
92
+ data['data'].append(f'{k}: {v}')
93
+ data['metadata'] = item.get('metadata', {})
90
94
  return data
91
95
 
92
96
  @staticmethod
secator/template.py ADDED
@@ -0,0 +1,137 @@
1
+ import glob
2
+ from pathlib import Path
3
+
4
+ import yaml
5
+ from dotmap import DotMap
6
+
7
+ from secator.rich import console
8
+ from secator.config import CONFIG, CONFIGS_FOLDER
9
+
10
+ TEMPLATES_DIR_KEYS = ['workflow', 'scan', 'profile']
11
+
12
+
13
+ def load_template(name):
14
+ """Load a config by name.
15
+
16
+ Args:
17
+ name: Name of the config, for instances profiles/aggressive or workflows/domain_scan.
18
+
19
+ Returns:
20
+ dict: Loaded config.
21
+ """
22
+ path = CONFIGS_FOLDER / f'{name}.yaml'
23
+ if not path.exists():
24
+ console.log(f'Config "{name}" could not be loaded.')
25
+ return
26
+ with path.open('r') as f:
27
+ return yaml.load(f.read(), Loader=yaml.Loader)
28
+
29
+
30
+ def find_templates():
31
+ results = {'scan': [], 'workflow': [], 'profile': []}
32
+ dirs_type = [CONFIGS_FOLDER]
33
+ if CONFIG.dirs.templates:
34
+ dirs_type.append(CONFIG.dirs.templates)
35
+ paths = []
36
+ for dir in dirs_type:
37
+ dir_paths = [
38
+ Path(path)
39
+ for path in glob.glob(str(dir).rstrip('/') + '/**/*.y*ml', recursive=True)
40
+ ]
41
+ paths.extend(dir_paths)
42
+ for path in paths:
43
+ with path.open('r') as f:
44
+ try:
45
+ config = yaml.load(f.read(), yaml.Loader)
46
+ type = config.get('type')
47
+ if type:
48
+ results[type].append(path)
49
+ except yaml.YAMLError as exc:
50
+ console.log(f'Unable to load config at {path}')
51
+ console.log(str(exc))
52
+ return results
53
+
54
+
55
+ class TemplateLoader(DotMap):
56
+
57
+ def __init__(self, input={}, name=None, **kwargs):
58
+ if name:
59
+ name = name.replace('-', '_') # so that workflows have a nice '-' in CLI
60
+ config = self._load_from_name(name)
61
+ elif isinstance(input, str) or isinstance(input, Path):
62
+ config = self._load_from_file(input)
63
+ else:
64
+ config = input
65
+ super().__init__(config)
66
+
67
+ def _load_from_file(self, path):
68
+ if isinstance(path, str):
69
+ path = Path(path)
70
+ if not path.exists():
71
+ console.log(f'Config path {path} does not exists', style='bold red')
72
+ return
73
+ with path.open('r') as f:
74
+ return yaml.load(f.read(), Loader=yaml.Loader)
75
+
76
+ def _load_from_name(self, name):
77
+ return load_template(name)
78
+
79
+ @classmethod
80
+ def load_all(cls):
81
+ configs = find_templates()
82
+ return TemplateLoader({
83
+ key: [TemplateLoader(path) for path in configs[key]]
84
+ for key in TEMPLATES_DIR_KEYS
85
+ })
86
+
87
+ def get_tasks_class(self):
88
+ from secator.runners import Task
89
+ tasks = []
90
+ for name, conf in self.tasks.items():
91
+ if name == '_group':
92
+ group_conf = TemplateLoader(input={'tasks': conf})
93
+ tasks.extend(group_conf.get_tasks_class())
94
+ else:
95
+ tasks.append(Task.get_task_class(name))
96
+ return tasks
97
+
98
+ def get_workflows(self):
99
+ return [TemplateLoader(name=f'workflows/{name}') for name, _ in self.workflows.items()]
100
+
101
+ def get_workflow_supported_opts(self):
102
+ opts = {}
103
+ tasks = self.get_tasks_class()
104
+ for task_cls in tasks:
105
+ task_opts = task_cls.get_supported_opts()
106
+ for name, conf in task_opts.items():
107
+ supported = opts.get(name, {}).get('supported', False)
108
+ opts[name] = conf
109
+ opts[name]['supported'] = conf['supported'] or supported
110
+ return opts
111
+
112
+ def get_scan_supported_opts(self):
113
+ opts = {}
114
+ workflows = self.get_workflows()
115
+ for workflow in workflows:
116
+ workflow_opts = workflow.get_workflow_supported_opts()
117
+ for name, conf in workflow_opts.items():
118
+ supported = opts.get(name, {}).get('supported', False)
119
+ opts[name] = conf
120
+ opts[name]['supported'] = conf['supported'] or supported
121
+ return opts
122
+
123
+ @property
124
+ def supported_opts(self):
125
+ return self.get_supported_opts()
126
+
127
+ def get_supported_opts(self):
128
+ opts = {}
129
+ if self.type == 'workflow':
130
+ opts = self.get_workflow_supported_opts()
131
+ elif self.type == 'scan':
132
+ opts = self.get_scan_supported_opts()
133
+ elif self.type == 'task':
134
+ tasks = self.get_tasks_class()
135
+ if tasks:
136
+ opts = tasks[0].get_supported_opts()
137
+ return dict(sorted(opts.items()))
secator/utils.py CHANGED
@@ -19,8 +19,8 @@ import ifaddr
19
19
  import yaml
20
20
  from rich.markdown import Markdown
21
21
 
22
- from secator.definitions import (DEBUG, DEBUG_COMPONENT, DEFAULT_STDIN_TIMEOUT, VERSION, DEV_PACKAGE, ROOT_FOLDER,
23
- LIB_FOLDER)
22
+ from secator.definitions import (DEBUG, DEBUG_COMPONENT, VERSION, DEV_PACKAGE)
23
+ from secator.config import CONFIG, ROOT_FOLDER, LIB_FOLDER
24
24
  from secator.rich import console
25
25
 
26
26
  logger = logging.getLogger(__name__)
@@ -65,7 +65,7 @@ def expand_input(input):
65
65
  """
66
66
  if input is None: # read from stdin
67
67
  console.print('Waiting for input on stdin ...', style='bold yellow')
68
- rlist, _, _ = select.select([sys.stdin], [], [], DEFAULT_STDIN_TIMEOUT)
68
+ rlist, _, _ = select.select([sys.stdin], [], [], CONFIG.cli.stdin_timeout)
69
69
  if rlist:
70
70
  data = sys.stdin.read().splitlines()
71
71
  else:
@@ -312,10 +312,6 @@ def detect_host(interface=None):
312
312
  return None
313
313
 
314
314
 
315
- def find_list_item(array, val, key='id', default=None):
316
- return next((item for item in array if item[key] == val), default)
317
-
318
-
319
315
  def print_results_table(results, title=None, exclude_fields=[], log=False):
320
316
  from secator.output_types import OUTPUT_TYPES
321
317
  from secator.rich import build_table
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: secator
3
- Version: 0.3.6
3
+ Version: 0.4.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
@@ -29,11 +29,13 @@ Requires-Dist: humanize<5
29
29
  Requires-Dist: ifaddr<1
30
30
  Requires-Dist: jinja2<4
31
31
  Requires-Dist: packaging<25
32
+ Requires-Dist: pydantic<3
32
33
  Requires-Dist: python-dotenv<2
33
34
  Requires-Dist: pyyaml<7
34
35
  Requires-Dist: requests<3
35
36
  Requires-Dist: rich-click<1.7
36
37
  Requires-Dist: rich<14
38
+ Requires-Dist: typing-extensions<5
37
39
  Requires-Dist: validators<1
38
40
  Requires-Dist: xmltodict<1
39
41
  Provides-Extra: build
@@ -90,7 +92,7 @@ and it is designed to improve productivity for pentesters and security researche
90
92
 
91
93
  # Features
92
94
 
93
- ![](images/short_demo.gif)
95
+ ![](images/demo.gif)
94
96
 
95
97
  * **Curated list of commands**
96
98
 
@@ -177,14 +179,18 @@ wget -O - https://raw.githubusercontent.com/freelabz/secator/main/scripts/instal
177
179
  <summary>Docker</summary>
178
180
 
179
181
  ```sh
180
- docker run -it --rm --net=host -v $HOME/.secator:/root/.secator freelabz/secator --help
182
+ docker run -it --rm --net=host -v ~/.secator:/root/.secator freelabz/secator --help
181
183
  ```
182
184
 
183
- The volume mount `-v` is necessary to save all `secator` reports to your host machine.
185
+ The volume mount -v is necessary to save all secator reports to your host machine, and--net=host is recommended to grant full access to the host network.
184
186
 
185
- You can set up an alias to facilitate running `secator` from Docker:
187
+ You can alias this command to run it easier:
186
188
  ```sh
187
- alias secator="docker run -it --rm --net=host -v $HOME/.secator:/root/.secator freelabz/secator"
189
+ alias secator="docker run -it --rm --net=host -v ~/.secator:/root/.secator freelabz/secator"
190
+ ```
191
+
192
+ Now you can run secator like if it was installed on baremetal:
193
+ ```
188
194
  secator --help
189
195
  ```
190
196
 
@@ -1,14 +1,15 @@
1
1
  secator/.gitignore,sha256=da8MUc3hdb6Mo0WjZu2upn5uZMbXcBGvhdhTQ1L89HI,3093
2
2
  secator/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- secator/celery.py,sha256=4jryWgB7Ydqtosc1HrE2VkMhWXqdhb-A8wJiUem4Mh4,12266
4
- secator/cli.py,sha256=zwHB7JcWppX38IE39p4eSUUYDP5SdehYOJ-ByKNtVDw,31565
5
- secator/config.py,sha256=iOeRzq7u1rvR1-Oq5v9wGxQYB613X0xKGLIcrfhEGc4,3693
6
- secator/decorators.py,sha256=xH9QzAPd1DspoAzFv54Ss4JhCiZ9dd1zD5cdYGE7WKY,10784
7
- secator/definitions.py,sha256=ZFDPZW5R4CiAMWjyGvWmrePEljiWFyabgoTVM5Zedt4,7599
8
- secator/installer.py,sha256=wa5YFmbqMEpVI0jNiPvNE8-IDvr6vHNcdALV5rFYBr4,9329
3
+ secator/celery.py,sha256=5Raua1rDFJACdmP4b1HLS15kx3ObcUrVConQ0UcopTc,12135
4
+ secator/cli.py,sha256=qf55GtYARFcCqOTumq3N5_dne3twxRkExolMrUI5UiU,34148
5
+ secator/config.py,sha256=Mzubha9pSzmpJnwA6f87OUScKrYo-szf8i9PJvKkz8w,17501
6
+ secator/decorators.py,sha256=SIS_32SbeN9iTx82mvy9F9vLpjofRYspOOLCXytIO2g,10764
7
+ secator/definitions.py,sha256=Spr62Nc0TweBAa84iRGSwNkIvXlKofPxtIi795gqTjc,3047
8
+ secator/installer.py,sha256=fpjf5fbA5M5zDQVP4Fdr51sLoMwtoGZTe3mXh7DvD6s,9466
9
9
  secator/report.py,sha256=g0stVCcx9klbUS01uKvWcxNE9MJfNFMexYA2SoDIWJU,2596
10
10
  secator/rich.py,sha256=W4PipeZfIVnERfW3ySeWSvnZ90jhCFiABBoERYy_6kM,3177
11
- secator/utils.py,sha256=9bfNqwlk55XBfT475rTafIwOwtEDFPIde417gxGTbEg,10945
11
+ secator/template.py,sha256=MRCzvn8FJ7D4n8V4ceBwAjPsdLhTWjDRu5VLefmLb6M,3705
12
+ secator/utils.py,sha256=_npGVl85skBAMdGDzrhvnNwg4-aRhbisl8oxsB9Q1q8,10824
12
13
  secator/utils_test.py,sha256=xVF9RH1-p3X0TdmODJi4k62H7Xth96Ib7qnUZ4vAJs8,5043
13
14
  secator/configs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
15
  secator/configs/profiles/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -37,12 +38,12 @@ secator/configs/workflows/wordpress.yaml,sha256=QgBUNi8Gav_efbmczUGfzlByWsmogTmG
37
38
  secator/exporters/__init__.py,sha256=2nBPOOas9Fp4nmo9pjSw3mvklZNHL8BmH88w_i-eaJc,356
38
39
  secator/exporters/_base.py,sha256=-RrrwO_qp0ETLLHSta4T-zKtMbWdiEmz1Cw5mNo6USU,77
39
40
  secator/exporters/csv.py,sha256=xsPMljzJhoTc8lcfxWBIKH2niK6KeYL7Bx2NzpdsYw0,982
40
- secator/exporters/gdrive.py,sha256=VI6r1vlChz39myaN4sFvOlHO32SAhZS5_mI5EwGUdq8,4056
41
+ secator/exporters/gdrive.py,sha256=hq6PtCVejeqp9cipcAkH5ZsijBWB_SXIcW9uctYJAYM,4143
41
42
  secator/exporters/json.py,sha256=cWkDugUdy-lbcPFKNgBrRFxHspiFhjVbJfdDABjJ9uk,431
42
43
  secator/exporters/table.py,sha256=RHQoaFeeyeoBGNucJgrlk2KtmVqe9BGNtAAYee7xJ8Y,210
43
44
  secator/exporters/txt.py,sha256=QbiwWYGgHpITGw1sL2TX-S3AfmBdJ-VOWkPJzuBvOu4,785
44
45
  secator/hooks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
45
- secator/hooks/mongodb.py,sha256=GTd6BeiGtWUPWjmXKmalZYNoeGNZfNqEJ6BxRJh1Mr8,7149
46
+ secator/hooks/mongodb.py,sha256=PGcM6hkTl4bt46-cPlFgcY-PfNWmHpz_eiv77XeV0-A,7036
46
47
  secator/output_types/__init__.py,sha256=uj6AXDeorECPwhwekNVGjQbGv41jHG_8udkuoc4XzW0,854
47
48
  secator/output_types/_base.py,sha256=bld1ED0pN1hOvwBV2canrlKrfBCgawzWKPDH6F3jVQE,2469
48
49
  secator/output_types/exploit.py,sha256=NIa0mbhm3ZTyV5kyjEvrI5QK2swMpdMCj3f1gIWcsro,1581
@@ -55,46 +56,46 @@ secator/output_types/tag.py,sha256=8AlT0VigsYP04GN8sPCTM07IlL5uMUmFgsNa9IDCoyY,1
55
56
  secator/output_types/target.py,sha256=gJWzzqhal34Cnl9oAKf0m1MSaGxRtUGdA2XbkhD_yd0,848
56
57
  secator/output_types/url.py,sha256=yDozBXCuPfuybH1iX_xGmbCJPXO6Ei14C8Hp5CnzNbE,2535
57
58
  secator/output_types/user_account.py,sha256=EiT2BFl2LTCdqHF1meoMEKVhjKGroyf8-JoWHPuBOTc,1378
58
- secator/output_types/vulnerability.py,sha256=p0DTbr5w7Vv5D3dgbdnvsG5qXzqVVk4YPOPWYS1lxmM,2843
59
+ secator/output_types/vulnerability.py,sha256=hV6gsCFLdZ9IQV1ZSVCnsUms8H3md2_XZqp3wJDYDn4,2896
59
60
  secator/runners/__init__.py,sha256=EBbOk37vkBy9p8Hhrbi-2VtM_rTwQ3b-0ggTyiD22cE,290
60
- secator/runners/_base.py,sha256=jhglHTz1yf-LBdCdTX2YyAt664yBeQkkySQCrJYpjnM,28290
61
- secator/runners/_helpers.py,sha256=7UUboSsr4b6srIOOHtSSYhJ9Jxq_qaMVbbF2gVEBnR4,3703
62
- secator/runners/command.py,sha256=JzdwhbvsDujOyE-i_XgBGH-g6jaEoDNwL7CU2BIZ-Ng,18737
63
- secator/runners/scan.py,sha256=ZRfSgJd0RxtmxWp7cDGZsnmhdo-t1TSBH26XKxvH94k,1675
64
- secator/runners/task.py,sha256=hv9O8yeVBHuznDoNeQuDPxB6Doc2MKV_P838qJdO7b0,2772
65
- secator/runners/workflow.py,sha256=tQD03JqebVve9ncR9gxpzcgTsP6yvAWjUs2YBX80jzc,3717
61
+ secator/runners/_base.py,sha256=RHEQq-OvoC_rnpws30LmXDaO907pcblPe_WbWRcXQqk,28370
62
+ secator/runners/_helpers.py,sha256=kxXfxP4LOCz49p5Y-OKuUqvVAmRPtAoK2O9PHoUxCX0,3947
63
+ secator/runners/command.py,sha256=F6Eg5hLisk6KLXKSBgNIURu2A67heNzmkVF_OYF_Xdo,18688
64
+ secator/runners/scan.py,sha256=ZN6bgb3yqu5wemq_VVqul5VTU64TtYUl_0wkcW1aXRU,1647
65
+ secator/runners/task.py,sha256=c038lkkQ2H1GpLcHp46PEmSSXsIIRA5jnDgw6x8rEAY,2826
66
+ secator/runners/workflow.py,sha256=i2s-lJYIMJfHrxdVwglG9bkCGKu90yUNAM2lfwT6RIA,3689
66
67
  secator/serializers/__init__.py,sha256=OP5cmFl77ovgSCW_IDcZ21St2mUt5UK4QHfrsK2KvH8,248
67
68
  secator/serializers/dataclass.py,sha256=g5gMT4NwndjhGcGbFuYEs07AZW_Q_m9orov_edVEGlI,792
68
69
  secator/serializers/json.py,sha256=XwuSQOBwrOAs16F5HtY-Q-rAGAxfNvlq3z-Nb2gwigE,304
69
70
  secator/serializers/regex.py,sha256=hGJ_1JSOv9xPtfn_umHlsjnR_alnsDFv-UmjYCC3vwU,314
70
71
  secator/tasks/__init__.py,sha256=Wp2QF5QS2e_BlVygsIEFbmYPTfTg7v_Vd3LQJeXTC7I,344
71
- secator/tasks/_categories.py,sha256=w4vxKffTQFJEHNzi6BV5DslGpnSAlKEN0K7H6slG3Vg,9015
72
+ secator/tasks/_categories.py,sha256=2cUsZOdYHA-YXJwryU2FTTT4Y4xXzmDJ92F8ud-MDJQ,10402
72
73
  secator/tasks/cariddi.py,sha256=GKVJ8nWtJu9fB_FhAVYA2TX3fMdKYdbMpH2IhCkj_no,3155
73
74
  secator/tasks/dalfox.py,sha256=nrLkIbTNz_J7LgUy_3kBgzhTUbQi3RmiSJhc9HWa05c,1744
74
75
  secator/tasks/dirsearch.py,sha256=2hJeJZJwaAl3-UAjBwlmjW1w9bxjVWxxwfcaTTxqClc,2387
75
76
  secator/tasks/dnsx.py,sha256=H_3z87KAK-ndAQgCwS8TRWaUX_Hh54qEeuKQCS4rjBw,1771
76
- secator/tasks/dnsxbrute.py,sha256=obr2SsxIJlO2KckxrCOPHvvzyfequFW6-D4ZAUq4Egk,1224
77
+ secator/tasks/dnsxbrute.py,sha256=TT1wEU6BSS0VVwk7c5cFRKEnPji3HeK_tLrWtLJBSvk,1245
77
78
  secator/tasks/feroxbuster.py,sha256=9QQpd8T0CSMfXf_BMmCX4LeIogyvsc_ccXFJnEocxVo,3011
78
- secator/tasks/ffuf.py,sha256=ocmFfJJoV4zF8zkhUxHqUyDuJe9flmuijHCq_xk2pa4,2558
79
+ secator/tasks/ffuf.py,sha256=eJyXY912hg8e_8sibzo7X7704QM4vI4C0o317bcTV-c,2428
79
80
  secator/tasks/fping.py,sha256=P2EAPUGgwEC4Geh2zUbBPKF9bdqrlrdDg-R_TYLTFng,1127
80
81
  secator/tasks/gau.py,sha256=Sq5l277cGxpT2bB5s1RqrggP804RKbC6xxgLDZZzLFs,1391
81
82
  secator/tasks/gf.py,sha256=WlhoEyL6xE79w6nE5XNSXHs-jVeO10njqJxBF8w20sA,945
82
83
  secator/tasks/gospider.py,sha256=_UlTb9G5Ss8D68NT53s0_rI6TnG00Ph0yxWyHic7cKs,2172
83
84
  secator/tasks/grype.py,sha256=n60Zs9d1NWJFHQ0DwIZib5wu3xH-tV2RzgLYwuQSTo4,2413
84
85
  secator/tasks/h8mail.py,sha256=hZBpfV6M1mbpD_PbDHxLI5HMvqAvTeY_W0lbkq3Hugo,2037
85
- secator/tasks/httpx.py,sha256=NuycnbPejEZoUdFYFXyahYiZnzhz1cPJarHdP7WyP6c,3979
86
- secator/tasks/katana.py,sha256=Xa03zP2-78Ns59unUPrR_MHSd1DugTQlThxl8cL6pX4,4370
86
+ secator/tasks/httpx.py,sha256=ugk4AOIqhvT5-HVhlRsQw_oF2BGovgHlS-_D9wav8wo,3972
87
+ secator/tasks/katana.py,sha256=3JHtvxoSxJtju9xqvQptVaYXKnLLlCkOn6oY0A8h7wM,4371
87
88
  secator/tasks/maigret.py,sha256=PZDTICJ4LZF3joKe-dXu2alffakD_1sxBuNEUBtJDm4,2098
88
89
  secator/tasks/mapcidr.py,sha256=7aa2WXQATWgIQo5oA12URjAg80L6MFMGdxScxls8DuA,980
89
- secator/tasks/msfconsole.py,sha256=VlhEzsdYMHb6eJy4HBRdXMtRKhdzf5KtQGh7qZqO9Rs,6073
90
+ secator/tasks/msfconsole.py,sha256=Cm0vzOFff17C4M1YjkgU6T7Jc5-ClBK0Qi_529qVRb0,6065
90
91
  secator/tasks/naabu.py,sha256=RNs4NCZXgKhPqzR78l6l61tau0mGHuj6C3If7fimpgs,1594
91
- secator/tasks/nmap.py,sha256=LS5FBo-vFxbHVK4DxF5x-O2cAvAK3zL1pROT1GddX9E,9459
92
- secator/tasks/nuclei.py,sha256=7MlTygHd4EVz81ndrVwP5y6PZ-4j-Y8Oxuk3G3ayHPI,3343
92
+ secator/tasks/nmap.py,sha256=WS071HX7dnb2bP-M4Ah0yNYWva-WTVaj9oVzMMFUvRY,11239
93
+ secator/tasks/nuclei.py,sha256=lKZYPVcnCYomd830-ZCOz4fyc8xAKjNDuKayyz0BPek,3507
93
94
  secator/tasks/searchsploit.py,sha256=RD2uv3GFI3Eb-DiTzJp59jyXnvAZRACq-WjDI1NgFM0,1664
94
95
  secator/tasks/subfinder.py,sha256=cpFyFCpVaDZ3QAjNId26ezOwntn3CA5Uk-AC2l0mo0E,1087
95
96
  secator/tasks/wpscan.py,sha256=UVWnBPOQ1RDB2wzMswWR6vc6cucYgHtuJ8pLZoqCM40,5434
96
- secator-0.3.6.dist-info/METADATA,sha256=HaAuvqTAtZiaWWcTsn4KcZditRPlRYdE5nZQIboxwbk,13933
97
- secator-0.3.6.dist-info/WHEEL,sha256=K0BPUNF1N3kQ9olb8aVEtkObePEjdr2JOLT1N83EVws,87
98
- secator-0.3.6.dist-info/entry_points.txt,sha256=lPgsqqUXWgiuGSfKy-se5gHdQlAXIwS_A46NYq7Acic,44
99
- secator-0.3.6.dist-info/licenses/LICENSE,sha256=19W5Jsy4WTctNkqmZIqLRV1gTDOp01S3LDj9iSgWaJ0,2867
100
- secator-0.3.6.dist-info/RECORD,,
97
+ secator-0.4.1.dist-info/METADATA,sha256=UWWDy4InD1uQ9MovLFt6zeSRKBj0b3Od9AwfX4cdoFY,14095
98
+ secator-0.4.1.dist-info/WHEEL,sha256=zEMcRr9Kr03x1ozGwg5v9NQBKn3kndp6LSoSlVg-jhU,87
99
+ secator-0.4.1.dist-info/entry_points.txt,sha256=lPgsqqUXWgiuGSfKy-se5gHdQlAXIwS_A46NYq7Acic,44
100
+ secator-0.4.1.dist-info/licenses/LICENSE,sha256=19W5Jsy4WTctNkqmZIqLRV1gTDOp01S3LDj9iSgWaJ0,2867
101
+ secator-0.4.1.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: hatchling 1.24.0
2
+ Generator: hatchling 1.24.2
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any