Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
125 commits
Select commit Hold shift + click to select a range
0098faf
new module: aspnet_bin_exposure
liquidsec Jan 28, 2025
1dc6716
adding aspnet_bin_exposure to dotnet-audit preset
liquidsec Jan 28, 2025
0f93014
formatting
liquidsec Jan 29, 2025
cea9cff
add confirmation check
liquidsec Jan 30, 2025
556ffbe
added scope_distance options for hunt module
Giardi77 May 17, 2025
5a12c26
Bump pytest-rerunfailures from 15.0 to 15.1
dependabot[bot] Jun 2, 2025
d5ce210
Bump pycryptodome from 3.22.0 to 3.23.0
dependabot[bot] Jun 2, 2025
e3c3270
Fix broken chromium on M4 Mac
mukesh-dream11 Jun 3, 2025
624a1e3
Respect PATH when searching for chrom(e/ium)
mukesh-dream11 Jun 3, 2025
cf719dd
Handle case where chrome_path is None
mukesh-dream11 Jun 5, 2025
3cfa286
Don't retry securitytrails ping API on HTTP 429
mukesh-dream11 Jun 5, 2025
badd72f
Remove binaryedge as it has been shut down
mukesh-dream11 Jun 5, 2025
860aab3
run docs script
invalid-email-address Jun 5, 2025
4e33a32
docs update
invalid-email-address Jun 5, 2025
87f1be0
Merge pull request #2491 from mukesh-dream11/fix/remove-binaryedge
TheTechromancer Jun 5, 2025
1335ff2
by default never retry 429s when pinging
invalid-email-address Jun 5, 2025
dab7b8c
chrome path tweaks
invalid-email-address Jun 5, 2025
5118cdc
fix test
invalid-email-address Jun 6, 2025
9b2c5cc
Update trufflehog
blsaccess Jun 7, 2025
4096edd
Merge pull request #2475 from blacklanternsecurity/update-trufflehog
TheTechromancer Jun 7, 2025
a87c83f
Respect --force-deps for common dependencies
mukesh-dream11 Jun 8, 2025
7b2d7de
Add chromium auto-install for Darwin
mukesh-dream11 Jun 8, 2025
a962e90
Fix failing tests
mukesh-dream11 Jun 8, 2025
dfef2c9
Fix linting error
mukesh-dream11 Jun 8, 2025
340ce4c
Merge pull request #2487 from mukesh-dream11/stable
TheTechromancer Jun 8, 2025
751d9e1
Merge pull request #2490 from mukesh-dream11/fix/securitytrails-fail-…
TheTechromancer Jun 9, 2025
1456bc6
ruthless
invalid-email-address Jun 10, 2025
28cfbd8
saucy, demonstrative
invalid-email-address Jun 10, 2025
33e391a
Merge pull request #2494 from blacklanternsecurity/rachael-adjectives
TheTechromancer Jun 11, 2025
0b1d720
Update trufflehog
blsaccess Jun 12, 2025
920b329
Merge pull request #2495 from blacklanternsecurity/update-trufflehog
TheTechromancer Jun 12, 2025
28c0d7d
Merge branch 'dev' into aspnet-bin-exposure
liquidsec Jun 13, 2025
24f1669
ruff format
liquidsec Jun 13, 2025
4c0a8c6
Merge branch 'dev' into dependabot/pip/dev/pycryptodome-3.23.0
liquidsec Jun 13, 2025
5f9e9b5
adding module test
liquidsec Jun 13, 2025
912d836
Merge pull request #2480 from blacklanternsecurity/dependabot/pip/dev…
liquidsec Jun 13, 2025
77d799c
add zip extention finding
liquidsec Jun 13, 2025
4fe7a74
correct naming of test
liquidsec Jun 13, 2025
2ddcc8b
removing scope_distance_modifier from hunt module
Giardi77 Jun 13, 2025
8fc3fa7
Merge branch 'dev' into dev
Giardi77 Jun 13, 2025
ea4b533
Delete pytest_debug.log
Giardi77 Jun 13, 2025
09e763d
Merge pull request #2457 from Giardi77/dev
TheTechromancer Jun 13, 2025
1ec28e3
testing for extension
liquidsec Jun 13, 2025
5f03718
Merge branch 'dev' into shortnames-zip
liquidsec Jun 13, 2025
f3f1c01
Merge pull request #2498 from blacklanternsecurity/shortnames-zip
liquidsec Jun 16, 2025
41586dc
use integrated deduping
liquidsec Jun 16, 2025
7740118
Merge pull request #2497 from blacklanternsecurity/aspnet-bin-exposure
liquidsec Jun 17, 2025
66167a7
Add "pensive" to adj, "trent" to names.
ausmaster Jun 18, 2025
852136c
Order.
ausmaster Jun 18, 2025
08ae6b7
Idk what.
ausmaster Jun 18, 2025
901a198
Merge pull request #2505 from blacklanternsecurity/add-pensive-trent
ausmaster Jun 18, 2025
e29c24c
Update trufflehog
blsaccess Jun 19, 2025
6b18b4a
update tldextract
invalid-email-address Jun 20, 2025
147eb07
Merge pull request #2507 from blacklanternsecurity/update-tldextract
TheTechromancer Jun 20, 2025
68a1415
Merge pull request #2501 from blacklanternsecurity/update-trufflehog
TheTechromancer Jun 20, 2025
2124bcc
add missing massdns dependency
invalid-email-address Jun 25, 2025
6034dd8
stringify command
invalid-email-address Jun 26, 2025
9c756ad
fix tests
invalid-email-address Jun 26, 2025
500d18d
Merge pull request #2511 from blacklanternsecurity/fix-dnscommonsrv
TheTechromancer Jun 26, 2025
936cc42
Add graphql introspection module
mukesh-dream11 Jul 1, 2025
242b046
Fix minor formatting error
mukesh-dream11 Jul 1, 2025
6704332
Add unit tests for graphql introspection module
mukesh-dream11 Jul 3, 2025
3025ae6
Fix minor formatting error
mukesh-dream11 Jul 3, 2025
a9fa97d
Add web-basic flag to graphql_introspection module
mukesh-dream11 Jul 3, 2025
8934884
clean temp dir on exit
invalid-email-address Jul 8, 2025
d069bd4
rm tree at exit
invalid-email-address Jul 8, 2025
1903313
clean temp dir at end of scan
invalid-email-address Jul 8, 2025
5903949
rename test
invalid-email-address Jul 8, 2025
fca6072
troubleshoot tests
invalid-email-address Jul 9, 2025
c68fcff
Merge pull request #2521 from blacklanternsecurity/clean-temp-dir-on-…
TheTechromancer Jul 9, 2025
d18d766
download git repos, docker images etc. to scan-specific temp folder
invalid-email-address Jul 11, 2025
6286c47
remove debugs
invalid-email-address Jul 14, 2025
a4201ba
Merge pull request #2524 from blacklanternsecurity/clean-temp-dir-on-…
TheTechromancer Jul 14, 2025
1f0df63
Merge remote-tracking branch 'origin/dev' into feat/graphql-introspec…
mukesh-dream11 Jul 15, 2025
28e1b6e
improve dedup filtering
invalid-email-address Jul 17, 2025
e984b37
tagify filename
invalid-email-address Jul 17, 2025
51ebdbc
Bump ruff from 0.11.11 to 0.12.4
dependabot[bot] Jul 21, 2025
4123e73
add openssl dev dependency
invalid-email-address Jul 23, 2025
43ac113
add xz
invalid-email-address Jul 23, 2025
4e56edd
missing_ok=True
invalid-email-address Jul 23, 2025
1d0b3de
fix string truncation bug
invalid-email-address Jul 23, 2025
79aedaf
fix tests
invalid-email-address Jul 23, 2025
bee1126
Merge pull request #2540 from blacklanternsecurity/fix-unlink-bug
TheTechromancer Jul 23, 2025
b611548
Merge pull request #2541 from blacklanternsecurity/fix-httpx-bug
TheTechromancer Jul 23, 2025
c9c0b11
Merge pull request #2539 from blacklanternsecurity/fix-medusa
TheTechromancer Jul 23, 2025
92496ed
Update trufflehog
blsaccess Jul 24, 2025
ecfc461
upgrade gowitness
invalid-email-address Jul 24, 2025
535deee
Merge pull request #2533 from blacklanternsecurity/dependabot/pip/dev…
TheTechromancer Jul 24, 2025
062b48b
Merge pull request #2529 from blacklanternsecurity/update-trufflehog
TheTechromancer Jul 24, 2025
460b0e6
Merge pull request #2515 from mukesh-dream11/feat/graphql-introspection
TheTechromancer Jul 24, 2025
05744d0
Merge pull request #2543 from blacklanternsecurity/upgrade-gowitness
TheTechromancer Jul 25, 2025
4995303
Bump lxml from 5.4.0 to 6.0.0
dependabot[bot] Jul 28, 2025
f1b977f
Bump mkdocs-material from 9.6.12 to 9.6.16
dependabot[bot] Jul 28, 2025
cab7a6e
Bump orjson from 3.10.16 to 3.11.1
dependabot[bot] Jul 28, 2025
33d308f
run ansible tasks after all the other deps
invalid-email-address Jul 28, 2025
386034f
Merge pull request #2549 from blacklanternsecurity/fix-deps-common
TheTechromancer Jul 28, 2025
e636d9a
Merge pull request #2546 from blacklanternsecurity/dependabot/pip/dev…
TheTechromancer Jul 30, 2025
6d91592
Bump urllib3 from 2.4.0 to 2.5.0
dependabot[bot] Aug 4, 2025
d303fb3
fixing TestNucleiSevere
liquidsec Aug 11, 2025
99101eb
fixing nuclei.py path
liquidsec Aug 11, 2025
595d30e
re-remove deadly folder
liquidsec Aug 11, 2025
c36d808
Merge pull request #2556 from blacklanternsecurity/nuclei-fixes
liquidsec Aug 11, 2025
8905ec4
Merge branch 'dev' into remove-deadly-folder
liquidsec Aug 11, 2025
03a9428
Merge branch 'dev' into nuclei-updater-fix
liquidsec Aug 11, 2025
ea3caa7
Merge branch 'dev' into dependabot/pip/dev/urllib3-2.5.0
liquidsec Aug 11, 2025
6c2592b
Merge branch 'dev' into dependabot/pip/dev/mkdocs-material-9.6.16
liquidsec Aug 11, 2025
6cb8b56
Merge pull request #2558 from blacklanternsecurity/remove-deadly-folder
liquidsec Aug 11, 2025
b747224
Merge pull request #2557 from blacklanternsecurity/nuclei-updater-fix
liquidsec Aug 11, 2025
31865a4
Merge branch 'dev' into dependabot/pip/dev/orjson-3.11.1
liquidsec Aug 11, 2025
147cf7d
update doc
liquidsec Aug 11, 2025
1b78e1c
cleanup
liquidsec Aug 11, 2025
63480b8
Merge pull request #2547 from blacklanternsecurity/dependabot/pip/dev…
liquidsec Aug 11, 2025
aa1a71b
Merge branch 'dev' into dependabot/pip/dev/urllib3-2.5.0
liquidsec Aug 11, 2025
ba9cc28
Bump uvicorn from 0.34.2 to 0.35.0
dependabot[bot] Aug 11, 2025
a16cbf9
Merge pull request #2479 from blacklanternsecurity/dependabot/pip/dev…
liquidsec Aug 11, 2025
096b04d
Merge pull request #2548 from blacklanternsecurity/dependabot/pip/dev…
liquidsec Aug 11, 2025
30efe17
Merge pull request #2550 from blacklanternsecurity/dependabot/pip/dev…
liquidsec Aug 11, 2025
6f41859
Merge pull request #2514 from blacklanternsecurity/dependabot/pip/dev…
liquidsec Aug 11, 2025
39b732b
Bump setproctitle from 1.3.5 to 1.3.6
dependabot[bot] Aug 11, 2025
1675814
Bump poetry-dynamic-versioning from 1.7.1 to 1.9.1
dependabot[bot] Aug 11, 2025
edc2d69
Merge pull request #2477 from blacklanternsecurity/dependabot/pip/dev…
liquidsec Aug 12, 2025
a18efeb
Merge pull request #2528 from blacklanternsecurity/dependabot/pip/dev…
liquidsec Aug 12, 2025
bce3ab4
bump version
TheTechromancer Aug 12, 2025
5e3ed11
Merge pull request #2560 from blacklanternsecurity/bump-version
TheTechromancer Aug 12, 2025
f4da38f
Merge pull request #2559 from blacklanternsecurity/update-yara-doc
liquidsec Aug 12, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/version_updater.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,12 @@ jobs:
- name: Get current version
id: get-current-version
run: |
version=$(grep -m 1 -oP '(?<=version": ")[^"]*' bbot/modules/deadly/nuclei.py)
version=$(grep -m 1 -oP '(?<=version": ")[^"]*' bbot/modules/nuclei.py)
echo "current_version=$version" >> $GITHUB_ENV
- name: Update version
id: update-version
if: env.latest_version != env.current_version
run: "sed -i '0,/\"version\": \".*\",/ s/\"version\": \".*\",/\"version\": \"${{ env.latest_version }}\",/g' bbot/modules/deadly/nuclei.py"
run: "sed -i '0,/\"version\": \".*\",/ s/\"version\": \".*\",/\"version\": \"${{ env.latest_version }}\",/g' bbot/modules/nuclei.py"
- name: Create pull request to update the version
if: steps.update-version.outcome == 'success'
uses: peter-evans/create-pull-request@v7
Expand All @@ -50,7 +50,7 @@ jobs:
commit-message: "Update nuclei"
title: "Update nuclei to ${{ env.latest_version }}"
body: |
This PR uses https://api.github.com/repos/projectdiscovery/nuclei/releases/latest to obtain the latest version of nuclei and update the version in bbot/modules/deadly/nuclei.py."
This PR uses https://api.github.com/repos/projectdiscovery/nuclei/releases/latest to obtain the latest version of nuclei and update the version in bbot/modules/nuclei.py."

# Release notes:
${{ env.release_notes }}
Expand Down
7 changes: 5 additions & 2 deletions bbot/core/helpers/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ async def run_live(self, *command, check=False, text=True, idle_timeout=None, **
proc.send_signal(SIGINT)
raise
except ValueError as e:
command_str = " ".join([str(c) for c in command])
command_str = " ".join(command)
log.warning(f"Error executing command {command_str}: {e}")
log.trace(traceback.format_exc())
continue
Expand Down Expand Up @@ -185,7 +185,9 @@ async def _spawn_proc(self, *command, **kwargs):
try:
command, kwargs = self._prepare_command_kwargs(command, kwargs)
except SubprocessError as e:
log.warning(e)
command_str = " ".join([str(s) for s in command])
log.warning(f"Error running command: '{command_str}': {e}")
log.trace(traceback.format_exc())
return None, None, None
_input = kwargs.pop("input", None)
if _input is not None:
Expand Down Expand Up @@ -279,6 +281,7 @@ def _prepare_command_kwargs(self, command, kwargs):

if len(command) == 1 and isinstance(command[0], (list, tuple)):
command = command[0]

command = [str(s) for s in command]

if not command:
Expand Down
64 changes: 58 additions & 6 deletions bbot/core/helpers/depsinstaller/installer.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,20 @@ class DepsInstaller:
"bash": "bash",
"which": "which",
"tar": "tar",
"xz": [
{
"name": "Install xz-utils (Debian)",
"package": {"name": ["xz-utils"], "state": "present"},
"become": True,
"when": "ansible_facts['os_family'] == 'Debian'",
},
{
"name": "Install xz (Non-Debian)",
"package": {"name": ["xz"], "state": "present"},
"become": True,
"when": "ansible_facts['os_family'] != 'Debian'",
},
],
# debian why are you like this
"7z": [
{
Expand All @@ -53,6 +67,44 @@ class DepsInstaller:
"when": "ansible_facts['distribution'] == 'Fedora'",
},
],
# to compile just about any tool, we need the openssl dev headers
"openssl": [
{
"name": "Install OpenSSL library and development headers (Debian/Ubuntu)",
"package": {"name": ["libssl-dev", "openssl"], "state": "present"},
"become": True,
"when": "ansible_facts['os_family'] == 'Debian'",
"ignore_errors": True,
},
{
"name": "Install OpenSSL library and development headers (RedHat/CentOS/Fedora)",
"package": {"name": ["openssl", "openssl-devel"], "state": "present"},
"become": True,
"when": "ansible_facts['os_family'] == 'RedHat' or ansible_facts['os_family'] == 'Suse' ",
"ignore_errors": True,
},
{
"name": "Install OpenSSL library and development headers (Arch)",
"package": {"name": ["openssl"], "state": "present"},
"become": True,
"when": "ansible_facts['os_family'] == 'Archlinux'",
"ignore_errors": True,
},
{
"name": "Install OpenSSL library and development headers (Alpine)",
"package": {"name": ["openssl", "openssl-dev"], "state": "present"},
"become": True,
"when": "ansible_facts['os_family'] == 'Alpine'",
"ignore_errors": True,
},
{
"name": "Install OpenSSL library and development headers (FreeBSD)",
"package": {"name": ["openssl"], "state": "present"},
"become": True,
"when": "ansible_facts['os_family'] == 'FreeBSD'",
"ignore_errors": True,
},
],
}

def __init__(self, parent_helper):
Expand Down Expand Up @@ -171,11 +223,6 @@ async def install_module(self, module):
success = True
preloaded = self.all_modules_preloaded[module]

# ansible tasks
ansible_tasks = preloaded["deps"]["ansible"]
if ansible_tasks:
success &= self.tasks(module, ansible_tasks)

# apt
deps_apt = preloaded["deps"]["apt"]
if deps_apt:
Expand All @@ -196,7 +243,7 @@ async def install_module(self, module):
deps_common = preloaded["deps"]["common"]
if deps_common:
for dep_common in deps_common:
if self.setup_status.get(dep_common, False) is True:
if self.setup_status.get(dep_common, False) is True and self.deps_behavior != "force_install":
log.debug(
f'Skipping installation of dependency "{dep_common}" for module "{module}" since it is already installed'
)
Expand All @@ -206,6 +253,11 @@ async def install_module(self, module):
self.setup_status[dep_common] = result
success &= result

# ansible tasks
ansible_tasks = preloaded["deps"]["ansible"]
if ansible_tasks:
success &= self.tasks(module, ansible_tasks)

return success

async def pip_install(self, packages, constraints=None):
Expand Down
12 changes: 7 additions & 5 deletions bbot/core/helpers/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -831,7 +831,9 @@ def rand_string(length=10, digits=True, numeric_only=False):
return "".join(random.choice(pool) for _ in range(length))


