← 返回首页

corCTF vouch:时间侧信道分析

2025-12-05

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 迭代 → 耗时 几百毫秒

结论:响应时间 ∝ 已匹配的前缀长度

约束:

我们可以:

  1. 固定 User-Agent(比如 "jazzzzzzzzzzzzzzzzzz")
  2. 对每个猜测的 voucher,自己算出 signature
  3. 发送完整合法请求
  4. 测量响应时间 → 时间越长,说明匹配前缀越长