分析这段代码 找到漏洞
Tạo vào: 8 tháng 1, 2026
Trả lời bằng GPT-5.2 Thinking bởi Chat01
Tạo vào: 8 tháng 1, 2026
Trả lời bằng GPT-5.2 Thinking bởi Chat01
分析这段代码 找到漏洞
下面按“可利用漏洞/成因/修复建议”把这段服务端代码里最关键的问题梳理出来(我会把最可打的那条绕过链路也讲清楚)。
服务端登录时会计算 hashed = gethash(username, password),然后遍历所有账号的 hashed_users,只要 hash 相等就直接把对应账号 k 当成登录用户返回,完全不要求“你提交的 username == k”。见:for k,v in hashed_users.items(): if hashed == v: data={"user":k,...} (main.py)
影响: 只要你能构造出某个账号的 hash(哪怕不提交那个账号名),就能直接被当成那个账号登录。
修复:
username 定位到用户记录,然后只验证该用户的密码(而不是遍历全表比 hash)。gethash() 用“MD5 + XOR”导致线性可抵消,且 admin 的 hash 固定为 0gethash(*items) 把每个 item 做 md5(salt + "[" + item + "]" + salt),然后用 XOR 累起来 (main.py)。
同时代码强制 users["admin"] == "admin" (main.py),所以:
hashed_users["admin"] = gethash("admin","admin")"0")也就是说:只要你让 gethash(username,password) == "0",就会在遍历时命中 admin,拿到真正 flag(因为 k == "admin" 才返回 FLAG)(main.py)。
修复:
bcrypt/argon2/scrypt 存储密码哈希;或者用 HMAC(salt, username || password) 之类的不可伪造结构(但密码存储仍推荐专用 KDF)。NaN 绕过“用户名=密码”检测,且仍能把 hash 变成 0登录时有两条拦截:
"admin" (main.py)username == password (main.py)但这里用的是 Python 的 json.loads,它默认接受非标准 JSON 常量 NaN/Infinity。如果你让解密后的 params 里:
json{"username": NaN, "password": NaN}
那么在 Python 里这两者是 float('nan'),而 nan == nan 为 False,所以第二条“相等”检测不会触发 (main.py)。
接着 gethash 里对 item 用 f-string,会把两个 NaN 都转成字符串 "nan",于是 XOR 两次同一 MD5 又抵消成 0 (main.py),最终命中 admin,返回真正 flag (main.py)。
这条链路不需要知道 salt,也不需要做 MD5 碰撞,就是纯逻辑漏洞。
修复:
json.loads(..., parse_constant=...) 直接抛错,或换用严格 JSON 解析器/配置为不接受 NaN。username/password 类型必须是 str,并且做格式/长度约束。eval(...) 混淆执行,偷偷篡改 base64 行为代码在启动时执行了一句巨大 eval(int.to_bytes(...).decode()...) (main.py)。这属于不必要且高风险的动态执行:无论当前字符串是否固定,这种模式本身就是“后门温床”。
更关键的是,它会让下面这个“decrypt”看起来在 b64encode,实际行为可能被替换/劫持(它本来就写得很怪)(main.py)。
修复:
eval 与混淆逻辑。print(params) 会把登录凭据打印到日志里,容易泄露 (main.py)Content-Length 不做上限,self.rfile.read(...) 可被大包 DoS (main.py)“只用 hash 全表匹配 + XOR 可抵消 + JSON NaN 绕过相等校验” 这三者组合,直接导致无需 admin 用户名/无需 salt/无需碰撞即可命中 hashed_users["admin"] 并拿到 flag。相关关键代码点分别在 (main.py)、(main.py)、(main.py)。
如果你想让我把“如何在本地复现(构造 params 的 5 层 base64 编码并发请求)”写成一段最小 PoC(只针对这份代码/CTF 环境),我也可以直接给。