def truncate_string(s, n):
def truncate_string(s: str, n: int) -> str:
if not isinstance(s, str):
raise ValueError(f"Expected string, got {type(s)}")
if len(s) > n:
return s[: n - 3] + "..."
else:
Expand Down Expand Up @@ -1309,7 +1311,7 @@ def make_netloc(host, port=None):
return f"{host}:{port}"


def which(*executables):
def which(*executables, path=None):
"""Finds the full path of the first available executable from a list of executables.

Args:
Expand All @@ -1325,7 +1327,7 @@ def which(*executables):
import shutil

for e in executables:
location = shutil.which(e)
location = shutil.which(e, path=path)
if location:
return location

Expand Down Expand Up @@ -1642,7 +1644,7 @@ def filesize(f):
return 0


def rm_rf(f):
def rm_rf(f, ignore_errors=False):
"""Recursively delete a directory

Args:
Expand All @@ -1653,7 +1655,7 @@ def rm_rf(f):
"""
import shutil

shutil.rmtree(f)
shutil.rmtree(f, ignore_errors=ignore_errors)


def clean_old(d, keep=10, filter=lambda x: True, key=latest_mtime, reverse=True, raise_error=False):
Expand Down
5 changes: 5 additions & 0 deletions bbot/core/helpers/names_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
"delicious",
"demented",
"demonic",
"demonstrative",
"depraved",
"depressed",
"deranged",
Expand Down Expand Up @@ -172,6 +173,7 @@
"pasty",
"peckish",
"pedantic",
"pensive",
"pernicious",
"perturbed",
"perverted",
Expand Down Expand Up @@ -201,8 +203,10 @@
"reckless",
"reductive",
"ripped",
"ruthless",
"sadistic",
"satanic",
"saucy",
"savvy",
"scheming",
"schizophrenic",
Expand Down Expand Up @@ -668,6 +672,7 @@
"tracy",
"travis",
"treebeard",
"trent",
"triss",
"tyler",
"tyrell",
Expand Down
2 changes: 1 addition & 1 deletion bbot/core/helpers/web/engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ async def _acatch(self, url, raise_error):
raise
else:
log.warning(
f"Invalid URL (possibly due to dangerous redirect) on request to : {url}: {truncate_string(e, 200)}"
f"Invalid URL (possibly due to dangerous redirect) on request to : {url}: {truncate_string(str(e), 200)}"
)
log.trace(traceback.format_exc())
except ssl.SSLError as e:
Expand Down
38 changes: 38 additions & 0 deletions bbot/core/shared_deps.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,24 @@
"when": "ansible_facts['os_family'] == 'Debian'",
"ignore_errors": True,
},
{
"name": "Get latest Chromium version (Darwin x86_64)",
"uri": {
"url": "https://www.googleapis.com/download/storage/v1/b/chromium-browser-snapshots/o/Mac%2FLAST_CHANGE?alt=media",
"return_content": True,
},
"register": "chromium_version_darwin_x86_64",
"when": "ansible_facts['os_family'] == 'Darwin' and ansible_facts['architecture'] == 'x86_64'",
},
{
"name": "Get latest Chromium version (Darwin arm64)",
"uri": {
"url": "https://www.googleapis.com/download/storage/v1/b/chromium-browser-snapshots/o/Mac_Arm%2FLAST_CHANGE?alt=media",
"return_content": True,
},
"register": "chromium_version_darwin_arm64",
"when": "ansible_facts['os_family'] == 'Darwin' and ansible_facts['architecture'] == 'arm64'",
},
{
"name": "Download Chromium (Debian)",
"unarchive": {
Expand All @@ -119,6 +137,26 @@
"when": "ansible_facts['os_family'] == 'Debian'",
"ignore_errors": True,
},
{
"name": "Download Chromium (Darwin x86_64)",
"unarchive": {
"src": "https://www.googleapis.com/download/storage/v1/b/chromium-browser-snapshots/o/Mac%2F{{ chromium_version_darwin_x86_64.content }}%2Fchrome-mac.zip?alt=media",
"remote_src": True,
"dest": "#{BBOT_TOOLS}",
"creates": "#{BBOT_TOOLS}/chrome-mac",
},
"when": "ansible_facts['os_family'] == 'Darwin' and ansible_facts['architecture'] == 'x86_64'",
},
{
"name": "Download Chromium (Darwin arm64)",
"unarchive": {
"src": "https://www.googleapis.com/download/storage/v1/b/chromium-browser-snapshots/o/Mac_Arm%2F{{ chromium_version_darwin_arm64.content }}%2Fchrome-mac.zip?alt=media",
"remote_src": True,
"dest": "#{BBOT_TOOLS}",
"creates": "#{BBOT_TOOLS}/chrome-mac",
},
"when": "ansible_facts['os_family'] == 'Darwin' and ansible_facts['architecture'] == 'arm64'",
},
# Because Ubuntu is a special snowflake, we have to bend over backwards to fix the chrome sandbox
# see https://chromium.googlesource.com/chromium/src/+/main/docs/security/apparmor-userns-restrictions.md
{
Expand Down
2 changes: 1 addition & 1 deletion bbot/modules/apkpure.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ async def setup(self):
if output_folder:
self.output_dir = Path(output_folder) / "apk_files"
else:
self.output_dir = self.helpers.temp_dir / "apk_files"
self.output_dir = self.scan.temp_dir / "apk_files"
self.helpers.mkdir(self.output_dir)
return await super().setup()

Expand Down
80 changes: 80 additions & 0 deletions bbot/modules/aspnet_bin_exposure.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
from bbot.modules.base import BaseModule


class aspnet_bin_exposure(BaseModule):
watched_events = ["URL"]
produced_events = ["VULNERABILITY"]
flags = ["active", "safe", "web-thorough"]
meta = {
"description": "Check for ASP.NET Security Feature Bypasses (CVE-2023-36899 and CVE-2023-36560)",
"created_date": "2025-01-28",
"author": "@liquidsec",
}

in_scope_only = True
test_dlls = [
"Telerik.Web.UI.dll",
"Newtonsoft.Json.dll",
"System.Net.Http.dll",
"EntityFramework.dll",
"AjaxControlToolkit.dll",
]

@staticmethod
def normalize_url(url):
return str(url.rstrip("/") + "/").lower()

def _incoming_dedup_hash(self, event):
return hash(self.normalize_url(event.data))

async def handle_event(self, event):
normalized_url = self.normalize_url(event.data)
for test_dll in self.test_dlls:
for technique in ["b/(S(X))in/###DLL_PLACEHOLDER###/(S(X))/", "(S(X))/b/(S(X))in/###DLL_PLACEHOLDER###"]:
test_url = f"{normalized_url}{technique.replace('###DLL_PLACEHOLDER###', test_dll)}"
self.debug(f"Sending test URL: [{test_url}]")
kwargs = {"method": "GET", "allow_redirects": False, "timeout": 10}
test_result = await self.helpers.request(test_url, **kwargs)
if test_result:
if test_result.status_code == 200 and (
"content-type" in test_result.headers
and "application/x-msdownload" in test_result.headers["content-type"]
):
self.debug(
f"Got positive result for probe with test url: [{test_url}]. Status Code: [{test_result.status_code}] Content Length: [{len(test_result.content)}]"
)

if test_result.status_code == 200 and (
"content-type" in test_result.headers
and "application/x-msdownload" in test_result.headers["content-type"]
):
confirm_url = (
f"{normalized_url}{technique.replace('###DLL_PLACEHOLDER###', 'oopsnotarealdll.dll')}"
)
confirm_result = await self.helpers.request(confirm_url, **kwargs)

if confirm_result and (
confirm_result.status_code != 200
or not (
"content-type" in confirm_result.headers
and "application/x-msdownload" in confirm_result.headers["content-type"]
)
):
description = f"IIS Bin Directory DLL Exposure. Detection Url: [{test_url}]"
await self.emit_event(
{
"severity": "HIGH",
"host": str(event.host),
"url": normalized_url,
"description": description,
},
"VULNERABILITY",
event,
context="{module} detected IIS Bin Directory DLL Exposure vulnerability",
)
return True

async def filter_event(self, event):
if "dir" in event.tags:
return True
return False
Loading
Loading