bbot 2.3.0.5418rc0__py3-none-any.whl → 2.3.0.5438rc0__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/cli.py +12 -2
- bbot/core/helpers/names_generator.py +1 -0
- bbot/modules/base.py +1 -1
- bbot/modules/internal/cloudcheck.py +5 -1
- bbot/modules/internal/dnsresolve.py +9 -2
- bbot/modules/internal/excavate.py +2 -0
- bbot/modules/internal/speculate.py +1 -1
- bbot/modules/output/mysql.py +1 -1
- bbot/modules/output/nmap_xml.py +171 -0
- bbot/modules/output/postgres.py +5 -1
- bbot/modules/output/sqlite.py +5 -1
- bbot/modules/output/stdout.py +1 -1
- bbot/modules/output/txt.py +1 -1
- bbot/scanner/preset/args.py +12 -6
- bbot/scanner/target.py +6 -1
- bbot/test/test_step_1/test_cli.py +14 -2
- bbot/test/test_step_1/test_modules_basic.py +9 -11
- bbot/test/test_step_1/test_target.py +1 -0
- bbot/test/test_step_2/module_tests/test_module_nmap_xml.py +85 -0
- {bbot-2.3.0.5418rc0.dist-info → bbot-2.3.0.5438rc0.dist-info}/METADATA +1 -1
- {bbot-2.3.0.5418rc0.dist-info → bbot-2.3.0.5438rc0.dist-info}/RECORD +25 -23
- {bbot-2.3.0.5418rc0.dist-info → bbot-2.3.0.5438rc0.dist-info}/LICENSE +0 -0
- {bbot-2.3.0.5418rc0.dist-info → bbot-2.3.0.5438rc0.dist-info}/WHEEL +0 -0
- {bbot-2.3.0.5418rc0.dist-info → bbot-2.3.0.5438rc0.dist-info}/entry_points.txt +0 -0
bbot/__init__.py
CHANGED
bbot/cli.py
CHANGED
|
@@ -78,7 +78,7 @@ async def _main():
|
|
|
78
78
|
return
|
|
79
79
|
|
|
80
80
|
# if we're listing modules or their options
|
|
81
|
-
if options.list_modules or options.list_module_options:
|
|
81
|
+
if options.list_modules or options.list_output_modules or options.list_module_options:
|
|
82
82
|
# if no modules or flags are specified, enable everything
|
|
83
83
|
if not (options.modules or options.output_modules or options.flags):
|
|
84
84
|
for module, preloaded in preset.module_loader.preloaded().items():
|
|
@@ -96,7 +96,17 @@ async def _main():
|
|
|
96
96
|
print("")
|
|
97
97
|
print("### MODULES ###")
|
|
98
98
|
print("")
|
|
99
|
-
|
|
99
|
+
modules = sorted(set(preset.scan_modules + preset.internal_modules))
|
|
100
|
+
for row in preset.module_loader.modules_table(modules).splitlines():
|
|
101
|
+
print(row)
|
|
102
|
+
return
|
|
103
|
+
|
|
104
|
+
# --list-output-modules
|
|
105
|
+
if options.list_output_modules:
|
|
106
|
+
print("")
|
|
107
|
+
print("### OUTPUT MODULES ###")
|
|
108
|
+
print("")
|
|
109
|
+
for row in preset.module_loader.modules_table(preset.output_modules).splitlines():
|
|
100
110
|
print(row)
|
|
101
111
|
return
|
|
102
112
|
|
bbot/modules/base.py
CHANGED
|
@@ -51,7 +51,7 @@ class BaseModule:
|
|
|
51
51
|
|
|
52
52
|
target_only (bool): Accept only the initial target event(s). Default is False.
|
|
53
53
|
|
|
54
|
-
in_scope_only (bool): Accept only explicitly in-scope events. Default is False.
|
|
54
|
+
in_scope_only (bool): Accept only explicitly in-scope events, regardless of the scan's search distance. Default is False.
|
|
55
55
|
|
|
56
56
|
options (Dict): Customizable options for the module, e.g., {"api_key": ""}. Empty dict by default.
|
|
57
57
|
|
|
@@ -5,7 +5,11 @@ from bbot.modules.base import BaseInterceptModule
|
|
|
5
5
|
|
|
6
6
|
class CloudCheck(BaseInterceptModule):
|
|
7
7
|
watched_events = ["*"]
|
|
8
|
-
meta = {
|
|
8
|
+
meta = {
|
|
9
|
+
"description": "Tag events by cloud provider, identify cloud resources like storage buckets",
|
|
10
|
+
"created_date": "2024-07-07",
|
|
11
|
+
"author": "@TheTechromancer",
|
|
12
|
+
}
|
|
9
13
|
scope_distance_modifier = 1
|
|
10
14
|
_priority = 3
|
|
11
15
|
|
|
@@ -9,6 +9,8 @@ from bbot.modules.base import BaseInterceptModule, BaseModule
|
|
|
9
9
|
|
|
10
10
|
class DNSResolve(BaseInterceptModule):
|
|
11
11
|
watched_events = ["*"]
|
|
12
|
+
produced_events = ["DNS_NAME", "IP_ADDRESS", "RAW_DNS_RECORD"]
|
|
13
|
+
meta = {"description": "Perform DNS resolution", "created_date": "2022-04-08", "author": "@TheTechromancer"}
|
|
12
14
|
_priority = 1
|
|
13
15
|
scope_distance_modifier = None
|
|
14
16
|
|
|
@@ -83,9 +85,14 @@ class DNSResolve(BaseInterceptModule):
|
|
|
83
85
|
event_data_changed = await self.handle_wildcard_event(main_host_event)
|
|
84
86
|
if event_data_changed:
|
|
85
87
|
# since data has changed, we check again whether it's a duplicate
|
|
86
|
-
if event.type == "DNS_NAME" and self.scan.ingress_module.is_incoming_duplicate(
|
|
88
|
+
if event.type == "DNS_NAME" and self.scan.ingress_module.is_incoming_duplicate(
|
|
89
|
+
event, add=True
|
|
90
|
+
):
|
|
87
91
|
if not event._graph_important:
|
|
88
|
-
return
|
|
92
|
+
return (
|
|
93
|
+
False,
|
|
94
|
+
"it's a DNS wildcard, and its module already emitted a similar wildcard event",
|
|
95
|
+
)
|
|
89
96
|
else:
|
|
90
97
|
self.debug(
|
|
91
98
|
f"Event {event} was already emitted by its module, but it's graph-important so it gets a pass"
|
|
@@ -656,8 +656,10 @@ class excavate(BaseInternalModule, BaseInterceptModule):
|
|
|
656
656
|
continue
|
|
657
657
|
if parsed_url.scheme in ["http", "https"]:
|
|
658
658
|
continue
|
|
659
|
+
|
|
659
660
|
def abort_if(e):
|
|
660
661
|
return e.scope_distance > 0
|
|
662
|
+
|
|
661
663
|
finding_data = {"host": str(host), "description": f"Non-HTTP URI: {parsed_url.geturl()}"}
|
|
662
664
|
await self.report(finding_data, event, yara_rule_settings, discovery_context, abort_if=abort_if)
|
|
663
665
|
protocol_data = {"protocol": parsed_url.scheme, "host": str(host)}
|
|
@@ -104,7 +104,7 @@ class speculate(BaseInternalModule):
|
|
|
104
104
|
# don't act on unresolved DNS_NAMEs
|
|
105
105
|
usable_dns = False
|
|
106
106
|
if event.type == "DNS_NAME":
|
|
107
|
-
if self.dns_disable or
|
|
107
|
+
if self.dns_disable or event.resolved_hosts:
|
|
108
108
|
usable_dns = True
|
|
109
109
|
|
|
110
110
|
if event.type == "IP_ADDRESS" or usable_dns:
|
bbot/modules/output/mysql.py
CHANGED
|
@@ -3,7 +3,7 @@ from bbot.modules.templates.sql import SQLTemplate
|
|
|
3
3
|
|
|
4
4
|
class MySQL(SQLTemplate):
|
|
5
5
|
watched_events = ["*"]
|
|
6
|
-
meta = {"description": "Output scan data to a MySQL database"}
|
|
6
|
+
meta = {"description": "Output scan data to a MySQL database", "created_date": "2024-11-13", "author": "@TheTechromancer"}
|
|
7
7
|
options = {
|
|
8
8
|
"username": "root",
|
|
9
9
|
"password": "bbotislife",
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
from xml.dom import minidom
|
|
3
|
+
from datetime import datetime
|
|
4
|
+
from xml.etree.ElementTree import Element, SubElement, tostring
|
|
5
|
+
|
|
6
|
+
from bbot import __version__
|
|
7
|
+
from bbot.modules.output.base import BaseOutputModule
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class NmapHost:
|
|
11
|
+
__slots__ = ["hostnames", "open_ports"]
|
|
12
|
+
|
|
13
|
+
def __init__(self):
|
|
14
|
+
self.hostnames = set()
|
|
15
|
+
# a dict of {port: {protocol: banner}}
|
|
16
|
+
self.open_ports = dict()
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class Nmap_XML(BaseOutputModule):
|
|
20
|
+
watched_events = ["OPEN_TCP_PORT", "DNS_NAME", "IP_ADDRESS", "PROTOCOL", "HTTP_RESPONSE"]
|
|
21
|
+
meta = {"description": "Output to Nmap XML", "created_date": "2024-11-16", "author": "@TheTechromancer"}
|
|
22
|
+
output_filename = "output.nmap.xml"
|
|
23
|
+
in_scope_only = True
|
|
24
|
+
|
|
25
|
+
async def setup(self):
|
|
26
|
+
self.hosts = {}
|
|
27
|
+
self._prep_output_dir(self.output_filename)
|
|
28
|
+
return True
|
|
29
|
+
|
|
30
|
+
async def handle_event(self, event):
|
|
31
|
+
event_host = event.host
|
|
32
|
+
|
|
33
|
+
# we always record by IP
|
|
34
|
+
ips = []
|
|
35
|
+
for ip in event.resolved_hosts:
|
|
36
|
+
try:
|
|
37
|
+
ips.append(self.helpers.make_ip_type(ip))
|
|
38
|
+
except ValueError:
|
|
39
|
+
continue
|
|
40
|
+
if not ips and self.helpers.is_ip(event_host):
|
|
41
|
+
ips = [event_host]
|
|
42
|
+
|
|
43
|
+
for ip in ips:
|
|
44
|
+
try:
|
|
45
|
+
nmap_host = self.hosts[ip]
|
|
46
|
+
except KeyError:
|
|
47
|
+
nmap_host = NmapHost()
|
|
48
|
+
self.hosts[ip] = nmap_host
|
|
49
|
+
|
|
50
|
+
event_port = getattr(event, "port", None)
|
|
51
|
+
if event.type == "OPEN_TCP_PORT":
|
|
52
|
+
if event_port not in nmap_host.open_ports:
|
|
53
|
+
nmap_host.open_ports[event.port] = {}
|
|
54
|
+
elif event.type in ("PROTOCOL", "HTTP_RESPONSE"):
|
|
55
|
+
if event_port is not None:
|
|
56
|
+
try:
|
|
57
|
+
existing_services = nmap_host.open_ports[event.port]
|
|
58
|
+
except KeyError:
|
|
59
|
+
existing_services = {}
|
|
60
|
+
nmap_host.open_ports[event.port] = existing_services
|
|
61
|
+
if event.type == "PROTOCOL":
|
|
62
|
+
protocol = event.data["protocol"].lower()
|
|
63
|
+
banner = event.data.get("banner", None)
|
|
64
|
+
elif event.type == "HTTP_RESPONSE":
|
|
65
|
+
protocol = event.parsed_url.scheme.lower()
|
|
66
|
+
banner = event.http_title
|
|
67
|
+
if protocol not in existing_services:
|
|
68
|
+
existing_services[protocol] = banner
|
|
69
|
+
|
|
70
|
+
if self.helpers.is_ip(event_host):
|
|
71
|
+
if str(event.module) == "PTR":
|
|
72
|
+
nmap_host.hostnames.add(event.parent.data)
|
|
73
|
+
else:
|
|
74
|
+
nmap_host.hostnames.add(event_host)
|
|
75
|
+
|
|
76
|
+
async def report(self):
|
|
77
|
+
scan_start_time = str(int(self.scan.start_time.timestamp()))
|
|
78
|
+
scan_start_time_str = self.scan.start_time.strftime("%a %b %d %H:%M:%S %Y")
|
|
79
|
+
scan_end_time = datetime.now()
|
|
80
|
+
scan_end_time_str = scan_end_time.strftime("%a %b %d %H:%M:%S %Y")
|
|
81
|
+
scan_end_time_timestamp = str(scan_end_time.timestamp())
|
|
82
|
+
scan_duration = scan_end_time - self.scan.start_time
|
|
83
|
+
num_hosts_up = len(self.hosts)
|
|
84
|
+
|
|
85
|
+
# Create the root element
|
|
86
|
+
nmaprun = Element(
|
|
87
|
+
"nmaprun",
|
|
88
|
+
{
|
|
89
|
+
"scanner": "bbot",
|
|
90
|
+
"args": " ".join(sys.argv),
|
|
91
|
+
"start": scan_start_time,
|
|
92
|
+
"startstr": scan_start_time_str,
|
|
93
|
+
"version": str(__version__),
|
|
94
|
+
"xmloutputversion": "1.05",
|
|
95
|
+
},
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
ports_scanned = []
|
|
99
|
+
speculate_module = self.scan.modules.get("speculate", None)
|
|
100
|
+
if speculate_module is not None:
|
|
101
|
+
ports_scanned = speculate_module.ports
|
|
102
|
+
portscan_module = self.scan.modules.get("portscan", None)
|
|
103
|
+
if portscan_module is not None:
|
|
104
|
+
ports_scanned = self.helpers.parse_port_string(str(portscan_module.ports))
|
|
105
|
+
num_ports_scanned = len(sorted(ports_scanned))
|
|
106
|
+
ports_scanned = ",".join(str(x) for x in sorted(ports_scanned))
|
|
107
|
+
|
|
108
|
+
# Add scaninfo
|
|
109
|
+
SubElement(
|
|
110
|
+
nmaprun,
|
|
111
|
+
"scaninfo",
|
|
112
|
+
{"type": "syn", "protocol": "tcp", "numservices": str(num_ports_scanned), "services": ports_scanned},
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
# Add host information
|
|
116
|
+
for ip, nmap_host in self.hosts.items():
|
|
117
|
+
hostnames = sorted(nmap_host.hostnames)
|
|
118
|
+
ports = sorted(nmap_host.open_ports)
|
|
119
|
+
|
|
120
|
+
host_elem = SubElement(nmaprun, "host")
|
|
121
|
+
SubElement(host_elem, "status", {"state": "up", "reason": "user-set", "reason_ttl": "0"})
|
|
122
|
+
SubElement(host_elem, "address", {"addr": str(ip), "addrtype": f"ipv{ip.version}"})
|
|
123
|
+
|
|
124
|
+
if hostnames:
|
|
125
|
+
hostnames_elem = SubElement(host_elem, "hostnames")
|
|
126
|
+
for hostname in hostnames:
|
|
127
|
+
SubElement(hostnames_elem, "hostname", {"name": hostname, "type": "user"})
|
|
128
|
+
|
|
129
|
+
ports = SubElement(host_elem, "ports")
|
|
130
|
+
for port, protocols in nmap_host.open_ports.items():
|
|
131
|
+
port_elem = SubElement(ports, "port", {"protocol": "tcp", "portid": str(port)})
|
|
132
|
+
SubElement(port_elem, "state", {"state": "open", "reason": "syn-ack", "reason_ttl": "0"})
|
|
133
|
+
# <port protocol="tcp" portid="443"><state state="open" reason="syn-ack" reason_ttl="53"/><service name="http" product="AkamaiGHost" extrainfo="Akamai's HTTP Acceleration/Mirror service" tunnel="ssl" method="probed" conf="10"/></port>
|
|
134
|
+
for protocol, banner in protocols.items():
|
|
135
|
+
attrs = {"name": protocol, "method": "probed", "conf": "10"}
|
|
136
|
+
if banner is not None:
|
|
137
|
+
attrs["product"] = banner
|
|
138
|
+
attrs["extrainfo"] = banner
|
|
139
|
+
SubElement(port_elem, "service", attrs)
|
|
140
|
+
|
|
141
|
+
# Add runstats
|
|
142
|
+
runstats = SubElement(nmaprun, "runstats")
|
|
143
|
+
SubElement(
|
|
144
|
+
runstats,
|
|
145
|
+
"finished",
|
|
146
|
+
{
|
|
147
|
+
"time": scan_end_time_timestamp,
|
|
148
|
+
"timestr": scan_end_time_str,
|
|
149
|
+
"summary": f"BBOT done at {scan_end_time_str}; {num_hosts_up} scanned in {scan_duration} seconds",
|
|
150
|
+
"elapsed": str(scan_duration.total_seconds()),
|
|
151
|
+
"exit": "success",
|
|
152
|
+
},
|
|
153
|
+
)
|
|
154
|
+
SubElement(runstats, "hosts", {"up": str(num_hosts_up), "down": "0", "total": str(num_hosts_up)})
|
|
155
|
+
|
|
156
|
+
# make backup of the file
|
|
157
|
+
self.helpers.backup_file(self.output_file)
|
|
158
|
+
|
|
159
|
+
# Pretty-format the XML
|
|
160
|
+
rough_string = tostring(nmaprun, encoding="utf-8")
|
|
161
|
+
reparsed = minidom.parseString(rough_string)
|
|
162
|
+
|
|
163
|
+
# Create a new document with the doctype
|
|
164
|
+
doctype = minidom.DocumentType("nmaprun")
|
|
165
|
+
reparsed.insertBefore(doctype, reparsed.documentElement)
|
|
166
|
+
|
|
167
|
+
pretty_xml = reparsed.toprettyxml(indent=" ")
|
|
168
|
+
|
|
169
|
+
with open(self.output_file, "w") as f:
|
|
170
|
+
f.write(pretty_xml)
|
|
171
|
+
self.info(f"Saved Nmap XML output to {self.output_file}")
|
bbot/modules/output/postgres.py
CHANGED
|
@@ -3,7 +3,11 @@ from bbot.modules.templates.sql import SQLTemplate
|
|
|
3
3
|
|
|
4
4
|
class Postgres(SQLTemplate):
|
|
5
5
|
watched_events = ["*"]
|
|
6
|
-
meta = {
|
|
6
|
+
meta = {
|
|
7
|
+
"description": "Output scan data to a SQLite database",
|
|
8
|
+
"created_date": "2024-11-08",
|
|
9
|
+
"author": "@TheTechromancer",
|
|
10
|
+
}
|
|
7
11
|
options = {
|
|
8
12
|
"username": "postgres",
|
|
9
13
|
"password": "bbotislife",
|
bbot/modules/output/sqlite.py
CHANGED
|
@@ -5,7 +5,11 @@ from bbot.modules.templates.sql import SQLTemplate
|
|
|
5
5
|
|
|
6
6
|
class SQLite(SQLTemplate):
|
|
7
7
|
watched_events = ["*"]
|
|
8
|
-
meta = {
|
|
8
|
+
meta = {
|
|
9
|
+
"description": "Output scan data to a SQLite database",
|
|
10
|
+
"created_date": "2024-11-07",
|
|
11
|
+
"author": "@TheTechromancer",
|
|
12
|
+
}
|
|
9
13
|
options = {
|
|
10
14
|
"database": "",
|
|
11
15
|
}
|
bbot/modules/output/stdout.py
CHANGED
|
@@ -6,7 +6,7 @@ from bbot.modules.output.base import BaseOutputModule
|
|
|
6
6
|
|
|
7
7
|
class Stdout(BaseOutputModule):
|
|
8
8
|
watched_events = ["*"]
|
|
9
|
-
meta = {"description": "Output to text"}
|
|
9
|
+
meta = {"description": "Output to text", "created_date": "2024-04-03", "author": "@TheTechromancer"}
|
|
10
10
|
options = {"format": "text", "event_types": [], "event_fields": [], "in_scope_only": False, "accept_dupes": True}
|
|
11
11
|
options_desc = {
|
|
12
12
|
"format": "Which text format to display, choices: text,json",
|
bbot/modules/output/txt.py
CHANGED
|
@@ -5,7 +5,7 @@ from bbot.modules.output.base import BaseOutputModule
|
|
|
5
5
|
|
|
6
6
|
class TXT(BaseOutputModule):
|
|
7
7
|
watched_events = ["*"]
|
|
8
|
-
meta = {"description": "Output to text"}
|
|
8
|
+
meta = {"description": "Output to text", "created_date": "2024-04-03", "author": "@TheTechromancer"}
|
|
9
9
|
options = {"output_file": ""}
|
|
10
10
|
options_desc = {"output_file": "Output to file"}
|
|
11
11
|
|
bbot/scanner/preset/args.py
CHANGED
|
@@ -52,6 +52,11 @@ class BBOTArgs:
|
|
|
52
52
|
"",
|
|
53
53
|
"bbot -l",
|
|
54
54
|
),
|
|
55
|
+
(
|
|
56
|
+
"List output modules",
|
|
57
|
+
"",
|
|
58
|
+
"bbot -lo",
|
|
59
|
+
),
|
|
55
60
|
(
|
|
56
61
|
"List presets",
|
|
57
62
|
"",
|
|
@@ -290,12 +295,6 @@ class BBOTArgs:
|
|
|
290
295
|
)
|
|
291
296
|
|
|
292
297
|
output = p.add_argument_group(title="Output")
|
|
293
|
-
output.add_argument(
|
|
294
|
-
"-o",
|
|
295
|
-
"--output-dir",
|
|
296
|
-
help="Directory to output scan results",
|
|
297
|
-
metavar="DIR",
|
|
298
|
-
)
|
|
299
298
|
output.add_argument(
|
|
300
299
|
"-om",
|
|
301
300
|
"--output-modules",
|
|
@@ -304,6 +303,13 @@ class BBOTArgs:
|
|
|
304
303
|
help=f'Output module(s). Choices: {",".join(sorted(self.preset.module_loader.output_module_choices))}',
|
|
305
304
|
metavar="MODULE",
|
|
306
305
|
)
|
|
306
|
+
output.add_argument("-lo", "--list-output-modules", action="store_true", help="List available output modules")
|
|
307
|
+
output.add_argument(
|
|
308
|
+
"-o",
|
|
309
|
+
"--output-dir",
|
|
310
|
+
help="Directory to output scan results",
|
|
311
|
+
metavar="DIR",
|
|
312
|
+
)
|
|
307
313
|
output.add_argument("--json", "-j", action="store_true", help="Output scan data in JSON format")
|
|
308
314
|
output.add_argument("--brief", "-br", action="store_true", help="Output only the data itself")
|
|
309
315
|
output.add_argument("--event-types", nargs="+", default=[], help="Choose which event types to display")
|
bbot/scanner/target.py
CHANGED
|
@@ -192,7 +192,6 @@ class ScanBlacklist(ACLTarget):
|
|
|
192
192
|
@special_target_type(r"^(?:RE|REGEX):(.*)")
|
|
193
193
|
def handle_regex(self, match):
|
|
194
194
|
pattern = match.group(1)
|
|
195
|
-
log.info(f"Blacklisting by custom regex: {pattern}")
|
|
196
195
|
blacklist_regex = re.compile(pattern, re.IGNORECASE)
|
|
197
196
|
self.blacklist_regexes.add(blacklist_regex)
|
|
198
197
|
return []
|
|
@@ -225,6 +224,12 @@ class ScanBlacklist(ACLTarget):
|
|
|
225
224
|
hosts = [str(h).encode() for h in self.sorted_hosts]
|
|
226
225
|
return hosts + regex_patterns
|
|
227
226
|
|
|
227
|
+
def __len__(self):
|
|
228
|
+
return super().__len__() + len(self.blacklist_regexes)
|
|
229
|
+
|
|
230
|
+
def __bool__(self):
|
|
231
|
+
return bool(len(self))
|
|
232
|
+
|
|
228
233
|
|
|
229
234
|
class BBOTTarget:
|
|
230
235
|
"""
|
|
@@ -150,11 +150,23 @@ async def test_cli_args(monkeypatch, caplog, capsys, clean_default_config):
|
|
|
150
150
|
out, err = capsys.readouterr()
|
|
151
151
|
# internal modules
|
|
152
152
|
assert "| excavate " in out
|
|
153
|
-
# output modules
|
|
154
|
-
assert "| csv " in out
|
|
153
|
+
# no output modules
|
|
154
|
+
assert not "| csv " in out
|
|
155
155
|
# scan modules
|
|
156
156
|
assert "| wayback " in out
|
|
157
157
|
|
|
158
|
+
# list output modules
|
|
159
|
+
monkeypatch.setattr("sys.argv", ["bbot", "--list-output-modules"])
|
|
160
|
+
result = await cli._main()
|
|
161
|
+
assert result == None
|
|
162
|
+
out, err = capsys.readouterr()
|
|
163
|
+
# no internal modules
|
|
164
|
+
assert not "| excavate " in out
|
|
165
|
+
# output modules
|
|
166
|
+
assert "| csv " in out
|
|
167
|
+
# no scan modules
|
|
168
|
+
assert not "| wayback " in out
|
|
169
|
+
|
|
158
170
|
# output dir and scan name
|
|
159
171
|
output_dir = bbot_test_dir / "bbot_cli_args_output"
|
|
160
172
|
scan_name = "bbot_cli_args_scan_name"
|
|
@@ -156,17 +156,15 @@ async def test_modules_basic_checks(events, httpx_mock):
|
|
|
156
156
|
assert not (
|
|
157
157
|
"web-basic" in flags and "web-thorough" in flags
|
|
158
158
|
), f'module "{module_name}" should have either "web-basic" or "web-thorough" flags, not both'
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
created_date
|
|
169
|
-
), f"{module_name}'s created_date must match the format YYYY-MM-DD"
|
|
159
|
+
meta = preloaded.get("meta", {})
|
|
160
|
+
# make sure every module has a description
|
|
161
|
+
assert meta.get("description", ""), f"{module_name} must have a description"
|
|
162
|
+
# make sure every module has an author
|
|
163
|
+
assert meta.get("author", ""), f"{module_name} must have an author"
|
|
164
|
+
# make sure every module has a created date
|
|
165
|
+
created_date = meta.get("created_date", "")
|
|
166
|
+
assert created_date, f"{module_name} must have a created date"
|
|
167
|
+
assert created_date_regex.match(created_date), f"{module_name}'s created_date must match the format YYYY-MM-DD"
|
|
170
168
|
|
|
171
169
|
# attribute checks
|
|
172
170
|
watched_events = preloaded.get("watched_events")
|
|
@@ -395,6 +395,7 @@ async def test_blacklist_regex(bbot_scanner, bbot_httpserver):
|
|
|
395
395
|
config={"excavate": True},
|
|
396
396
|
debug=True,
|
|
397
397
|
)
|
|
398
|
+
assert len(scan.target.blacklist) == 2
|
|
398
399
|
assert scan.target.blacklist.blacklist_regexes
|
|
399
400
|
assert {r.pattern for r in scan.target.blacklist.blacklist_regexes} == {
|
|
400
401
|
r"evil[0-9]{3}",
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import xml.etree.ElementTree as ET
|
|
2
|
+
|
|
3
|
+
from bbot.modules.base import BaseModule
|
|
4
|
+
from .base import ModuleTestBase
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class TestNmap_XML(ModuleTestBase):
|
|
8
|
+
modules_overrides = ["nmap_xml", "speculate"]
|
|
9
|
+
targets = ["blacklanternsecurity.com", "127.0.0.3"]
|
|
10
|
+
config_overrides = {"dns": {"minimal": False}}
|
|
11
|
+
|
|
12
|
+
class DummyModule(BaseModule):
|
|
13
|
+
watched_events = ["OPEN_TCP_PORT"]
|
|
14
|
+
_name = "dummy_module"
|
|
15
|
+
|
|
16
|
+
async def handle_event(self, event):
|
|
17
|
+
if event.port == 80:
|
|
18
|
+
await self.emit_event(
|
|
19
|
+
{"host": str(event.host), "port": event.port, "protocol": "http", "banner": "Apache"},
|
|
20
|
+
"PROTOCOL",
|
|
21
|
+
parent=event,
|
|
22
|
+
)
|
|
23
|
+
elif event.port == 443:
|
|
24
|
+
await self.emit_event(
|
|
25
|
+
{"host": str(event.host), "port": event.port, "protocol": "https"}, "PROTOCOL", parent=event
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
async def setup_before_prep(self, module_test):
|
|
29
|
+
self.dummy_module = self.DummyModule(module_test.scan)
|
|
30
|
+
module_test.scan.modules["dummy_module"] = self.dummy_module
|
|
31
|
+
await module_test.mock_dns(
|
|
32
|
+
{
|
|
33
|
+
"blacklanternsecurity.com": {"A": ["127.0.0.1", "127.0.0.2"]},
|
|
34
|
+
"3.0.0.127.in-addr.arpa": {"PTR": ["www.blacklanternsecurity.com"]},
|
|
35
|
+
"www.blacklanternsecurity.com": {"A": ["127.0.0.1"]},
|
|
36
|
+
}
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
def check(self, module_test, events):
|
|
40
|
+
nmap_xml_file = module_test.scan.modules["nmap_xml"].output_file
|
|
41
|
+
nmap_xml = open(nmap_xml_file).read()
|
|
42
|
+
|
|
43
|
+
# Parse the XML
|
|
44
|
+
root = ET.fromstring(nmap_xml)
|
|
45
|
+
|
|
46
|
+
# Expected IP addresses
|
|
47
|
+
expected_ips = {"127.0.0.1", "127.0.0.2", "127.0.0.3"}
|
|
48
|
+
found_ips = set()
|
|
49
|
+
|
|
50
|
+
# Iterate over each host in the XML
|
|
51
|
+
for host in root.findall("host"):
|
|
52
|
+
# Get the IP address
|
|
53
|
+
address = host.find("address").get("addr")
|
|
54
|
+
found_ips.add(address)
|
|
55
|
+
|
|
56
|
+
# Get hostnames if available
|
|
57
|
+
hostnames = sorted([hostname.get("name") for hostname in host.findall(".//hostname")])
|
|
58
|
+
|
|
59
|
+
# Get open ports and services
|
|
60
|
+
ports = []
|
|
61
|
+
for port in host.findall(".//port"):
|
|
62
|
+
port_id = port.get("portid")
|
|
63
|
+
state = port.find("state").get("state")
|
|
64
|
+
if state == "open":
|
|
65
|
+
service_name = port.find("service").get("name")
|
|
66
|
+
service_product = port.find("service").get("product", "")
|
|
67
|
+
service_extrainfo = port.find("service").get("extrainfo", "")
|
|
68
|
+
ports.append((port_id, service_name, service_product, service_extrainfo))
|
|
69
|
+
|
|
70
|
+
# Sort ports for consistency
|
|
71
|
+
ports.sort()
|
|
72
|
+
|
|
73
|
+
# Assertions
|
|
74
|
+
if address == "127.0.0.1":
|
|
75
|
+
assert hostnames == ["blacklanternsecurity.com", "www.blacklanternsecurity.com"]
|
|
76
|
+
assert ports == sorted([("80", "http", "Apache", "Apache"), ("443", "https", "", "")])
|
|
77
|
+
elif address == "127.0.0.2":
|
|
78
|
+
assert hostnames == sorted(["blacklanternsecurity.com"])
|
|
79
|
+
assert ports == sorted([("80", "http", "Apache", "Apache"), ("443", "https", "", "")])
|
|
80
|
+
elif address == "127.0.0.3":
|
|
81
|
+
assert hostnames == [] # No hostnames for this IP
|
|
82
|
+
assert ports == sorted([("80", "http", "Apache", "Apache"), ("443", "https", "", "")])
|
|
83
|
+
|
|
84
|
+
# Assert that all expected IPs were found
|
|
85
|
+
assert found_ips == expected_ips
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
bbot/__init__.py,sha256=
|
|
2
|
-
bbot/cli.py,sha256=
|
|
1
|
+
bbot/__init__.py,sha256=PSBAzvTIlXQ6VGkKm7voHEz1M3On9Kmudq3sMhhIMQM,130
|
|
2
|
+
bbot/cli.py,sha256=Qlgqabm8N6r6uO1RuwGaM7-VXDSP_NH-YUnDUTsDYPM,10877
|
|
3
3
|
bbot/core/__init__.py,sha256=l255GJE_DvUnWvrRb0J5lG-iMztJ8zVvoweDOfegGtI,46
|
|
4
4
|
bbot/core/config/__init__.py,sha256=zYNw2Me6tsEr8hOOkLb4BQ97GB7Kis2k--G81S8vofU,342
|
|
5
5
|
bbot/core/config/files.py,sha256=zANvrTRLJQIOWSNkxd9MpWmf9cQFr0gRZLUxeIbTwQc,1412
|
|
@@ -30,7 +30,7 @@ bbot/core/helpers/helper.py,sha256=eD9yJUhrFUmmoXm4pyi31dulJ5W2eyS-YLGXmx7AyDQ,8
|
|
|
30
30
|
bbot/core/helpers/interactsh.py,sha256=VBYYH6-rWBofRsgemndK6iZNmyifOps8vgQOw2mac4k,12624
|
|
31
31
|
bbot/core/helpers/libmagic.py,sha256=QMHyxjgDLb2jyjBvK1MQ-xt6WkGXhKcHu9ZP1li-sik,3460
|
|
32
32
|
bbot/core/helpers/misc.py,sha256=156tWmNGZ0I1X537hQ8cAlShVq8D2dQVGz3DxaLh5d0,87734
|
|
33
|
-
bbot/core/helpers/names_generator.py,sha256=
|
|
33
|
+
bbot/core/helpers/names_generator.py,sha256=x6nZfEPKMwv3qR_RI4U6TBNbo6PgCF4fqbldtwilvpw,10334
|
|
34
34
|
bbot/core/helpers/ntlm.py,sha256=P2Xj4-GPos2iAzw4dfk0FJp6oGyycGhu2x6sLDVjYjs,2573
|
|
35
35
|
bbot/core/helpers/process.py,sha256=00uRpLMFi3Pt3uT8qXwAIhsXdoa7h-ifoXh0sGYgwqs,1702
|
|
36
36
|
bbot/core/helpers/ratelimiter.py,sha256=K8qFIyJPJtfdb9kSW6_lL6ahWqxR2uWyCBkDlg6uJgo,1990
|
|
@@ -61,7 +61,7 @@ bbot/modules/baddns.py,sha256=SP-o0M2dq5QIkaQZUKl9YZiOXdZasty-fHPxTJJAeR0,6378
|
|
|
61
61
|
bbot/modules/baddns_direct.py,sha256=pe_seO74XI4b6w4Q_IBDNvtBjmD-7it5ts0Z-FB0L6k,3818
|
|
62
62
|
bbot/modules/baddns_zone.py,sha256=IcewDBtA_-64NCNFojEFd9jt2YBek6ltB2mmqdDH6LE,1034
|
|
63
63
|
bbot/modules/badsecrets.py,sha256=JSukBYdD3yuvVy84DkyX48428R_LgQ7P39tjTRAD_Mo,5107
|
|
64
|
-
bbot/modules/base.py,sha256=
|
|
64
|
+
bbot/modules/base.py,sha256=Ala_jLu3I2iEadn_NNiOb4RnFdJPwlrtywASDvd-P6c,71143
|
|
65
65
|
bbot/modules/bevigil.py,sha256=0VLIxmeXRUI2-EoR6IzuHJMcX8KCHNNta-WYa3gVlDg,2862
|
|
66
66
|
bbot/modules/binaryedge.py,sha256=5F9LnZwRM_rZnzTv29hLJLI2GEQdzOwSpahPFC1kJC0,1397
|
|
67
67
|
bbot/modules/bucket_amazon.py,sha256=mwjYeEAcdfOpjbOa1sD8U9KBMMVY_c8FoHjSGR9GQbg,730
|
|
@@ -121,10 +121,10 @@ bbot/modules/iis_shortnames.py,sha256=bIlmC21a0eK_cjMu1UQkDl9EfpfCN1SAggDqJL8LJf
|
|
|
121
121
|
bbot/modules/internal/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
122
122
|
bbot/modules/internal/aggregate.py,sha256=csWYIt2fUp9K_CRxP3bndUMIjpNIh8rmBubp5Fr1-nc,395
|
|
123
123
|
bbot/modules/internal/base.py,sha256=BXO4Hc7XKaAOaLzolF3krJX1KibPxtek2GTQUgnCHk0,387
|
|
124
|
-
bbot/modules/internal/cloudcheck.py,sha256=
|
|
125
|
-
bbot/modules/internal/dnsresolve.py,sha256=
|
|
126
|
-
bbot/modules/internal/excavate.py,sha256=
|
|
127
|
-
bbot/modules/internal/speculate.py,sha256=
|
|
124
|
+
bbot/modules/internal/cloudcheck.py,sha256=k9Sg7R06wV0hx0HJI86oWZ2ozeKa1S2VLpVPlx7XPe8,4845
|
|
125
|
+
bbot/modules/internal/dnsresolve.py,sha256=1fwWChIGpSEIIkswueiIhEwIahQ7YngZ-njFK-RIsfU,15679
|
|
126
|
+
bbot/modules/internal/excavate.py,sha256=IazekmFOnjrqghTf9YhBbMM4dohv27vIEvfNZXJSZvg,51529
|
|
127
|
+
bbot/modules/internal/speculate.py,sha256=NolqW2s8tokibc6gVM960KlrABkjhLB-7YlCdVx4O9s,9223
|
|
128
128
|
bbot/modules/internetdb.py,sha256=Edg0Z84dH8dPTZMd7RlzvYBYNq8JHs_ns_ldnFxwRKo,5415
|
|
129
129
|
bbot/modules/ip2location.py,sha256=yGivX9fzvwvLpnqmYCP2a8SPjTarzrZxfRluog-nkME,2628
|
|
130
130
|
bbot/modules/ipneighbor.py,sha256=b_0IhorihFLtXJZEz57EGXjXW30gIOEzzVgz2GFvM3A,1591
|
|
@@ -144,17 +144,18 @@ bbot/modules/output/discord.py,sha256=BzZW0T-DgZHo3xwaQbZ6DAA59wKIvCDV1LK82ev7A2
|
|
|
144
144
|
bbot/modules/output/emails.py,sha256=mzZideMCNfB8-naQANO5g8Y9HdgviAihRsdY_xPQjbQ,1095
|
|
145
145
|
bbot/modules/output/http.py,sha256=4UWKpbQx3EHpi24VIem6oSvXr0W0NZ3lDpJOmQ3Mwik,2582
|
|
146
146
|
bbot/modules/output/json.py,sha256=zvM2NwWScGk3pN4wF0mm-OqVW_0ADYy95Am4T02VVD4,1289
|
|
147
|
-
bbot/modules/output/mysql.py,sha256=
|
|
147
|
+
bbot/modules/output/mysql.py,sha256=mdIdu17otSuElA-_1OwnB3DV31lL0WcMrti38vqGsrY,1944
|
|
148
148
|
bbot/modules/output/neo4j.py,sha256=u950eUwu8YMql_WaBA38TN2bUhx7xnZdIIvYfR3xVcY,6114
|
|
149
|
-
bbot/modules/output/
|
|
149
|
+
bbot/modules/output/nmap_xml.py,sha256=RZx3LFNi_OWxd0lJXY6Nk-_sSQBRidRnoWKyZEaUXrQ,7048
|
|
150
|
+
bbot/modules/output/postgres.py,sha256=vsz3Gl9SKoWKhDidMFczksJzTeM0TZ7G9qY2rIYETF0,1938
|
|
150
151
|
bbot/modules/output/python.py,sha256=RvK2KN-Zp0Vy_1zGSNioE5eeL5hIh6Z_riFtaTymyIM,270
|
|
151
152
|
bbot/modules/output/slack.py,sha256=Ir_z11VYBdXDx8DwntWCv33Ic43vO1UIbxcp9gj0vvk,1181
|
|
152
153
|
bbot/modules/output/splunk.py,sha256=TjTCUmDwRwKOFKBJw-Xbjku64U77OauHjtR56gyaAPs,1952
|
|
153
|
-
bbot/modules/output/sqlite.py,sha256=
|
|
154
|
-
bbot/modules/output/stdout.py,sha256=
|
|
154
|
+
bbot/modules/output/sqlite.py,sha256=N0p6RRUcuCqGd4HIP0nG6JOPMs88LDQx4ImkdZVBM5E,979
|
|
155
|
+
bbot/modules/output/stdout.py,sha256=aLUtODqStdxmhh4lg7PRUsPEwTPLzdp3Hx7ZwbUvP_c,3084
|
|
155
156
|
bbot/modules/output/subdomains.py,sha256=3KZz4vD0itmqpo56uCyk43Z_zN1Q0Q_nyXjdnEublPA,1515
|
|
156
157
|
bbot/modules/output/teams.py,sha256=I2d52LqDC7e_oboLHoYBaRK6UpN0nkJ0uRnBXrhZf9E,4628
|
|
157
|
-
bbot/modules/output/txt.py,sha256=
|
|
158
|
+
bbot/modules/output/txt.py,sha256=I4zGvsFvqYZtruiCLg5spAYwR-wqjxCU0FRkPhqBUJo,976
|
|
158
159
|
bbot/modules/output/web_report.py,sha256=lZ0FqRZ7Jz1lljI9JMhH9gjtWLaTCSpSnAKQGAcPx-Q,3720
|
|
159
160
|
bbot/modules/output/websocket.py,sha256=sDTtHU-Ey_tvS0gMi6PVPV9L4qAmGyWeccxAKfEWCac,2278
|
|
160
161
|
bbot/modules/paramminer_cookies.py,sha256=q1PzftHQpCHLz81_VgLZsO6moia7ZtnU32igfcySi2w,1816
|
|
@@ -220,14 +221,14 @@ bbot/scanner/__init__.py,sha256=gCyAAbkNm8_KozNpDENCKqO3E3ZCgseplnz40AtiJ1U,56
|
|
|
220
221
|
bbot/scanner/dispatcher.py,sha256=_hsIegfUDrt8CUdXqgRvp1J0UwwzqVSDxjQmiviO41c,793
|
|
221
222
|
bbot/scanner/manager.py,sha256=_5FBfxOmSMUeGp_-ryyGGl0pxb_eu-NSWft-lH1Pyog,10466
|
|
222
223
|
bbot/scanner/preset/__init__.py,sha256=Jf2hWsHlTFtWNXL6gXD8_ZbKPFUM564ppdSxHFYnIJU,27
|
|
223
|
-
bbot/scanner/preset/args.py,sha256=
|
|
224
|
+
bbot/scanner/preset/args.py,sha256=pMJ0PfQDbLwOnggaKJl_CHz1SpQpqhhQQPvVWQaoIKA,16269
|
|
224
225
|
bbot/scanner/preset/conditions.py,sha256=hFL9cSIWGEsv2TfM5UGurf0c91cyaM8egb5IngBmIjA,1569
|
|
225
226
|
bbot/scanner/preset/environ.py,sha256=9KbEOLWkUdoAf5Ez_2A1NNm6QduQElbnNnrPi6VDhZs,4731
|
|
226
227
|
bbot/scanner/preset/path.py,sha256=Q29MO8cOEn690yW6bB08P72kbZ3C-H_TOEoXuwWnFM8,2274
|
|
227
228
|
bbot/scanner/preset/preset.py,sha256=R8-RNEstx4kLMZcfz878qzmTpEH45kgg3itRK-FWw5I,40038
|
|
228
229
|
bbot/scanner/scanner.py,sha256=GTTimZPPjX7vFIAgmMpPcxnn4ZijHE3yjMEfTORKy88,53853
|
|
229
230
|
bbot/scanner/stats.py,sha256=re93sArKXZSiD0Owgqk2J3Kdvfm3RL4Y9Qy_VOcaVk8,3623
|
|
230
|
-
bbot/scanner/target.py,sha256=
|
|
231
|
+
bbot/scanner/target.py,sha256=kYB2ItVzZDPaz1tj3iOe0LTkpntK7S8mfJ4qEJSOiSQ,11551
|
|
231
232
|
bbot/scripts/docs.py,sha256=ZLY9-O6OeEElzOUvTglO5EMkRv1s4aEuxJb2CthCVsI,10782
|
|
232
233
|
bbot/test/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
233
234
|
bbot/test/bbot_fixtures.py,sha256=PNIycAMcNWM8oZ6BvvQmSbif1sztdOgyQ_e9lfQA6gA,9981
|
|
@@ -242,7 +243,7 @@ bbot/test/test_step_1/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3h
|
|
|
242
243
|
bbot/test/test_step_1/test__module__tests.py,sha256=uwuROxdXI52D-V9z3Q9VNslvBfaduj6MQS5tQ_UOqXA,1460
|
|
243
244
|
bbot/test/test_step_1/test_bbot_fastapi.py,sha256=FNGvlax4lFZVd0T3HvV9SJh1lsngOX58GrUnJVzoy20,2531
|
|
244
245
|
bbot/test/test_step_1/test_bloom_filter.py,sha256=GodseGF98sarWXZ5C3JCVWblnycS4BA75HEAzhx4xXg,2139
|
|
245
|
-
bbot/test/test_step_1/test_cli.py,sha256=
|
|
246
|
+
bbot/test/test_step_1/test_cli.py,sha256=osCnJFA5S7NpGeAukVFTx3EkmLZPX6vITectU062Rsg,26299
|
|
246
247
|
bbot/test/test_step_1/test_command.py,sha256=5IeGV6TKB0xtFEsfsU_0mNrOmEdIQiQ3FHkUmsBNoOI,6485
|
|
247
248
|
bbot/test/test_step_1/test_config.py,sha256=Q38hygpke2GDcv8OguVZuiSOnfDJxEMrRy20dN5Qsn0,887
|
|
248
249
|
bbot/test/test_step_1/test_depsinstaller.py,sha256=zr9f-wJDotD1ZvKXGEuDRWzFYMAYBI6209mI_PWPtTQ,703
|
|
@@ -254,13 +255,13 @@ bbot/test/test_step_1/test_files.py,sha256=5Q_3jPpMXULxDHsanSDUaj8zF8bXzKdiJZHOm
|
|
|
254
255
|
bbot/test/test_step_1/test_helpers.py,sha256=6WG2rqnI7Jt0Z7Dc5AyqTDcL16QM0_WJ3CXE1M-xSMc,39506
|
|
255
256
|
bbot/test/test_step_1/test_manager_deduplication.py,sha256=hZQpDXzg6zvzxFolVOcJuY-ME8NXjZUsqS70BRNXp8A,15594
|
|
256
257
|
bbot/test/test_step_1/test_manager_scope_accuracy.py,sha256=JV1bQHt9EIM0GmGS4T4Brz_L2lfcwTxtNC06cfv7r64,79763
|
|
257
|
-
bbot/test/test_step_1/test_modules_basic.py,sha256=
|
|
258
|
+
bbot/test/test_step_1/test_modules_basic.py,sha256=hxXdsrBwme5elGQtvyvA52-KzahyQC3FlWQZ3T0EheA,19989
|
|
258
259
|
bbot/test/test_step_1/test_presets.py,sha256=CCwXb0gxTd8lSYtp0a_2PkfrwfdD5f9VngetbCLecL0,38211
|
|
259
260
|
bbot/test/test_step_1/test_python_api.py,sha256=GM5Kp2AAFl92ozo1kL6axsM87F8Gdq2_mWQvRnbXW_0,5503
|
|
260
261
|
bbot/test/test_step_1/test_regexes.py,sha256=34-BHzDE5qdltE-sQIzkrTmJTL49QUYoTn2uT1DZLwI,14356
|
|
261
262
|
bbot/test/test_step_1/test_scan.py,sha256=h3JP5RXnOUH8dqqq2Q_7yLpx1LCAEvqfE1bpHL7bDS0,5756
|
|
262
263
|
bbot/test/test_step_1/test_scope.py,sha256=S2nssENKJKCvgXUMyU8MFQmXHeUIz0C_sbWGkdYti2A,3063
|
|
263
|
-
bbot/test/test_step_1/test_target.py,sha256=
|
|
264
|
+
bbot/test/test_step_1/test_target.py,sha256=O-r7WxLdO6C3FmhjhA9rfRWb3uX4xW0eEQX4qCMFG7Q,19127
|
|
264
265
|
bbot/test/test_step_1/test_web.py,sha256=n9p9WhsEyN5I7S8RUUOEzF8v1CyeJjkmk4l6hnpOblY,18804
|
|
265
266
|
bbot/test/test_step_2/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
266
267
|
bbot/test/test_step_2/module_tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -350,6 +351,7 @@ bbot/test/test_step_2/module_tests/test_module_mysql.py,sha256=4wAPjbjhlxmOkEhQn
|
|
|
350
351
|
bbot/test/test_step_2/module_tests/test_module_myssl.py,sha256=zRJ1sOEespWtBx2jA07bW5sHD1XQ9pV0PtHtGogo7Gs,1531
|
|
351
352
|
bbot/test/test_step_2/module_tests/test_module_neo4j.py,sha256=pUUaqxBsF6s11dEDhrETpvlR2pqiUcc0uvH8Z5GvVUQ,1332
|
|
352
353
|
bbot/test/test_step_2/module_tests/test_module_newsletters.py,sha256=uf5t2oRqxhNToPjEfkY9vMdOUzrSocvx8w5itS6HUaM,2295
|
|
354
|
+
bbot/test/test_step_2/module_tests/test_module_nmap_xml.py,sha256=KbUAjhARvtERv7Jx666n2hkuLOmK8Zah8RpLZqNyAuE,3548
|
|
353
355
|
bbot/test/test_step_2/module_tests/test_module_ntlm.py,sha256=tPUrsOnq8iV0l_qiD_4xkqp0-o_T2uI1e-yH22oNveA,1132
|
|
354
356
|
bbot/test/test_step_2/module_tests/test_module_nuclei.py,sha256=rLCTuKWnGWiGDcVnMjk4D7x6RGftEj3D4Woqpam-cgQ,7050
|
|
355
357
|
bbot/test/test_step_2/module_tests/test_module_oauth.py,sha256=pN1o0DmcwGCa985FrIhUuX1jIGriDjaxMzWozuv8pR0,9481
|
|
@@ -414,8 +416,8 @@ bbot/wordlists/raft-small-extensions-lowercase_CLEANED.txt,sha256=ZSIVebs7ptMvHx
|
|
|
414
416
|
bbot/wordlists/top_open_ports_nmap.txt,sha256=LmdFYkfapSxn1pVuQC2LkOIY2hMLgG-Xts7DVtYzweM,42727
|
|
415
417
|
bbot/wordlists/valid_url_schemes.txt,sha256=0B_VAr9Dv7aYhwi6JSBDU-3M76vNtzN0qEC_RNLo7HE,3310
|
|
416
418
|
bbot/wordlists/wordninja_dns.txt.gz,sha256=DYHvvfW0TvzrVwyprqODAk4tGOxv5ezNmCPSdPuDUnQ,570241
|
|
417
|
-
bbot-2.3.0.
|
|
418
|
-
bbot-2.3.0.
|
|
419
|
-
bbot-2.3.0.
|
|
420
|
-
bbot-2.3.0.
|
|
421
|
-
bbot-2.3.0.
|
|
419
|
+
bbot-2.3.0.5438rc0.dist-info/LICENSE,sha256=GzeCzK17hhQQDNow0_r0L8OfLpeTKQjFQwBQU7ZUymg,32473
|
|
420
|
+
bbot-2.3.0.5438rc0.dist-info/METADATA,sha256=i5UQgB9yhkyfzqgT3X74QNPpmFrdp0oZcTsLXFWUzcg,17949
|
|
421
|
+
bbot-2.3.0.5438rc0.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
|
422
|
+
bbot-2.3.0.5438rc0.dist-info/entry_points.txt,sha256=cWjvcU_lLrzzJgjcjF7yeGuRA_eDS8pQ-kmPUAyOBfo,38
|
|
423
|
+
bbot-2.3.0.5438rc0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|