secator 0.10.1a6__py3-none-any.whl → 0.10.1a8__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/celery.py CHANGED
@@ -170,8 +170,8 @@ def run_scan(self, args=[], kwargs={}):
170
170
  def run_command(self, results, name, targets, opts={}):
171
171
  if IN_CELERY_WORKER_PROCESS:
172
172
  opts.update({'print_item': True, 'print_line': True, 'print_cmd': True})
173
- routing_key = self.request.delivery_info['routing_key']
174
- console.print(Info(message=f'Task "{name}" running with routing key "{routing_key}"'))
173
+ # routing_key = self.request.delivery_info['routing_key']
174
+ # console.print(Info(message=f'Task "{name}" running with routing key "{routing_key}"'))
175
175
 
176
176
  # Flatten + dedupe + filter results
177
177
  results = forward_results(results)
@@ -188,8 +188,7 @@ def run_command(self, results, name, targets, opts={}):
188
188
  sync = not IN_CELERY_WORKER_PROCESS
189
189
  task_cls = Task.get_task_class(name)
190
190
  task = task_cls(targets, **opts)
191
- task.started = True
192
- task.run_hooks('on_start')
191
+ task.mark_started()
193
192
  update_state(self, task, force=True)
194
193
 
195
194
  # Chunk task if needed
@@ -220,50 +219,43 @@ def forward_results(results):
220
219
  results = results['results']
221
220
  results = flatten(results)
222
221
  results = deduplicate(results, attr='_uuid')
223
- if IN_CELERY_WORKER_PROCESS:
224
- console.print(Info(message=f'Forwarding {len(results)} results ...'))
225
222
  return results
226
223
 
227
224
 
228
225
  @app.task
229
- def mark_runner_started(runner):
226
+ def mark_runner_started(runner, enable_hooks=True):
230
227
  """Mark a runner as started and run on_start hooks.
231
228
 
232
229
  Args:
233
- runner (Runner): Secator runner instance
230
+ runner (Runner): Secator runner instance.
231
+ enable_hooks (bool): Enable hooks.
234
232
 
235
233
  Returns:
236
234
  list: Runner results
237
235
  """
238
- runner.started = True
239
- # runner.start_time = time()
240
- runner.run_hooks('on_start')
241
- return runner.results
236
+ debug(f'Runner {runner.unique_name} has started, running mark_started', sub='celery')
237
+ runner.enable_hooks = enable_hooks
238
+ runner.mark_started()
239
+ return forward_results(runner.results)
242
240
 
243
241
 
244
242
  @app.task
245
- def mark_runner_complete(results, runner):
243
+ def mark_runner_completed(results, runner, enable_hooks=True):
246
244
  """Mark a runner as completed and run on_end hooks.
247
245
 
248
246
  Args:
249
247
  results (list): Task results
250
248
  runner (Runner): Secator runner instance
249
+ enable_hooks (bool): Enable hooks.
251
250
 
252
251
  Returns:
253
252
  list: Final results
254
253
  """
254
+ debug(f'Runner {runner.unique_name} has finished, running mark_completed', sub='celery')
255
255
  results = forward_results(results)
256
-
257
- # If sync mode, don't update the runner as it's already done
258
- if runner.sync:
259
- return results
260
-
261
- # Run final processing
262
- runner.results = results
263
- if not runner.no_process:
264
- runner.mark_duplicates()
265
- runner.log_results()
266
- runner.run_hooks('on_end')
256
+ runner.enable_hooks = enable_hooks
257
+ [runner.add_result(item) for item in results]
258
+ runner.mark_completed()
267
259
  return runner.results
268
260
 
269
261
 
@@ -325,6 +317,6 @@ def break_task(task, task_opts, results=[]):
325
317
  # Build Celery workflow
326
318
  workflow = chord(
327
319
  tuple(sigs),
328
- mark_runner_complete.s(runner=task).set(queue='results')
320
+ mark_runner_completed.s(runner=task).set(queue='results')
329
321
  )
330
322
  return workflow
secator/celery_utils.py CHANGED
@@ -144,7 +144,7 @@ class CeleryData(object):
144
144
  _source='celery'
145
145
  )
146
146
  debug(f"Main task state: {result.id} - {result.state}", sub='celery.poll', verbose=True)
147
- yield {'id': result.id, 'results': [main_task]}
147
+ yield {'id': result.id, 'state': result.state, 'results': [main_task]}
148
148
  yield from CeleryData.get_all_data(result, ids_map)
149
149
 
150
150
  if result.ready():
@@ -155,7 +155,7 @@ class CeleryData(object):
155
155
  _source='celery'
156
156
  )
157
157
  debug(f"Final main task state: {result.id} - {result.state}", sub='celery.poll', verbose=True)
158
- yield {'id': result.id, 'results': [main_task]}
158
+ yield {'id': result.id, 'state': result.state, 'results': [main_task]}
159
159
  yield from CeleryData.get_all_data(result, ids_map)
160
160
  break
161
161
  except (KeyboardInterrupt, GreenletExit):
@@ -11,7 +11,7 @@ tasks:
11
11
  fping:
12
12
  description: Check for alive IPs
13
13
  targets_: ip.ip
14
- naabu:
14
+ nmap:
15
15
  description: Scan alive IPs' ports
16
16
  targets_:
17
17
  - type: ip
@@ -7,21 +7,23 @@ input_types:
7
7
  - host
8
8
  - cidr_range
9
9
  tasks:
10
- naabu:
11
- description: Find open ports
12
10
  nmap:
13
11
  description: Search for vulnerabilities on open ports
14
12
  skip_host_discovery: True
15
- version_detection: True
16
- targets_: port.host
17
- ports_: port.port
18
- httpx:
19
- description: Probe HTTP services on open ports
20
- targets_:
21
- - type: port
22
- field: '{host}:{port}'
23
- condition: item._source.startswith('nmap')
24
- _group:
13
+ ports: "-" # scan all ports
14
+ _group/1:
15
+ httpx:
16
+ description: Probe HTTP services on open ports
17
+ targets_:
18
+ - type: port
19
+ field: '{host}:{port}'
20
+ searchsploit:
21
+ description: Search for related exploits
22
+ targets_:
23
+ - type: port
24
+ field: service_name
25
+ condition: len(item.service_name.split('/')) > 1
26
+ _group/2:
25
27
  nuclei/network:
26
28
  description: Scan network and SSL vulnerabilities
27
29
  tags: [network, ssl]
@@ -32,12 +34,3 @@ tasks:
32
34
  - type: url
33
35
  field: url
34
36
  condition: item.status_code != 0
35
- results:
36
- - type: port
37
- condition: item._source.startswith('nmap')
38
-
39
- - type: vulnerability
40
- # condition: item.confidence == 'high'
41
-
42
- - type: url
43
- condition: item.status_code != 0
secator/runners/_base.py CHANGED
@@ -1,6 +1,5 @@
1
1
  import json
2
2
  import logging
3
- import os
4
3
  import sys
5
4
  import uuid
6
5
  from datetime import datetime
@@ -65,9 +64,6 @@ class Runner:
65
64
  # Run hooks
66
65
  enable_hooks = True
67
66
 
68
- # Reports folder
69
- reports_folder = None
70
-
71
67
  def __init__(self, config, inputs=[], results=[], run_opts={}, hooks={}, validators={}, context={}):
72
68
  self.uuids = []
73
69
  self.results = []
@@ -98,6 +94,8 @@ class Runner:
98
94
  self.no_poll = self.run_opts.get('no_poll', False)
99
95
  self.quiet = self.run_opts.get('quiet', False)
100
96
  self.started = False
97
+ self.enable_reports = self.run_opts.get('enable_reports', not self.sync)
98
+ self._reports_folder = self.run_opts.get('reports_folder', None)
101
99
 
102
100
  # Runner process options
103
101
  self.no_process = self.run_opts.get('no_process', False)
@@ -135,7 +133,7 @@ class Runner:
135
133
  inputs, run_opts, errors = run_extractors(self.results, run_opts, inputs)
136
134
  for error in errors:
137
135
  self.add_result(error, print=True)
138
- self.inputs = inputs
136
+ self.inputs = list(set(inputs))
139
137
 
140
138
  # Debug
141
139
  self.debug('Inputs', obj=self.inputs, sub='init')
@@ -146,16 +144,6 @@ class Runner:
146
144
  exporters_str = self.run_opts.get('output') or self.default_exporters
147
145
  self.exporters = self.resolve_exporters(exporters_str)
148
146
 
149
- # Determine report folder
150
- default_reports_folder_base = f'{CONFIG.dirs.reports}/{self.workspace_name}/{self.config.type}s'
151
- _id = get_task_folder_id(default_reports_folder_base)
152
- self.reports_folder = f'{default_reports_folder_base}/{_id}'
153
-
154
- # Make reports folders
155
- os.makedirs(self.reports_folder, exist_ok=True)
156
- os.makedirs(f'{self.reports_folder}/.inputs', exist_ok=True)
157
- os.makedirs(f'{self.reports_folder}/.outputs', exist_ok=True)
158
-
159
147
  # Profiler
160
148
  self.enable_profiler = self.run_opts.get('enable_profiler', False) and ADDONS_ENABLED['trace']
161
149
  if self.enable_profiler:
@@ -260,6 +248,23 @@ class Runner:
260
248
  'descr': self.config.description or '',
261
249
  }
262
250
 
251
+ @property
252
+ def reports_folder(self):
253
+ if self._reports_folder and Path(self._reports_folder).exists():
254
+ return self._reports_folder
255
+ _base = f'{CONFIG.dirs.reports}/{self.workspace_name}/{self.config.type}s'
256
+ _id = get_task_folder_id(_base)
257
+ path = Path(f'{_base}/{_id}')
258
+ path_inputs = path / '.inputs'
259
+ path_outputs = path / '.outputs'
260
+ if not path.exists():
261
+ self.debug(f'Creating reports folder {path}')
262
+ path.mkdir(parents=True, exist_ok=True)
263
+ path_inputs.mkdir(exist_ok=True)
264
+ path_outputs.mkdir(exist_ok=True)
265
+ self._reports_folder = path.resolve()
266
+ return self._reports_folder
267
+
263
268
  def run(self):
264
269
  """Run method.
265
270
 
@@ -275,16 +280,14 @@ class Runner:
275
280
  OutputType: runner result.
276
281
  """
277
282
  try:
278
- self.log_start()
279
- self.run_hooks('on_start')
283
+ # If sync mode, set started
284
+ if self.sync:
285
+ self.mark_started()
280
286
 
281
- # If any errors happened during valid ation, exit
287
+ # If any errors happened during validation, exit
282
288
  if self.errors:
283
289
  yield from self.errors
284
- if self.no_process:
285
- return
286
- self.log_results()
287
- self.run_hooks('on_end')
290
+ self.mark_completed()
288
291
  return
289
292
 
290
293
  # Loop and process items
@@ -304,13 +307,13 @@ class Runner:
304
307
  self.stop_celery_tasks()
305
308
  yield from self.join_threads()
306
309
  yield error
310
+ self.mark_completed()
307
311
 
308
312
  finally:
309
- if self.no_process:
310
- return
311
- self.mark_duplicates()
312
- self.log_results()
313
- self.run_hooks('on_end')
313
+ if self.sync:
314
+ self.mark_completed()
315
+ if self.enable_reports:
316
+ self.export_reports()
314
317
 
315
318
  def join_threads(self):
316
319
  """Wait for all running threads to complete."""
@@ -496,7 +499,6 @@ class Runner:
496
499
  # Run workflow and get results
497
500
  if self.sync:
498
501
  self.print_item = False
499
- self.started = True
500
502
  results = workflow.apply().get()
501
503
  yield from results
502
504
  else:
@@ -508,6 +510,7 @@ class Runner:
508
510
  )
509
511
  if self.no_poll:
510
512
  self.enable_hooks = False
513
+ self.enable_reports = False
511
514
  self.no_process = True
512
515
  return
513
516
  results = CeleryData.iter_results(
@@ -677,30 +680,53 @@ class Runner:
677
680
  self.debug('', obj={name + ' [dim yellow]->[/] ' + fun: 'registered (user)'}, sub='validators')
678
681
  self.validators[key].extend(user_validators)
679
682
 
683
+ def mark_started(self):
684
+ """Mark runner as started."""
685
+ if self.started:
686
+ return
687
+ self.started = True
688
+ self.start_time = datetime.fromtimestamp(time())
689
+ self.debug(f'started (sync: {self.sync}, hooks: {self.enable_hooks})')
690
+ self.log_start()
691
+ self.run_hooks('on_start')
692
+
693
+ def mark_completed(self):
694
+ """Mark runner as completed."""
695
+ if self.done:
696
+ return
697
+ self.started = True
698
+ self.done = True
699
+ self.progress = 100
700
+ self.end_time = datetime.fromtimestamp(time())
701
+ self.debug(f'completed (sync: {self.sync}, reports: {self.enable_reports}, hooks: {self.enable_hooks})')
702
+ self.mark_duplicates()
703
+ self.run_hooks('on_end')
704
+ self.export_profiler()
705
+ self.log_results()
706
+
680
707
  def log_start(self):
681
708
  """Log runner start."""
682
709
  if not self.print_remote_info:
683
710
  return
684
711
  remote_str = 'starting' if self.sync else 'sent to Celery worker'
685
- runner_name = self.__class__.__name__
686
- info = Info(message=f'{runner_name} {self.config.name} {remote_str}...', _source=self.unique_name)
712
+ info = Info(message=f'{self.config.type.capitalize()} {self.unique_name} {remote_str}...', _source=self.unique_name)
687
713
  self._print_item(info)
688
714
 
689
715
  def log_results(self):
690
716
  """Log runner results."""
691
- self.started = True
692
- self.done = True
693
- self.progress = 100
694
- self.end_time = datetime.fromtimestamp(time())
695
- if self.status == 'FAILURE':
696
- self.debug('', obj={self.__class__.__name__: self.status, 'errors': [str(_.message) for _ in self.errors]}, sub='status') # noqa: E501
697
- else:
698
- self.debug('', obj={self.__class__.__name__: self.status}, sub='status')
699
- if self.exporters and not self.no_process:
717
+ info = Info(message=f'{self.config.type.capitalize()} {self.unique_name} finished with status {self.status} and found {len(self.self_findings)} findings', _source=self.unique_name) # noqa: E501
718
+ self._print_item(info)
719
+
720
+ def export_reports(self):
721
+ """Export reports."""
722
+ if self.enable_reports and self.exporters and not self.no_process:
700
723
  report = Report(self, exporters=self.exporters)
701
724
  report.build()
702
725
  report.send()
703
726
  self.report = report
727
+
728
+ def export_profiler(self):
729
+ """Export profiler."""
704
730
  if self.enable_profiler:
705
731
  self.profiler.stop()
706
732
  profile_path = Path(self.reports_folder) / f'{self.unique_name}_profile.html'
@@ -858,13 +884,16 @@ class Runner:
858
884
 
859
885
  # Check for state updates
860
886
  if isinstance(item, State) and self.celery_result and item.task_id == self.celery_result.id:
861
- self.debug(f'Updating runner state from Celery: {item.state}', sub='state')
887
+ self.debug(f'Sync runner state from remote: {item.state}')
862
888
  if item.state in ['FAILURE', 'SUCCESS', 'REVOKED']:
863
889
  self.started = True
864
890
  self.done = True
891
+ self.progress = 100
892
+ self.end_time = datetime.fromtimestamp(time())
865
893
  elif item.state in ['RUNNING']:
866
894
  self.started = True
867
- self.debug(f'Runner {self.unique_name} is {self.status} (started: {self.started}, done: {self.done})', sub='state')
895
+ self.start_time = datetime.fromtimestamp(time())
896
+ self.end_time = None
868
897
  self.last_updated_celery = item._timestamp
869
898
  return
870
899
 
secator/runners/scan.py CHANGED
@@ -24,7 +24,7 @@ class Scan(Runner):
24
24
  celery.Signature: Celery task signature.
25
25
  """
26
26
  from celery import chain
27
- from secator.celery import mark_runner_started, mark_runner_complete
27
+ from secator.celery import mark_runner_started, mark_runner_completed
28
28
  from secator.template import TemplateLoader
29
29
 
30
30
  scan_opts = self.config.options
@@ -52,5 +52,5 @@ class Scan(Runner):
52
52
  return chain(
53
53
  mark_runner_started.si(self).set(queue='results'),
54
54
  *sigs,
55
- mark_runner_complete.s(self).set(queue='results'),
55
+ mark_runner_completed.s(self).set(queue='results'),
56
56
  )
secator/runners/task.py CHANGED
@@ -24,7 +24,7 @@ class Task(Runner):
24
24
  Returns:
25
25
  celery.Signature: Celery task signature.
26
26
  """
27
- from secator.celery import run_command, mark_runner_started, mark_runner_complete
27
+ from secator.celery import run_command
28
28
 
29
29
  # Get task class
30
30
  task_cls = Task.get_task_class(self.config.name)
@@ -34,27 +34,25 @@ class Task(Runner):
34
34
  opts.pop('output', None)
35
35
  opts.pop('no_poll', False)
36
36
 
37
- # Set task output types
37
+ # Set output types
38
38
  self.output_types = task_cls.output_types
39
- self.enable_duplicate_check = False
40
- self.enable_hooks = False
39
+
40
+ # Set hooks and reports
41
+ self.enable_hooks = False # Celery will handle hooks
42
+ self.enable_reports = True # Task will handle reports
41
43
 
42
44
  # Get hooks
43
45
  hooks = self._hooks.get(Task, {})
44
46
  opts['hooks'] = hooks
45
- opts['context'] = self.context
47
+ opts['context'] = self.context.copy()
48
+ opts['reports_folder'] = str(self.reports_folder)
49
+ opts['enable_reports'] = False # Task will handle reports
46
50
 
47
51
  # Create task signature
48
52
  task_id = str(uuid.uuid4())
49
- sig = run_command.s(self.config.name, self.inputs, opts).set(queue=task_cls.profile, task_id=task_id)
53
+ sig = run_command.si(self.results, self.config.name, self.inputs, opts).set(queue=task_cls.profile, task_id=task_id)
50
54
  self.add_subtask(task_id, self.config.name, self.config.description or '')
51
-
52
- # Build signature chain with lifecycle management
53
- return chain(
54
- mark_runner_started.si(self).set(queue='results'),
55
- sig,
56
- mark_runner_complete.s(self).set(queue='results'),
57
- )
55
+ return chain(sig)
58
56
 
59
57
  @staticmethod
60
58
  def get_task_class(name):
@@ -27,13 +27,25 @@ class Workflow(Runner):
27
27
  celery.Signature: Celery task signature.
28
28
  """
29
29
  from celery import chain
30
- from secator.celery import mark_runner_started, mark_runner_complete
30
+ from secator.celery import mark_runner_started, mark_runner_completed
31
31
 
32
32
  # Prepare run options
33
33
  opts = self.run_opts.copy()
34
- opts['hooks'] = self._hooks.get(Task, {})
34
+ opts.pop('output', None)
35
35
  opts.pop('no_poll', False)
36
36
 
37
+ # Set hooks and reports
38
+ self.enable_reports = True # Workflow will handle reports
39
+ self.enable_hooks = False # Celery will handle hooks
40
+ # Get hooks
41
+ hooks = self._hooks.get(Task, {})
42
+ opts['hooks'] = hooks
43
+ opts['context'] = self.context.copy()
44
+ opts['reports_folder'] = str(self.reports_folder)
45
+ opts['enable_reports'] = False # Workflow will handle reports
46
+ opts['has_parent'] = True
47
+ opts['skip_if_no_inputs'] = True
48
+
37
49
  # Build task signatures
38
50
  sigs = self.get_tasks(
39
51
  self.config.tasks.toDict(),
@@ -43,9 +55,9 @@ class Workflow(Runner):
43
55
 
44
56
  # Build workflow chain with lifecycle management
45
57
  return chain(
46
- mark_runner_started.si(self).set(queue='results'),
58
+ mark_runner_started.si(self, enable_hooks=True).set(queue='results'),
47
59
  *sigs,
48
- mark_runner_complete.s(self).set(queue='results'),
60
+ mark_runner_completed.s(self, enable_hooks=True).set(queue='results'),
49
61
  )
50
62
 
51
63
  def get_tasks(self, config, inputs, workflow_opts, run_opts):
@@ -91,13 +103,7 @@ class Workflow(Runner):
91
103
 
92
104
  # Merge task options (order of priority with overrides)
93
105
  opts = merge_opts(workflow_opts, task_opts, run_opts)
94
-
95
- # Add task context and hooks to options
96
- opts['hooks'] = {task: self._hooks.get(Task, {})}
97
- opts['context'] = self.context.copy()
98
106
  opts['name'] = task_name
99
- opts['has_parent'] = True
100
- opts['skip_if_no_inputs'] = True
101
107
 
102
108
  # Create task signature
103
109
  task_id = str(uuid.uuid4())
secator/tasks/naabu.py CHANGED
@@ -48,7 +48,7 @@ class naabu(ReconPort):
48
48
  }
49
49
  output_types = [Port]
50
50
  install_cmd = 'go install -v github.com/projectdiscovery/naabu/v2/cmd/naabu@v2.3.3'
51
- # install_github_handle = 'projectdiscovery/naabu'
51
+ install_github_handle = 'projectdiscovery/naabu'
52
52
  install_pre = {'apt': ['libpcap-dev'], 'apk': ['libpcap-dev', 'libc6-compat'], 'pacman|brew': ['libpcap']}
53
53
  install_post = {'arch|alpine': 'sudo ln -sf /usr/lib/libpcap.so /usr/lib/libpcap.so.0.8'}
54
54
  proxychains = False
secator/tasks/nmap.py CHANGED
@@ -30,14 +30,55 @@ class nmap(VulnMulti):
30
30
  opt_prefix = '--'
31
31
  output_types = [Port, Vulnerability, Exploit]
32
32
  opts = {
33
- PORTS: {'type': str, 'short': 'p', 'help': 'Ports to scan'},
34
- TOP_PORTS: {'type': int, 'short': 'tp', 'help': 'Top ports to scan [full, 100, 1000]'},
35
- SCRIPT: {'type': str, 'default': 'vulners', 'help': 'NSE scripts'},
33
+ # Port specification and scan order
34
+ PORTS: {'type': str, 'short': 'p', 'help': 'Ports to scan (- to scan all)'},
35
+ TOP_PORTS: {'type': int, 'short': 'tp', 'help': 'Top ports to scan [100, 1000, full]'},
36
+
37
+ # Script scanning
38
+ SCRIPT: {'type': str, 'default': None, 'help': 'NSE scripts'},
39
+ 'script_args': {'type': str, 'default': None, 'help': 'NSE script arguments (n1=v1,n2=v2,...)'},
40
+
41
+ # Host discovery
36
42
  'skip_host_discovery': {'is_flag': True, 'short': 'Pn', 'default': False, 'help': 'Skip host discovery (no ping)'},
37
- 'version_detection': {'is_flag': True, 'short': 'sV', 'default': False, 'help': 'Version detection'},
43
+
44
+ # Service and version detection
45
+ 'version_detection': {'is_flag': True, 'short': 'sV', 'default': False, 'help': 'Enable version detection (slow)'},
46
+ 'detect_all': {'is_flag': True, 'short': 'A', 'default': False, 'help': 'Enable OS detection, version detection, script scanning, and traceroute on open ports'}, # noqa: E501
47
+ 'detect_os': {'is_flag': True, 'short': 'O', 'default': False, 'help': 'Enable OS detection'},
48
+
49
+ # Scan techniques
38
50
  'tcp_syn_stealth': {'is_flag': True, 'short': 'sS', 'default': False, 'help': 'TCP SYN Stealth'},
39
51
  'tcp_connect': {'is_flag': True, 'short': 'sT', 'default': False, 'help': 'TCP Connect scan'},
40
52
  'udp_scan': {'is_flag': True, 'short': 'sU', 'default': False, 'help': 'UDP scan'},
53
+ 'tcp_null_scan': {'is_flag': True, 'short': 'sN', 'default': False, 'help': 'TCP Null scan'},
54
+ 'tcp_fin_scan': {'is_flag': True, 'short': 'sF', 'default': False, 'help': 'TCP FIN scan'},
55
+ 'tcp_xmas_scan': {'is_flag': True, 'short': 'sX', 'default': False, 'help': 'TCP Xmas scan'},
56
+ 'tcp_ack_scan': {'is_flag': True, 'short': 'sA', 'default': False, 'help': 'TCP ACK scan'},
57
+ 'tcp_window_scan': {'is_flag': True, 'short': 'sW', 'default': False, 'help': 'TCP Window scan'},
58
+ 'tcp_maimon_scan': {'is_flag': True, 'short': 'sM', 'default': False, 'help': 'TCP Maimon scan'},
59
+ 'sctp_init_scan': {'is_flag': True, 'short': 'sY', 'default': False, 'help': 'SCTP Init scan'},
60
+ 'sctp_cookie_echo_scan': {'is_flag': True, 'short': 'sZ', 'default': False, 'help': 'SCTP Cookie Echo scan'},
61
+ 'ping_scan': {'is_flag': True, 'short': 'sn', 'default': False, 'help': 'Ping scan (disable port scan)'},
62
+ 'ip_protocol_scan': {'type': str, 'short': 'sO', 'default': None, 'help': 'IP protocol scan'},
63
+ 'script_scan': {'is_flag': True, 'short': 'sC', 'default': False, 'help': 'Enable default scanning'},
64
+ 'zombie_host': {'type': str, 'short': 'sI', 'default': None, 'help': 'Use a zombie host for idle scan'},
65
+ 'ftp_relay_host': {'type': str, 'short': 'sB', 'default': None, 'help': 'FTP bounce scan relay host'},
66
+
67
+ # Firewall / IDS evasion and spoofing
68
+ 'spoof_source_port': {'type': int, 'short': 'g', 'default': None, 'help': 'Send packets from a specific port'},
69
+ 'spoof_source_ip': {'type': str, 'short': 'S', 'default': None, 'help': 'Spoof source IP address'},
70
+ 'spoof_source_mac': {'type': str, 'short': 'spoofmac', 'default': None, 'help': 'Spoof MAC address'},
71
+ 'fragment': {'is_flag': True, 'short': 'fragment', 'default': False, 'help': 'Fragment packets'},
72
+ 'mtu': {'type': int, 'short': 'mtu', 'default': None, 'help': 'Fragment packets with given MTU'},
73
+ 'ttl': {'type': int, 'short': 'ttl', 'default': None, 'help': 'Set TTL'},
74
+ 'badsum': {'is_flag': True, 'short': 'badsum', 'default': False, 'help': 'Create a bad checksum in the TCP header'},
75
+ 'ipv6': {'is_flag': True, 'short': 'ipv6', 'default': False, 'help': 'Enable IPv6 scanning'},
76
+
77
+ # Host discovery
78
+ 'traceroute': {'is_flag': True, 'short': 'traceroute', 'default': False, 'help': 'Traceroute'},
79
+ 'disable_arp_ping': {'is_flag': True, 'short': 'disable-arp-ping', 'default': False, 'help': 'Disable ARP ping'},
80
+
81
+ # Misc
41
82
  'output_path': {'type': str, 'short': 'oX', 'default': None, 'help': 'Output XML file path'},
42
83
  }
43
84
  opt_key_map = {
@@ -55,9 +96,34 @@ class nmap(VulnMulti):
55
96
  PORTS: '-p',
56
97
  'skip_host_discovery': '-Pn',
57
98
  'version_detection': '-sV',
58
- 'tcp_connect': '-sT',
99
+ 'detect_all': '-A',
100
+ 'detect_os': '-O',
59
101
  'tcp_syn_stealth': '-sS',
102
+ 'tcp_connect': '-sT',
103
+ 'tcp_window_scan': '-sW',
104
+ 'tcp_maimon_scan': '-sM',
60
105
  'udp_scan': '-sU',
106
+ 'tcp_null_scan': '-sN',
107
+ 'tcp_fin_scan': '-sF',
108
+ 'tcp_xmas_scan': '-sX',
109
+ 'tcp_ack_scan': '-sA',
110
+ 'sctp_init_scan': '-sY',
111
+ 'sctp_cookie_echo_scan': '-sZ',
112
+ 'ping_scan': '-sn',
113
+ 'ip_protocol_scan': '-sO',
114
+ 'script_scan': '-sC',
115
+ 'zombie_host': '-sI',
116
+ 'ftp_relay_host': '-b',
117
+ 'spoof_source_port': '-g',
118
+ 'spoof_source_ip': '-S',
119
+ 'spoof_source_mac': '--spoof-mac',
120
+ 'fragmentation': '-f',
121
+ 'mtu': '--mtu',
122
+ 'ttl': '--ttl',
123
+ 'badsum': '--badsum',
124
+ 'ipv6': '-6',
125
+ 'traceroute': '--traceroute',
126
+ 'disable_arp_ping': '--disable-arp-ping',
61
127
  'output_path': '-oX',
62
128
  }
63
129
  opt_value_map = {
secator/tasks/wpscan.py CHANGED
@@ -16,7 +16,7 @@ from secator.tasks._categories import VulnHttp
16
16
  @task()
17
17
  class wpscan(VulnHttp):
18
18
  """Wordpress security scanner."""
19
- cmd = 'wpscan --random-user-agent --force --verbose'
19
+ cmd = 'wpscan --random-user-agent --force --verbose --disable-tls-checks --ignore-main-redirect'
20
20
  file_flag = None
21
21
  input_flag = '--url'
22
22
  input_type = URL
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: secator
3
- Version: 0.10.1a6
3
+ Version: 0.10.1a8
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,8 +1,8 @@
1
1
  secator/.gitignore,sha256=da8MUc3hdb6Mo0WjZu2upn5uZMbXcBGvhdhTQ1L89HI,3093
2
2
  secator/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- secator/celery.py,sha256=PC4l00gLNN9ftxbTqMPgYNsFq5jOlCrEgFPyiWwbJLg,9620
3
+ secator/celery.py,sha256=o-8s9TNaApVVeYanok0SzvmGD_zsSMzf55DgERjnUgs,9635
4
4
  secator/celery_signals.py,sha256=iumfx7tTeoavAbHijBtij0JzeIqElxQldNZtuZmFY_U,4456
5
- secator/celery_utils.py,sha256=bW1yzMCjfIiesU4SOVNVuy0I8HukJyh8KmNB4w0woJM,8857
5
+ secator/celery_utils.py,sha256=_wcUC42VPUotPhh9YYqbuq0dkARI8_RoCklDlhQL9Jg,8903
6
6
  secator/cli.py,sha256=3_tTTusW12MCejFgtOeYjiedjrJpyQj_gsCK8FkTMJA,43922
7
7
  secator/config.py,sha256=CdVBh6d4k13SpkQKyHQfMFHgkLypUH07kAKLmCJJO1w,19688
8
8
  secator/decorators.py,sha256=3kYadCz6haIZtnjkFHSRfenTdc6Yu7bHd-0IVjhD72w,13902
@@ -26,10 +26,9 @@ secator/configs/scans/network.yaml,sha256=ghlgIwkWhJKQeT6V5TE51dFL-VRszWJtm4qx4I
26
26
  secator/configs/scans/subdomain.yaml,sha256=I007b1V5Rmm_4R9mODp6jxonHNIjXkQT9sU-AOxLSIo,123
27
27
  secator/configs/scans/url.yaml,sha256=zhRiqyHq7BZHtKsmjpMvp3vmt5DRNtmfqW44sZm1tWw,158
28
28
  secator/configs/workflows/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
29
- secator/configs/workflows/cidr_recon.yaml,sha256=u1QKDKGbpJEez5QqC20Yd_nBLZd_z4nA-XFRQV7pVI4,558
29
+ secator/configs/workflows/cidr_recon.yaml,sha256=ytmirZxtJ8lKnzdo83mwTHOhy1OpnltuN3HFkk6XwzI,557
30
30
  secator/configs/workflows/code_scan.yaml,sha256=3H8H55NVskiDbBwNueVF8FUYkquEQn2C6evnid9zhB4,207
31
- secator/configs/workflows/host_recon.yaml,sha256=9ypKWRbcGRmMgzuyrCjQ2EAbJO9q8HN_A-hlTKkypVg,1095
32
- secator/configs/workflows/port_scan.yaml,sha256=JKbT01_q4CaOKZYjVspl8PjMefUtsiJmDbUlHcGc8vw,921
31
+ secator/configs/workflows/host_recon.yaml,sha256=4xzUI5jwPc932wY4OvlITFr3QF6lqXdWkcxIwIl6TC4,985
33
32
  secator/configs/workflows/subdomain_recon.yaml,sha256=GFhAyatzWRVx3a2kphNWNoTB13wY3GZTSZ2tusFgo8E,722
34
33
  secator/configs/workflows/url_bypass.yaml,sha256=_uBzDhevJ2DOD9UkE25n7ZrmnjjfdU3lV3mnUudgdU0,180
35
34
  secator/configs/workflows/url_crawl.yaml,sha256=h74dvDBNLuY1EHc9FMby3ydr34VH1qFJHQKUaIIYpcw,573
@@ -69,13 +68,13 @@ secator/output_types/user_account.py,sha256=rm10somxyu30JHjj629IkR15Nhahylud_fVO
69
68
  secator/output_types/vulnerability.py,sha256=nF7OT9zGez8sZvLrkhjBOORjVi8hCqfCYUFq3eZ_ywo,2870
70
69
  secator/output_types/warning.py,sha256=47GtmG083GqGPb_R5JDFmARJ9Mqrme58UxwJhgdGPuI,853
71
70
  secator/runners/__init__.py,sha256=EBbOk37vkBy9p8Hhrbi-2VtM_rTwQ3b-0ggTyiD22cE,290
72
- secator/runners/_base.py,sha256=FMqUix_6GVe5U2OT1jiQ_zbaWEieBBxtZVQfeGZKWpU,30512
71
+ secator/runners/_base.py,sha256=C50WhU1WC8y69kLVqlR-to_ijwzh0Lgkf2j8bVTFy0M,31416
73
72
  secator/runners/_helpers.py,sha256=QhJmdmFdu5XSx3LBFf4Q4Hy2EXS6bLGnJUq8G7C6f68,2410
74
73
  secator/runners/celery.py,sha256=bqvDTTdoHiGRCt0FRvlgFHQ_nsjKMP5P0PzGbwfCj_0,425
75
74
  secator/runners/command.py,sha256=9AvjZgSXctP8D-ffPCtlnXEiGqTeaD2wVGhiGNuROb0,25469
76
- secator/runners/scan.py,sha256=jKguiqlH4jw0uRGMN6GNsqgexw9T0HBIL7_4mIUo3xA,1530
77
- secator/runners/task.py,sha256=RXVnNLPflFC7g9u6M8u6cnB7MYVyRALmQsjCCBtk7kA,1876
78
- secator/runners/workflow.py,sha256=qldnRm7r_SCvRHJFkZ7eaml62RZkOeCdT18PU357grY,2982
75
+ secator/runners/scan.py,sha256=L-6YfdgeVXjTEHiSriwNVFyBmSCNhHTj-6A7R9lka6c,1532
76
+ secator/runners/task.py,sha256=NuAEPtSc13XrA41QShx_R8H5NoSAcvjk-oP7wIlJDLA,1869
77
+ secator/runners/workflow.py,sha256=wa82AwsVqxk50xxSXAm3dOjutp2qFSr5Klj5Lot7TFc,3236
79
78
  secator/scans/__init__.py,sha256=s4Ojsk5CWwyWqHu_A4zaXUL5Hm5L5nCmCHZn7wdD3Io,623
80
79
  secator/serializers/__init__.py,sha256=OP5cmFl77ovgSCW_IDcZ21St2mUt5UK4QHfrsK2KvH8,248
81
80
  secator/serializers/dataclass.py,sha256=RqICpfsYWGjHAACAA2h2jZ_69CFHim4VZwcBqowGMcQ,1010
@@ -103,15 +102,15 @@ secator/tasks/katana.py,sha256=J0HKPT4QIrDj4uW2gZe7ByW6iEwPortSszqaHDvziwY,5355
103
102
  secator/tasks/maigret.py,sha256=6anhBzB4lEM90Lk23cAD_ku7I_ghTpj0W0i3h6HARD8,2088
104
103
  secator/tasks/mapcidr.py,sha256=56ocbaDmB5_C_ns-773CgZXGOKOtkI9q9xJs2Rlfqio,990
105
104
  secator/tasks/msfconsole.py,sha256=TXVrvzSWw9Ncv2h9QJtaEinTMbps_z0zX1PFirERVho,6430
106
- secator/tasks/naabu.py,sha256=90WORQhwFwy71OGNaFe10pCkIG8IJP1XwWQ24OMgSc4,2091
107
- secator/tasks/nmap.py,sha256=Zu24sJHnlOf3NXLj3Ohi07-x7m-5Ajr5ULpNsUF-QT0,12546
105
+ secator/tasks/naabu.py,sha256=LjtyX3RTsME6RegVWm3VshzREmufRfFQ9Pn0WC4hqeE,2089
106
+ secator/tasks/nmap.py,sha256=191jBXlZ3jpGMfJxEsTOG9lGaMB7EQCWA630JSiMx_E,16144
108
107
  secator/tasks/nuclei.py,sha256=bMXCRU5VWyrwI7Cv6BCj84NTpfjuALFumPqUSZ4Y6Ug,4243
109
108
  secator/tasks/searchsploit.py,sha256=gvtLZbL2hzAZ07Cf0cSj2Qs0GvWK94XyHvoPFsetXu8,3321
110
109
  secator/tasks/subfinder.py,sha256=C6W5NnXT92OUB1aSS9IYseqdI3wDMAz70TOEl8X-o3U,1213
111
- secator/tasks/wpscan.py,sha256=036ywiEqZfX_Bt071U7qIm7bi6pNk7vodflmuslJurA,5550
110
+ secator/tasks/wpscan.py,sha256=cSRwRfJEsZlqt1pVP3jWQ-7XhFfwR3i7FuL1PDRyWBQ,5594
112
111
  secator/workflows/__init__.py,sha256=R_TTyjg9f2Ph2_LYiF0lL07IjTrfRE_zqJzy-N7_WCk,675
113
- secator-0.10.1a6.dist-info/METADATA,sha256=mCzqqxVeSyNqStpurizNJqoDeXE_HbIsabiuxZ48-xE,14726
114
- secator-0.10.1a6.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
115
- secator-0.10.1a6.dist-info/entry_points.txt,sha256=lPgsqqUXWgiuGSfKy-se5gHdQlAXIwS_A46NYq7Acic,44
116
- secator-0.10.1a6.dist-info/licenses/LICENSE,sha256=19W5Jsy4WTctNkqmZIqLRV1gTDOp01S3LDj9iSgWaJ0,2867
117
- secator-0.10.1a6.dist-info/RECORD,,
112
+ secator-0.10.1a8.dist-info/METADATA,sha256=A44X6h4lPlEo3Lk1RP9CGrwc4XA-cYn78iM8KtRVsqI,14726
113
+ secator-0.10.1a8.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
114
+ secator-0.10.1a8.dist-info/entry_points.txt,sha256=lPgsqqUXWgiuGSfKy-se5gHdQlAXIwS_A46NYq7Acic,44
115
+ secator-0.10.1a8.dist-info/licenses/LICENSE,sha256=19W5Jsy4WTctNkqmZIqLRV1gTDOp01S3LDj9iSgWaJ0,2867
116
+ secator-0.10.1a8.dist-info/RECORD,,
@@ -1,38 +0,0 @@
1
- type: workflow
2
- name: port_scan
3
- alias: pscan
4
- description: Port scan
5
- tags: [recon, network, http, vuln]
6
- input_types:
7
- - host
8
- - cidr_range
9
- tasks:
10
- naabu:
11
- description: Find open ports
12
- ports: "-" # scan all ports
13
- nmap:
14
- description: Search for vulnerabilities on open ports
15
- skip_host_discovery: True
16
- version_detection: True
17
- targets_: port.host
18
- ports_: port.port
19
- _group:
20
- searchsploit:
21
- description: Search for related exploits
22
- targets_:
23
- - type: port
24
- field: '{host}~{service_name}'
25
- condition: item._source.startswith('nmap') and len(item.service_name.split('/')) > 1
26
- httpx:
27
- description: Probe HTTP services on open ports
28
- targets_:
29
- - type: port
30
- field: '{host}:{port}'
31
- condition: item._source.startswith('nmap')
32
- results:
33
- - type: port
34
-
35
- - type: url
36
- condition: item.status_code != 0
37
-
38
- - type: vulnerability