ctf show web入门98

这是一道经典的 PHP 变量覆盖(Variable Coverage)与三元运算符特性的 CTF 题目。代码看似杂乱,但核心考点在于理解 PHP 的变量引用、三元运算符的优先级以及如何让代码走向输出 flag 的分支。

以下是详细的解题思路和分析:

  1. 核心源码分析
    我们逐行拆解最关键的 4 行 PHP 代码:
php 复制代码
14: include("flag.php");
15: $_GET?$_GET=&$_POST:'flag';
16: $_GET['flag']=='flag'?$_GET=&$_COOKIE:'flag';
17: $_GET['flag']=='flag'?$_GET=&$_SERVER:'flag';
18: highlight_file($_GET['HTTP_FLAG']=='flag'?$flag:__FILE__);

注:图片中的 Notice 提示第 15, 16, 17 行报错,是因为我们没有通过 GET、COOKIE 或 SERVER 传参,导致对应的键值未定义。

关键点一:PHP 三元运算符的缺陷

在 PHP 中,三元运算符 ? : 是从左向右(left-associative)结合的,而且在这个题目的特殊写法中,它其实充当了一个条件分支。

例如第 15 行:
GET?(_GET ? (GET?(_GET = &$_POST) : 'flag';

意思是:如果 _GET 数组不为空(即我们发起了 GET 请求),那么就会执行 KaTeX parse error: Expected 'EOF', got '\&' at position 8: _GET = \&̲_POST(将 _GET 变为 KaTeX parse error: Expected 'EOF', got '&' at position 23: ...引用)。 关键点二:引用传递(&̲)的连环套

第 15 行:一旦我们发送了任意 GET 参数,_GET 就变成了 _POST 的引用。此时,修改 _GET 就等于修改 POST。第16行:如果满足条件,_POST。 第 16 行:如果满足条件,POST。第16行:如果满足条件,_GET 变为 _COOKIE 的引用。因为第 15 行的关系,此时 _POST 也变成了 _COOKIE 的引用。

第 17 行:同理,如果满足条件,最终 GET、_GET、GET、_POST、_COOKIE 都会通过引用的链条指向 _SERVER。

  1. 逆推解题步骤

我们的最终目标是让第 18 行的 highlight_file 输出 $flag:

php 复制代码
highlight_file($_GET['HTTP_FLAG']=='flag' ? $flag : __FILE__);

所以,必须满足的最终条件是:$_GET['HTTP_FLAG'] == 'flag'。

为了达到这个目标,我们需要从后往前逆推每一步的条件:

步骤三:突破第 17 行

php 复制代码
$_GET['flag']=='flag' ? $_GET=&$_SERVER : 'flag';

目标:我们希望进入 KaTeX parse error: Expected 'EOF', got '&' at position 8: _GET = &̲_SERVER 这一步。

条件:需要当前的 GET[′flag′]==′flag′。结果:一旦成功,_GET['flag'] == 'flag'。 结果:一旦成功,GET[′flag′]==′flag′。结果:一旦成功,_GET 就会指向 _SERVER 数组。而在 _SERVER 数组中,通常只要我们发送一个自定义的 HTTP 请求头 HTTP_FLAG: flag,PHP 就会自动将其解析为 $_SERVER['HTTP_FLAG'] = 'flag'。这正好完美契合了最终第 18 行的要求!

步骤二:突破第 16 行

php 复制代码
$_GET['flag']=='flag' ? $_GET=&$_COOKIE : 'flag';

目标:为了让第 17 行的 _GET\['flag'\] 依然等于 'flag',我们需要在这一步让 _GET 变为 COOKIE的引用,并且在COOKIE中传入flag=flag。条件:进入这一步前,_COOKIE 的引用,并且在 COOKIE 中传入 flag=flag。 条件:进入这一步前,COOKIE的引用,并且在COOKIE中传入flag=flag。条件:进入这一步前,_GET['flag'] 必须等于 'flag'。

步骤一:起点(第 15 行)

php 复制代码
$_GET ? $_GET=&$_POST : 'flag';

目标:开启这个链条。我们需要发送一个 GET 请求,让 _GET 变为 _POST 的引用。

条件:带上任意 GET 参数(为了后面几行能判断,直接带上 ?flag=flag 即可)。

  1. 最终 Payload 构造

根据上面的逆推,我们需要同时在 GET、POST、COOKIE、HTTP Headers 中传入对应的参数,形成一个完美的传参链条:

GET 参数:?flag=flag

作用:触发第 15 行,使 _GET 变为 _POST 的引用。同时让第 16 行的 $_GET['flag']=='flag' 成立。

POST 参数:flag=flag

作用:此时 _GET 已经是 POST的引用了。第16行成立后,_POST 的引用了。第 16 行成立后,POST的引用了。第16行成立后,_GET(即当前的 _POST)变为 _COOKIE 的引用。为了让第 17 行的 _GET['flag']=='flag' 成立,我们需要 POST 里也有 flag=flag。

COOKIE 参数:HTTP_FLAG=flag

![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/7f60cf735b374e1491029c467fb5e01e.png

作用:第 17 行成立后,_GET 彻底变成了 _SERVER 的引用。

HTTP 请求头(Headers):添加 HTTP_FLAG: flag(或者 Http-Flag: flag,PHP 解析后会变成 HTTP_FLAG)

作用:让 SERVER[′HTTPFLAG′]==′flag′成立,从而触发highlightfile(_SERVER['HTTP_FLAG'] == 'flag' 成立,从而触发 highlight_file(SERVER[′HTTPFLAG′]==′flag′成立,从而触发highlightfile(flag)。

flag为:ctfshow{7391f0f0-d866-49ba-a8cf-d28586bdb98e}

相关推荐
sheeta19982 小时前
LeetCode 每日一题笔记 日期:2026.05.18 题目:1345. 跳跃游戏 IV
笔记·leetcode·游戏
贵州数擎科技有限公司2 小时前
雨滴特效的 Three.js 实现
前端·three.js
irving同学462382 小时前
Drizzle ORM + PostgreSQL + Hono 学习笔记
前端·后端
明豆2 小时前
HTTPS / TLS 1.3 深度解析 — Web 安全传输协议生产实战
前端·安全·https
Linsk2 小时前
Rollup 官方插件 @rollup/plugin-inject 详解
前端·rollup.js·前端工程化
2601_958492552 小时前
Performance Audit of Paper Boats Racing - HTML5 Racing Game
前端·html·html5
irving同学462382 小时前
TypeScript 后端入门全景:Hono + Zod + Drizzle + PostgreSQL
前端·后端
一致性2 小时前
项目总结:桌宠(Desktop Pet)
前端
李斯维2 小时前
Jetpack 生命周期组件 Lifecycle 的设计思想和使用
android·android studio·android jetpack