CTF Web入门:从Secret File到php://filter利用链完整解析
CTF Web方向入门题里Secret File 这类题目出现频率非常高。它本身不考多深的知识点但给新手造成了一个很经典的困惑明明页面里藏着线索却不知道下一步怎么办好不容易找到文件拿到一串编码又不知道怎么处理。这篇题解会把完整链路拆开讲从点开题目页面的第一眼到最终拿到 flag每一步背后的判断依据是什么都会说清楚。如果你刚开始接触 Web 方向的 CTF或者做这类题总是卡在某一步这篇内容应该能帮你把整条思路串起来。其实这类题目的内核特别朴素信息收集、源码审计、文件读取、编码转换。难点不在某个单独环节而在于把几个环节串成一条线。很多新手不是不会用某个函数而是不知道“什么时候该用”。所以我会用一场完整的解题过程来演示顺便把踩过的坑也列出来。1. 信息收集入口往往藏在你不注意的地方1.1 打开场景后的第一眼拿到题目环境后我第一件事不是急着乱点而是先整体扫一遍页面。当年做这道题时页面结构非常简单一张普通的背景图一行文字提示除此之外没有任何输入框或者按钮。这种极度简洁的页面在 CTF 里通常只有两种可能一种是漏洞在后续交互里另一种是入口就藏在前端代码中。先按 F12 打开开发者工具从 Elements 面板看页面结构。这里的核心思维是题目方不会把漏洞直接摆在页面上但前端代码是必须交付给浏览器的所以任何隐藏的链接、注释掉的提示、奇怪的标签都会在这里露出马脚。很多新手一上来就在 URL 后面手动改参数反而忽略了最基础的 HTML 源码信息收集。看源码时要关注三个点注释、超链接、还有内联事件。注释里经常直接写提示比如“到这里看看”之类超链接则可能指向一个不显眼的路由内联事件和隐藏表单也会暴露后端参数。在这道题里源码中确实存在一个被注释标记的链接这也是整道题的突破口。1.2 顺着链接进入下一层发现源码里的链接后先别急着点击要观察链接的路径和参数格式。把鼠标悬停在链接上浏览器底部状态栏会显示目标地址。这道题里的链接指向一个看起来像入口文件的地址同时也带了一个查询参数比如 index.php 后面跟着一个 id 或者 file 之类的键名。此时记录下这个参数名后面很可能就是注入点。点击链接后页面发生了跳转。跳转本身不重要重要的是跳转后的页面长什么样。我遇到的这个场景跳转后的页面同样是一张图片和一个文字提示没有任何交互元素。但再次查看源码时发现页面的注释文本里出现了一段提示大意是“看不到你仔细看看”同时留下了一个相对路径或者文件名。到这一步信息收集阶段算是完成了。核心收获有两个一个入口文件或隐藏文件的地址一个可能用于读取的后端参数名。这两条信息在后面会合并成一条完整的利用链。这里也想多说一句CTF 的 Web 题尤其是入门题逻辑链通常很短只要耐心地把每个页面的源码看完大多数入口都能找得到真正的分水岭在于你敢不敢逐层点下去。提示养成“每到一个页面都要看源码”的习惯。哪怕是空白页也要看一下 HTML 结构有时题目会故意把关键文件藏在空白注释里。2. 源码审计确定漏洞类型比直接打更重要2.1 从页面观察切换到代码思维拿到上一层的隐藏文件地址后直接访问发现页面返回了一段 PHP 代码的片段或者跳转逻辑。这段代码往往就是整个题目的核心。很多新手到这里就卡住了因为页面上根本没有 flag 的字样。但这里有一个关键的思维转换页面给你看的代码只是前端输出的那一小部分。如果后端存在文件包含、文件读取类的逻辑那么你看到的代码可能就是漏洞本身。比如我在这道题里看到的页面HTML 主体里嵌着一小段 PHP 逻辑它做的事情是接收某个 GET 参数然后把另一个文件的内容包含进来或者输出出来。看到这段代码后要立刻判断这是一个典型的文件读取点初判为任意文件读取或者本地文件包含。如果是 include 一类函数那么后续甚至可以直接读取 PHP 源文件如果是 file_get_contents 再输出那就要找文件路径来读取目标文件。这里建议的做法是把代码里的关键函数圈出来。include、require、file_get_contents、fopen、readfile 这几个函数只要参数来自用户输入就存在被利用的可能性。接下来要判断的点是后端是否对参数值做了过滤。常见的过滤包括不允许出现点号、斜杠、伪协议关键字等。这道题从表面代码看比较“朴素”没有额外过滤直接接收参数并包含文件。这也给后续构造 payload 提供了很高的自由度。2.2 为什么说这是 file 漏洞的核心理解 file 漏洞的核心需要先想明白一个场景一个网站为了让某个页面能显示不同内容会把内容放在不同文件里然后用一个参数决定加载哪一个。这种做法本身不一定是坏事问题出在它没有控制参数范围。如果参数可以被用户指定为任意路径那攻击者就能把服务器上任意文件的内容拉出来。这道题背后的原理就是如此。它先把入口隐藏在一个文件里访问该文件后文件内通过 include 包含了你传入的另一个文件。看到这里我的第一反应是能不能直接包含 flag 文件。但在实际尝试前要先考虑一个限制直接包含一个 PHP 文件时文件内的 PHP 代码会被执行而不是显示源代码。如果 flag 是用 PHP 变量定义的直接包含可能什么都看不到。这时候就必须引入伪协议来解决问题。php://filter 是一个非常实用的流封装协议它可以对文件内容做一步处理再输出。我们常用的是 convert.base64-encode也就是先读取目标文件的原始内容再转成 base64 编码输出。这样即使目标文件是 PHP 源码也不会被服务器执行而是以编码后的文本形式返回给我们解码之后就能看到完整的源代码。提示看到“把文件包含进来”这种代码不要只想到“把文件读出来”。要分清楚直接包含和编码读取的区别二者面对 PHP 文件时结果完全不同。3. 漏洞利用一条 payload 从构造到落地3.1 构造读取目标文件的请求现在手头有两个已知条件漏洞点在某个入口页面参数名是 file目标文件大概率是 flag.php 或者 flag.txt 之类的文件名。第一步就是构造最基础的读取请求。如果你不知道文件名可以先读当前文件自身或者读一个明确存在的文件比如入口页面文件名来验证读取功能确实可以生效。在验证阶段我用的是 php://filter 配合 base64 的方式。如果入口页面的文件名为 index.php那么请求构造如下入口页面路径?filephp://filter/readconvert.base64-encode/resourceindex.php发送请求后页面上没有直接显示 PHP 源码而是返回了一长串包含大小写字母、数字和等号的字符串。这个现象基本就能确认两点一是 file 参数确实能控制被读取的文件二是服务器执行了我们的伪协议把文件内容做了 base64 转换。这里需要解释一下为什么用 base64 而不是直接输出。因为服务器端如果直接 include index.php那么该文件会被当作 PHP 执行输出结果是执行后的 HTML而不是源码。而经过 base64 编码后文件原始内容会以文本形式输出源码细节全部保留。这也是 CTF 中读取源码最常用的手段。3.2 解码不是随便找个工具就行拿到 base64 字符串后新手经常犯的错是把整个字符串复制到在线解密工具里结果发现内容乱码或者不完整。这里有两个非常实际的注意点一是服务器返回的字符串可能包含 HTML 标签的包裹比如页面结构的外层 div 或者 PHP 错误提示复制时不要带上这些杂讯二是 base64 内容有时会因为页面输出被截断需要观察末尾是否有完整的填充符号。解码之后我看到了 index.php 的完整源码。源码里进一步提示了另一个文件的名字也就是真正的 flag 文件。这里再次强调一个细节如果 flag 文件以 .php 结尾直接包含是无法看到内容的必须继续使用伪协议读取。于是第二次请求把 resource 后的文件名改成新的目标文件。假设目标文件是 flag.php请求如下入口页面路径?filephp://filter/readconvert.base64-encode/resourceflag.php返回的 base64 字符串解码后就能看到 flag.php 的源代码。flag 一般定义成一个变量或常量内容格式通常是 flag{...} 或者类似的自定义格式。到这一步题目就已经基本解出来了。3.3 编码页面的细节处理在实际操作中还有几个容易忽略的细节会直接影响结果。第一URL 中的参数值如果包含特殊字符需要做 URL 编码。比如 php://filter 中的冒号、斜杠在某些环境下会被前端组件或 WAF 拦截。出现这种情况时可以把 : 换成 %3a把 / 换成 %2f比如?filephp%3a%2f%2ffilter%2fread%3dconvert.base64-encode%2fresource%3dflag.php第二有些题目会对 file 参数做简单的关键词过滤比如屏蔽 select、resource、convert 等字样。如果遇到这种情况可以尝试大小写混合、双写、换行编码等方式。不过这道题比较友好没有做过滤所以直接构造即可。第三如果读取后返回的空内容或者页面报告文件不存在那可能是文件名猜错了。可以回过去再看源码有时文件名藏在注释里或者带有路径前缀比如 ./flag.php 或 templates/flag.php。多留意路径层级问题往往就出在这里。注意遇到 base64 字符串较长时不要直接肉眼判断有没有读完建议复制到本地文件中用命令解避免页面渲染时自动换行导致的格式问题。命令行解码在多数环境下都很稳定。4. 常见问题与排查实录4.1 最常见卡点被跳转绕晕这类题里有一个非常经典的陷阱入口链接会先跳到一个无关键词的关注页如果这个页面本身还有一个隐藏链接很多新手会在第一步跳转后误以为题目卡死直接放弃。我一开始也差点漏掉原因是跳转后的页面看起来和首页几乎一样都属于“一张图一句话”的风格。排查的方法很简单遇到任何跳转后的页面马上再看一次源码并且不要只看可见文本还要看注释区块。这道题的关键线索其实就在注释里如果只看渲染后的页面永远也发现不了下一步。另外有些跳转是通过 JavaScript 定时器或 location 实现的这类跳转不会发生在看到源码之前。如果页面还没有加载完就被自动跳走可以在浏览器设置里禁用 JavaScript或者直接看抓包记录用工具截获中间页面的响应内容。熟练之后直接在 Burp 的 History 里就能看到每一次跳转的请求和响应效率更高。4.2 base64 解码出现乱码解码结果乱码大概率是因为复制内容里混入了页面结构标签。比如 base64 字符串前后有div或空格在线解码器会把它们一并解析结果自然混乱。处理技巧是选中有疑问的字符串先观察它是不是只包含 base64 字符集A-Z a-z 0-9 / 以及末尾的 。如果发现明显的 HTML 标签就要把杂讯剔除。另外有些浏览器会折叠很长的字符串复制时容易漏掉中间部分导致解码结果残缺。我的习惯是把完整响应保存下来再用命令行工具处理。echo 完整base64字符串 | base64 -d这样能避免手动选中漏字符的问题。4.3 伪协议被过滤时的绕过思路如果题目在 file 参数上加了过滤直接构造伪协议会被拦截。常见的过滤方式是拦截字符串 convert、base64、filter、resource甚至是php://这个整体。面对这种情况有一个基础且非常实用的方向寻找可用的替代协议或者利用包含逻辑本身的特性。比如filter 被限制时可以先尝试直接读取不包含 PHP 代码的文件例如用filephp://filter/resourceflag.txt如果 target 是纯文本文件不经过 base64 也能正常返回内容。如果目标必须是 PHP 文件那可以思考能不能用 include 把已经生成的缓存文件包含进来或者通过日志注入的方式写文件再包含。这些属于进阶思路。对于入门题更常见的做法是大小写绕过把 Convert、BASE64 做大小写混写因为 PHP 的流封装器对大小写并不敏感而过滤规则往往只匹配固定小写。另外如果过滤规则是基于黑名单检测子串双写也可能有效。例如检测到 filter 后直接把它替换为空那么构造php://filterfilter/readconvert.base64-encode/resourceflag.php过滤后变成php://filter/...反而顺利通过。不过这类绕过方式在不同题目中差异较大最好先做一个基础探测确认过滤的生效位置再决定用哪种绕过方式。4.4 快速判断漏洞类型的小表格为了帮助新手快速对号入座我把这类题常见的情况整理成一个速查表。看到相应特征时可以直接参考应对方案页面特征可疑代码模式首选利用方式最终目标页面有隐藏链接指向另一个 PHP 文件include/$filephp://filter 读源码找到下一个文件跳转页注释里有路径提示注释文本包含文件名直接访问该文件锁定漏洞参数参数传入后页面回显文件内容include/$filebase64 伪协议读取源码flag 通常定义在 PHP 文件里直接访问 PHP 文件看不到变量变量赋值后无输出filter 编码后解码看到完整源码返回乱码或夹杂标签响应混入 HTML用命令行解码排除杂讯干扰这个表格适合贴在自己的笔记里。Web 入门题很大一部分就是在代码层面做“确认漏洞类型”的动作一旦你养成了“看到 include 就想到伪协议看到参数就想到路径拼接”的习惯后续做题速度会有明显提升。5. 赛后复盘这套打法还能延伸到哪些地方5.1 从题目场景迁移到实际业务很多人觉得 CTF 里的套路离开了比赛就不适用但这类文件读取问题在实际业务场景中同样存在。比如某个后台管理系统通过参数切换皮肤包、语言包或者快速预览某个模板文件参数没有做白名单限制就可能被用来读取服务端其他文件。理解了这套逻辑后你会更容易理解其他相关漏洞的原理。比如任意文件下载、目录遍历、日志包含本质上都和“用户可控的文件路径”有关。学会 php://filter 的用法相当于掌握了读取 PHP 源码的钥匙而不再把 Web 题单纯理解为“找到 flag”。5.2 给新手的三个持续训练建议第一个建议是多看源码。不是说把源码背下来而是看到一段代码后能快速定位其中可被控制的输入。做题时把每个参数都当作“可能被利用”的对象逐个尝试比漫无目的地乱扫更有效。第二个建议是建立自己的 payload 速查表。php://filter 的写法、常见的绕过方式、日志包含的方法整理成笔记用的时候直接翻。不要企图一次记住所有内容能查得到也是一种能力。我第一次接触伪协议时也不知道 convert.base64-encode 这个写法是反复查文档才记牢的。第三个建议是学会用工具但不依赖工具。Burp Suite 肯定要会但前端源码和注释信息用手动查看反而更直观。对于这类入门题先把手工路径走通再去考虑自动化脚本这样你对漏洞成因的理解才会扎实。我在实际刷题中还有一个习惯每次做完题会把整条利用链用文字重新写一遍。这个习惯看起来麻烦但写出来的过程能逼自己把“为什么”想清楚而不只是照着 payload 复制粘贴。下次再遇到同类型题目时就不需要重新踩坑了。这道题的价值不在于答案有多少难度而在于它把 Web 信息收集和文件读取的链路完整展现了一次。把这套思路吃透后面的同类题目基本都是一路平推。

