基于 2026 年 2 月 4 日的 CTFshow Web 入门(web29–web38)练习记录,对命令执行与文件包含类题目进行一次系统的方法论总结与思路抽象。


一、整体题型识别思路

今天的题目几乎全部围绕两个核心漏洞展开:

  • 命令执行(Command Execution)
  • 文件包含(File Inclusion)

判断题型时,我主要关注以下几个信号:

  1. 是否存在 eval() / system() / passthru() / include() 等危险函数
  2. 用户可控参数(如 $_GET['c'])是否直接参与执行或包含
  3. 是否存在 preg_match 黑名单过滤(而非白名单)

👉 一旦出现 “用户输入 + eval/include + 黑名单”,基本可以直接进入绕过思路阶段。


二、命令执行题的通用解题框架

1️⃣ 第一步:确认执行能力

典型代码结构:

if(isset($_GET['c'])){
eval($_GET['c']);
}

这类题的第一目标不是 flag,而是确认:

  • 能否执行 PHP 代码?
  • 能否执行系统命令?

常见测试方式(择一):

  • phpinfo();
  • system('ls');
  • passthru('ls');

2️⃣ 第二步:定位 flag 文件

即使知道有命令执行,也不要盲目 cat flag,而是:

  • ls
  • 再确定 flag 的文件名与路径

这一步我主要用了两种方式:

  • 手工:ls -la
  • 工具:dirsearch

👉 经验总结:工具不是替代思考,而是节省试错成本


3️⃣ 第三步:系统化绕过黑名单

CTFshow 的命令执行题,本质是在不断升级 preg_match 规则。

我的应对策略是:不死磕某一个 payload,而是准备“绕过工具箱”

🔹(1)文件名绕过(绕 flag)

  • 通配符:f* / fla?
  • 字符拼接:"f"."lag"
  • 变量拼接:$a='fla';$b='g';

🔹(2)命令绕过(绕 cat / system)

  • cattac
  • systempassthru / exec
  • 反引号执行(未被禁用时)

🔹(3)空格绕过

  • %09(tab)
  • ${IFS}(高级场景)

🔹(4)编码绕过

  • base64_decode + eval

4️⃣ 第四步:PHP 语言特性利用

这是 web32 之后难度明显提升的关键点。

✅ 省略括号调用函数

include$_GET[a]

等价于:

include($_GET[a])

👉 这是 PHP 的历史设计特性,在高强度过滤下非常好用。


三、文件包含题的通用解题框架

从 web37 开始,题型从 eval 过渡到 include,但危险等级并没有下降

1️⃣ 文件包含 ≠ 安全

include($c);
echo $flag;

虽然没有代码执行函数,但:

  • include 会解析 PHP
  • 可以通过 伪协议 注入 PHP 代码

2️⃣ 核心武器:PHP 伪协议

🔥 data://

?c=data://text/plain,<?php system("tac fla*.php")?>

原理:

  • data:// 允许直接在 URI 中嵌入数据
  • include 会把数据当成 PHP 代码解析

3️⃣ 短标签绕过

php 被过滤时:

<?=system("tac fla*")?>

这是 PHP 的短 echo 标签,同样会被解析。


四、黑名单过滤的本质问题

通过今天这一整组题,可以非常清晰地看到:

黑名单过滤是注定失败的防御方式

原因很简单:

  • 关键字可以拼接
  • 函数可以替代
  • 语法可以等价变形
  • 编码可以再编码

CTF 的这些题,本质是在训练:

攻击者如何比防御者更了解语言本身


五、个人方法论总结

今天这一批题,最大的收获不是 payload,而是思路:

  1. 先判断题型,再想绕过
  2. 绕不过规则,就绕过语法
  3. 把 payload 拆成“功能模块”来组合
  4. 对 PHP 特性保持敬畏(和利用)

当过滤规则越来越复杂时,说明出题人已经在提示:
该换思路了,而不是继续硬刚关键字。


六、后续提升方向

接下来我会重点补充:

  • 无回显命令执行
  • disable_functions 场景
  • LD_PRELOAD / 环境变量利用
  • 真实 WebShell 写入

今天就先到这里 🎵

CTF 不在于一把梭,而在于每一题都留下些什么到自己的工具箱里