You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CTF Web:如何向端点发送特定请求体以获取Flag

问题分析与解决方法

你的代码无法成功的核心原因是:客户端生成的哈希与服务端验证所需的哈希完全无关。

服务端的验证逻辑是:在接收请求后,生成自己的60位随机字符串,拼接当前服务端的Unix时间戳,计算SHA256哈希,再与你发送的__字段对比。而你的代码是用本地生成的随机字符串+本地时间戳计算哈希,两者的随机值和时间戳都不匹配,自然无法通过验证。

正确思路:预测服务端的哈希生成逻辑

要通过验证,你需要精确复现服务端生成random() . time()的过程,从而计算出正确的哈希值。关键在于利用PHP rand()函数的可预测性(针对低版本PHP)和服务端时间戳的同步。

步骤1:模拟PHP低版本的rand()函数

PHP 7.0及以下版本的rand()基于线性同余生成器(LCG),默认用系统时间戳作为种子。我们可以在Python中复现这个生成逻辑:

def php_lcg_rand(seed, min_val, max_val):
    # PHP LCG的官方参数
    a = 1103515245
    c = 12345
    mod = 2**31
    seed = (a * seed + c) % mod
    return (seed % (max_val - min_val + 1)) + min_val, seed

def simulate_php_random(timestamp, length=60):
    characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
    char_count = len(characters)
    seed = timestamp  # PHP默认用time()作为rand的种子
    random_str = ''
    for _ in range(length):
        rand_val, seed = php_lcg_rand(seed, 0, char_count - 1)
        random_str += characters[rand_val]
    return random_str

步骤2:获取服务端的时间戳

通过HTTP响应头的Date字段获取服务端的当前时间,转换为Unix时间戳:

def get_server_timestamp(url):
    response = requests.get(url)
    date_header = response.headers.get('Date')
    from datetime import datetime
    import pytz
    # 解析HTTP Date头为UTC时间戳
    dt = datetime.strptime(date_header, '%a, %d %b %Y %H:%M:%S %Z')
    dt_utc = dt.replace(tzinfo=pytz.UTC)
    return int(dt_utc.timestamp())

步骤3:生成正确哈希并发送请求

由于网络延迟,需要尝试服务端时间戳前后1秒的范围,确保覆盖服务端处理请求的时间:

import requests
import hashlib
import json

def get_correct_hash(server_timestamp):
    random_val = simulate_php_random(server_timestamp)
    data_to_hash = random_val + str(server_timestamp)
    return hashlib.sha256(data_to_hash.encode()).hexdigest()

def request():
    url = "http://206.189.50.236:1337"
    server_ts = get_server_timestamp(url)
    # 尝试前后1秒的时间戳,覆盖网络延迟
    for ts in [server_ts -1, server_ts, server_ts +1]:
        generated_hash = get_correct_hash(ts)
        payload = {"__": generated_hash}
        response = requests.post(url, json=payload)
        print(f"尝试时间戳 {ts}:")
        print(response.text)
        if 'FLAG{' in response.text:
            print("\n已获取到Flag!")
            break

request()

针对PHP 7.1+版本的补充说明

如果服务端使用PHP 7.1+,rand()会使用Mersenne Twister算法,预测难度更高。此时需要借助专门的工具(如php_mt_seed)来破解种子,但前提是需要获取多个rand()的输出样本——而本题中服务端并未泄露随机字符串,因此大概率题目使用的是低版本PHP。

内容的提问来源于stack exchange,提问作者Smokem

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 03:44:58