相关新闻

CefSharp 多标签分页实战:进程模型、资源释放与避坑指南

CefSharp 多标签分页实战:进程模型、资源释放与避坑指南

简介:这份资源面向.NET桌面开发者与CefSharp初学者,聚焦在WinForms应用中嵌入Chromium内核并实现类浏览器交互。内容围绕Tab分页管理、页面刷新、标签删除与新窗口创建四条主线展开,涉及ChromiumWebBrowser多实例动态增删、Reload强制忽略缓存…

2026/10/13 3:48:55 阅读更多 →
2026年网络安全转行全解析:岗位供需、薪资真相与实战路径

2026年网络安全转行全解析:岗位供需、薪资真相与实战路径

“现在转网安还来得及吗?”“听说2026年缺口300万,是真的吗?”“35岁转行会不会太晚?”——2026年了,这些问题依然在各大社区被反复刷屏。我做了近十年安全工作,从乙方驻场干到甲方安全负责人,也…

2026/10/13 3:47:55 阅读更多 →
Windows文件夹被占用无法删除?用句柄机制和Process Explorer五分钟定位真凶

Windows文件夹被占用无法删除?用句柄机制和Process Explorer五分钟定位真凶

遇到这种问题真的烦:右键删除一个文件夹,Windows 弹出一句“操作无法完成,因为文件夹已在另一个程序中打开”,英文环境就是 Unable to delete / Unable to rename。文件夹就那么杵在屏幕上,删不掉也改不了名&#xff0…

2026/10/13 3:47:55 阅读更多 →

最新新闻

Open Code Review:一种透明、结构化、低摩擦的代码评审实践体系

Open Code Review:一种透明、结构化、低摩擦的代码评审实践体系

1. “Open Code Review”不是开源项目,而是一套可落地的代码评审实践体系“Open Code Review”这个词最近在技术社区里频繁出现,但很多人第一反应是——这又是个新出的开源工具?或者某个大厂刚开源的代码审查平台?其实都不是。它既…

2026/10/13 5:14:27 阅读更多 →
Python字典为什么有序?3.7插入顺序保证背后的哈希表实现与工程取舍

Python字典为什么有序?3.7插入顺序保证背后的哈希表实现与工程取舍

Python 3.6 刚发布那会儿,我把项目解释器版本从 3.5 升上来,第一件让我愣住的事不是 f-string,也不是 async/await 的完善,而是普通字典的打印顺序突然变了。以前每次跑 dict 输出出来的顺序都像抽奖,那次却和赋值的先…

2026/10/13 5:14:27 阅读更多 →
S变换短窗能量法:解决缆-线混合配电网故障选线难题

S变换短窗能量法:解决缆-线混合配电网故障选线难题

雷雨季节凌晨两点,某城区配电运维站的值班电话比闹钟还准。监控屏上,四条出线的零序电流同时跳了起来,哪一条是真正发生单相接地的故障线路,波形上看着都差不多,但只要拿尺子去比一组稳态幅值,很快就会发现…

2026/10/13 5:14:27 阅读更多 →
Agent技能独立化架构:让大模型从“能聊”到“能干活”的工程实践

Agent技能独立化架构:让大模型从“能聊”到“能干活”的工程实践

最近接了个活儿,要把一套“只会聊天”的对话系统升级成真正能帮忙干活的智能体。结果我发现,朋友圈里聊得火热的那个“agent-skills”项目,正好就是解决这类问题的关键拼图。这半年我在实际落地项目里反复折腾这套东西,把“技能”…

2026/10/13 5:14:27 阅读更多 →
Python字典为何从无序变有序:3.6紧凑哈希表到3.7规范保证的完整实证

Python字典为何从无序变有序:3.6紧凑哈希表到3.7规范保证的完整实证

Python 的字典到底有没有序?这个问题放到五年前,老手几乎会统一口径:无序,别依赖迭代顺序。而现在你再问同样的问题,答案已经完全反过来了——从 Python 3.7 开始,字典按键的插入顺序迭代,是语言…

2026/10/13 5:14:27 阅读更多 →
LiteLLM统一网关实战:搞定大模型API接入与模型切换难题

LiteLLM统一网关实战:搞定大模型API接入与模型切换难题

不知道你们有没有这种经历:项目对接了好几个模型服务商的API,每个服务商的鉴权方式不一样、返回结构不一样、限流策略也不一样。最难受的是,方案评审时说的是“随时可以切换模型”,真正切的时候才发现,切换一次要改几十…

2026/10/13 5:13:27 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目,我最大的感受是,大部分坑不是出在技术前沿,而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节,最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了,很难不碰到舵机控制这道坎。做智能小车要转方向,做机械臂要抬关节,做云台要偏航俯仰,背后都是同一个东西在干活:舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”?——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台?或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜?又或者,在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 21:05:09 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 14:48:49 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →