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}

相关推荐
葡萄城技术团队2 小时前
1000 人协同压测的环境瓶颈排查:CPU 争用与 Wi\-Fi
前端
excel3 小时前
Marked 与 Markdown 有什么区别?该怎么选?
前端
Da Da 泓4 小时前
五子棋 Web 端测试用例报告
前端·网络·websocket·网络协议·测试用例·项目
zxcvb1535 小时前
远程查看本地文档:一条轻量 Web 文件服务的工程化链路
前端·远程查看文档
一木 之林5 小时前
Dify学习笔记 03 · RAG检索增强生成:三代范式、评估与落地(第40-45、55-56集)
笔记·小程序·交互·dify
niucloud-admin5 小时前
NIUCLOUD PHP SAAS上门家政使用文档:城市管理
java·前端·php
北岛贰6 小时前
啵啵音乐迎来全新升级!
前端
hkNaruto7 小时前
【AI】基于大模型的AI游戏地图生成、控制方案:AI Native Game Harness 迁移操作手册
前端·人工智能·游戏
IT_陈寒8 小时前
Java序列化踩坑记:对象循环引用让我加班两小时
前端·人工智能·后端
Acro8 小时前
快给macOS 上的Grok Bot换一套皮肤
前端