bbot 2.2.0.5263rc0__py3-none-any.whl → 2.2.0.5279rc0__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 bbot might be problematic. Click here for more details.
- bbot/__init__.py +1 -1
- bbot/core/helpers/depsinstaller/installer.py +8 -5
- bbot/core/helpers/misc.py +18 -0
- bbot/defaults.yml +3 -0
- bbot/modules/internal/speculate.py +33 -23
- bbot/modules/leakix.py +2 -3
- bbot/presets/fast.yml +16 -0
- bbot/scanner/preset/args.py +17 -1
- bbot/scanner/preset/preset.py +8 -8
- bbot/test/bbot_fixtures.py +5 -2
- bbot/test/conftest.py +95 -83
- bbot/test/test_step_1/test_cli.py +29 -0
- bbot/test/test_step_1/test_events.py +0 -1
- bbot/test/test_step_1/test_modules_basic.py +0 -3
- bbot/test/test_step_1/test_presets.py +1 -2
- bbot/test/test_step_1/test_web.py +3 -0
- bbot/test/test_step_2/module_tests/test_module_dotnetnuke.py +0 -6
- bbot/test/test_step_2/module_tests/test_module_leakix.py +5 -1
- {bbot-2.2.0.5263rc0.dist-info → bbot-2.2.0.5279rc0.dist-info}/METADATA +1 -1
- {bbot-2.2.0.5263rc0.dist-info → bbot-2.2.0.5279rc0.dist-info}/RECORD +23 -22
- {bbot-2.2.0.5263rc0.dist-info → bbot-2.2.0.5279rc0.dist-info}/LICENSE +0 -0
- {bbot-2.2.0.5263rc0.dist-info → bbot-2.2.0.5279rc0.dist-info}/WHEEL +0 -0
- {bbot-2.2.0.5263rc0.dist-info → bbot-2.2.0.5279rc0.dist-info}/entry_points.txt +0 -0
bbot/__init__.py
CHANGED
|
@@ -14,7 +14,7 @@ from secrets import token_bytes
|
|
|
14
14
|
from ansible_runner.interface import run
|
|
15
15
|
from subprocess import CalledProcessError
|
|
16
16
|
|
|
17
|
-
from ..misc import can_sudo_without_password, os_platform, rm_at_exit
|
|
17
|
+
from ..misc import can_sudo_without_password, os_platform, rm_at_exit, get_python_constraints
|
|
18
18
|
|
|
19
19
|
log = logging.getLogger("bbot.core.helpers.depsinstaller")
|
|
20
20
|
|
|
@@ -176,10 +176,13 @@ class DepsInstaller:
|
|
|
176
176
|
|
|
177
177
|
command = [sys.executable, "-m", "pip", "install", "--upgrade"] + packages
|
|
178
178
|
|
|
179
|
-
if constraints
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
179
|
+
# if no custom constraints are provided, use the constraints of the currently installed version of bbot
|
|
180
|
+
if constraints is not None:
|
|
181
|
+
constraints = get_python_constraints()
|
|
182
|
+
|
|
183
|
+
constraints_tempfile = self.parent_helper.tempfile(constraints, pipe=False)
|
|
184
|
+
command.append("--constraint")
|
|
185
|
+
command.append(constraints_tempfile)
|
|
183
186
|
|
|
184
187
|
process = None
|
|
185
188
|
try:
|
bbot/core/helpers/misc.py
CHANGED
|
@@ -2807,3 +2807,21 @@ def safe_format(s, **kwargs):
|
|
|
2807
2807
|
Format string while ignoring unused keys (prevents KeyError)
|
|
2808
2808
|
"""
|
|
2809
2809
|
return s.format_map(SafeDict(kwargs))
|
|
2810
|
+
|
|
2811
|
+
|
|
2812
|
+
def get_python_constraints():
|
|
2813
|
+
req_regex = re.compile(r"([^(]+)\s*\((.*)\)", re.IGNORECASE)
|
|
2814
|
+
|
|
2815
|
+
def clean_requirement(req_string):
|
|
2816
|
+
# Extract package name and version constraints from format like "package (>=1.0,<2.0)"
|
|
2817
|
+
match = req_regex.match(req_string)
|
|
2818
|
+
if match:
|
|
2819
|
+
name, constraints = match.groups()
|
|
2820
|
+
return f"{name.strip()}{constraints}"
|
|
2821
|
+
|
|
2822
|
+
return req_string
|
|
2823
|
+
|
|
2824
|
+
from importlib.metadata import distribution
|
|
2825
|
+
|
|
2826
|
+
dist = distribution("bbot")
|
|
2827
|
+
return [clean_requirement(r) for r in dist.requires]
|
bbot/defaults.yml
CHANGED
|
@@ -14,6 +14,9 @@ folder_blobs: false
|
|
|
14
14
|
### SCOPE ###
|
|
15
15
|
|
|
16
16
|
scope:
|
|
17
|
+
# strict scope means only exact DNS names are considered in-scope
|
|
18
|
+
# subdomains are not included unless they are explicitly provided in the target list
|
|
19
|
+
strict: false
|
|
17
20
|
# Filter by scope distance which events are displayed in the output
|
|
18
21
|
# 0 == show only in-scope events (affiliates are always shown)
|
|
19
22
|
# 1 == show all events up to distance-1 (1 hop from target)
|
|
@@ -32,10 +32,11 @@ class speculate(BaseInternalModule):
|
|
|
32
32
|
"author": "@liquidsec",
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
options = {"max_hosts": 65536, "ports": "80,443"}
|
|
35
|
+
options = {"max_hosts": 65536, "ports": "80,443", "essential_only": False}
|
|
36
36
|
options_desc = {
|
|
37
37
|
"max_hosts": "Max number of IP_RANGE hosts to convert into IP_ADDRESS events",
|
|
38
38
|
"ports": "The set of ports to speculate on",
|
|
39
|
+
"essential_only": "Only enable essential speculate features (no extra discovery)",
|
|
39
40
|
}
|
|
40
41
|
scope_distance_modifier = 1
|
|
41
42
|
_priority = 4
|
|
@@ -52,6 +53,7 @@ class speculate(BaseInternalModule):
|
|
|
52
53
|
self.emit_open_ports = self.open_port_consumers and not self.portscanner_enabled
|
|
53
54
|
self.range_to_ip = True
|
|
54
55
|
self.dns_disable = self.scan.config.get("dns", {}).get("disable", False)
|
|
56
|
+
self.essential_only = self.config.get("essential_only", False)
|
|
55
57
|
self.org_stubs_seen = set()
|
|
56
58
|
|
|
57
59
|
port_string = self.config.get("ports", "80,443")
|
|
@@ -75,6 +77,14 @@ class speculate(BaseInternalModule):
|
|
|
75
77
|
return True
|
|
76
78
|
|
|
77
79
|
async def handle_event(self, event):
|
|
80
|
+
### BEGIN ESSENTIAL SPECULATION ###
|
|
81
|
+
# These features are required for smooth operation of bbot
|
|
82
|
+
# I.e. they are not "osinty" or intended to discover anything, they only compliment other modules
|
|
83
|
+
|
|
84
|
+
# we speculate on distance-1 stuff too, because distance-1 open ports are needed by certain modules like sslcert
|
|
85
|
+
event_in_scope_distance = event.scope_distance <= (self.scan.scope_search_distance + 1)
|
|
86
|
+
speculate_open_ports = self.emit_open_ports and event_in_scope_distance
|
|
87
|
+
|
|
78
88
|
# generate individual IP addresses from IP range
|
|
79
89
|
if event.type == "IP_RANGE" and self.range_to_ip:
|
|
80
90
|
net = ipaddress.ip_network(event.data)
|
|
@@ -89,6 +99,28 @@ class speculate(BaseInternalModule):
|
|
|
89
99
|
context=f"speculate converted range into individual IP_ADDRESS: {ip}",
|
|
90
100
|
)
|
|
91
101
|
|
|
102
|
+
# IP_ADDRESS / DNS_NAME --> OPEN_TCP_PORT
|
|
103
|
+
if speculate_open_ports:
|
|
104
|
+
# don't act on unresolved DNS_NAMEs
|
|
105
|
+
usable_dns = False
|
|
106
|
+
if event.type == "DNS_NAME":
|
|
107
|
+
if self.dns_disable or ("a-record" in event.tags or "aaaa-record" in event.tags):
|
|
108
|
+
usable_dns = True
|
|
109
|
+
|
|
110
|
+
if event.type == "IP_ADDRESS" or usable_dns:
|
|
111
|
+
for port in self.ports:
|
|
112
|
+
await self.emit_event(
|
|
113
|
+
self.helpers.make_netloc(event.data, port),
|
|
114
|
+
"OPEN_TCP_PORT",
|
|
115
|
+
parent=event,
|
|
116
|
+
internal=True,
|
|
117
|
+
context="speculated {event.type}: {event.data}",
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
### END ESSENTIAL SPECULATION ###
|
|
121
|
+
if self.essential_only:
|
|
122
|
+
return
|
|
123
|
+
|
|
92
124
|
# parent domains
|
|
93
125
|
if event.type.startswith("DNS_NAME"):
|
|
94
126
|
parent = self.helpers.parent_domain(event.host_original)
|
|
@@ -97,10 +129,6 @@ class speculate(BaseInternalModule):
|
|
|
97
129
|
parent, "DNS_NAME", parent=event, context=f"speculated parent {{event.type}}: {{event.data}}"
|
|
98
130
|
)
|
|
99
131
|
|
|
100
|
-
# we speculate on distance-1 stuff too, because distance-1 open ports are needed by certain modules like sslcert
|
|
101
|
-
event_in_scope_distance = event.scope_distance <= (self.scan.scope_search_distance + 1)
|
|
102
|
-
speculate_open_ports = self.emit_open_ports and event_in_scope_distance
|
|
103
|
-
|
|
104
132
|
# URL --> OPEN_TCP_PORT
|
|
105
133
|
event_is_url = event.type == "URL"
|
|
106
134
|
if event_is_url or (event.type == "URL_UNVERIFIED" and self.open_port_consumers):
|
|
@@ -144,24 +172,6 @@ class speculate(BaseInternalModule):
|
|
|
144
172
|
context="speculated {event.type}: {event.data}",
|
|
145
173
|
)
|
|
146
174
|
|
|
147
|
-
# IP_ADDRESS / DNS_NAME --> OPEN_TCP_PORT
|
|
148
|
-
if speculate_open_ports:
|
|
149
|
-
# don't act on unresolved DNS_NAMEs
|
|
150
|
-
usable_dns = False
|
|
151
|
-
if event.type == "DNS_NAME":
|
|
152
|
-
if self.dns_disable or ("a-record" in event.tags or "aaaa-record" in event.tags):
|
|
153
|
-
usable_dns = True
|
|
154
|
-
|
|
155
|
-
if event.type == "IP_ADDRESS" or usable_dns:
|
|
156
|
-
for port in self.ports:
|
|
157
|
-
await self.emit_event(
|
|
158
|
-
self.helpers.make_netloc(event.data, port),
|
|
159
|
-
"OPEN_TCP_PORT",
|
|
160
|
-
parent=event,
|
|
161
|
-
internal=True,
|
|
162
|
-
context="speculated {event.type}: {event.data}",
|
|
163
|
-
)
|
|
164
|
-
|
|
165
175
|
# ORG_STUB from TLD, SOCIAL, AZURE_TENANT
|
|
166
176
|
org_stubs = set()
|
|
167
177
|
if event.type == "DNS_NAME" and event.scope_distance == 0:
|
bbot/modules/leakix.py
CHANGED
|
@@ -15,20 +15,19 @@ class leakix(subdomain_enum_apikey):
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
base_url = "https://leakix.net"
|
|
18
|
-
ping_url = f"{base_url}/host/1.
|
|
18
|
+
ping_url = f"{base_url}/host/1.1.1.1"
|
|
19
19
|
|
|
20
20
|
async def setup(self):
|
|
21
21
|
ret = await super(subdomain_enum_apikey, self).setup()
|
|
22
|
-
self.headers = {"Accept": "application/json"}
|
|
23
22
|
self.api_key = self.config.get("api_key", "")
|
|
24
23
|
if self.api_key:
|
|
25
|
-
self.headers["api-key"] = self.api_key
|
|
26
24
|
return await self.require_api_key()
|
|
27
25
|
return ret
|
|
28
26
|
|
|
29
27
|
def prepare_api_request(self, url, kwargs):
|
|
30
28
|
if self.api_key:
|
|
31
29
|
kwargs["headers"]["api-key"] = self.api_key
|
|
30
|
+
kwargs["headers"]["Accept"] = "application/json"
|
|
32
31
|
return url, kwargs
|
|
33
32
|
|
|
34
33
|
async def request_url(self, query):
|
bbot/presets/fast.yml
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
description: Scan only the provided targets as fast as possible - no extra discovery
|
|
2
|
+
|
|
3
|
+
exclude_modules:
|
|
4
|
+
- excavate
|
|
5
|
+
|
|
6
|
+
config:
|
|
7
|
+
# only scan the exact targets specified
|
|
8
|
+
scope:
|
|
9
|
+
strict: true
|
|
10
|
+
# speed up dns resolution by doing A/AAAA only - not MX/NS/SRV/etc
|
|
11
|
+
dns:
|
|
12
|
+
minimal: true
|
|
13
|
+
# essential speculation only
|
|
14
|
+
modules:
|
|
15
|
+
speculate:
|
|
16
|
+
essential_only: true
|
bbot/scanner/preset/args.py
CHANGED
|
@@ -91,7 +91,6 @@ class BBOTArgs:
|
|
|
91
91
|
*self.parsed.targets,
|
|
92
92
|
whitelist=self.parsed.whitelist,
|
|
93
93
|
blacklist=self.parsed.blacklist,
|
|
94
|
-
strict_scope=self.parsed.strict_scope,
|
|
95
94
|
name="args_preset",
|
|
96
95
|
)
|
|
97
96
|
|
|
@@ -149,6 +148,9 @@ class BBOTArgs:
|
|
|
149
148
|
if self.parsed.force:
|
|
150
149
|
args_preset.force_start = self.parsed.force
|
|
151
150
|
|
|
151
|
+
if self.parsed.proxy:
|
|
152
|
+
args_preset.core.merge_custom({"web": {"http_proxy": self.parsed.proxy}})
|
|
153
|
+
|
|
152
154
|
if self.parsed.custom_headers:
|
|
153
155
|
args_preset.core.merge_custom({"web": {"http_headers": self.parsed.custom_headers}})
|
|
154
156
|
|
|
@@ -165,6 +167,10 @@ class BBOTArgs:
|
|
|
165
167
|
except Exception as e:
|
|
166
168
|
raise BBOTArgumentError(f'Error parsing command-line config option: "{config_arg}": {e}')
|
|
167
169
|
|
|
170
|
+
# strict scope
|
|
171
|
+
if self.parsed.strict_scope:
|
|
172
|
+
args_preset.core.merge_custom({"scope": {"strict": True}})
|
|
173
|
+
|
|
168
174
|
return args_preset
|
|
169
175
|
|
|
170
176
|
def create_parser(self, *args, **kwargs):
|
|
@@ -265,6 +271,11 @@ class BBOTArgs:
|
|
|
265
271
|
help="Run scan even in the case of condition violations or failed module setups",
|
|
266
272
|
)
|
|
267
273
|
scan.add_argument("-y", "--yes", action="store_true", help="Skip scan confirmation prompt")
|
|
274
|
+
scan.add_argument(
|
|
275
|
+
"--fast-mode",
|
|
276
|
+
action="store_true",
|
|
277
|
+
help="Scan only the provided targets as fast as possible, with no extra discovery",
|
|
278
|
+
)
|
|
268
279
|
scan.add_argument("--dry-run", action="store_true", help=f"Abort before executing scan")
|
|
269
280
|
scan.add_argument(
|
|
270
281
|
"--current-preset",
|
|
@@ -310,6 +321,7 @@ class BBOTArgs:
|
|
|
310
321
|
|
|
311
322
|
misc = p.add_argument_group(title="Misc")
|
|
312
323
|
misc.add_argument("--version", action="store_true", help="show BBOT version and exit")
|
|
324
|
+
misc.add_argument("--proxy", help="Use this proxy for all HTTP requests", metavar="HTTP_PROXY")
|
|
313
325
|
misc.add_argument(
|
|
314
326
|
"-H",
|
|
315
327
|
"--custom-headers",
|
|
@@ -359,6 +371,10 @@ class BBOTArgs:
|
|
|
359
371
|
custom_headers_dict[k] = v
|
|
360
372
|
self.parsed.custom_headers = custom_headers_dict
|
|
361
373
|
|
|
374
|
+
# --fast-mode
|
|
375
|
+
if self.parsed.fast_mode:
|
|
376
|
+
self.parsed.preset += ["fast"]
|
|
377
|
+
|
|
362
378
|
def validate(self):
|
|
363
379
|
# validate config options
|
|
364
380
|
sentinel = object()
|
bbot/scanner/preset/preset.py
CHANGED
|
@@ -47,7 +47,6 @@ class Preset:
|
|
|
47
47
|
target (Target): Target(s) of scan.
|
|
48
48
|
whitelist (Target): Scan whitelist (by default this is the same as `target`).
|
|
49
49
|
blacklist (Target): Scan blacklist (this takes ultimate precedence).
|
|
50
|
-
strict_scope (bool): If True, subdomains of targets are not considered to be in-scope.
|
|
51
50
|
helpers (ConfigAwareHelper): Helper containing various reusable functions, regexes, etc.
|
|
52
51
|
output_dir (pathlib.Path): Output directory for scan.
|
|
53
52
|
scan_name (str): Name of scan. Defaults to random value, e.g. "demonic_jimmy".
|
|
@@ -87,7 +86,6 @@ class Preset:
|
|
|
87
86
|
*targets,
|
|
88
87
|
whitelist=None,
|
|
89
88
|
blacklist=None,
|
|
90
|
-
strict_scope=False,
|
|
91
89
|
modules=None,
|
|
92
90
|
output_modules=None,
|
|
93
91
|
exclude_modules=None,
|
|
@@ -117,7 +115,6 @@ class Preset:
|
|
|
117
115
|
*targets (str): Target(s) to scan. Types supported: hostnames, IPs, CIDRs, emails, open ports.
|
|
118
116
|
whitelist (list, optional): Whitelisted target(s) to scan. Defaults to the same as `targets`.
|
|
119
117
|
blacklist (list, optional): Blacklisted target(s). Takes ultimate precedence. Defaults to empty.
|
|
120
|
-
strict_scope (bool, optional): If True, subdomains of targets are not in-scope.
|
|
121
118
|
modules (list[str], optional): List of scan modules to enable for the scan. Defaults to empty list.
|
|
122
119
|
output_modules (list[str], optional): List of output modules to use. Defaults to csv, human, and json.
|
|
123
120
|
exclude_modules (list[str], optional): List of modules to exclude from the scan.
|
|
@@ -234,7 +231,6 @@ class Preset:
|
|
|
234
231
|
self.module_dirs = module_dirs
|
|
235
232
|
|
|
236
233
|
# target / whitelist / blacklist
|
|
237
|
-
self.strict_scope = strict_scope
|
|
238
234
|
# these are temporary receptacles until they all get .baked() together
|
|
239
235
|
self._seeds = set(targets if targets else [])
|
|
240
236
|
self._whitelist = set(whitelist) if whitelist else whitelist
|
|
@@ -353,7 +349,6 @@ class Preset:
|
|
|
353
349
|
else:
|
|
354
350
|
self._whitelist.update(other._whitelist)
|
|
355
351
|
self._blacklist.update(other._blacklist)
|
|
356
|
-
self.strict_scope = self.strict_scope or other.strict_scope
|
|
357
352
|
|
|
358
353
|
# module dirs
|
|
359
354
|
self.module_dirs = self.module_dirs.union(other.module_dirs)
|
|
@@ -537,6 +532,14 @@ class Preset:
|
|
|
537
532
|
def web_config(self):
|
|
538
533
|
return self.core.config.get("web", {})
|
|
539
534
|
|
|
535
|
+
@property
|
|
536
|
+
def scope_config(self):
|
|
537
|
+
return self.config.get("scope", {})
|
|
538
|
+
|
|
539
|
+
@property
|
|
540
|
+
def strict_scope(self):
|
|
541
|
+
return self.scope_config.get("strict", False)
|
|
542
|
+
|
|
540
543
|
def apply_log_level(self, apply_core=False):
|
|
541
544
|
# silent takes precedence
|
|
542
545
|
if self.silent:
|
|
@@ -635,7 +638,6 @@ class Preset:
|
|
|
635
638
|
debug=preset_dict.get("debug", False),
|
|
636
639
|
silent=preset_dict.get("silent", False),
|
|
637
640
|
config=preset_dict.get("config"),
|
|
638
|
-
strict_scope=preset_dict.get("strict_scope", False),
|
|
639
641
|
module_dirs=preset_dict.get("module_dirs", []),
|
|
640
642
|
include=list(preset_dict.get("include", [])),
|
|
641
643
|
scan_name=preset_dict.get("scan_name"),
|
|
@@ -764,8 +766,6 @@ class Preset:
|
|
|
764
766
|
preset_dict["whitelist"] = whitelist
|
|
765
767
|
if blacklist:
|
|
766
768
|
preset_dict["blacklist"] = blacklist
|
|
767
|
-
if self.strict_scope:
|
|
768
|
-
preset_dict["strict_scope"] = True
|
|
769
769
|
|
|
770
770
|
# flags + modules
|
|
771
771
|
if self.require_flags:
|
bbot/test/bbot_fixtures.py
CHANGED
|
@@ -15,8 +15,8 @@ from werkzeug.wrappers import Request
|
|
|
15
15
|
from bbot.errors import * # noqa: F401
|
|
16
16
|
from bbot.core import CORE
|
|
17
17
|
from bbot.scanner import Preset
|
|
18
|
-
from bbot.core.helpers.misc import mkdir, rand_string
|
|
19
18
|
from bbot.core.helpers.async_helpers import get_event_loop
|
|
19
|
+
from bbot.core.helpers.misc import mkdir, rand_string, get_python_constraints
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
log = logging.getLogger(f"bbot.test.fixtures")
|
|
@@ -229,4 +229,7 @@ def install_all_python_deps():
|
|
|
229
229
|
deps_pip = set()
|
|
230
230
|
for module in DEFAULT_PRESET.module_loader.preloaded().values():
|
|
231
231
|
deps_pip.update(set(module.get("deps", {}).get("pip", [])))
|
|
232
|
-
|
|
232
|
+
|
|
233
|
+
constraint_file = tempwordlist(get_python_constraints())
|
|
234
|
+
|
|
235
|
+
subprocess.run([sys.executable, "-m", "pip", "install", "--constraint", constraint_file] + list(deps_pip))
|
bbot/test/conftest.py
CHANGED
|
@@ -94,9 +94,21 @@ def bbot_httpserver_ssl():
|
|
|
94
94
|
server.clear()
|
|
95
95
|
|
|
96
96
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
97
|
+
def should_mock(request):
|
|
98
|
+
return not request.url.host in ["127.0.0.1", "localhost", "raw.githubusercontent.com"] + interactsh_servers
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def pytest_collection_modifyitems(config, items):
|
|
102
|
+
# make sure all tests have the httpx_mock marker
|
|
103
|
+
for item in items:
|
|
104
|
+
item.add_marker(
|
|
105
|
+
pytest.mark.httpx_mock(
|
|
106
|
+
should_mock=should_mock,
|
|
107
|
+
assert_all_requests_were_expected=False,
|
|
108
|
+
assert_all_responses_were_requested=False,
|
|
109
|
+
can_send_already_matched_responses=True,
|
|
110
|
+
)
|
|
111
|
+
)
|
|
100
112
|
|
|
101
113
|
|
|
102
114
|
@pytest.fixture
|
|
@@ -239,80 +251,80 @@ def pytest_terminal_summary(terminalreporter, exitstatus, config): # pragma: no
|
|
|
239
251
|
|
|
240
252
|
|
|
241
253
|
# BELOW: debugging for frozen/hung tests
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
254
|
+
import psutil
|
|
255
|
+
import traceback
|
|
256
|
+
import inspect
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
def _print_detailed_info(): # pragma: no cover
|
|
260
|
+
"""
|
|
261
|
+
Debugging pytests hanging
|
|
262
|
+
"""
|
|
263
|
+
print("=== Detailed Thread and Process Information ===\n")
|
|
264
|
+
try:
|
|
265
|
+
print("=== Threads ===")
|
|
266
|
+
for thread in threading.enumerate():
|
|
267
|
+
print(f"Thread Name: {thread.name}")
|
|
268
|
+
print(f"Thread ID: {thread.ident}")
|
|
269
|
+
print(f"Is Alive: {thread.is_alive()}")
|
|
270
|
+
print(f"Daemon: {thread.daemon}")
|
|
271
|
+
|
|
272
|
+
if hasattr(thread, "_target"):
|
|
273
|
+
target = thread._target
|
|
274
|
+
if target:
|
|
275
|
+
qualname = (
|
|
276
|
+
f"{target.__module__}.{target.__qualname__}"
|
|
277
|
+
if hasattr(target, "__qualname__")
|
|
278
|
+
else str(target)
|
|
279
|
+
)
|
|
280
|
+
print(f"Target Function: {qualname}")
|
|
281
|
+
|
|
282
|
+
if hasattr(thread, "_args"):
|
|
283
|
+
args = thread._args
|
|
284
|
+
kwargs = thread._kwargs if hasattr(thread, "_kwargs") else {}
|
|
285
|
+
arg_spec = inspect.getfullargspec(target)
|
|
286
|
+
|
|
287
|
+
all_args = list(args) + [f"{k}={v}" for k, v in kwargs.items()]
|
|
288
|
+
|
|
289
|
+
if inspect.ismethod(target) and arg_spec.args[0] == "self":
|
|
290
|
+
arg_spec.args.pop(0)
|
|
291
|
+
|
|
292
|
+
named_args = list(zip(arg_spec.args, all_args))
|
|
293
|
+
if arg_spec.varargs:
|
|
294
|
+
named_args.extend((f"*{arg_spec.varargs}", arg) for arg in all_args[len(arg_spec.args) :])
|
|
295
|
+
|
|
296
|
+
print("Arguments:")
|
|
297
|
+
for name, value in named_args:
|
|
298
|
+
print(f" {name}: {value}")
|
|
299
|
+
else:
|
|
300
|
+
print("Target Function: None")
|
|
301
|
+
else:
|
|
302
|
+
print("Target Function: Unknown")
|
|
303
|
+
|
|
304
|
+
print()
|
|
305
|
+
|
|
306
|
+
print("=== Processes ===")
|
|
307
|
+
current_process = psutil.Process()
|
|
308
|
+
for child in current_process.children(recursive=True):
|
|
309
|
+
print(f"Process ID: {child.pid}")
|
|
310
|
+
print(f"Name: {child.name()}")
|
|
311
|
+
print(f"Status: {child.status()}")
|
|
312
|
+
print(f"CPU Times: {child.cpu_times()}")
|
|
313
|
+
print(f"Memory Info: {child.memory_info()}")
|
|
314
|
+
print()
|
|
315
|
+
|
|
316
|
+
print("=== Current Process ===")
|
|
317
|
+
print(f"Process ID: {current_process.pid}")
|
|
318
|
+
print(f"Name: {current_process.name()}")
|
|
319
|
+
print(f"Status: {current_process.status()}")
|
|
320
|
+
print(f"CPU Times: {current_process.cpu_times()}")
|
|
321
|
+
print(f"Memory Info: {current_process.memory_info()}")
|
|
322
|
+
print()
|
|
323
|
+
|
|
324
|
+
except Exception as e:
|
|
325
|
+
print(f"An error occurred: {str(e)}")
|
|
326
|
+
print("Traceback:")
|
|
327
|
+
traceback.print_exc()
|
|
316
328
|
|
|
317
329
|
|
|
318
330
|
@pytest.hookimpl(tryfirst=True, hookwrapper=True)
|
|
@@ -330,11 +342,11 @@ def pytest_sessionfinish(session, exitstatus):
|
|
|
330
342
|
yield
|
|
331
343
|
|
|
332
344
|
# temporarily suspend stdout capture and print detailed thread info
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
345
|
+
capmanager = session.config.pluginmanager.get_plugin("capturemanager")
|
|
346
|
+
if capmanager:
|
|
347
|
+
capmanager.suspend_global_capture(in_=True)
|
|
336
348
|
|
|
337
|
-
|
|
349
|
+
_print_detailed_info()
|
|
338
350
|
|
|
339
|
-
|
|
340
|
-
|
|
351
|
+
if capmanager:
|
|
352
|
+
capmanager.resume_global_capture()
|
|
@@ -626,6 +626,35 @@ config:
|
|
|
626
626
|
stdout_preset = yaml.safe_load(captured.out)
|
|
627
627
|
assert stdout_preset["config"]["web"]["http_proxy"] == "http://proxy2"
|
|
628
628
|
|
|
629
|
+
# --fast-mode
|
|
630
|
+
monkeypatch.setattr("sys.argv", ["bbot", "--current-preset"])
|
|
631
|
+
cli.main()
|
|
632
|
+
captured = capsys.readouterr()
|
|
633
|
+
stdout_preset = yaml.safe_load(captured.out)
|
|
634
|
+
assert list(stdout_preset) == ["description"]
|
|
635
|
+
|
|
636
|
+
monkeypatch.setattr("sys.argv", ["bbot", "--fast", "--current-preset"])
|
|
637
|
+
cli.main()
|
|
638
|
+
captured = capsys.readouterr()
|
|
639
|
+
stdout_preset = yaml.safe_load(captured.out)
|
|
640
|
+
stdout_preset.pop("description")
|
|
641
|
+
assert stdout_preset == {
|
|
642
|
+
"config": {
|
|
643
|
+
"scope": {"strict": True},
|
|
644
|
+
"dns": {"minimal": True},
|
|
645
|
+
"modules": {"speculate": {"essential_only": True}},
|
|
646
|
+
},
|
|
647
|
+
"exclude_modules": ["excavate"],
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
# --proxy
|
|
651
|
+
monkeypatch.setattr("sys.argv", ["bbot", "--proxy", "http://127.0.0.1:8080", "--current-preset"])
|
|
652
|
+
cli.main()
|
|
653
|
+
captured = capsys.readouterr()
|
|
654
|
+
stdout_preset = yaml.safe_load(captured.out)
|
|
655
|
+
stdout_preset.pop("description")
|
|
656
|
+
assert stdout_preset == {"config": {"web": {"http_proxy": "http://127.0.0.1:8080"}}}
|
|
657
|
+
|
|
629
658
|
# cli config overrides all presets
|
|
630
659
|
monkeypatch.setattr(
|
|
631
660
|
"sys.argv",
|
|
@@ -484,7 +484,6 @@ async def test_events(events, helpers):
|
|
|
484
484
|
json_event = db_event.json()
|
|
485
485
|
assert isinstance(json_event["uuid"], str)
|
|
486
486
|
assert json_event["uuid"] == str(db_event.uuid)
|
|
487
|
-
print(f"{json_event} / {db_event.uuid} / {db_event.parent_uuid} / {scan.root_event.uuid}")
|
|
488
487
|
assert json_event["parent_uuid"] == str(scan.root_event.uuid)
|
|
489
488
|
assert json_event["scope_distance"] == 1
|
|
490
489
|
assert json_event["data"] == "evilcorp.com:80"
|
|
@@ -10,9 +10,6 @@ from bbot.modules.internal.base import BaseInternalModule
|
|
|
10
10
|
|
|
11
11
|
@pytest.mark.asyncio
|
|
12
12
|
async def test_modules_basic_checks(events, httpx_mock):
|
|
13
|
-
for http_method in ("GET", "CONNECT", "HEAD", "POST", "PUT", "TRACE", "DEBUG", "PATCH", "DELETE", "OPTIONS"):
|
|
14
|
-
httpx_mock.add_response(method=http_method, url=re.compile(r".*"), json={"test": "test"})
|
|
15
|
-
|
|
16
13
|
from bbot.scanner import Scanner
|
|
17
14
|
|
|
18
15
|
scan = Scanner(config={"omit_event_types": ["URL_UNVERIFIED"]})
|
|
@@ -86,7 +86,6 @@ def test_preset_yaml(clean_default_config):
|
|
|
86
86
|
debug=False,
|
|
87
87
|
silent=True,
|
|
88
88
|
config={"preset_test_asdf": 1},
|
|
89
|
-
strict_scope=False,
|
|
90
89
|
)
|
|
91
90
|
preset1 = preset1.bake()
|
|
92
91
|
assert "evilcorp.com" in preset1.target
|
|
@@ -210,7 +209,7 @@ def test_preset_scope():
|
|
|
210
209
|
"evilcorp.org",
|
|
211
210
|
whitelist=["evilcorp.de"],
|
|
212
211
|
blacklist=["test.www.evilcorp.de"],
|
|
213
|
-
|
|
212
|
+
config={"scope": {"strict": True}},
|
|
214
213
|
)
|
|
215
214
|
|
|
216
215
|
preset1.merge(preset3)
|
|
@@ -471,6 +471,9 @@ async def test_web_cookies(bbot_scanner, httpx_mock):
|
|
|
471
471
|
# but that they're not sent in the response
|
|
472
472
|
with pytest.raises(httpx.TimeoutException):
|
|
473
473
|
r = await client2.get(url="http://www2.evilcorp.com/cookies/test")
|
|
474
|
+
# make sure cookies are sent
|
|
475
|
+
r = await client2.get(url="http://www2.evilcorp.com/cookies/test", cookies={"wats": "fdsa"})
|
|
476
|
+
assert r.status_code == 200
|
|
474
477
|
# make sure we can manually send cookies
|
|
475
478
|
httpx_mock.add_response(url="http://www2.evilcorp.com/cookies/test2", match_headers={"Cookie": "fdsa=wats"})
|
|
476
479
|
r = await client2.get(url="http://www2.evilcorp.com/cookies/test2", cookies={"fdsa": "wats"})
|
|
@@ -92,9 +92,6 @@ MAPI=1
|
|
|
92
92
|
dnn_installwizard_privesc_detection = False
|
|
93
93
|
|
|
94
94
|
for e in events:
|
|
95
|
-
print(e)
|
|
96
|
-
print(e.type)
|
|
97
|
-
|
|
98
95
|
if e.type == "TECHNOLOGY" and "DotNetNuke" in e.data["technology"]:
|
|
99
96
|
dnn_technology_detection = True
|
|
100
97
|
|
|
@@ -170,9 +167,6 @@ class TestDotnetnuke_blindssrf(ModuleTestBase):
|
|
|
170
167
|
dnn_dnnimagehandler_blindssrf = False
|
|
171
168
|
|
|
172
169
|
for e in events:
|
|
173
|
-
|
|
174
|
-
print(e)
|
|
175
|
-
print(e.type)
|
|
176
170
|
if e.type == "TECHNOLOGY" and "DotNetNuke" in e.data["technology"]:
|
|
177
171
|
dnn_technology_detection = True
|
|
178
172
|
|
|
@@ -6,7 +6,7 @@ class TestLeakIX(ModuleTestBase):
|
|
|
6
6
|
|
|
7
7
|
async def setup_before_prep(self, module_test):
|
|
8
8
|
module_test.httpx_mock.add_response(
|
|
9
|
-
url="https://leakix.net/host/1.
|
|
9
|
+
url="https://leakix.net/host/1.1.1.1",
|
|
10
10
|
match_headers={"api-key": "asdf"},
|
|
11
11
|
json={"title": "Not Found", "description": "Host not found"},
|
|
12
12
|
)
|
|
@@ -30,6 +30,10 @@ class TestLeakIX_NoAPIKey(ModuleTestBase):
|
|
|
30
30
|
modules_overrides = ["leakix"]
|
|
31
31
|
|
|
32
32
|
async def setup_before_prep(self, module_test):
|
|
33
|
+
module_test.httpx_mock.add_response(
|
|
34
|
+
url="https://leakix.net/host/1.1.1.1",
|
|
35
|
+
json={"title": "Not Found", "description": "Host not found"},
|
|
36
|
+
)
|
|
33
37
|
module_test.httpx_mock.add_response(
|
|
34
38
|
url=f"https://leakix.net/api/subdomains/blacklanternsecurity.com",
|
|
35
39
|
json=[
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
bbot/__init__.py,sha256=
|
|
1
|
+
bbot/__init__.py,sha256=G7qyJkDYdbjzsG2LISkABgKOGKTOSAGPXYM0nhFcAxM,130
|
|
2
2
|
bbot/cli.py,sha256=7S3a4eB-Dl8yodc5WC-927Z30CNlLl9EXimGvIVypJo,10434
|
|
3
3
|
bbot/core/__init__.py,sha256=l255GJE_DvUnWvrRb0J5lG-iMztJ8zVvoweDOfegGtI,46
|
|
4
4
|
bbot/core/config/__init__.py,sha256=zYNw2Me6tsEr8hOOkLb4BQ97GB7Kis2k--G81S8vofU,342
|
|
@@ -16,7 +16,7 @@ bbot/core/helpers/bloom.py,sha256=z7gttz-ugvwj7s2L14feJhEx2rzECdqcB255A0hjvNI,25
|
|
|
16
16
|
bbot/core/helpers/cache.py,sha256=1aMr3HVD45cDtHEG5xlznDUCywRgO9oRFidscrs_5sA,1537
|
|
17
17
|
bbot/core/helpers/command.py,sha256=2i0hz-uo6zUV9oGtXf-9erh_g3SazDtYeh6pETlfPPA,12810
|
|
18
18
|
bbot/core/helpers/depsinstaller/__init__.py,sha256=2mx1nYylSyvwl0GCM9YDHqrFEt2_5dSWAjP1RmhmbQg,37
|
|
19
|
-
bbot/core/helpers/depsinstaller/installer.py,sha256=
|
|
19
|
+
bbot/core/helpers/depsinstaller/installer.py,sha256=1YQfPNSYKSgDVUtOCMiTECTqZuA5U1whI2IlSiSVZF8,17125
|
|
20
20
|
bbot/core/helpers/depsinstaller/sudo_askpass.py,sha256=yGa2OQv30RO75QkMuG1iruKqb7amQxRVRRcHmvIeGhk,1276
|
|
21
21
|
bbot/core/helpers/diff.py,sha256=7waBeHFGnAKn-R-sBd-wc3yjwxT_umwy4YxfE7JFd6w,10599
|
|
22
22
|
bbot/core/helpers/dns/__init__.py,sha256=2JK8P0BUfPlh4CTuuOWQCOacwL7NEtGFYPJsxbA0Zwo,27
|
|
@@ -29,7 +29,7 @@ bbot/core/helpers/files.py,sha256=GqrwNGJljUvGSzaOW5-Y357hkt7j88dOYbzQxJGsdTc,57
|
|
|
29
29
|
bbot/core/helpers/helper.py,sha256=3O96peNBvSkaJosft8w9-nKjCscEdykTayGcUlHRqLw,8394
|
|
30
30
|
bbot/core/helpers/interactsh.py,sha256=Q9IHUzH-T7e1s4YTHevHe-VJj1Mokv0EHY16UZJdl8M,12627
|
|
31
31
|
bbot/core/helpers/libmagic.py,sha256=a9tmL558cM5lzN69YahBc7JNHmPnBJgu9Wa8Q5bH1S0,3631
|
|
32
|
-
bbot/core/helpers/misc.py,sha256=
|
|
32
|
+
bbot/core/helpers/misc.py,sha256=dk7O0SDKe6eP_AjKEHXyItKcJXLpQOa2gghWmKMSLnI,87430
|
|
33
33
|
bbot/core/helpers/names_generator.py,sha256=Sj_Q-7KQyElEpalzlUadSwaniESqrIVVEle9ycPIiho,10322
|
|
34
34
|
bbot/core/helpers/ntlm.py,sha256=P2Xj4-GPos2iAzw4dfk0FJp6oGyycGhu2x6sLDVjYjs,2573
|
|
35
35
|
bbot/core/helpers/process.py,sha256=2bbveUuLIrr6wjixZRdFX-gqNE-b7rxVpzBPHYNcmzM,1704
|
|
@@ -48,7 +48,7 @@ bbot/core/modules.py,sha256=OOUSncr-EM6bJBrI3iH5wvfnpTXKQ-A8OL8UMvkL0CU,31432
|
|
|
48
48
|
bbot/core/multiprocess.py,sha256=ocQHanskJ09gHwe7RZmwNdZyCOQyeyUoIHCtLbtvXUk,1771
|
|
49
49
|
bbot/core/shared_deps.py,sha256=A3vrI62uPTTayNIHhWAj6xz43cj--oXWC4prmDlgJnw,6958
|
|
50
50
|
bbot/db/sql/models.py,sha256=AXefz4nEtpV2p19d6rLaEcCQNnqXODpldA-P5uSUntg,4729
|
|
51
|
-
bbot/defaults.yml,sha256=
|
|
51
|
+
bbot/defaults.yml,sha256=v6YZ2g-nnUZQdhD-rhod4LZiYciI-cMDFz4JF7Kh5Lk,6213
|
|
52
52
|
bbot/errors.py,sha256=xwQcD26nU9oc7-o0kv5jmEDTInmi8_W8eKAgQZZxdVM,953
|
|
53
53
|
bbot/logger.py,sha256=rLcLzNDvfR8rFj7_tZ-f5QB3Z8T0RVroact3W0ogjpA,1408
|
|
54
54
|
bbot/modules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -123,13 +123,13 @@ bbot/modules/internal/base.py,sha256=BXO4Hc7XKaAOaLzolF3krJX1KibPxtek2GTQUgnCHk0
|
|
|
123
123
|
bbot/modules/internal/cloudcheck.py,sha256=kkD5DC5Y7EPCiVTdEspZktkflArU3unx--9ciBikxHo,4099
|
|
124
124
|
bbot/modules/internal/dnsresolve.py,sha256=UW88BlpJ7gOjPARrjVgtwpDIDPNQZRpuIRpL2yVP6T4,15251
|
|
125
125
|
bbot/modules/internal/excavate.py,sha256=1kPiaUlpJVT_xgPgmzqhpf04uanIe9ZayQsWANbzhd4,51238
|
|
126
|
-
bbot/modules/internal/speculate.py,sha256=
|
|
126
|
+
bbot/modules/internal/speculate.py,sha256=FvrtxfzBZHL48tPAdQeU_uBpCaDEBCkfk5pU6fdAyac,9264
|
|
127
127
|
bbot/modules/internetdb.py,sha256=Edg0Z84dH8dPTZMd7RlzvYBYNq8JHs_ns_ldnFxwRKo,5415
|
|
128
128
|
bbot/modules/ip2location.py,sha256=yGivX9fzvwvLpnqmYCP2a8SPjTarzrZxfRluog-nkME,2628
|
|
129
129
|
bbot/modules/ipneighbor.py,sha256=Gr-HGtyZRDp_fPjpw-Mq1al7ocFdiZbKsAoAit-EUlA,1591
|
|
130
130
|
bbot/modules/ipstack.py,sha256=j_S8WMNqQuSQgBT7AX4tO70fgbWuRYrpsS3tVsu_hn4,2200
|
|
131
131
|
bbot/modules/jadx.py,sha256=O8134-Rda5PxZyGFBNHCtvXAEUplOqQPlhTrxBGOtCw,3048
|
|
132
|
-
bbot/modules/leakix.py,sha256=
|
|
132
|
+
bbot/modules/leakix.py,sha256=9mJViaIJJ2aDD-dPPdGqW3uTTRqkiDBvp4SHw5SthCc,1501
|
|
133
133
|
bbot/modules/myssl.py,sha256=yypGgAwkPAsoo9_eUFx1TO7qdE4UAUPW24Ca6G0z76M,936
|
|
134
134
|
bbot/modules/newsletters.py,sha256=5PfkzYmnrP2Pbqsch5z575Isck5TG4RJPH8vPr_vM2c,2632
|
|
135
135
|
bbot/modules/ntlm.py,sha256=EGmb4k3YC_ZuHIU3mGUZ4yaMjE35wVQQSv8HwTsQJzY,4391
|
|
@@ -201,6 +201,7 @@ bbot/presets/baddns-thorough.yml,sha256=FXiNnsf3IIms3UJtS2CwLk82Yp0IXm1OvRM61-CH
|
|
|
201
201
|
bbot/presets/cloud-enum.yml,sha256=U1IuN_Vx4zFSvobQenXwSeEqFxRX28beS1Aek3hNUBg,121
|
|
202
202
|
bbot/presets/code-enum.yml,sha256=fRThe5_vY8IqO5nZBC0y3JZwA6ynx81bBcIHBB6o9IU,83
|
|
203
203
|
bbot/presets/email-enum.yml,sha256=SBPDp2s6z0kx-dpjObCjqCV09P7OrhAUob_JJ1XVrT8,120
|
|
204
|
+
bbot/presets/fast.yml,sha256=Sb_yKy0skkGSHsTr-97hwajUFu8IETHdZPu7BfYQqEU,371
|
|
204
205
|
bbot/presets/kitchen-sink.yml,sha256=I0rxhbPJAp8f0TzR2_nkeu_Ycw_HAoipbJhmf7LSNG8,282
|
|
205
206
|
bbot/presets/spider.yml,sha256=G6GZ_Iwfb9buSOs9aH8PltgTjnlm5Zf-4AUP8fA3znY,296
|
|
206
207
|
bbot/presets/subdomain-enum.yml,sha256=tn9h8TlVB_uS3nKZFUP72HzceoRONSef66mGLWzxj9w,414
|
|
@@ -216,18 +217,18 @@ bbot/scanner/__init__.py,sha256=gCyAAbkNm8_KozNpDENCKqO3E3ZCgseplnz40AtiJ1U,56
|
|
|
216
217
|
bbot/scanner/dispatcher.py,sha256=_hsIegfUDrt8CUdXqgRvp1J0UwwzqVSDxjQmiviO41c,793
|
|
217
218
|
bbot/scanner/manager.py,sha256=335d002f_qryO4PK65Q6e4TkWtlTqoDqCvfjojqMgDQ,10500
|
|
218
219
|
bbot/scanner/preset/__init__.py,sha256=Jf2hWsHlTFtWNXL6gXD8_ZbKPFUM564ppdSxHFYnIJU,27
|
|
219
|
-
bbot/scanner/preset/args.py,sha256=
|
|
220
|
+
bbot/scanner/preset/args.py,sha256=tW4DtqH9u6h4TwRipdDCY6943IOs9b3tFoUV2-hKBuw,16000
|
|
220
221
|
bbot/scanner/preset/conditions.py,sha256=hFL9cSIWGEsv2TfM5UGurf0c91cyaM8egb5IngBmIjA,1569
|
|
221
222
|
bbot/scanner/preset/environ.py,sha256=-wbFk1YHpU8IJLKVw23Q3btQTICeX0iulURo7D673L0,4732
|
|
222
223
|
bbot/scanner/preset/path.py,sha256=p9tZC7XcgZv2jXpbEJAg1lU2b4ZLX5COFnCxEUOXz2g,2234
|
|
223
|
-
bbot/scanner/preset/preset.py,sha256
|
|
224
|
+
bbot/scanner/preset/preset.py,sha256=_mqMbLmv0UaVeTKwi3CySh9w5JoSd5TfK3L248-gE18,39898
|
|
224
225
|
bbot/scanner/scanner.py,sha256=pcnJJyDJiHLSuWfeM22_5Zv3S0HhFUq1oEDZDngX704,53835
|
|
225
226
|
bbot/scanner/stats.py,sha256=re93sArKXZSiD0Owgqk2J3Kdvfm3RL4Y9Qy_VOcaVk8,3623
|
|
226
227
|
bbot/scanner/target.py,sha256=X25gpgRv5HmqQjGADiSe6b8744yOkRhAGAvKKYbXnSI,19886
|
|
227
228
|
bbot/scripts/docs.py,sha256=kg2CzovmUVGJx9hBZjAjUdE1hXeIwC7Ry3CyrnE8GL8,10782
|
|
228
229
|
bbot/test/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
229
|
-
bbot/test/bbot_fixtures.py,sha256=
|
|
230
|
-
bbot/test/conftest.py,sha256=
|
|
230
|
+
bbot/test/bbot_fixtures.py,sha256=Mov8IRGyFLkVMNaG8bNvHBjsplSOeD8I0wjJli7H1b8,9982
|
|
231
|
+
bbot/test/conftest.py,sha256=DDz2_R3Ej4XTQsqq7aSZlsia1dBe8axHbiTXkaeyVUc,11486
|
|
231
232
|
bbot/test/coverage.cfg,sha256=ko9RacAYsJxWJCL8aEuNtkAOtP9lexYiDbeFWe8Tp8Y,31
|
|
232
233
|
bbot/test/fastapi_test.py,sha256=9OhOFRyagXTshMsnuzuKIcR4uzS6VW65m7h9KgB4jSA,381
|
|
233
234
|
bbot/test/owasp_mastg.apk,sha256=Hai_V9JmEJ-aB8Ab9xEaGXXOAfGQudkUvNOuPb75byE,66651
|
|
@@ -238,26 +239,26 @@ bbot/test/test_step_1/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3h
|
|
|
238
239
|
bbot/test/test_step_1/test__module__tests.py,sha256=RpD4yuVuQRgbbUkfuasxUlyoVxhTm6TeDyi87y_AaK0,1461
|
|
239
240
|
bbot/test/test_step_1/test_bbot_fastapi.py,sha256=Ph1oTgwOz-oz5H_5Scjv0ItGwenS93lyF4eOkOOlfZ0,2538
|
|
240
241
|
bbot/test/test_step_1/test_bloom_filter.py,sha256=OpiZXsBX-I8QdTK0LqSYkGMDLA6vL_6t0wco9ypxxtQ,2114
|
|
241
|
-
bbot/test/test_step_1/test_cli.py,sha256=
|
|
242
|
+
bbot/test/test_step_1/test_cli.py,sha256=4jt_yUhSPVwaXdyi2QvGf05ImYr3cnC8vL_pDGUs2lo,25726
|
|
242
243
|
bbot/test/test_step_1/test_command.py,sha256=5IeGV6TKB0xtFEsfsU_0mNrOmEdIQiQ3FHkUmsBNoOI,6485
|
|
243
244
|
bbot/test/test_step_1/test_config.py,sha256=Q38hygpke2GDcv8OguVZuiSOnfDJxEMrRy20dN5Qsn0,887
|
|
244
245
|
bbot/test/test_step_1/test_depsinstaller.py,sha256=zr9f-wJDotD1ZvKXGEuDRWzFYMAYBI6209mI_PWPtTQ,703
|
|
245
246
|
bbot/test/test_step_1/test_dns.py,sha256=uFNQCaHLmmVz8KLIHTtZXSLXYLKZkRd7NiIQC5TSGXY,32132
|
|
246
247
|
bbot/test/test_step_1/test_docs.py,sha256=YWVGNRfzcrvDmFekX0Cq9gutQplsqvhKTpZ0XK4tWvo,82
|
|
247
248
|
bbot/test/test_step_1/test_engine.py,sha256=Bfid3-D9ziN93w4vym97tFEn_l2Iof08wjITTv_lAZw,4269
|
|
248
|
-
bbot/test/test_step_1/test_events.py,sha256=
|
|
249
|
+
bbot/test/test_step_1/test_events.py,sha256=kHrVwZtindhYWZy1x43w1cP3PGg8FWTSOSKRLaKAiaM,48078
|
|
249
250
|
bbot/test/test_step_1/test_files.py,sha256=5Q_3jPpMXULxDHsanSDUaj8zF8bXzKdiJZHOmoYpLhQ,699
|
|
250
251
|
bbot/test/test_step_1/test_helpers.py,sha256=oY2hWhgL-TCB67ve1bAyIwZO3wNRWpx4SjCHNUxHep8,38676
|
|
251
252
|
bbot/test/test_step_1/test_manager_deduplication.py,sha256=hZQpDXzg6zvzxFolVOcJuY-ME8NXjZUsqS70BRNXp8A,15594
|
|
252
253
|
bbot/test/test_step_1/test_manager_scope_accuracy.py,sha256=_4O5bW9PA2DIeguvqzb4CMm0i1joqqBBppw7qElL2a0,79767
|
|
253
|
-
bbot/test/test_step_1/test_modules_basic.py,sha256=
|
|
254
|
-
bbot/test/test_step_1/test_presets.py,sha256=
|
|
254
|
+
bbot/test/test_step_1/test_modules_basic.py,sha256=K-RAgEDU8_oHlj2TmgbmP-79_fUmjctIh48lAr-znhI,20082
|
|
255
|
+
bbot/test/test_step_1/test_presets.py,sha256=krABHglyphH-p2tYm87ogSxSfrDv6CtU-bredmVeC98,37288
|
|
255
256
|
bbot/test/test_step_1/test_python_api.py,sha256=BYIVREUy7rd7tKfUsnIX-w_eqQDTEo5UplMZeGMb4bs,5317
|
|
256
257
|
bbot/test/test_step_1/test_regexes.py,sha256=btlDgwM5crSkXFZNydLYn8lCDmyLW_8oX_6Aos5xAHk,14376
|
|
257
258
|
bbot/test/test_step_1/test_scan.py,sha256=yLQAZ5tvIwTULBGgUmXVg8KwMmujal7kB2p-S2_ORzA,5461
|
|
258
259
|
bbot/test/test_step_1/test_scope.py,sha256=S2nssENKJKCvgXUMyU8MFQmXHeUIz0C_sbWGkdYti2A,3063
|
|
259
260
|
bbot/test/test_step_1/test_target.py,sha256=jjG9FUmYIfyqmcmvxzBHRDkP45LIQkbym07uKO8emJg,14185
|
|
260
|
-
bbot/test/test_step_1/test_web.py,sha256=
|
|
261
|
+
bbot/test/test_step_1/test_web.py,sha256=sFkUutelRBXn2L48vZEMzB3LS5nHLQ-vzAH4cbPXo1c,18811
|
|
261
262
|
bbot/test/test_step_2/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
262
263
|
bbot/test/test_step_2/module_tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
263
264
|
bbot/test/test_step_2/module_tests/base.py,sha256=ewnKM4yQr0HfZD51L2iEwtwlR8sCvGz7qA9yqPU5OM4,5821
|
|
@@ -308,7 +309,7 @@ bbot/test/test_step_2/module_tests/test_module_dnsdumpster.py,sha256=pgwOrfq_qNx
|
|
|
308
309
|
bbot/test/test_step_2/module_tests/test_module_dnsresolve.py,sha256=15LEcggP_eVYFQdMO1zHTvoGc6n8IaUjsQDmX0sZS4o,2077
|
|
309
310
|
bbot/test/test_step_2/module_tests/test_module_docker_pull.py,sha256=-JSAo51dS3Ie9RaLBcWK0kfbg8bCPr7mohpFGAwOKPQ,27988
|
|
310
311
|
bbot/test/test_step_2/module_tests/test_module_dockerhub.py,sha256=9T8CFcFP32MOppUmSVNBUSifnk2kMONqzW_7vvvKdpk,3907
|
|
311
|
-
bbot/test/test_step_2/module_tests/test_module_dotnetnuke.py,sha256=
|
|
312
|
+
bbot/test/test_step_2/module_tests/test_module_dotnetnuke.py,sha256=UyVmrw22n7AfBoh_eEjDU_IBqyofXO2lV6GFFudaJTI,8116
|
|
312
313
|
bbot/test/test_step_2/module_tests/test_module_emailformat.py,sha256=cKxBPnEQ4AiRKV_-hSYEE6756ypst3hi6MN0L5RTukY,461
|
|
313
314
|
bbot/test/test_step_2/module_tests/test_module_emails.py,sha256=bZjtO8N3GG2_g6SUEYprAFLcsi7SlwNPJJ0nODfrWYU,944
|
|
314
315
|
bbot/test/test_step_2/module_tests/test_module_excavate.py,sha256=Myq6xkLPueT4m-Rzp8PPC_zF5vzq9JbtV8N46yAhWYE,42179
|
|
@@ -340,7 +341,7 @@ bbot/test/test_step_2/module_tests/test_module_ipneighbor.py,sha256=Bc5xaiIpleC7
|
|
|
340
341
|
bbot/test/test_step_2/module_tests/test_module_ipstack.py,sha256=BgCeE9Bef2RM6akluq0XVzr4G23kpP0Nqfydm_RoTXU,2767
|
|
341
342
|
bbot/test/test_step_2/module_tests/test_module_jadx.py,sha256=qTBfDc_Iv03n8iGdyLm6kBaKeEdSxFYeKj5xL1PmyF0,2391
|
|
342
343
|
bbot/test/test_step_2/module_tests/test_module_json.py,sha256=gmlqge5ZJpjVMGs7OLZBsNlSFTTrKnKjIZMIU23o8VQ,3350
|
|
343
|
-
bbot/test/test_step_2/module_tests/test_module_leakix.py,sha256=
|
|
344
|
+
bbot/test/test_step_2/module_tests/test_module_leakix.py,sha256=Pg1vbmi5z6xIHV1X0z0VCqfpgxksCycrJI5p2ogiIpQ,1819
|
|
344
345
|
bbot/test/test_step_2/module_tests/test_module_myssl.py,sha256=dweSmwUYEcC3DapozRSpHvvvdbw54HVlc_L2pC7ILew,1532
|
|
345
346
|
bbot/test/test_step_2/module_tests/test_module_neo4j.py,sha256=PaKSQWKJKY-5tQhDCGNu_uALlIJwjCVrEtv2grMK9wo,1332
|
|
346
347
|
bbot/test/test_step_2/module_tests/test_module_newsletters.py,sha256=4u2RghHpxlsOy859Fd-4_9EbRL9pupUDubHDJ6ym7YI,2305
|
|
@@ -407,8 +408,8 @@ bbot/wordlists/raft-small-extensions-lowercase_CLEANED.txt,sha256=ruUQwVfia1_m2u
|
|
|
407
408
|
bbot/wordlists/top_open_ports_nmap.txt,sha256=LmdFYkfapSxn1pVuQC2LkOIY2hMLgG-Xts7DVtYzweM,42727
|
|
408
409
|
bbot/wordlists/valid_url_schemes.txt,sha256=VciB-ww0y-O8Ii1wpTR6rJzGDiC2r-dhVsIJApS1ZYU,3309
|
|
409
410
|
bbot/wordlists/wordninja_dns.txt.gz,sha256=DYHvvfW0TvzrVwyprqODAk4tGOxv5ezNmCPSdPuDUnQ,570241
|
|
410
|
-
bbot-2.2.0.
|
|
411
|
-
bbot-2.2.0.
|
|
412
|
-
bbot-2.2.0.
|
|
413
|
-
bbot-2.2.0.
|
|
414
|
-
bbot-2.2.0.
|
|
411
|
+
bbot-2.2.0.5279rc0.dist-info/LICENSE,sha256=GzeCzK17hhQQDNow0_r0L8OfLpeTKQjFQwBQU7ZUymg,32473
|
|
412
|
+
bbot-2.2.0.5279rc0.dist-info/METADATA,sha256=A-RNEyUQ3kqyCUvsELUaodqkTBlPdCI89bBdFur3R68,17109
|
|
413
|
+
bbot-2.2.0.5279rc0.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
|
414
|
+
bbot-2.2.0.5279rc0.dist-info/entry_points.txt,sha256=cWjvcU_lLrzzJgjcjF7yeGuRA_eDS8pQ-kmPUAyOBfo,38
|
|
415
|
+
bbot-2.2.0.5279rc0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|