ctf show web入门110

这是一道典型的 PHP 代码审计与绕过题(通常出现在 CTF 比赛中)。题目核心在于通过 eval() 函数执行任意代码以获取 Flag。

执行点:

php 复制代码
eval("echo new $v1($v2());");

但是v1v2都被正则限制

被禁用的字符包括:绝大多数特殊符号(包括括号 ()、分号 ;、美元符号 KaTeX parse error: Undefined control sequence: \、 at position 6: 、反斜杠 \̲、̲引号等)以及所有数字 [0-9...v1 和 $v2 中只能包含纯英文字母。

致命细节:注意到 v2 在 eval 中是以 v2() 的形式被调用的,而正则中禁用了括号 ()。因此,我们不能在 v2 的输入中自带括号,必须让它保持纯字母,依赖代码原本自带的 () 执行。例如,若 v2 = 'phpinfo',则会被解析执行为 phpinfo()

因为受到严格的字母限制无法使用 system() 等需要传参的函数,我们必须利用 PHP 的内置类 来读取文件

我们需要寻找一个满足以下条件的 PHP 内置类:

类名完全由纯字母组成(配合 $v1)。

其构造函数接受一个字符串参数。

或者是可以通过 echo 直接输出该对象的实例(即该类实现了 __toString() 魔术方法)。

核心武器:FilesystemIterator 或 GlobIterator

FilesystemIterator:用于遍历文件系统目录。

GlobIterator:可以通过匹配模式遍历文件目录(支持通配符 *)。

当使用 echo 打印这些类的实例时,它们会默认返回当前目录下的第一个文件名。

  1. 具体构造与构造链步骤
    第一步:查看当前目录下的文件
    由于 v2 会以 v2() 形式执行,我们需要找到一个不需要参数、返回值为字符串或可用路径的内置函数。

getcwd:这是一个完美的函数。getcwd() 不需要参数,返回当前工作目录的绝对路径(字符串)。

如果我们传入:

v1 = FilesystemIterator

v2 = getcwd

eval 实际执行的语句将是:

php 复制代码
echo new FilesystemIterator(getcwd());

发现有一个文件名为fl36dga.txt的我们尝试访问

这里直接在原url后加上文件名就可以访问

在原 URL 后面加上 fl36dga.txt 就能直接访问,这并不是因为题目代码执行了什么逻辑,而是因为 Web 服务器(如 Apache、Nginx)的核心工作原理。

我们可以把这个过程拆解为两个层面:

  1. Web 服务器的"文件映射"机制(为什么能直接访问)
    当你访问一个网站时(例如 http://example.com/),Web 服务器的后台其实对应着服务器硬盘上的一个具体文件夹(通常称为 Web 根目录,比如 /var/www/html/)。

当你访问 http://example.com/index.php 时,服务器就会去根目录下找到 index.php 这个文件,通过 PHP 解释器执行它,然后把结果发给你的浏览器。

同理,如果你在上一阶段通过漏洞发现了当前目录下还有一个叫 flag.php 的文件,你直接在浏览器输入 http://example.com/flag.php,Web 服务器就会绕过原本的 index.php,直接去读取并执行 flag.php。

这就是为什么你不需要再去研究怎么构造复杂的 Payload,直接修改 URL 就能访问它的原因。

  1. 为什么有时候直接访问 flag.php 却看不到 Flag?
    虽然你可以直接访问它,但在实际的 CTF 比赛中,你大概率会遇到以下两种情况:

情况 A:页面是一片空白

原因:flag.php 内部的代码通常是这样写的:

PHP
<?php $flag = "flag{this_is_a_fake_flag}"; ?>

或者它只是把 Flag 赋值给了一个变量,但没有使用 echo 或 print 把它打印出来。

结果:Web 服务器确实执行了这个文件,但因为代码没有输出任何内容,所以你看到的浏览器页面是一片空白。

情况 B:权限被拒绝(403 Forbidden)或找不到(404 Not Found)

原因:出题人为了防止你"爆破文件名直接下载",通常会把 flag.php 放在 Web 根目录之外(例如放在 / 根目录下,或者 /var/ 目录下)。

结果:这时候,Web 服务器的 URL 根本无法直接映射到这个文件。你通过浏览器无论怎么输入 URL 都访问不到它。

总结:什么时候该用什么方法?

因此,在得到 Flag 的文件名或路径后,最稳妥的思路是:

先尝试直接访问:在 URL 后面直接改成 flag.php。如果出题人偷懒,Flag 直接写在 HTML 里面,或者直接 echo 出来了,你就能直接秒杀此题(右键查看网页源代码防止被浏览器隐藏)。

如果直接访问失败(空白或403):说明必须通过题目自带的漏洞去读取文件内容。这时候就需要用上一步提到的 SplFileObject 配合 session_id() 的方法,强行让后台代码把 flag.php 的内部源码读出来并打印在网页上。

相关推荐
用户9385156350712 小时前
从零在浏览器里跑 DeepSeek-R1:WebGPU + Transformers.js 全链路实战(三)
前端·react.js·typescript
excel12 小时前
当前端行情变差,我们为什么还要坚持?
前端
鸿是江边鸟,曾是心上人13 小时前
快速搭建HTTPS本地开发环境
前端
摇滚侠13 小时前
《SpringBoot 3:入门与应用实战》第 2 章 IOC 思想与实现 阅读笔记 1
spring boot·笔记·后端
To_OC13 小时前
写了 5 个表单 Demo 后,我终于彻底搞懂了 React 受控与非受控组件
前端·react.js·前端框架
Sterting14 小时前
第9课 Vue Router 路由
前端·vue.js
用户0595401744614 小时前
LangChain Memory 测试踩坑实录:用 pytest 自动化回归对话记忆,我折腾了整整一个周末
前端·css
kyriewen14 小时前
Claude Code后天起默认Auto模式了——我第一时间改了这6个设置
前端·ai编程·claude
LuminousCPP14 小时前
数据结构-双向循环链表
c语言·数据结构·笔记·链表