bbot 2.3.2.5915rc0__py3-none-any.whl → 2.3.2.5938rc0__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 +5 -2
- bbot/core/helpers/depsinstaller/installer.py +17 -2
- bbot/core/helpers/names_generator.py +0 -1
- bbot/core/helpers/regex.py +4 -0
- bbot/core/helpers/web/client.py +1 -0
- bbot/modules/git.py +8 -1
- bbot/modules/gitdumper.py +270 -0
- bbot/modules/portfilter.py +1 -1
- bbot/test/test_step_2/module_tests/test_module_gitdumper.py +385 -0
- {bbot-2.3.2.5915rc0.dist-info → bbot-2.3.2.5938rc0.dist-info}/METADATA +12 -12
- {bbot-2.3.2.5915rc0.dist-info → bbot-2.3.2.5938rc0.dist-info}/RECORD +15 -13
- {bbot-2.3.2.5915rc0.dist-info → bbot-2.3.2.5938rc0.dist-info}/LICENSE +0 -0
- {bbot-2.3.2.5915rc0.dist-info → bbot-2.3.2.5938rc0.dist-info}/WHEEL +0 -0
- {bbot-2.3.2.5915rc0.dist-info → bbot-2.3.2.5938rc0.dist-info}/entry_points.txt +0 -0
bbot/__init__.py
CHANGED
bbot/cli.py
CHANGED
|
@@ -161,8 +161,11 @@ async def _main():
|
|
|
161
161
|
all_modules = list(preset.module_loader.preloaded())
|
|
162
162
|
scan.helpers.depsinstaller.force_deps = True
|
|
163
163
|
succeeded, failed = await scan.helpers.depsinstaller.install(*all_modules)
|
|
164
|
-
|
|
165
|
-
|
|
164
|
+
if failed:
|
|
165
|
+
log.hugewarning(f"Failed to install dependencies for the following modules: {', '.join(failed)}")
|
|
166
|
+
return False
|
|
167
|
+
log.hugesuccess(f"Successfully installed dependencies for the following modules: {', '.join(succeeded)}")
|
|
168
|
+
return True
|
|
166
169
|
|
|
167
170
|
scan_name = str(scan.name)
|
|
168
171
|
|
|
@@ -96,7 +96,7 @@ class DepsInstaller:
|
|
|
96
96
|
self.ensure_root_lock = Lock()
|
|
97
97
|
|
|
98
98
|
async def install(self, *modules):
|
|
99
|
-
self.install_core_deps()
|
|
99
|
+
await self.install_core_deps()
|
|
100
100
|
succeeded = []
|
|
101
101
|
failed = []
|
|
102
102
|
try:
|
|
@@ -386,13 +386,14 @@ class DepsInstaller:
|
|
|
386
386
|
else:
|
|
387
387
|
log.warning("Incorrect password")
|
|
388
388
|
|
|
389
|
-
def install_core_deps(self):
|
|
389
|
+
async def install_core_deps(self):
|
|
390
390
|
to_install = set()
|
|
391
391
|
to_install_friendly = set()
|
|
392
392
|
playbook = []
|
|
393
393
|
self._install_sudo_askpass()
|
|
394
394
|
# ensure tldextract data is cached
|
|
395
395
|
self.parent_helper.tldextract("evilcorp.co.uk")
|
|
396
|
+
# install any missing commands
|
|
396
397
|
for command, package_name_or_playbook in self.CORE_DEPS.items():
|
|
397
398
|
if not self.parent_helper.which(command):
|
|
398
399
|
to_install_friendly.add(command)
|
|
@@ -400,6 +401,19 @@ class DepsInstaller:
|
|
|
400
401
|
to_install.add(package_name_or_playbook)
|
|
401
402
|
else:
|
|
402
403
|
playbook.extend(package_name_or_playbook)
|
|
404
|
+
# install ansible community.general collection
|
|
405
|
+
if not self.setup_status.get("ansible:community.general", False):
|
|
406
|
+
log.info("Installing Ansible Community General Collection")
|
|
407
|
+
try:
|
|
408
|
+
command = ["ansible-galaxy", "collection", "install", "community.general"]
|
|
409
|
+
await self.parent_helper.run(command, check=True)
|
|
410
|
+
self.setup_status["ansible:community.general"] = True
|
|
411
|
+
log.info("Successfully installed Ansible Community General Collection")
|
|
412
|
+
except CalledProcessError as err:
|
|
413
|
+
log.warning(
|
|
414
|
+
f"Failed to install Ansible Community.General Collection (return code {err.returncode}): {err.stderr}"
|
|
415
|
+
)
|
|
416
|
+
# construct ansible playbook
|
|
403
417
|
if to_install:
|
|
404
418
|
playbook.append(
|
|
405
419
|
{
|
|
@@ -408,6 +422,7 @@ class DepsInstaller:
|
|
|
408
422
|
"become": True,
|
|
409
423
|
}
|
|
410
424
|
)
|
|
425
|
+
# run playbook
|
|
411
426
|
if playbook:
|
|
412
427
|
log.info(f"Installing core BBOT dependencies: {','.join(sorted(to_install_friendly))}")
|
|
413
428
|
self.ensure_root()
|
bbot/core/helpers/regex.py
CHANGED
|
@@ -31,6 +31,10 @@ class RegexHelper:
|
|
|
31
31
|
self.ensure_compiled_regex(compiled_regex)
|
|
32
32
|
return await self.parent_helper.run_in_executor(compiled_regex.search, *args, **kwargs)
|
|
33
33
|
|
|
34
|
+
async def sub(self, compiled_regex, *args, **kwargs):
|
|
35
|
+
self.ensure_compiled_regex(compiled_regex)
|
|
36
|
+
return await self.parent_helper.run_in_executor(compiled_regex.sub, *args, **kwargs)
|
|
37
|
+
|
|
34
38
|
async def findall(self, compiled_regex, *args, **kwargs):
|
|
35
39
|
self.ensure_compiled_regex(compiled_regex)
|
|
36
40
|
return await self.parent_helper.run_in_executor(compiled_regex.findall, *args, **kwargs)
|
bbot/core/helpers/web/client.py
CHANGED
|
@@ -83,6 +83,7 @@ class BBOTAsyncClient(httpx.AsyncClient):
|
|
|
83
83
|
# TODO: re-enable this
|
|
84
84
|
if self._target.in_scope(str(request.url)):
|
|
85
85
|
for hk, hv in self._web_config.get("http_headers", {}).items():
|
|
86
|
+
hv = str(hv)
|
|
86
87
|
# don't clobber headers
|
|
87
88
|
if hk not in request.headers:
|
|
88
89
|
request.headers[hk] = hv
|
bbot/modules/git.py
CHANGED
|
@@ -5,7 +5,7 @@ from bbot.modules.base import BaseModule
|
|
|
5
5
|
|
|
6
6
|
class git(BaseModule):
|
|
7
7
|
watched_events = ["URL"]
|
|
8
|
-
produced_events = ["FINDING"]
|
|
8
|
+
produced_events = ["FINDING", "CODE_REPOSITORY"]
|
|
9
9
|
flags = ["active", "safe", "web-basic", "code-enum"]
|
|
10
10
|
meta = {
|
|
11
11
|
"description": "Check for exposed .git repositories",
|
|
@@ -37,3 +37,10 @@ class git(BaseModule):
|
|
|
37
37
|
event,
|
|
38
38
|
context="{module} detected {event.type}: {description}",
|
|
39
39
|
)
|
|
40
|
+
await self.emit_event(
|
|
41
|
+
{"url": url.rstrip("config")},
|
|
42
|
+
"CODE_REPOSITORY",
|
|
43
|
+
event,
|
|
44
|
+
tags="git_directory",
|
|
45
|
+
context="{module} detected {event.type}: {description}",
|
|
46
|
+
)
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
import regex as re
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from subprocess import CalledProcessError
|
|
4
|
+
from bbot.modules.base import BaseModule
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class gitdumper(BaseModule):
|
|
8
|
+
watched_events = ["CODE_REPOSITORY"]
|
|
9
|
+
produced_events = ["FILESYSTEM"]
|
|
10
|
+
flags = ["passive", "safe", "slow", "code-enum"]
|
|
11
|
+
meta = {
|
|
12
|
+
"description": "Download a leaked .git folder recursively or by fuzzing common names",
|
|
13
|
+
"created_date": "2025-02-11",
|
|
14
|
+
"author": "@domwhewell-sage",
|
|
15
|
+
}
|
|
16
|
+
options = {
|
|
17
|
+
"output_folder": "",
|
|
18
|
+
"fuzz_tags": False,
|
|
19
|
+
"max_semanic_version": 10,
|
|
20
|
+
}
|
|
21
|
+
options_desc = {
|
|
22
|
+
"output_folder": "Folder to download repositories to",
|
|
23
|
+
"fuzz_tags": "Fuzz for common git tag names (v0.0.1, 0.0.2, etc.) up to the max_semanic_version",
|
|
24
|
+
"max_semanic_version": "Maximum version number to fuzz for (default < v10.10.10)",
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
scope_distance_modifier = 2
|
|
28
|
+
|
|
29
|
+
async def setup(self):
|
|
30
|
+
self.urls_downloaded = set()
|
|
31
|
+
output_folder = self.config.get("output_folder")
|
|
32
|
+
if output_folder:
|
|
33
|
+
self.output_dir = Path(output_folder) / "git_repos"
|
|
34
|
+
else:
|
|
35
|
+
self.output_dir = self.scan.home / "git_repos"
|
|
36
|
+
self.helpers.mkdir(self.output_dir)
|
|
37
|
+
self.unsafe_regex = self.helpers.re.compile(r"^\s*fsmonitor|sshcommand|askpass|editor|pager", re.IGNORECASE)
|
|
38
|
+
self.ref_regex = self.helpers.re.compile(r"ref: refs/heads/([a-zA-Z\d_-]+)")
|
|
39
|
+
self.obj_regex = self.helpers.re.compile(r"[a-f0-9]{40}")
|
|
40
|
+
self.pack_regex = self.helpers.re.compile(r"pack-([a-f0-9]{40})\.pack")
|
|
41
|
+
self.git_files = [
|
|
42
|
+
"HEAD",
|
|
43
|
+
"description",
|
|
44
|
+
"config",
|
|
45
|
+
"COMMIT_EDITMSG",
|
|
46
|
+
"index",
|
|
47
|
+
"packed-refs",
|
|
48
|
+
"info/refs",
|
|
49
|
+
"info/exclude",
|
|
50
|
+
"refs/stash",
|
|
51
|
+
"refs/wip/index/refs/heads/master",
|
|
52
|
+
"refs/wip/wtree/refs/heads/master",
|
|
53
|
+
"logs/HEAD",
|
|
54
|
+
"objects/info/packs",
|
|
55
|
+
]
|
|
56
|
+
self.info("Compiling fuzz list with common branch names")
|
|
57
|
+
branch_names = [
|
|
58
|
+
"bugfix",
|
|
59
|
+
"daily",
|
|
60
|
+
"dev",
|
|
61
|
+
"develop",
|
|
62
|
+
"development",
|
|
63
|
+
"feat",
|
|
64
|
+
"feature",
|
|
65
|
+
"fix",
|
|
66
|
+
"hotfix",
|
|
67
|
+
"integration",
|
|
68
|
+
"issue",
|
|
69
|
+
"main",
|
|
70
|
+
"master",
|
|
71
|
+
"ng",
|
|
72
|
+
"prod",
|
|
73
|
+
"production",
|
|
74
|
+
"qa",
|
|
75
|
+
"quickfix",
|
|
76
|
+
"release",
|
|
77
|
+
"stable",
|
|
78
|
+
"stage",
|
|
79
|
+
"staging",
|
|
80
|
+
"test",
|
|
81
|
+
"testing",
|
|
82
|
+
"wip",
|
|
83
|
+
]
|
|
84
|
+
url_patterns = [
|
|
85
|
+
"logs/refs/heads/{branch}",
|
|
86
|
+
"logs/refs/remotes/origin/{branch}",
|
|
87
|
+
"refs/remotes/origin/{branch}",
|
|
88
|
+
"refs/heads/{branch}",
|
|
89
|
+
]
|
|
90
|
+
for branch in branch_names:
|
|
91
|
+
for pattern in url_patterns:
|
|
92
|
+
self.git_files.append(pattern.format(branch=branch))
|
|
93
|
+
self.fuzz_tags = self.config.get("fuzz_tags", "10")
|
|
94
|
+
self.max_semanic_version = self.config.get("max_semanic_version", "10")
|
|
95
|
+
if self.fuzz_tags:
|
|
96
|
+
self.info("Adding symantec version tags to fuzz list")
|
|
97
|
+
for major in range(self.max_semanic_version):
|
|
98
|
+
for minor in range(self.max_semanic_version):
|
|
99
|
+
for patch in range(self.max_semanic_version):
|
|
100
|
+
self.verbose(f"{major}.{minor}.{patch}")
|
|
101
|
+
self.git_files.append(f"refs/tags/{major}.{minor}.{patch}")
|
|
102
|
+
self.verbose(f"v{major}.{minor}.{patch}")
|
|
103
|
+
self.git_files.append(f"refs/tags/v{major}.{minor}.{patch}")
|
|
104
|
+
else:
|
|
105
|
+
self.info("Adding symantec version tags to fuzz list (v0.0.1, 0.0.1, v1.0.0, 1.0.0)")
|
|
106
|
+
for path in ["refs/tags/v0.0.1", "refs/tags/0.0.1", "refs/tags/v1.0.0", "refs/tags/1.0.0"]:
|
|
107
|
+
self.git_files.append(path)
|
|
108
|
+
return await super().setup()
|
|
109
|
+
|
|
110
|
+
async def filter_event(self, event):
|
|
111
|
+
if event.type == "CODE_REPOSITORY":
|
|
112
|
+
if "git-directory" not in event.tags:
|
|
113
|
+
return False, "event is not a leaked .git directory"
|
|
114
|
+
return True
|
|
115
|
+
|
|
116
|
+
async def handle_event(self, event):
|
|
117
|
+
repo_url = event.data.get("url")
|
|
118
|
+
self.info(f"Processing leaked .git directory at {repo_url}")
|
|
119
|
+
repo_folder = self.output_dir / self.helpers.tagify(repo_url)
|
|
120
|
+
self.helpers.mkdir(repo_folder)
|
|
121
|
+
dir_listing = await self.directory_listing_enabled(repo_url)
|
|
122
|
+
if dir_listing:
|
|
123
|
+
urls = await self.recursive_dir_list(dir_listing)
|
|
124
|
+
result = await self.download_files(urls, repo_folder)
|
|
125
|
+
else:
|
|
126
|
+
result = await self.git_fuzz(repo_url, repo_folder)
|
|
127
|
+
if result:
|
|
128
|
+
await self.sanitize_config(repo_folder)
|
|
129
|
+
await self.git_checkout(repo_folder)
|
|
130
|
+
codebase_event = self.make_event({"path": str(repo_folder)}, "FILESYSTEM", tags=["git"], parent=event)
|
|
131
|
+
await self.emit_event(
|
|
132
|
+
codebase_event,
|
|
133
|
+
context=f"{{module}} cloned git repo at {repo_url} to {{event.type}}: {str(repo_folder)}",
|
|
134
|
+
)
|
|
135
|
+
else:
|
|
136
|
+
self.helpers.rm_rf(repo_folder)
|
|
137
|
+
|
|
138
|
+
async def directory_listing_enabled(self, repo_url):
|
|
139
|
+
response = await self.helpers.request(repo_url)
|
|
140
|
+
if "<title>Index of" in getattr(response, "text", ""):
|
|
141
|
+
self.info(f"Directory listing enabled at {repo_url}")
|
|
142
|
+
return response
|
|
143
|
+
return None
|
|
144
|
+
|
|
145
|
+
async def recursive_dir_list(self, dir_listing):
|
|
146
|
+
file_list = []
|
|
147
|
+
soup = self.helpers.beautifulsoup(dir_listing.text, "html.parser")
|
|
148
|
+
links = soup.find_all("a")
|
|
149
|
+
for link in links:
|
|
150
|
+
href = link["href"]
|
|
151
|
+
if href == "../" or href == "/":
|
|
152
|
+
continue
|
|
153
|
+
if href.endswith("/"):
|
|
154
|
+
folder_url = self.helpers.urljoin(str(dir_listing.url), href)
|
|
155
|
+
response = await self.helpers.request(folder_url)
|
|
156
|
+
if getattr(response, "status_code", 0) == 200:
|
|
157
|
+
file_list.extend(await self.recursive_dir_list(response))
|
|
158
|
+
else:
|
|
159
|
+
file_url = self.helpers.urljoin(str(dir_listing.url), href)
|
|
160
|
+
# Ensure the file is in the same domain as the directory listing
|
|
161
|
+
if file_url.startswith(str(dir_listing.url)):
|
|
162
|
+
url = self.helpers.urlparse(file_url)
|
|
163
|
+
file_list.append(url)
|
|
164
|
+
return file_list
|
|
165
|
+
|
|
166
|
+
async def git_fuzz(self, repo_url, repo_folder):
|
|
167
|
+
self.info("Directory listing not enabled, fuzzing common git files")
|
|
168
|
+
url_list = []
|
|
169
|
+
for file in self.git_files:
|
|
170
|
+
url_list.append(self.helpers.urlparse(self.helpers.urljoin(repo_url, file)))
|
|
171
|
+
result = await self.download_files(url_list, repo_folder)
|
|
172
|
+
if result:
|
|
173
|
+
await self.download_current_branch(repo_url, repo_folder)
|
|
174
|
+
await self.download_git_objects(repo_url, repo_folder)
|
|
175
|
+
await self.download_git_packs(repo_url, repo_folder)
|
|
176
|
+
return True
|
|
177
|
+
else:
|
|
178
|
+
return False
|
|
179
|
+
|
|
180
|
+
async def download_current_branch(self, repo_url, repo_folder):
|
|
181
|
+
for branch in await self.regex_files(self.ref_regex, file=repo_folder / ".git/HEAD"):
|
|
182
|
+
await self.download_files(
|
|
183
|
+
[self.helpers.urlparse(self.helpers.urljoin(repo_url, f"refs/heads/{branch}"))], repo_folder
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
async def download_git_objects(self, url, folder):
|
|
187
|
+
for object in await self.regex_files(self.obj_regex, folder=folder):
|
|
188
|
+
await self.download_object(object, url, folder)
|
|
189
|
+
|
|
190
|
+
async def download_git_packs(self, url, folder):
|
|
191
|
+
url_list = []
|
|
192
|
+
for sha1 in await self.regex_files(self.pack_regex, file=folder / ".git/objects/info/packs"):
|
|
193
|
+
url_list.append(self.helpers.urlparse(self.helpers.urljoin(url, f"objects/pack/pack-{sha1}.idx")))
|
|
194
|
+
url_list.append(self.helpers.urlparse(self.helpers.urljoin(url, f"objects/pack/pack-{sha1}.pack")))
|
|
195
|
+
if url_list:
|
|
196
|
+
await self.download_files(url_list, folder)
|
|
197
|
+
|
|
198
|
+
async def regex_files(self, regex, folder=Path(), file=Path(), files=[]):
|
|
199
|
+
results = []
|
|
200
|
+
if folder:
|
|
201
|
+
if folder.is_dir():
|
|
202
|
+
for file_path in folder.rglob("*"):
|
|
203
|
+
if file_path.is_file():
|
|
204
|
+
results.extend(await self.regex_file(regex, file_path))
|
|
205
|
+
if files:
|
|
206
|
+
for file in files:
|
|
207
|
+
results.extend(await self.regex_file(regex, file))
|
|
208
|
+
if file:
|
|
209
|
+
results.extend(await self.regex_file(regex, file))
|
|
210
|
+
return results
|
|
211
|
+
|
|
212
|
+
async def regex_file(self, regex, file=Path()):
|
|
213
|
+
if file.exists() and file.is_file():
|
|
214
|
+
with file.open("r", encoding="utf-8", errors="ignore") as file:
|
|
215
|
+
content = file.read()
|
|
216
|
+
matches = await self.helpers.re.findall(regex, content)
|
|
217
|
+
if matches:
|
|
218
|
+
return matches
|
|
219
|
+
return []
|
|
220
|
+
|
|
221
|
+
async def download_object(self, object, repo_url, repo_folder):
|
|
222
|
+
await self.download_files(
|
|
223
|
+
[self.helpers.urlparse(self.helpers.urljoin(repo_url, f"objects/{object[:2]}/{object[2:]}"))], repo_folder
|
|
224
|
+
)
|
|
225
|
+
output = await self.git_catfile(object, option="-p", folder=repo_folder)
|
|
226
|
+
for obj in await self.helpers.re.findall(self.obj_regex, output):
|
|
227
|
+
await self.download_object(obj, repo_url, repo_folder)
|
|
228
|
+
|
|
229
|
+
async def download_files(self, urls, folder):
|
|
230
|
+
for url in urls:
|
|
231
|
+
git_index = url.path.find(".git")
|
|
232
|
+
file_url = url.geturl()
|
|
233
|
+
filename = folder / url.path[git_index:]
|
|
234
|
+
self.helpers.mkdir(filename.parent)
|
|
235
|
+
if hash(str(file_url)) not in self.urls_downloaded:
|
|
236
|
+
self.verbose(f"Downloading {file_url} to {filename}")
|
|
237
|
+
await self.helpers.download(file_url, filename=filename, warn=False)
|
|
238
|
+
self.urls_downloaded.add(hash(str(file_url)))
|
|
239
|
+
if any(folder.rglob("*")):
|
|
240
|
+
return True
|
|
241
|
+
else:
|
|
242
|
+
self.debug(f"Unable to download git files to {folder}")
|
|
243
|
+
return False
|
|
244
|
+
|
|
245
|
+
async def sanitize_config(self, folder):
|
|
246
|
+
config_file = folder / ".git/config"
|
|
247
|
+
if config_file.exists():
|
|
248
|
+
with config_file.open("r", encoding="utf-8", errors="ignore") as file:
|
|
249
|
+
content = file.read()
|
|
250
|
+
sanitized = await self.helpers.re.sub(self.unsafe_regex, r"# \g<0>", content)
|
|
251
|
+
with config_file.open("w", encoding="utf-8") as file:
|
|
252
|
+
file.write(sanitized)
|
|
253
|
+
|
|
254
|
+
async def git_catfile(self, hash, option="-t", folder=Path()):
|
|
255
|
+
command = ["git", "cat-file", option, hash]
|
|
256
|
+
try:
|
|
257
|
+
output = await self.run_process(command, env={"GIT_TERMINAL_PROMPT": "0"}, cwd=folder, check=True)
|
|
258
|
+
except CalledProcessError:
|
|
259
|
+
return ""
|
|
260
|
+
|
|
261
|
+
return output.stdout
|
|
262
|
+
|
|
263
|
+
async def git_checkout(self, folder):
|
|
264
|
+
self.verbose(f"Running git checkout to reconstruct the git repository at {folder}")
|
|
265
|
+
command = ["git", "checkout", "."]
|
|
266
|
+
try:
|
|
267
|
+
await self.run_process(command, env={"GIT_TERMINAL_PROMPT": "0"}, cwd=folder, check=True)
|
|
268
|
+
except CalledProcessError as e:
|
|
269
|
+
# Still emit the event even if the checkout fails
|
|
270
|
+
self.debug(f"Error running git checkout in {folder}. STDERR: {repr(e.stderr)}")
|
bbot/modules/portfilter.py
CHANGED
|
@@ -2,7 +2,7 @@ from bbot.modules.base import BaseInterceptModule
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
class portfilter(BaseInterceptModule):
|
|
5
|
-
watched_events = ["OPEN_TCP_PORT"]
|
|
5
|
+
watched_events = ["OPEN_TCP_PORT", "URL_UNVERIFIED", "URL"]
|
|
6
6
|
flags = ["passive", "safe"]
|
|
7
7
|
meta = {
|
|
8
8
|
"description": "Filter out unwanted open ports from cloud/CDN targets",
|
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
from .base import ModuleTestBase
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class TestGitDumper_Dirlisting(ModuleTestBase):
|
|
6
|
+
targets = [
|
|
7
|
+
"http://127.0.0.1:8888/test",
|
|
8
|
+
]
|
|
9
|
+
|
|
10
|
+
modules_overrides = ["git", "gitdumper", "httpx"]
|
|
11
|
+
|
|
12
|
+
index_html = """<html>
|
|
13
|
+
<head>
|
|
14
|
+
<title>Index of /.git</title>
|
|
15
|
+
</head>
|
|
16
|
+
<body>
|
|
17
|
+
<h1>Index of /.git</h1>
|
|
18
|
+
<table>
|
|
19
|
+
<tr><th>Name</th><th>Size</th></tr>
|
|
20
|
+
<tr><td><a href='/test/.git/branches/'><branches></a></td><td></td></tr>
|
|
21
|
+
<tr><td><a href='/test/.git/COMMIT_EDITMSG'>COMMIT_EDITMSG</a></td><td>157B</td></tr>
|
|
22
|
+
<tr><td><a href='/test/.git/config'>config</a></td><td>157B</td></tr>
|
|
23
|
+
<tr><td><a href='/test/.git/description'>description</a></td><td>73B</td></tr>
|
|
24
|
+
<tr><td><a href='/test/.git/HEAD'>HEAD</a></td><td>23B</td></tr>
|
|
25
|
+
<tr><td><a href='/test/.git/hooks/'><hooks></a></td><td></td></tr>
|
|
26
|
+
<tr><td><a href='/test/.git/info/'><info></a></td><td></td></tr>
|
|
27
|
+
<tr><td><a href='/test/.git/objects/'><objects></a></td><td></td></tr>
|
|
28
|
+
<tr><td><a href='/test/.git/index'>index</a></td><td></td></tr>
|
|
29
|
+
<tr><td><a href='/test/.git/refs/'><refs></a></td><td></td></tr>
|
|
30
|
+
<tr><td><a href='/test/.git/logs/'><logs></a></td><td></td></tr>
|
|
31
|
+
</table>
|
|
32
|
+
</body>
|
|
33
|
+
</html>"""
|
|
34
|
+
|
|
35
|
+
info_index = """<html>
|
|
36
|
+
<head>
|
|
37
|
+
<title>Index of /.git/info</title>
|
|
38
|
+
</head>
|
|
39
|
+
<body>
|
|
40
|
+
<h1>Index of /.git/info</h1>
|
|
41
|
+
<table>
|
|
42
|
+
<tr><th>Name</th><th>Size</th></tr>
|
|
43
|
+
<tr><td><a href='../'>[..]</a></td><td></td></tr>
|
|
44
|
+
<tr><td><a href='/test/.git/info/exclude'>exclude</a></td><td>240B</td></tr>
|
|
45
|
+
<tr><td><a href='http://exclude.com/excludeme'>excludeme</a></td><td>0B</td></tr>
|
|
46
|
+
</table>
|
|
47
|
+
</body>
|
|
48
|
+
</html>"""
|
|
49
|
+
|
|
50
|
+
objects_index = """<html>
|
|
51
|
+
<head>
|
|
52
|
+
<title>Index of /.git/objects</title>
|
|
53
|
+
</head>
|
|
54
|
+
<body>
|
|
55
|
+
<h1>Index of /.git/objects</h1>
|
|
56
|
+
<table>
|
|
57
|
+
<tr><th>Name</th><th>Size</th></tr>
|
|
58
|
+
<tr><td><a href='../'>[..]</a></td><td></td></tr>
|
|
59
|
+
<tr><td><a href='/test/.git/objects/05/'><05></a></td><td></td></tr>
|
|
60
|
+
<tr><td><a href='/test/.git/objects/34/'><34></a></td><td></td></tr>
|
|
61
|
+
<tr><td><a href='/test/.git/objects/c2/'><c2></a></td><td></td></tr>
|
|
62
|
+
<tr><td><a href='/test/.git/objects/pack/'><pack></a></td><td></td></tr>
|
|
63
|
+
<tr><td><a href='/test/.git/objects/info/'><info></a></td><td></td></tr>
|
|
64
|
+
</table>
|
|
65
|
+
</body>
|
|
66
|
+
</html>"""
|
|
67
|
+
|
|
68
|
+
objects_o5_index = """<html>
|
|
69
|
+
<head>
|
|
70
|
+
<title>Index of /.git/objects/05</title>
|
|
71
|
+
</head>
|
|
72
|
+
<body>
|
|
73
|
+
<h1>Index of /.git/objects/05</h1>
|
|
74
|
+
<table>
|
|
75
|
+
<tr><th>Name</th><th>Size</th></tr>
|
|
76
|
+
<tr><td><a href='../'>[..]</a></td><td></td></tr>
|
|
77
|
+
<tr><td><a href='/test/.git/objects/05/27e6bd2d76b45e2933183f1b506c7ac49f5872'>27e6bd2d76b45e2933183f1b506c7ac49f5872</a></td><td></td></tr>
|
|
78
|
+
</table>
|
|
79
|
+
</body>
|
|
80
|
+
</html>"""
|
|
81
|
+
|
|
82
|
+
objects_34_index = """<html>
|
|
83
|
+
<head>
|
|
84
|
+
<title>Index of /.git/objects/34</title>
|
|
85
|
+
</head>
|
|
86
|
+
<body>
|
|
87
|
+
<h1>Index of /.git/objects/34</h1>
|
|
88
|
+
<table>
|
|
89
|
+
<tr><th>Name</th><th>Size</th></tr>
|
|
90
|
+
<tr><td><a href='../'>[..]</a></td><td></td></tr>
|
|
91
|
+
<tr><td><a href='/test/.git/objects/34/dc86f0247798892a89553e7c5c2d5aa06c2c5b'>dc86f0247798892a89553e7c5c2d5aa06c2c5b</a></td><td></td></tr>
|
|
92
|
+
</table>
|
|
93
|
+
</body>
|
|
94
|
+
</html>"""
|
|
95
|
+
|
|
96
|
+
objects_c2_index = """<html>
|
|
97
|
+
<head>
|
|
98
|
+
<title>Index of /.git/objects/c2</title>
|
|
99
|
+
</head>
|
|
100
|
+
<body>
|
|
101
|
+
<h1>Index of /.git/objects/c2</h1>
|
|
102
|
+
<table>
|
|
103
|
+
<tr><th>Name</th><th>Size</th></tr>
|
|
104
|
+
<tr><td><a href='../'>[..]</a></td><td></td></tr>
|
|
105
|
+
<tr><td><a href='/test/.git/objects/c2/69d751b8e2fd0be0d0dc7a6437a4dce4ec0200'>69d751b8e2fd0be0d0dc7a6437a4dce4ec0200</a></td><td></td></tr>
|
|
106
|
+
</table>
|
|
107
|
+
</body>
|
|
108
|
+
</html>"""
|
|
109
|
+
|
|
110
|
+
refs_index = """<html>
|
|
111
|
+
<head>
|
|
112
|
+
<title>Index of /.git/refs</title>
|
|
113
|
+
</head>
|
|
114
|
+
<body>
|
|
115
|
+
<h1>Index of /.git/refs</h1>
|
|
116
|
+
<table>
|
|
117
|
+
<tr><th>Name</th><th>Size</th></tr>
|
|
118
|
+
<tr><td><a href='../'>[..]</a></td><td></td></tr>
|
|
119
|
+
<tr><td><a href='/test/.git/refs/heads/'><heads></a></td><td></td></tr>
|
|
120
|
+
<tr><td><a href='/test/.git/refs/tags/'><tags></a></td><td></td></tr>
|
|
121
|
+
</table>
|
|
122
|
+
</body>
|
|
123
|
+
</html>
|
|
124
|
+
"""
|
|
125
|
+
|
|
126
|
+
refs_heads_index = """<html>
|
|
127
|
+
<head>
|
|
128
|
+
<title>Index of /.git/refs/heads</title>
|
|
129
|
+
</head>
|
|
130
|
+
<body>
|
|
131
|
+
<h1>Index of /.git/refs/heads</h1>
|
|
132
|
+
<table>
|
|
133
|
+
<tr><th>Name</th><th>Size</th></tr>
|
|
134
|
+
<tr><td><a href='../'>[..]</a></td><td></td></tr>
|
|
135
|
+
<tr><td><a href='/test/.git/refs/heads/master'>master</a></td><td></td></tr>
|
|
136
|
+
</table>
|
|
137
|
+
</body>
|
|
138
|
+
</html>
|
|
139
|
+
"""
|
|
140
|
+
|
|
141
|
+
logs_index = """<html>
|
|
142
|
+
<head>
|
|
143
|
+
<title>Index of /.git/logs</title>
|
|
144
|
+
</head>
|
|
145
|
+
<body>
|
|
146
|
+
<h1>Index of /.git/logs</h1>
|
|
147
|
+
<table>
|
|
148
|
+
<tr><th>Name</th><th>Size</th></tr>
|
|
149
|
+
<tr><td><a href='../'>[..]</a></td><td></td></tr>
|
|
150
|
+
<tr><td><a href='/test/.git/logs/HEAD'>HEAD</a></td><td></td></tr>
|
|
151
|
+
<tr><td><a href='/test/.git/logs/refs/'><tags></a></td><td></td></tr>
|
|
152
|
+
</table>
|
|
153
|
+
</body>
|
|
154
|
+
</html>
|
|
155
|
+
"""
|
|
156
|
+
|
|
157
|
+
logs_refs_index = """<html>
|
|
158
|
+
<head>
|
|
159
|
+
<title>Index of /.git/logs/refs</title>
|
|
160
|
+
</head>
|
|
161
|
+
<body>
|
|
162
|
+
<h1>Index of /.git/logs/refs</h1>
|
|
163
|
+
<table>
|
|
164
|
+
<tr><th>Name</th><th>Size</th></tr>
|
|
165
|
+
<tr><td><a href='../'>[..]</a></td><td></td></tr>
|
|
166
|
+
<tr><td><a href='/test/.git/logs/refs/heads/'><heads></a></td><td></td></tr>
|
|
167
|
+
</table>
|
|
168
|
+
</body>
|
|
169
|
+
</html>
|
|
170
|
+
"""
|
|
171
|
+
|
|
172
|
+
logs_refs_heads_index = """<html>
|
|
173
|
+
<head>
|
|
174
|
+
<title>Index of /.git/logs/refs/heads</title>
|
|
175
|
+
</head>
|
|
176
|
+
<body>
|
|
177
|
+
<h1>Index of /.git/logs/refs/heads</h1>
|
|
178
|
+
<table>
|
|
179
|
+
<tr><th>Name</th><th>Size</th></tr>
|
|
180
|
+
<tr><td><a href='../'>[..]</a></td><td></td></tr>
|
|
181
|
+
<tr><td><a href='/test/.git/logs/refs/heads/master'>master</a></td><td></td></tr>
|
|
182
|
+
</table>
|
|
183
|
+
</body>
|
|
184
|
+
</html>
|
|
185
|
+
"""
|
|
186
|
+
|
|
187
|
+
empty_index = """<html>
|
|
188
|
+
<head>
|
|
189
|
+
<title>Index of /.git/...</title>
|
|
190
|
+
</head>
|
|
191
|
+
<body>
|
|
192
|
+
<h1>Index of /.git/...</h1>
|
|
193
|
+
<table>
|
|
194
|
+
<tr><th>Name</th><th>Size</th></tr>
|
|
195
|
+
<tr><td><a href='../'>[..]</a></td><td></td></tr>
|
|
196
|
+
</table>
|
|
197
|
+
</body>
|
|
198
|
+
</html>"""
|
|
199
|
+
|
|
200
|
+
git_head = "ref: refs/heads/master"
|
|
201
|
+
|
|
202
|
+
refs_head = "34dc86f0247798892a89553e7c5c2d5aa06c2c5b"
|
|
203
|
+
|
|
204
|
+
logs_head = "0000000000000000000000000000000000000000 34dc86f0247798892a89553e7c5c2d5aa06c2c5b Test <test@test.com> 1738516534 +0000 commit (initial): Initial commit"
|
|
205
|
+
|
|
206
|
+
logs_master_head = "0000000000000000000000000000000000000000 34dc86f0247798892a89553e7c5c2d5aa06c2c5b Test <test@test.com> 1738516534 +0000 commit (initial): Initial commit"
|
|
207
|
+
|
|
208
|
+
git_description = "Unnamed repository; edit this file 'description' to name the repository."
|
|
209
|
+
|
|
210
|
+
git_commit_editmsg = "Initial commit"
|
|
211
|
+
|
|
212
|
+
git_config = """[core]
|
|
213
|
+
repositoryformatversion = 0
|
|
214
|
+
filemode = true
|
|
215
|
+
bare = false
|
|
216
|
+
logallrefupdates = true"""
|
|
217
|
+
|
|
218
|
+
git_exclude = """# git ls-files --others --exclude-from=.git/info/exclude
|
|
219
|
+
# Lines that start with '#' are comments.
|
|
220
|
+
# For a project mostly in C, the following would be a good set of
|
|
221
|
+
# exclude patterns (uncomment them if you want to use them):
|
|
222
|
+
# *.[oa]
|
|
223
|
+
# *~"""
|
|
224
|
+
|
|
225
|
+
filebytes_gitindex = b"DIRC\x00\x00\x00\x02\x00\x00\x00\x01g\x9f\xbe\x04\x14\xfcb\xd1g\x9f\xbe\x04\x14\xfcb\xd1\x00\x00\x08 \x00\x04aD\x00\x00\x81\xa4\x00\x00\x03\xe8\x00\x00\x03\xe8\x00\x00\x00\x0f\x05'\xe6\xbd-v\xb4^)3\x18?\x1bPlz\xc4\x9fXr\x00\x08test.txt\x00\x00TREE\x00\x00\x00\x19\x001 0\n\xc2i\xd7Q\xb8\xe2\xfd\x0b\xe0\xd0\xdczd7\xa4\xdc\xe4\xec\x02\x00\xe8m|iw\xbb\xd6\x88;f\xdbW\x10yY\xd2\xb0G\xcfJ"
|
|
226
|
+
filebytes_27e6bd2d76b45e2933183f1b506c7ac49f5872 = (
|
|
227
|
+
b"x\x01K\xca\xc9OR04e\x08\xc9\xc8,V\x00\xa2D\x85\x92\xd4\xe2\x12.\x00U\xab\x07%"
|
|
228
|
+
)
|
|
229
|
+
filebytes_dc86f0247798892a89553e7c5c2d5aa06c2c5b = b"x\x01\x9d\x8dK\n\x021\x10D]\xe7\x14\xbd\x17\x86\xce?\x82\x88\x0b7\x9e\xc0u\xa6\xd3:\x81\xc4\xc0\x18\x99\xeb\x1b\x98\x1bX\xbbzP\xaf\xa8\xd5\x9a;\xc8\xa0\x0f}e\x06R\xee\x94\xbc\x95s`\xf5L83&L\xe4\xa33\xdaG\x93\x88\r\x13*D\x11\xbf}i+\xdcZ\x85\xc7\xc2\x1b\x97\x02\xe7\xd4\xea\xb4\xed\xe5\xfa\x89/\x9e\xa8\xd5\x0bH\xaf\x83\x95\xcej\x03G\x1c\x11\x83\x8e\xcf\xce\xff\xad\xc5\xfd\x9d{\x8e\x05v\x8d\xf8\x01\xfaF<\x05"
|
|
230
|
+
filebytes_69d751b8e2fd0be0d0dc7a6437a4dce4ec0200 = b"x\x01+)JMU06c040031Q(I-.\xd1+\xa9(a`U\x7f\xb6W\xb7lK\x9c\xa6\xb1\x84\xbdt@N\xd5\x91\xf9\x11E\x00*\x05\x0e\x8c"
|
|
231
|
+
|
|
232
|
+
async def setup_after_prep(self, module_test):
|
|
233
|
+
module_test.set_expect_requests(
|
|
234
|
+
expect_args={"uri": "/test/.git/"}, respond_args={"response_data": self.index_html}
|
|
235
|
+
)
|
|
236
|
+
module_test.set_expect_requests(
|
|
237
|
+
expect_args={"uri": "/test/.git/index"}, respond_args={"response_data": self.filebytes_gitindex}
|
|
238
|
+
)
|
|
239
|
+
module_test.set_expect_requests(
|
|
240
|
+
expect_args={"uri": "/test/.git/COMMIT_EDITMSG"}, respond_args={"response_data": self.git_commit_editmsg}
|
|
241
|
+
)
|
|
242
|
+
module_test.set_expect_requests(
|
|
243
|
+
expect_args={"uri": "/test/.git/config"}, respond_args={"response_data": self.git_config}
|
|
244
|
+
)
|
|
245
|
+
module_test.set_expect_requests(
|
|
246
|
+
expect_args={"uri": "/test/.git/branches/"}, respond_args={"response_data": self.empty_index}
|
|
247
|
+
)
|
|
248
|
+
module_test.set_expect_requests(
|
|
249
|
+
expect_args={"uri": "/test/.git/description"}, respond_args={"response_data": self.git_description}
|
|
250
|
+
)
|
|
251
|
+
module_test.set_expect_requests(
|
|
252
|
+
expect_args={"uri": "/test/.git/HEAD"}, respond_args={"response_data": self.git_head}
|
|
253
|
+
)
|
|
254
|
+
module_test.set_expect_requests(
|
|
255
|
+
expect_args={"uri": "/test/.git/hooks/"}, respond_args={"response_data": self.empty_index}
|
|
256
|
+
)
|
|
257
|
+
module_test.set_expect_requests(
|
|
258
|
+
expect_args={"uri": "/test/.git/info/"}, respond_args={"response_data": self.info_index}
|
|
259
|
+
)
|
|
260
|
+
module_test.set_expect_requests(
|
|
261
|
+
expect_args={"uri": "/test/.git/info/exclude"}, respond_args={"response_data": self.git_exclude}
|
|
262
|
+
)
|
|
263
|
+
module_test.set_expect_requests(
|
|
264
|
+
expect_args={"uri": "/test/.git/objects/"}, respond_args={"response_data": self.objects_index}
|
|
265
|
+
)
|
|
266
|
+
module_test.set_expect_requests(
|
|
267
|
+
expect_args={"uri": "/test/.git/objects/05/"}, respond_args={"response_data": self.objects_o5_index}
|
|
268
|
+
)
|
|
269
|
+
module_test.set_expect_requests(
|
|
270
|
+
expect_args={"uri": "/test/.git/objects/05/27e6bd2d76b45e2933183f1b506c7ac49f5872"},
|
|
271
|
+
respond_args={"response_data": self.filebytes_27e6bd2d76b45e2933183f1b506c7ac49f5872},
|
|
272
|
+
)
|
|
273
|
+
module_test.set_expect_requests(
|
|
274
|
+
expect_args={"uri": "/test/.git/objects/34/"}, respond_args={"response_data": self.objects_34_index}
|
|
275
|
+
)
|
|
276
|
+
module_test.set_expect_requests(
|
|
277
|
+
expect_args={"uri": "/test/.git/objects/34/dc86f0247798892a89553e7c5c2d5aa06c2c5b"},
|
|
278
|
+
respond_args={"response_data": self.filebytes_dc86f0247798892a89553e7c5c2d5aa06c2c5b},
|
|
279
|
+
)
|
|
280
|
+
module_test.set_expect_requests(
|
|
281
|
+
expect_args={"uri": "/test/.git/objects/c2/"}, respond_args={"response_data": self.objects_c2_index}
|
|
282
|
+
)
|
|
283
|
+
module_test.set_expect_requests(
|
|
284
|
+
expect_args={"uri": "/test/.git/objects/c2/69d751b8e2fd0be0d0dc7a6437a4dce4ec0200"},
|
|
285
|
+
respond_args={"response_data": self.filebytes_69d751b8e2fd0be0d0dc7a6437a4dce4ec0200},
|
|
286
|
+
)
|
|
287
|
+
module_test.set_expect_requests(
|
|
288
|
+
expect_args={"uri": "/test/.git/objects/info/"}, respond_args={"response_data": self.empty_index}
|
|
289
|
+
)
|
|
290
|
+
module_test.set_expect_requests(
|
|
291
|
+
expect_args={"uri": "/test/.git/objects/pack/"}, respond_args={"response_data": self.empty_index}
|
|
292
|
+
)
|
|
293
|
+
module_test.set_expect_requests(
|
|
294
|
+
expect_args={"uri": "/test/.git/refs/"}, respond_args={"response_data": self.refs_index}
|
|
295
|
+
)
|
|
296
|
+
module_test.set_expect_requests(
|
|
297
|
+
expect_args={"uri": "/test/.git/refs/heads/"}, respond_args={"response_data": self.refs_heads_index}
|
|
298
|
+
)
|
|
299
|
+
module_test.set_expect_requests(
|
|
300
|
+
expect_args={"uri": "/test/.git/refs/heads/master"}, respond_args={"response_data": self.refs_head}
|
|
301
|
+
)
|
|
302
|
+
module_test.set_expect_requests(
|
|
303
|
+
expect_args={"uri": "/test/.git/refs/tags/"}, respond_args={"response_data": self.empty_index}
|
|
304
|
+
)
|
|
305
|
+
module_test.set_expect_requests(
|
|
306
|
+
expect_args={"uri": "/test/.git/logs/"}, respond_args={"response_data": self.logs_index}
|
|
307
|
+
)
|
|
308
|
+
module_test.set_expect_requests(
|
|
309
|
+
expect_args={"uri": "/test/.git/logs/refs/"}, respond_args={"response_data": self.logs_refs_index}
|
|
310
|
+
)
|
|
311
|
+
module_test.set_expect_requests(
|
|
312
|
+
expect_args={"uri": "/test/.git/logs/refs/heads/"},
|
|
313
|
+
respond_args={"response_data": self.logs_refs_heads_index},
|
|
314
|
+
)
|
|
315
|
+
module_test.set_expect_requests(
|
|
316
|
+
expect_args={"uri": "/test/.git/logs/refs/heads/master"},
|
|
317
|
+
respond_args={"response_data": self.logs_master_head},
|
|
318
|
+
)
|
|
319
|
+
module_test.set_expect_requests(
|
|
320
|
+
expect_args={"uri": "/test/.git/logs/HEAD"}, respond_args={"response_data": self.logs_head}
|
|
321
|
+
)
|
|
322
|
+
|
|
323
|
+
def check(self, module_test, events):
|
|
324
|
+
assert any(
|
|
325
|
+
e.type == "CODE_REPOSITORY"
|
|
326
|
+
and "git-directory" in e.tags
|
|
327
|
+
and e.data["url"] == "http://127.0.0.1:8888/test/.git/"
|
|
328
|
+
for e in events
|
|
329
|
+
)
|
|
330
|
+
filesystem_events = [
|
|
331
|
+
e
|
|
332
|
+
for e in events
|
|
333
|
+
if e.type == "FILESYSTEM" and "http-127-0-0-1-8888-test-git" in e.data["path"] and "git" in e.tags
|
|
334
|
+
]
|
|
335
|
+
assert 1 == len(filesystem_events), "Failed to git clone CODE_REPOSITORY"
|
|
336
|
+
filesystem_event = filesystem_events[0]
|
|
337
|
+
folder = Path(filesystem_event.data["path"])
|
|
338
|
+
assert folder.is_dir(), "Destination folder doesn't exist"
|
|
339
|
+
with open(folder / "test.txt") as f:
|
|
340
|
+
content = f.read()
|
|
341
|
+
assert content == "This is a test\n", "File content doesn't match"
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
class TestGitDumper_NoDirlisting(TestGitDumper_Dirlisting):
|
|
345
|
+
async def setup_after_prep(self, module_test):
|
|
346
|
+
module_test.set_expect_requests(
|
|
347
|
+
expect_args={"uri": "/test/.git/index"}, respond_args={"response_data": self.filebytes_gitindex}
|
|
348
|
+
)
|
|
349
|
+
module_test.set_expect_requests(
|
|
350
|
+
expect_args={"uri": "/test/.git/COMMIT_EDITMSG"}, respond_args={"response_data": self.git_commit_editmsg}
|
|
351
|
+
)
|
|
352
|
+
module_test.set_expect_requests(
|
|
353
|
+
expect_args={"uri": "/test/.git/config"}, respond_args={"response_data": self.git_config}
|
|
354
|
+
)
|
|
355
|
+
module_test.set_expect_requests(
|
|
356
|
+
expect_args={"uri": "/test/.git/description"}, respond_args={"response_data": self.git_description}
|
|
357
|
+
)
|
|
358
|
+
module_test.set_expect_requests(
|
|
359
|
+
expect_args={"uri": "/test/.git/HEAD"}, respond_args={"response_data": self.git_head}
|
|
360
|
+
)
|
|
361
|
+
module_test.set_expect_requests(
|
|
362
|
+
expect_args={"uri": "/test/.git/info/exclude"}, respond_args={"response_data": self.git_exclude}
|
|
363
|
+
)
|
|
364
|
+
module_test.set_expect_requests(
|
|
365
|
+
expect_args={"uri": "/test/.git/objects/05/27e6bd2d76b45e2933183f1b506c7ac49f5872"},
|
|
366
|
+
respond_args={"response_data": self.filebytes_27e6bd2d76b45e2933183f1b506c7ac49f5872},
|
|
367
|
+
)
|
|
368
|
+
module_test.set_expect_requests(
|
|
369
|
+
expect_args={"uri": "/test/.git/objects/34/dc86f0247798892a89553e7c5c2d5aa06c2c5b"},
|
|
370
|
+
respond_args={"response_data": self.filebytes_dc86f0247798892a89553e7c5c2d5aa06c2c5b},
|
|
371
|
+
)
|
|
372
|
+
module_test.set_expect_requests(
|
|
373
|
+
expect_args={"uri": "/test/.git/objects/c2/69d751b8e2fd0be0d0dc7a6437a4dce4ec0200"},
|
|
374
|
+
respond_args={"response_data": self.filebytes_69d751b8e2fd0be0d0dc7a6437a4dce4ec0200},
|
|
375
|
+
)
|
|
376
|
+
module_test.set_expect_requests(
|
|
377
|
+
expect_args={"uri": "/test/.git/refs/heads/master"}, respond_args={"response_data": self.refs_head}
|
|
378
|
+
)
|
|
379
|
+
module_test.set_expect_requests(
|
|
380
|
+
expect_args={"uri": "/test/.git/logs/refs/heads/master"},
|
|
381
|
+
respond_args={"response_data": self.logs_master_head},
|
|
382
|
+
)
|
|
383
|
+
module_test.set_expect_requests(
|
|
384
|
+
expect_args={"uri": "/test/.git/logs/HEAD"}, respond_args={"response_data": self.logs_head}
|
|
385
|
+
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: bbot
|
|
3
|
-
Version: 2.3.2.
|
|
3
|
+
Version: 2.3.2.5938rc0
|
|
4
4
|
Summary: OSINT automation for hackers.
|
|
5
5
|
License: GPL-3.0
|
|
6
6
|
Keywords: python,cli,automation,osint,threat-intel,intelligence,neo4j,scanner,python-library,hacking,recursion,pentesting,recon,command-line-tool,bugbounty,subdomains,security-tools,subdomain-scanner,osint-framework,attack-surface,subdomain-enumeration,osint-tool
|
|
@@ -15,7 +15,7 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
15
15
|
Classifier: Programming Language :: Python :: 3.12
|
|
16
16
|
Classifier: Programming Language :: Python :: 3.13
|
|
17
17
|
Classifier: Topic :: Security
|
|
18
|
-
Requires-Dist: ansible (>=
|
|
18
|
+
Requires-Dist: ansible-core (>=2.15.13,<3.0.0)
|
|
19
19
|
Requires-Dist: ansible-runner (>=2.3.2,<3.0.0)
|
|
20
20
|
Requires-Dist: beautifulsoup4 (>=4.12.2,<5.0.0)
|
|
21
21
|
Requires-Dist: cachetools (>=5.3.2,<6.0.0)
|
|
@@ -367,16 +367,16 @@ bbot -t evilcorp.com evilcorp.org 1.2.3.0/24 -p subdomain-enum
|
|
|
367
367
|
|
|
368
368
|
Targets can be any of the following:
|
|
369
369
|
|
|
370
|
-
-
|
|
371
|
-
-
|
|
372
|
-
-
|
|
373
|
-
-
|
|
374
|
-
-
|
|
375
|
-
-
|
|
376
|
-
-
|
|
377
|
-
-
|
|
378
|
-
-
|
|
379
|
-
-
|
|
370
|
+
- DNS Name (`evilcorp.com`)
|
|
371
|
+
- IP Address (`1.2.3.4`)
|
|
372
|
+
- IP Range (`1.2.3.0/24`)
|
|
373
|
+
- Open TCP Port (`192.168.0.1:80`)
|
|
374
|
+
- URL (`https://www.evilcorp.com`)
|
|
375
|
+
- Email Address (`bob@evilcorp.com`)
|
|
376
|
+
- Organization (`ORG:evilcorp`)
|
|
377
|
+
- Username (`USER:bobsmith`)
|
|
378
|
+
- Filesystem (`FILESYSTEM:/tmp/asdf`)
|
|
379
|
+
- Mobile App (`MOBILE_APP:https://play.google.com/store/apps/details?id=com.evilcorp.app`)
|
|
380
380
|
|
|
381
381
|
For more information, see [Targets](https://www.blacklanternsecurity.com/bbot/Stable/scanning/#targets-t). To learn how BBOT handles scope, see [Scope](https://www.blacklanternsecurity.com/bbot/Stable/scanning/#scope).
|
|
382
382
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
bbot/__init__.py,sha256=
|
|
2
|
-
bbot/cli.py,sha256=
|
|
1
|
+
bbot/__init__.py,sha256=Aru214KorNuqpOkhOzn5hOGImv7I_W2SWOlM2XfGPU8,130
|
|
2
|
+
bbot/cli.py,sha256=H7L3yIoYuSpkrf1K1qqiBMQBTyt8UI9FfConpjqr7KI,11029
|
|
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
|
|
@@ -16,7 +16,7 @@ bbot/core/helpers/bloom.py,sha256=gk02rO6x3F5MICa7ZUDsinRudwoGAifsbiyiMCwd0Gs,27
|
|
|
16
16
|
bbot/core/helpers/cache.py,sha256=1aMr3HVD45cDtHEG5xlznDUCywRgO9oRFidscrs_5sA,1537
|
|
17
17
|
bbot/core/helpers/command.py,sha256=UBJa2RInEJtGjZ5e24PUQxPu1aTCIFkcCrrB0ERLdGI,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=0sEut_B1rJKEnlTJvtk6nsWv1_1hJsbDRsVzylidmYc,19774
|
|
20
20
|
bbot/core/helpers/depsinstaller/sudo_askpass.py,sha256=yGa2OQv30RO75QkMuG1iruKqb7amQxRVRRcHmvIeGhk,1276
|
|
21
21
|
bbot/core/helpers/diff.py,sha256=7pDibPTSsF_1_PoFypa8WvxbFDGeB_SGNzSyOEa1QQw,10791
|
|
22
22
|
bbot/core/helpers/dns/__init__.py,sha256=2JK8P0BUfPlh4CTuuOWQCOacwL7NEtGFYPJsxbA0Zwo,27
|
|
@@ -30,16 +30,16 @@ 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=r-FUL5zdZagmLjNd_F577IE1CrT22f5qPb69RQcEHD0,87452
|
|
33
|
-
bbot/core/helpers/names_generator.py,sha256=
|
|
33
|
+
bbot/core/helpers/names_generator.py,sha256=rJE6G-Brrgm1uFJUiCw2hseJVDGe4WfRZyCMeAcQ0lM,10314
|
|
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=fQp5mKfqfCkDkZzgntDu4NWlRsWSMCto0V8vaV8-34k,2115
|
|
37
|
-
bbot/core/helpers/regex.py,sha256=
|
|
37
|
+
bbot/core/helpers/regex.py,sha256=YCyvK78piK8p4YMTPH9hD1mILkZtPzLC0lNRf0vsj9g,4371
|
|
38
38
|
bbot/core/helpers/regexes.py,sha256=whzgjomHsXVvKtvXLS037EMPxT9RSOxdWukpUHY8Pfc,5818
|
|
39
39
|
bbot/core/helpers/url.py,sha256=1NDrvirODzzD6Mcssu-4WDNerMeMdekHCFzhRCS0m3g,5947
|
|
40
40
|
bbot/core/helpers/validators.py,sha256=RBRCWpU-tKvcThx-KnEePpWTjsIxfQ_CrPEUBmiqPF0,9695
|
|
41
41
|
bbot/core/helpers/web/__init__.py,sha256=pIEkL3DhjaGTSmZ7D3yKKYwWpntoLRILekV2wWsbsws,27
|
|
42
|
-
bbot/core/helpers/web/client.py,sha256=
|
|
42
|
+
bbot/core/helpers/web/client.py,sha256=12lKbyWJQpVKBnKGCuMNNUn47ifs1fsB02nebceX75Y,3591
|
|
43
43
|
bbot/core/helpers/web/engine.py,sha256=mzXpYmlB1pvNSXs8FuliGMv7myUwAcQWTtnMHqblMHA,8875
|
|
44
44
|
bbot/core/helpers/web/ssl_context.py,sha256=aWVgl-d0HoE8B4EBKNxaa5UAzQmx79DjDByfBw9tezo,356
|
|
45
45
|
bbot/core/helpers/web/web.py,sha256=sesBGwqXRmePwQIScfg8PbrlCPMArQVj55E1aJsWctI,23685
|
|
@@ -103,8 +103,9 @@ bbot/modules/filedownload.py,sha256=TOxftfxguaRSEKI8oG79XVRQqUGg1_IhYDYl_Jw9eYc,
|
|
|
103
103
|
bbot/modules/fingerprintx.py,sha256=rdlR9d64AntAhbS_eJzh8bZCeLPTJPSKdkdKdhH_qAo,3269
|
|
104
104
|
bbot/modules/fullhunt.py,sha256=zeehQb9akBSbHW9dF4icH8Vfd8LqoTrpIvnQEEMWes8,1311
|
|
105
105
|
bbot/modules/generic_ssrf.py,sha256=KFdcHpUV9-Z7oN7emzbirimsNc2xZ_1IFqnsfIkEbcM,9196
|
|
106
|
-
bbot/modules/git.py,sha256=
|
|
106
|
+
bbot/modules/git.py,sha256=zmHeI0bn181T1P8C55HSebkdVGLTpzGxPc-LRqiHrbc,1723
|
|
107
107
|
bbot/modules/git_clone.py,sha256=XFZXx0k97EMY3E5PZzdNvqQzZddOfRMaVp5ol2gk11s,2468
|
|
108
|
+
bbot/modules/gitdumper.py,sha256=XBYt6oSXm09FJVdH37zrn9T1Nhqc0zK4KLugMevedOw,11531
|
|
108
109
|
bbot/modules/github_codesearch.py,sha256=a-r2vE9N9WyBpFUiKCsg0TK4Qn7DaEGyVRTUKzkDLWA,3641
|
|
109
110
|
bbot/modules/github_org.py,sha256=WM18vJCHuOHJJ5rPzQzQ3Pmp7XPPuaMeVgNfW-FlO0k,8938
|
|
110
111
|
bbot/modules/github_workflows.py,sha256=RDtzR0DC2sqiWzMtiqlrCSwtZHWL2MoIJBKd6LVTAdI,9720
|
|
@@ -164,7 +165,7 @@ bbot/modules/paramminer_getparams.py,sha256=_j6rgaqV5wGJoa8p5-KKbe2YsVGUtmWIanCV
|
|
|
164
165
|
bbot/modules/paramminer_headers.py,sha256=CuiqT3nY3eIrZhT4CAEkRDfCbCYci8CmnXsippf3Qb4,10450
|
|
165
166
|
bbot/modules/passivetotal.py,sha256=uGT6c_CUxBNInmClsTg8afIYA2ZykKYYCgjkyzujfHg,1653
|
|
166
167
|
bbot/modules/pgp.py,sha256=Xu2M9WEIlwTm5-Lv29g7BblI05tD9Dl0XsYSeY6UURs,2065
|
|
167
|
-
bbot/modules/portfilter.py,sha256=
|
|
168
|
+
bbot/modules/portfilter.py,sha256=FB1plaBTZxiJnLJ8RiyPyc2Hrh7N7_DRSiyfeQEAfms,1723
|
|
168
169
|
bbot/modules/portscan.py,sha256=dM2p3tBGQKSdeZRMlCpOwqRpz0XJfIMwY2n3Ajaig_M,13441
|
|
169
170
|
bbot/modules/postman.py,sha256=vo761Nzu3kPBzfCY3KJcvsGEsjImaa7iA2z-LyASBDc,4589
|
|
170
171
|
bbot/modules/postman_download.py,sha256=LUB9cP-otkB1HaNACGS5YPwsxnwp1uSo28SpGvmQ60A,3467
|
|
@@ -333,6 +334,7 @@ bbot/test/test_step_2/module_tests/test_module_fullhunt.py,sha256=NblfNHQrE82j-c
|
|
|
333
334
|
bbot/test/test_step_2/module_tests/test_module_generic_ssrf.py,sha256=ZhfZpH0QTl6_YftGoZzZk6_2x0ZDnWjZ7vNZMTibBHw,3228
|
|
334
335
|
bbot/test/test_step_2/module_tests/test_module_git.py,sha256=gyBS3vZUWAyatGlcY26mGOYeqXSqJA5pbhJWgTmLqNo,1656
|
|
335
336
|
bbot/test/test_step_2/module_tests/test_module_git_clone.py,sha256=Mo0Q7bCXcrkGWJc3-u5y4sdfC13ei-qj79aKvEbnkk4,13198
|
|
337
|
+
bbot/test/test_step_2/module_tests/test_module_gitdumper.py,sha256=ya_eQUQk0344G7iqBYMls2z5H-bYM87rydbz-ACR2Ng,17461
|
|
336
338
|
bbot/test/test_step_2/module_tests/test_module_github_codesearch.py,sha256=M50xBiGG2EuPGXDJU6uFsSUE-fhqZl3CzYtNdszW7LM,4735
|
|
337
339
|
bbot/test/test_step_2/module_tests/test_module_github_org.py,sha256=5tKO6NH4TPBeIdeTf7Bz9PUZ1pcvKsjrG0nFhc3YgT0,25458
|
|
338
340
|
bbot/test/test_step_2/module_tests/test_module_github_workflows.py,sha256=o_teEaskm3H22QEKod5KJayFvvcgOQoG4eItGWv8C8E,38006
|
|
@@ -423,8 +425,8 @@ bbot/wordlists/raft-small-extensions-lowercase_CLEANED.txt,sha256=ZSIVebs7ptMvHx
|
|
|
423
425
|
bbot/wordlists/top_open_ports_nmap.txt,sha256=LmdFYkfapSxn1pVuQC2LkOIY2hMLgG-Xts7DVtYzweM,42727
|
|
424
426
|
bbot/wordlists/valid_url_schemes.txt,sha256=0B_VAr9Dv7aYhwi6JSBDU-3M76vNtzN0qEC_RNLo7HE,3310
|
|
425
427
|
bbot/wordlists/wordninja_dns.txt.gz,sha256=DYHvvfW0TvzrVwyprqODAk4tGOxv5ezNmCPSdPuDUnQ,570241
|
|
426
|
-
bbot-2.3.2.
|
|
427
|
-
bbot-2.3.2.
|
|
428
|
-
bbot-2.3.2.
|
|
429
|
-
bbot-2.3.2.
|
|
430
|
-
bbot-2.3.2.
|
|
428
|
+
bbot-2.3.2.5938rc0.dist-info/LICENSE,sha256=GzeCzK17hhQQDNow0_r0L8OfLpeTKQjFQwBQU7ZUymg,32473
|
|
429
|
+
bbot-2.3.2.5938rc0.dist-info/METADATA,sha256=JYgdVRHBmrMfy17beoLLQuzDtJJWpv8kcw6U2BgEDys,18218
|
|
430
|
+
bbot-2.3.2.5938rc0.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
|
|
431
|
+
bbot-2.3.2.5938rc0.dist-info/entry_points.txt,sha256=cWjvcU_lLrzzJgjcjF7yeGuRA_eDS8pQ-kmPUAyOBfo,38
|
|
432
|
+
bbot-2.3.2.5938rc0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|