secator 0.6.0__py3-none-any.whl → 0.8.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of secator might be problematic. Click here for more details.
- secator/celery.py +160 -185
- secator/celery_utils.py +268 -0
- secator/cli.py +427 -176
- secator/config.py +114 -68
- secator/configs/workflows/host_recon.yaml +5 -3
- secator/configs/workflows/port_scan.yaml +7 -3
- secator/configs/workflows/subdomain_recon.yaml +2 -2
- secator/configs/workflows/url_bypass.yaml +10 -0
- secator/configs/workflows/url_dirsearch.yaml +1 -1
- secator/configs/workflows/url_vuln.yaml +1 -1
- secator/decorators.py +170 -92
- secator/definitions.py +11 -4
- secator/exporters/__init__.py +7 -5
- secator/exporters/console.py +10 -0
- secator/exporters/csv.py +27 -19
- secator/exporters/gdrive.py +16 -11
- secator/exporters/json.py +3 -1
- secator/exporters/table.py +30 -2
- secator/exporters/txt.py +20 -16
- secator/hooks/gcs.py +53 -0
- secator/hooks/mongodb.py +53 -27
- secator/installer.py +277 -60
- secator/output_types/__init__.py +29 -11
- secator/output_types/_base.py +11 -1
- secator/output_types/error.py +36 -0
- secator/output_types/exploit.py +12 -8
- secator/output_types/info.py +24 -0
- secator/output_types/ip.py +8 -1
- secator/output_types/port.py +9 -2
- secator/output_types/progress.py +5 -0
- secator/output_types/record.py +5 -3
- secator/output_types/stat.py +33 -0
- secator/output_types/subdomain.py +1 -1
- secator/output_types/tag.py +8 -6
- secator/output_types/target.py +2 -2
- secator/output_types/url.py +14 -11
- secator/output_types/user_account.py +6 -6
- secator/output_types/vulnerability.py +8 -6
- secator/output_types/warning.py +24 -0
- secator/report.py +56 -23
- secator/rich.py +44 -39
- secator/runners/_base.py +629 -638
- secator/runners/_helpers.py +5 -91
- secator/runners/celery.py +18 -0
- secator/runners/command.py +404 -214
- secator/runners/scan.py +8 -24
- secator/runners/task.py +21 -55
- secator/runners/workflow.py +41 -40
- secator/scans/__init__.py +28 -0
- secator/serializers/dataclass.py +6 -0
- secator/serializers/json.py +10 -5
- secator/serializers/regex.py +12 -4
- secator/tasks/_categories.py +147 -42
- secator/tasks/bbot.py +295 -0
- secator/tasks/bup.py +99 -0
- secator/tasks/cariddi.py +38 -49
- secator/tasks/dalfox.py +3 -0
- secator/tasks/dirsearch.py +14 -25
- secator/tasks/dnsx.py +49 -30
- secator/tasks/dnsxbrute.py +4 -1
- secator/tasks/feroxbuster.py +10 -20
- secator/tasks/ffuf.py +3 -2
- secator/tasks/fping.py +4 -4
- secator/tasks/gau.py +5 -0
- secator/tasks/gf.py +2 -2
- secator/tasks/gospider.py +4 -0
- secator/tasks/grype.py +11 -13
- secator/tasks/h8mail.py +32 -42
- secator/tasks/httpx.py +58 -21
- secator/tasks/katana.py +19 -23
- secator/tasks/maigret.py +27 -25
- secator/tasks/mapcidr.py +2 -3
- secator/tasks/msfconsole.py +22 -19
- secator/tasks/naabu.py +18 -2
- secator/tasks/nmap.py +82 -55
- secator/tasks/nuclei.py +13 -3
- secator/tasks/searchsploit.py +26 -11
- secator/tasks/subfinder.py +5 -1
- secator/tasks/wpscan.py +91 -94
- secator/template.py +61 -45
- secator/thread.py +24 -0
- secator/utils.py +417 -78
- secator/utils_test.py +48 -23
- secator/workflows/__init__.py +28 -0
- {secator-0.6.0.dist-info → secator-0.8.0.dist-info}/METADATA +59 -48
- secator-0.8.0.dist-info/RECORD +115 -0
- {secator-0.6.0.dist-info → secator-0.8.0.dist-info}/WHEEL +1 -1
- secator-0.6.0.dist-info/RECORD +0 -101
- {secator-0.6.0.dist-info → secator-0.8.0.dist-info}/entry_points.txt +0 -0
- {secator-0.6.0.dist-info → secator-0.8.0.dist-info}/licenses/LICENSE +0 -0
secator/config.py
CHANGED
|
@@ -20,6 +20,7 @@ StrExpandHome = Annotated[str, AfterValidator(lambda v: v.replace('~', str(Path.
|
|
|
20
20
|
ROOT_FOLDER = Path(__file__).parent.parent
|
|
21
21
|
LIB_FOLDER = ROOT_FOLDER / 'secator'
|
|
22
22
|
CONFIGS_FOLDER = LIB_FOLDER / 'configs'
|
|
23
|
+
DATA_FOLDER = os.environ.get('SECATOR_DIRS_DATA') or str(Path.home() / '.secator')
|
|
23
24
|
|
|
24
25
|
|
|
25
26
|
class StrictModel(BaseModel, extra='forbid'):
|
|
@@ -28,12 +29,14 @@ class StrictModel(BaseModel, extra='forbid'):
|
|
|
28
29
|
|
|
29
30
|
class Directories(StrictModel):
|
|
30
31
|
bin: Directory = Path.home() / '.local' / 'bin'
|
|
31
|
-
|
|
32
|
+
share: Directory = Path.home() / '.local' / 'share'
|
|
33
|
+
data: Directory = Path(DATA_FOLDER)
|
|
32
34
|
templates: Directory = ''
|
|
33
35
|
reports: Directory = ''
|
|
34
36
|
wordlists: Directory = ''
|
|
35
37
|
cves: Directory = ''
|
|
36
38
|
payloads: Directory = ''
|
|
39
|
+
performance: Directory = ''
|
|
37
40
|
revshells: Directory = ''
|
|
38
41
|
celery: Directory = ''
|
|
39
42
|
celery_data: Directory = ''
|
|
@@ -42,7 +45,7 @@ class Directories(StrictModel):
|
|
|
42
45
|
@model_validator(mode='after')
|
|
43
46
|
def set_default_folders(self) -> Self:
|
|
44
47
|
"""Set folders to be relative to the data folders if they are unspecified in config."""
|
|
45
|
-
for folder in ['templates', 'reports', 'wordlists', 'cves', 'payloads', 'revshells', 'celery', 'celery_data', 'celery_results']: # noqa: E501
|
|
48
|
+
for folder in ['templates', 'reports', 'wordlists', 'cves', 'payloads', 'performance', 'revshells', 'celery', 'celery_data', 'celery_results']: # noqa: E501
|
|
46
49
|
rel_target = '/'.join(folder.split('_'))
|
|
47
50
|
val = getattr(self, folder) or self.data / rel_target
|
|
48
51
|
setattr(self, folder, val)
|
|
@@ -61,40 +64,52 @@ class Celery(StrictModel):
|
|
|
61
64
|
broker_visibility_timeout: int = 3600
|
|
62
65
|
override_default_logging: bool = True
|
|
63
66
|
result_backend: StrExpandHome = ''
|
|
67
|
+
result_expires: int = 86400 # 1 day
|
|
64
68
|
|
|
65
69
|
|
|
66
70
|
class Cli(StrictModel):
|
|
67
|
-
github_token: str = ''
|
|
71
|
+
github_token: str = os.environ.get('GITHUB_TOKEN', '')
|
|
68
72
|
record: bool = False
|
|
69
73
|
stdin_timeout: int = 1000
|
|
70
74
|
|
|
71
75
|
|
|
72
76
|
class Runners(StrictModel):
|
|
73
|
-
input_chunk_size: int =
|
|
74
|
-
progress_update_frequency: int =
|
|
77
|
+
input_chunk_size: int = 100
|
|
78
|
+
progress_update_frequency: int = 20
|
|
79
|
+
stat_update_frequency: int = 20
|
|
80
|
+
backend_update_frequency: int = 5
|
|
81
|
+
poll_frequency: int = 5
|
|
75
82
|
skip_cve_search: bool = False
|
|
76
|
-
|
|
83
|
+
skip_exploit_search: bool = False
|
|
84
|
+
skip_cve_low_confidence: bool = False
|
|
77
85
|
remove_duplicates: bool = False
|
|
78
86
|
|
|
79
87
|
|
|
88
|
+
class Security(StrictModel):
|
|
89
|
+
allow_local_file_access: bool = True
|
|
90
|
+
auto_install_commands: bool = True
|
|
91
|
+
force_source_install: bool = False
|
|
92
|
+
|
|
93
|
+
|
|
80
94
|
class HTTP(StrictModel):
|
|
81
95
|
socks5_proxy: str = 'socks5://127.0.0.1:9050'
|
|
82
96
|
http_proxy: str = 'https://127.0.0.1:9080'
|
|
83
97
|
store_responses: bool = False
|
|
98
|
+
response_max_size_bytes: int = 100000 # 100MB
|
|
84
99
|
proxychains_command: str = 'proxychains'
|
|
85
100
|
freeproxy_timeout: int = 1
|
|
86
101
|
|
|
87
102
|
|
|
88
103
|
class Tasks(StrictModel):
|
|
89
|
-
exporters: List[str] = ['json', 'csv']
|
|
104
|
+
exporters: List[str] = ['json', 'csv', 'txt']
|
|
90
105
|
|
|
91
106
|
|
|
92
107
|
class Workflows(StrictModel):
|
|
93
|
-
exporters: List[str] = ['json', 'csv']
|
|
108
|
+
exporters: List[str] = ['json', 'csv', 'txt']
|
|
94
109
|
|
|
95
110
|
|
|
96
111
|
class Scans(StrictModel):
|
|
97
|
-
exporters: List[str] = ['json', 'csv']
|
|
112
|
+
exporters: List[str] = ['json', 'csv', 'txt']
|
|
98
113
|
|
|
99
114
|
|
|
100
115
|
class Payloads(StrictModel):
|
|
@@ -109,17 +124,24 @@ class Wordlists(StrictModel):
|
|
|
109
124
|
defaults: Dict[str, str] = {'http': 'bo0m_fuzz', 'dns': 'combined_subdomains'}
|
|
110
125
|
templates: Dict[str, str] = {
|
|
111
126
|
'bo0m_fuzz': 'https://raw.githubusercontent.com/Bo0oM/fuzz.txt/master/fuzz.txt',
|
|
112
|
-
'combined_subdomains': 'https://raw.githubusercontent.com/danielmiessler/SecLists/master/Discovery/DNS/combined_subdomains.txt' # noqa: E501
|
|
127
|
+
'combined_subdomains': 'https://raw.githubusercontent.com/danielmiessler/SecLists/master/Discovery/DNS/combined_subdomains.txt', # noqa: E501
|
|
128
|
+
'directory_list_small': 'https://raw.githubusercontent.com/danielmiessler/SecLists/refs/heads/master/Discovery/Web-Content/directory-list-2.3-small.txt', # noqa: E501
|
|
113
129
|
}
|
|
114
130
|
lists: Dict[str, List[str]] = {}
|
|
115
131
|
|
|
116
132
|
|
|
117
|
-
class
|
|
133
|
+
class GoogleDriveAddon(StrictModel):
|
|
118
134
|
enabled: bool = False
|
|
119
135
|
drive_parent_folder_id: str = ''
|
|
120
136
|
credentials_path: str = ''
|
|
121
137
|
|
|
122
138
|
|
|
139
|
+
class GoogleCloudStorageAddon(StrictModel):
|
|
140
|
+
enabled: bool = False
|
|
141
|
+
bucket_name: str = ''
|
|
142
|
+
credentials_path: str = ''
|
|
143
|
+
|
|
144
|
+
|
|
123
145
|
class WorkerAddon(StrictModel):
|
|
124
146
|
enabled: bool = False
|
|
125
147
|
|
|
@@ -128,10 +150,13 @@ class MongodbAddon(StrictModel):
|
|
|
128
150
|
enabled: bool = False
|
|
129
151
|
url: str = 'mongodb://localhost'
|
|
130
152
|
update_frequency: int = 60
|
|
153
|
+
max_pool_size: int = 10
|
|
154
|
+
server_selection_timeout_ms: int = 5000
|
|
131
155
|
|
|
132
156
|
|
|
133
157
|
class Addons(StrictModel):
|
|
134
|
-
|
|
158
|
+
gdrive: GoogleDriveAddon = GoogleDriveAddon()
|
|
159
|
+
gcs: GoogleCloudStorageAddon = GoogleCloudStorageAddon()
|
|
135
160
|
worker: WorkerAddon = WorkerAddon()
|
|
136
161
|
mongodb: MongodbAddon = MongodbAddon()
|
|
137
162
|
|
|
@@ -149,6 +174,7 @@ class SecatorConfig(StrictModel):
|
|
|
149
174
|
payloads: Payloads = Payloads()
|
|
150
175
|
wordlists: Wordlists = Wordlists()
|
|
151
176
|
addons: Addons = Addons()
|
|
177
|
+
security: Security = Security()
|
|
152
178
|
offline_mode: bool = False
|
|
153
179
|
|
|
154
180
|
|
|
@@ -161,7 +187,7 @@ class Config(DotMap):
|
|
|
161
187
|
>>> config = Config.parse(path='/path/to/config.yml') # get custom config (from YAML file).
|
|
162
188
|
>>> config.print() # print config without defaults.
|
|
163
189
|
>>> config.print(partial=False) # print full config.
|
|
164
|
-
>>> config.set('addons.
|
|
190
|
+
>>> config.set('addons.gdrive.enabled', False) # set value in config.
|
|
165
191
|
>>> config.save() # save config back to disk.
|
|
166
192
|
"""
|
|
167
193
|
|
|
@@ -479,56 +505,81 @@ def download_files(data: dict, target_folder: Path, offline_mode: bool, type: st
|
|
|
479
505
|
offline_mode (bool): Offline mode.
|
|
480
506
|
"""
|
|
481
507
|
for name, url_or_path in data.items():
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
508
|
+
target_path = download_file(url_or_path, target_folder, offline_mode, type, name=name)
|
|
509
|
+
if target_path:
|
|
510
|
+
data[name] = target_path
|
|
511
|
+
|
|
512
|
+
|
|
513
|
+
def download_file(url_or_path, target_folder: Path, offline_mode: bool, type: str, name: str = None):
|
|
514
|
+
"""Download remote file to target folder, clone git repos, or symlink local files.
|
|
515
|
+
|
|
516
|
+
Args:
|
|
517
|
+
data (dict): Dict of name to url or local path prefixed with 'git+' for Git repos.
|
|
518
|
+
target_folder (Path): Target folder for storing files or repos.
|
|
519
|
+
offline_mode (bool): Offline mode.
|
|
520
|
+
type (str): Type of files to handle.
|
|
521
|
+
name (str, Optional): Name of object.
|
|
522
|
+
|
|
523
|
+
Returns:
|
|
524
|
+
path (Path): Path to downloaded file / folder.
|
|
525
|
+
"""
|
|
526
|
+
if url_or_path.startswith('git+'):
|
|
527
|
+
# Clone Git repository
|
|
528
|
+
git_url = url_or_path[4:] # remove 'git+' prefix
|
|
529
|
+
repo_name = git_url.split('/')[-1]
|
|
530
|
+
if repo_name.endswith('.git'):
|
|
531
|
+
repo_name = repo_name[:-4]
|
|
532
|
+
target_path = target_folder / repo_name
|
|
533
|
+
if not target_path.exists():
|
|
534
|
+
console.print(f'[bold turquoise4]Cloning git {type} [bold magenta]{repo_name}[/] ...[/] ', end='')
|
|
535
|
+
if offline_mode:
|
|
536
|
+
console.print('[bold orange1]skipped [dim][offline[/].[/]')
|
|
537
|
+
return
|
|
538
|
+
try:
|
|
539
|
+
call(['git', 'clone', git_url, str(target_path)], stderr=DEVNULL, stdout=DEVNULL)
|
|
540
|
+
console.print('[bold green]ok.[/]')
|
|
541
|
+
except Exception as e:
|
|
542
|
+
console.print(f'[bold red]failed ({str(e)}).[/]')
|
|
543
|
+
return target_path.resolve()
|
|
544
|
+
elif Path(url_or_path).exists():
|
|
545
|
+
# Create a symbolic link for a local file
|
|
546
|
+
local_path = Path(url_or_path)
|
|
547
|
+
target_path = target_folder / local_path.name
|
|
548
|
+
if not name:
|
|
549
|
+
name = url_or_path.split('/')[-1]
|
|
550
|
+
if not CONFIG.security.allow_local_file_access:
|
|
551
|
+
console.print(f'[bold red]Cannot reference local file {url_or_path}(disabled for security reasons)[/]')
|
|
552
|
+
return
|
|
553
|
+
if not target_path.exists():
|
|
554
|
+
console.print(f'[bold turquoise4]Symlinking {type} [bold magenta]{name}[/] ...[/] ', end='')
|
|
555
|
+
try:
|
|
556
|
+
target_path.symlink_to(local_path)
|
|
557
|
+
console.print('[bold green]ok.[/]')
|
|
558
|
+
except Exception as e:
|
|
559
|
+
console.print(f'[bold red]failed ({str(e)}).[/]')
|
|
560
|
+
return target_path.resolve()
|
|
561
|
+
else:
|
|
562
|
+
# Download file from URL
|
|
563
|
+
ext = url_or_path.split('.')[-1]
|
|
564
|
+
if not name:
|
|
565
|
+
name = url_or_path.split('/')[-1]
|
|
566
|
+
filename = f'{name}.{ext}' if not name.endswith(ext) else name
|
|
567
|
+
target_path = target_folder / filename
|
|
568
|
+
if not target_path.exists():
|
|
569
|
+
try:
|
|
570
|
+
console.print(f'[bold turquoise4]Downloading {type} [bold magenta]{filename}[/] ...[/] ', end='')
|
|
491
571
|
if offline_mode:
|
|
492
|
-
console.print('[bold orange1]skipped [dim]
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
target_path = target_folder / local_path.name
|
|
504
|
-
if not target_path.exists():
|
|
505
|
-
console.print(f'[bold turquoise4]Symlinking {type} [bold magenta]{name}[/] ...[/] ', end='')
|
|
506
|
-
try:
|
|
507
|
-
target_path.symlink_to(local_path)
|
|
508
|
-
console.print('[bold green]ok.[/]')
|
|
509
|
-
except Exception as e:
|
|
510
|
-
console.print(f'[bold red]failed ({str(e)}).[/]')
|
|
511
|
-
data[name] = target_path.resolve()
|
|
512
|
-
else:
|
|
513
|
-
# Download file from URL
|
|
514
|
-
ext = url_or_path.split('.')[-1]
|
|
515
|
-
filename = f'{name}.{ext}'
|
|
516
|
-
target_path = target_folder / filename
|
|
517
|
-
if not target_path.exists():
|
|
518
|
-
try:
|
|
519
|
-
console.print(f'[bold turquoise4]Downloading {type} [bold magenta]{filename}[/] ...[/] ', end='')
|
|
520
|
-
if offline_mode:
|
|
521
|
-
console.print('[bold orange1]skipped [dim](offline)[/].[/]')
|
|
522
|
-
continue
|
|
523
|
-
resp = requests.get(url_or_path, timeout=3)
|
|
524
|
-
resp.raise_for_status()
|
|
525
|
-
with open(target_path, 'wb') as f:
|
|
526
|
-
f.write(resp.content)
|
|
527
|
-
console.print('[bold green]ok.[/]')
|
|
528
|
-
except requests.RequestException as e:
|
|
529
|
-
console.print(f'[bold red]failed ({str(e)}).[/]')
|
|
530
|
-
continue
|
|
531
|
-
data[name] = target_path.resolve()
|
|
572
|
+
console.print('[bold orange1]skipped [dim](offline)[/].[/]')
|
|
573
|
+
return
|
|
574
|
+
resp = requests.get(url_or_path, timeout=3)
|
|
575
|
+
resp.raise_for_status()
|
|
576
|
+
with open(target_path, 'wb') as f:
|
|
577
|
+
f.write(resp.content)
|
|
578
|
+
console.print('[bold green]ok.[/]')
|
|
579
|
+
except requests.RequestException as e:
|
|
580
|
+
console.print(f'[bold red]failed ({str(e)}).[/]')
|
|
581
|
+
return
|
|
582
|
+
return target_path.resolve()
|
|
532
583
|
|
|
533
584
|
|
|
534
585
|
# Load default_config
|
|
@@ -560,13 +611,8 @@ for name, dir in CONFIG.dirs.items():
|
|
|
560
611
|
dir.mkdir(parents=False)
|
|
561
612
|
console.print('[bold green]ok.[/]')
|
|
562
613
|
|
|
563
|
-
# Download wordlists and
|
|
614
|
+
# Download wordlists and payloads
|
|
564
615
|
download_files(CONFIG.wordlists.templates, CONFIG.dirs.wordlists, CONFIG.offline_mode, 'wordlist')
|
|
565
|
-
for category, name in CONFIG.wordlists.defaults.items():
|
|
566
|
-
if name in CONFIG.wordlists.templates.keys():
|
|
567
|
-
CONFIG.wordlists.defaults[category] = str(CONFIG.wordlists.templates[name])
|
|
568
|
-
|
|
569
|
-
# Download payloads
|
|
570
616
|
download_files(CONFIG.payloads.templates, CONFIG.dirs.payloads, CONFIG.offline_mode, 'payload')
|
|
571
617
|
|
|
572
618
|
# Print config
|
|
@@ -11,6 +11,8 @@ tasks:
|
|
|
11
11
|
description: Find open ports
|
|
12
12
|
nmap:
|
|
13
13
|
description: Search for vulnerabilities on open ports
|
|
14
|
+
skip_host_discovery: True
|
|
15
|
+
version_detection: True
|
|
14
16
|
targets_: port.host
|
|
15
17
|
ports_: port.port
|
|
16
18
|
httpx:
|
|
@@ -18,7 +20,7 @@ tasks:
|
|
|
18
20
|
targets_:
|
|
19
21
|
- type: port
|
|
20
22
|
field: '{host}:{port}'
|
|
21
|
-
condition: item._source
|
|
23
|
+
condition: item._source.startswith('nmap')
|
|
22
24
|
_group:
|
|
23
25
|
nuclei/network:
|
|
24
26
|
description: Scan network and SSL vulnerabilities
|
|
@@ -32,10 +34,10 @@ tasks:
|
|
|
32
34
|
condition: item.status_code != 0
|
|
33
35
|
results:
|
|
34
36
|
- type: port
|
|
35
|
-
condition: item._source
|
|
37
|
+
condition: item._source.startswith('nmap')
|
|
36
38
|
|
|
37
39
|
- type: vulnerability
|
|
38
40
|
# condition: item.confidence == 'high'
|
|
39
41
|
|
|
40
42
|
- type: url
|
|
41
|
-
condition: item.status_code != 0
|
|
43
|
+
condition: item.status_code != 0
|
|
@@ -5,11 +5,15 @@ description: Port scan
|
|
|
5
5
|
tags: [recon, network, http, vuln]
|
|
6
6
|
input_types:
|
|
7
7
|
- host
|
|
8
|
+
- cidr_range
|
|
8
9
|
tasks:
|
|
9
10
|
naabu:
|
|
10
11
|
description: Find open ports
|
|
12
|
+
ports: "-" # scan all ports
|
|
11
13
|
nmap:
|
|
12
14
|
description: Search for vulnerabilities on open ports
|
|
15
|
+
skip_host_discovery: True
|
|
16
|
+
version_detection: True
|
|
13
17
|
targets_: port.host
|
|
14
18
|
ports_: port.port
|
|
15
19
|
_group:
|
|
@@ -18,17 +22,17 @@ tasks:
|
|
|
18
22
|
targets_:
|
|
19
23
|
- type: port
|
|
20
24
|
field: '{host}~{service_name}'
|
|
21
|
-
condition: item._source
|
|
25
|
+
condition: item._source.startswith('nmap') and len(item.service_name.split('/')) > 1
|
|
22
26
|
httpx:
|
|
23
27
|
description: Probe HTTP services on open ports
|
|
24
28
|
targets_:
|
|
25
29
|
- type: port
|
|
26
30
|
field: '{host}:{port}'
|
|
27
|
-
condition: item._source
|
|
31
|
+
condition: item._source.startswith('nmap')
|
|
28
32
|
results:
|
|
29
33
|
- type: port
|
|
30
34
|
|
|
31
35
|
- type: url
|
|
32
36
|
condition: item.status_code != 0
|
|
33
37
|
|
|
34
|
-
- type: vulnerability
|
|
38
|
+
- type: vulnerability
|
|
@@ -13,12 +13,12 @@ tasks:
|
|
|
13
13
|
# input: vhost
|
|
14
14
|
# domain_:
|
|
15
15
|
# - target.name
|
|
16
|
-
# wordlist:
|
|
16
|
+
# wordlist: combined_subdomains
|
|
17
17
|
# gobuster:
|
|
18
18
|
# input: dns
|
|
19
19
|
# domain_:
|
|
20
20
|
# - target.name
|
|
21
|
-
# wordlist:
|
|
21
|
+
# wordlist: combined_subdomains
|
|
22
22
|
_group:
|
|
23
23
|
nuclei:
|
|
24
24
|
description: Check for subdomain takeovers
|