corCTF vouch:时间侧信道分析
vouch( 时间分析攻击)
#!/usr/bin/env python3
from flask import Flask, render_template, request
import hashlib, hmac, binascii
import random
try:
from secret import FLAG
except ImportError:
FLAG = "FLAG{EXAMPLE_FLAG}"
app = Flask(__name__)
PBKDF2_ITERATIONS = 1750000
DKLEN = 32
def generate_voucher() -> str:
length = 12
dash_positions = [1, 4, 8]
chars = []
for i in range(length):
if i in dash_positions:
chars.append('-')
else:
chars.append(random.choice("ABCDEF0123456789"))
return ''.join(chars)
VOUCHER_CODE = generate_voucher() # 随机生成,如 "A1B2-C3D-E4F5"
print(f"[DEBUG] Voucher code: {VOUCHER_CODE}")
def calculate_signature(password: str, salt: str) -> str:
return binascii.hexlify(
hashlib.pbkdf2_hmac("sha256", password.encode(), salt.encode(), PBKDF2_ITERATIONS, dklen=DKLEN)
).decode()
@app.route("/")
def index():
return render_template("index.html")
@app.route("/check", methods=["POST"])
def check():
j = request.get_json(force=True)
voucher = j.get("voucher", "")
signature = j.get("signature", "")
if len(voucher) != len(VOUCHER_CODE):
return "Code incorrect"
for i, ch in enumerate(voucher):
if VOUCHER_CODE[i] != ch:
return "Code incorrect"
# Tampering protection
ua = request.headers.get("User-Agent", "")
expected = calculate_signature(voucher, ua)
if not hmac.compare_digest(signature, expected):
return "Tampering detected"
return f"See you at corCTF 2026, your ticket is: {FLAG}"
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8000, debug=False)
/check接口
| 情况 | 执行次数(循环内) | 调用 calculate_signature 次数 |
|---|---|---|
| 第 0 位错 | 循环 1 次 → 在 (A) 返回 | 0 次 |
| 第 0 位对,第 1 位错 | 循环 2 次 → 第 2 次在 (A) 返回 | 1 次 |
| 前 2 位对,第 3 位错 | 循环 3 次 → 第 3 次在 (A) 返回 | 2 次 |
| ... | ... | ... |
| 全部正确 | 循环 12 次 → 通过所有检查 | 12 - 3 = 9 次(因为 - 位置不进签名?其实进了,但不影响) |
每次循环都调用
calculate_signature(voucher, ua)
而这个函数要跑 1,750,000 次 PBKDF2 迭代 → 耗时 几百毫秒
结论:响应时间 ∝ 已匹配的前缀长度
约束:
- 必须提供合法
signature,否则被 (B) 拦截 signature = PBKDF2(voucher, User-Agent, ...)
我们可以:
- 固定
User-Agent(比如"jazzzzzzzzzzzzzzzzzz") - 对每个猜测的
voucher,自己算出 signature - 发送完整合法请求
- 测量响应时间 → 时间越长,说明匹配前缀越长