secator 0.0.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/__init__.py +0 -0
- secator/celery.py +482 -0
- secator/cli.py +617 -0
- secator/config.py +137 -0
- secator/configs/__init__.py +0 -0
- secator/configs/profiles/__init__.py +0 -0
- secator/configs/profiles/aggressive.yaml +7 -0
- secator/configs/profiles/default.yaml +9 -0
- secator/configs/profiles/stealth.yaml +7 -0
- secator/configs/scans/__init__.py +0 -0
- secator/configs/scans/domain.yaml +18 -0
- secator/configs/scans/host.yaml +14 -0
- secator/configs/scans/network.yaml +17 -0
- secator/configs/scans/subdomain.yaml +8 -0
- secator/configs/scans/url.yaml +12 -0
- secator/configs/workflows/__init__.py +0 -0
- secator/configs/workflows/cidr_recon.yaml +28 -0
- secator/configs/workflows/code_scan.yaml +11 -0
- secator/configs/workflows/host_recon.yaml +41 -0
- secator/configs/workflows/port_scan.yaml +34 -0
- secator/configs/workflows/subdomain_recon.yaml +33 -0
- secator/configs/workflows/url_crawl.yaml +29 -0
- secator/configs/workflows/url_dirsearch.yaml +29 -0
- secator/configs/workflows/url_fuzz.yaml +35 -0
- secator/configs/workflows/url_nuclei.yaml +11 -0
- secator/configs/workflows/url_vuln.yaml +55 -0
- secator/configs/workflows/user_hunt.yaml +10 -0
- secator/configs/workflows/wordpress.yaml +14 -0
- secator/decorators.py +309 -0
- secator/definitions.py +165 -0
- secator/exporters/__init__.py +12 -0
- secator/exporters/_base.py +3 -0
- secator/exporters/csv.py +30 -0
- secator/exporters/gdrive.py +118 -0
- secator/exporters/json.py +15 -0
- secator/exporters/table.py +7 -0
- secator/exporters/txt.py +25 -0
- secator/hooks/__init__.py +0 -0
- secator/hooks/mongodb.py +212 -0
- secator/output_types/__init__.py +24 -0
- secator/output_types/_base.py +95 -0
- secator/output_types/exploit.py +50 -0
- secator/output_types/ip.py +33 -0
- secator/output_types/port.py +45 -0
- secator/output_types/progress.py +35 -0
- secator/output_types/record.py +34 -0
- secator/output_types/subdomain.py +42 -0
- secator/output_types/tag.py +46 -0
- secator/output_types/target.py +30 -0
- secator/output_types/url.py +76 -0
- secator/output_types/user_account.py +41 -0
- secator/output_types/vulnerability.py +97 -0
- secator/report.py +107 -0
- secator/rich.py +124 -0
- secator/runners/__init__.py +12 -0
- secator/runners/_base.py +833 -0
- secator/runners/_helpers.py +153 -0
- secator/runners/command.py +638 -0
- secator/runners/scan.py +65 -0
- secator/runners/task.py +106 -0
- secator/runners/workflow.py +135 -0
- secator/serializers/__init__.py +8 -0
- secator/serializers/dataclass.py +33 -0
- secator/serializers/json.py +15 -0
- secator/serializers/regex.py +17 -0
- secator/tasks/__init__.py +10 -0
- secator/tasks/_categories.py +304 -0
- secator/tasks/cariddi.py +102 -0
- secator/tasks/dalfox.py +65 -0
- secator/tasks/dirsearch.py +90 -0
- secator/tasks/dnsx.py +56 -0
- secator/tasks/dnsxbrute.py +34 -0
- secator/tasks/feroxbuster.py +91 -0
- secator/tasks/ffuf.py +86 -0
- secator/tasks/fping.py +44 -0
- secator/tasks/gau.py +47 -0
- secator/tasks/gf.py +33 -0
- secator/tasks/gospider.py +71 -0
- secator/tasks/grype.py +79 -0
- secator/tasks/h8mail.py +81 -0
- secator/tasks/httpx.py +99 -0
- secator/tasks/katana.py +133 -0
- secator/tasks/maigret.py +78 -0
- secator/tasks/mapcidr.py +32 -0
- secator/tasks/msfconsole.py +174 -0
- secator/tasks/naabu.py +52 -0
- secator/tasks/nmap.py +344 -0
- secator/tasks/nuclei.py +97 -0
- secator/tasks/searchsploit.py +52 -0
- secator/tasks/subfinder.py +40 -0
- secator/tasks/wpscan.py +179 -0
- secator/utils.py +445 -0
- secator/utils_test.py +183 -0
- secator-0.0.1.dist-info/LICENSE +60 -0
- secator-0.0.1.dist-info/METADATA +199 -0
- secator-0.0.1.dist-info/RECORD +114 -0
- secator-0.0.1.dist-info/WHEEL +5 -0
- secator-0.0.1.dist-info/entry_points.txt +2 -0
- secator-0.0.1.dist-info/top_level.txt +2 -0
- tests/__init__.py +0 -0
- tests/integration/__init__.py +0 -0
- tests/integration/inputs.py +42 -0
- tests/integration/outputs.py +392 -0
- tests/integration/test_scans.py +82 -0
- tests/integration/test_tasks.py +103 -0
- tests/integration/test_workflows.py +163 -0
- tests/performance/__init__.py +0 -0
- tests/performance/loadtester.py +56 -0
- tests/unit/__init__.py +0 -0
- tests/unit/test_celery.py +39 -0
- tests/unit/test_scans.py +0 -0
- tests/unit/test_serializers.py +51 -0
- tests/unit/test_tasks.py +348 -0
- tests/unit/test_workflows.py +96 -0
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
from celery.result import AsyncResult, GroupResult
|
|
2
|
+
from rich.prompt import Confirm
|
|
3
|
+
|
|
4
|
+
from secator.utils import deduplicate
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def run_extractors(results, opts, targets=[]):
|
|
8
|
+
"""Run extractors and merge extracted values with option dict.
|
|
9
|
+
|
|
10
|
+
Args:
|
|
11
|
+
results (list): List of results.
|
|
12
|
+
opts (dict): Options.
|
|
13
|
+
targets (list): Original targets.
|
|
14
|
+
|
|
15
|
+
Returns:
|
|
16
|
+
tuple: targets, options.
|
|
17
|
+
"""
|
|
18
|
+
extractors = {k: v for k, v in opts.items() if k.endswith('_')}
|
|
19
|
+
for key, val in extractors.items():
|
|
20
|
+
key = key.rstrip('_')
|
|
21
|
+
values = extract_from_results(results, val)
|
|
22
|
+
if key == 'targets':
|
|
23
|
+
targets = deduplicate(values)
|
|
24
|
+
else:
|
|
25
|
+
opts[key] = deduplicate(values)
|
|
26
|
+
return targets, opts
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def extract_from_results(results, extractors):
|
|
30
|
+
"""Extract sub extractors from list of results dict.
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
results (list): List of dict.
|
|
34
|
+
extractors (list): List of extractors to extract from.
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
list: List of extracted results (flat).
|
|
38
|
+
"""
|
|
39
|
+
extracted = []
|
|
40
|
+
if not isinstance(extractors, list):
|
|
41
|
+
extractors = [extractors]
|
|
42
|
+
for extractor in extractors:
|
|
43
|
+
extracted.extend(process_extractor(results, extractor))
|
|
44
|
+
return extracted
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def process_extractor(results, extractor, ctx={}):
|
|
48
|
+
"""Process extractor.
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
results (list): List of results.
|
|
52
|
+
extractor (dict / str): extractor definition.
|
|
53
|
+
|
|
54
|
+
Returns:
|
|
55
|
+
list: List of extracted results.
|
|
56
|
+
"""
|
|
57
|
+
if isinstance(extractor, dict):
|
|
58
|
+
_type = extractor['type']
|
|
59
|
+
_field = extractor.get('field')
|
|
60
|
+
_condition = extractor.get('condition', 'True')
|
|
61
|
+
else:
|
|
62
|
+
_type, _field = tuple(extractor.split('.'))
|
|
63
|
+
_condition = 'True'
|
|
64
|
+
items = [
|
|
65
|
+
item for item in results if item._type == _type and eval(_condition)
|
|
66
|
+
]
|
|
67
|
+
if _field:
|
|
68
|
+
_field = '{' + _field + '}' if not _field.startswith('{') else _field
|
|
69
|
+
items = [_field.format(**item.toDict()) for item in items]
|
|
70
|
+
return items
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def get_task_ids(result, ids=[]):
|
|
74
|
+
"""Get all Celery task ids recursively.
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
result (Union[AsyncResult, GroupResult]): Celery result object.
|
|
78
|
+
ids (list): List of ids.
|
|
79
|
+
"""
|
|
80
|
+
if result is None:
|
|
81
|
+
return
|
|
82
|
+
|
|
83
|
+
if isinstance(result, GroupResult):
|
|
84
|
+
get_task_ids(result.parent, ids=ids)
|
|
85
|
+
|
|
86
|
+
elif isinstance(result, AsyncResult):
|
|
87
|
+
if result.id not in ids:
|
|
88
|
+
ids.append(result.id)
|
|
89
|
+
|
|
90
|
+
if hasattr(result, 'children') and result.children:
|
|
91
|
+
for child in result.children:
|
|
92
|
+
get_task_ids(child, ids=ids)
|
|
93
|
+
|
|
94
|
+
# Browse parent
|
|
95
|
+
if hasattr(result, 'parent') and result.parent:
|
|
96
|
+
get_task_ids(result.parent, ids=ids)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def get_task_data(task_id):
|
|
100
|
+
"""Get task info.
|
|
101
|
+
|
|
102
|
+
Args:
|
|
103
|
+
task_id (str): Celery task id.
|
|
104
|
+
|
|
105
|
+
Returns:
|
|
106
|
+
dict: Task info (id, name, state, results, chunk_info, count, error, ready).
|
|
107
|
+
"""
|
|
108
|
+
res = AsyncResult(task_id)
|
|
109
|
+
if not (res and res.args and len(res.args) > 1):
|
|
110
|
+
return
|
|
111
|
+
data = {}
|
|
112
|
+
task_name = res.args[1]
|
|
113
|
+
data['id'] = task_id
|
|
114
|
+
data['name'] = task_name
|
|
115
|
+
data['state'] = res.state
|
|
116
|
+
data['chunk_info'] = ''
|
|
117
|
+
data['count'] = 0
|
|
118
|
+
data['error'] = None
|
|
119
|
+
data['ready'] = False
|
|
120
|
+
data['descr'] = ''
|
|
121
|
+
data['progress'] = 0
|
|
122
|
+
data['results'] = []
|
|
123
|
+
if res.state in ['FAILURE', 'SUCCESS', 'REVOKED']:
|
|
124
|
+
data['ready'] = True
|
|
125
|
+
if res.info and not isinstance(res.info, list):
|
|
126
|
+
chunk = res.info.get('chunk', '')
|
|
127
|
+
chunk_count = res.info.get('chunk_count', '')
|
|
128
|
+
data['chunk'] = chunk
|
|
129
|
+
data['chunk_count'] = chunk_count
|
|
130
|
+
if chunk:
|
|
131
|
+
data['chunk_info'] = f'{chunk}/{chunk_count}'
|
|
132
|
+
data.update(res.info)
|
|
133
|
+
data['descr'] = data.pop('description', '')
|
|
134
|
+
# del data['results']
|
|
135
|
+
# del data['task_results']
|
|
136
|
+
return data
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def confirm_exit(func):
|
|
140
|
+
"""Decorator asking user for confirmation to exit.
|
|
141
|
+
|
|
142
|
+
Args:
|
|
143
|
+
func (func): Decorated function.
|
|
144
|
+
"""
|
|
145
|
+
def inner_function(self, *args, **kwargs):
|
|
146
|
+
try:
|
|
147
|
+
func(self, *args, **kwargs)
|
|
148
|
+
except KeyboardInterrupt:
|
|
149
|
+
exit_confirmed = Confirm.ask('Are you sure you want to exit ?')
|
|
150
|
+
if exit_confirmed:
|
|
151
|
+
self.log_results()
|
|
152
|
+
raise KeyboardInterrupt
|
|
153
|
+
return inner_function
|