Created
April 22, 2023 15:02
-
-
Save mnixry/6a4c8735792de6c42533cd2196be780d to your computer and use it in GitHub Desktop.
DASCTF 2023, dump leaked directory
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import asyncio | |
import re | |
from pathlib import Path | |
from urllib.parse import urljoin, urlparse | |
from anyio import open_file | |
from httpx import AsyncClient | |
from loguru import logger | |
MATCH_QUOTES = re.compile(r'["\'](.*?)["\']') | |
PARALLEL = 4 | |
HOST = "http://114.117.174.147:18886" | |
ENTRY_FILE = "app.js" | |
SAVE_DIRECTORY = Path("./website") | |
touched_paths = set[str]() | |
client = AsyncClient(base_url=HOST, http2=True) | |
sem = asyncio.Semaphore(PARALLEL) | |
def enum_paths(basic_path: str): | |
return [ | |
basic_path, | |
f"{basic_path}.js", | |
f"{basic_path}/index.js", | |
] | |
async def get_file_content(path): | |
logger.debug(f"Getting file: {path!r}") | |
async with sem: | |
resp = await client.get(path) | |
if not resp.is_success: | |
return | |
logger.info(f"Found file: {path!r}, size {len(resp.content)}") | |
await save_file(path, resp.content) | |
strings = [matched[1] for matched in MATCH_QUOTES.finditer(resp.text)] | |
possible_paths = [] | |
for string in strings: | |
parsed_path = urlparse(urljoin(str(resp.url), string)) | |
if parsed_path.hostname != urlparse(HOST).hostname: | |
continue | |
basic_path = parsed_path.path | |
if basic_path in touched_paths: | |
continue | |
touched_paths.add(basic_path) | |
paths = [ | |
*enum_paths(basic_path), | |
*enum_paths(basic_path.rstrip("/")), | |
*enum_paths("/api/" + basic_path.lstrip("/")), | |
] | |
basic_path = basic_path.lstrip("/") | |
possible_paths.extend(paths) | |
await asyncio.gather( | |
*[get_file_content(path) for path in possible_paths], return_exceptions=True | |
) | |
@logger.catch | |
async def save_file(path: str, content: bytes): | |
save_path = SAVE_DIRECTORY / path.replace("//", "/").lstrip("/") | |
save_path.parent.mkdir(parents=True, exist_ok=True) | |
async with await open_file(save_path, "wb") as file: | |
await file.write(content) | |
if __name__ == "__main__": | |
asyncio.run(get_file_content(ENTRY_FILE)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment