news 2026/6/4 15:32:59

【BUUCTF】【WEB】[HCTF 2018]WarmUp

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【BUUCTF】【WEB】[HCTF 2018]WarmUp

考点:PHP 文件包含漏洞、白名单绕过(问号截断)、目录穿越、mb_strpos/mb_substr 函数

打开题目,发现有个表情包。

右键检查,能看到有个source.php:

打开source.php发现是一段代码:

分析一下:

<?php // 高亮显示当前PHP文件的源代码,这是题目给我们看源码的入口 highlight_file(__FILE__); // 定义一个名为emmm的类,核心的白名单检查逻辑都在这个类里 class emmm { // 定义静态方法checkFile,用于检查传入的文件名是否合法 // 参数&$page是引用传递,但本函数中并未修改$page的值,引用无实际作用 public static function checkFile(&$page) { // 定义白名单数组,只允许访问source.php和hint.php两个文件 // 注意:数组的键名"source"和"hint"没有实际作用,只有值会被in_array检查 $whitelist = ["source"=>"source.php","hint"=>"hint.php"]; // 第一层基础校验:检查$page是否存在 且 是字符串类型 if (! isset($page) || !is_string($page)) { // 校验失败,输出提示信息 echo "you can't see it"; // 返回false,表示文件不合法 return false; } // 第一层白名单检查:直接匹配整个$page是否在白名单中 if (in_array($page, $whitelist)) { // 匹配成功,直接返回true,函数立即结束 return true; } // 第二层白名单检查:截取$page中第一个问号之前的内容进行匹配 // mb_substr:多字节字符串截取函数,从第0位开始截取 // mb_strpos:多字节字符串查找函数,查找第一个问号的位置 // 拼接$page . '?'的目的:如果$page中没有问号,mb_strpos会返回false // 拼接后保证至少有一个问号,此时会截取整个$page字符串 $_page = mb_substr( $page, 0, mb_strpos($page . '?', '?') ); // 检查截取后的字符串是否在白名单中 if (in_array($_page, $whitelist)) { // 匹配成功,直接返回true,函数立即结束 return true; } // 第三层白名单检查:先URL解码,再截取第一个问号之前的内容进行匹配 // urldecode:对URL编码的字符串进行一次解码 $_page = urldecode($page); // 重复第二层的截取逻辑 $_page = mb_substr( $_page, 0, mb_strpos($_page . '?', '?') ); // 检查解码并截取后的字符串是否在白名单中 if (in_array($_page, $whitelist)) { // 匹配成功,直接返回true,函数立即结束 return true; } // 所有三层检查都失败,输出提示信息 echo "you can't see it"; // 返回false,表示文件不合法 return false; } } // 主逻辑:处理用户的文件包含请求 // 三个条件必须同时满足: // 1. $_REQUEST['file']参数不为空 // 2. $_REQUEST['file']是字符串类型 // 3. 经过checkFile函数检查返回true if (! empty($_REQUEST['file']) && is_string($_REQUEST['file']) && emmm::checkFile($_REQUEST['file']) ) { // 所有条件满足,包含用户传入的文件 // 这是漏洞的核心:只要绕过checkFile检查,就能包含任意文件 include $_REQUEST['file']; // 包含文件后立即退出脚本,不再执行后续代码 exit; } else { // 任意一个条件不满足,显示滑稽表情包 echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />"; } ?>

看见有个hint.php,访问一下:

checkFile()函数有4 种返回 true 的情况,我们需要利用其中一种绕过白名单:

  1. 传入的$page直接在白名单中(只能访问 source.php 和 hint.php,无法直接读 flag)
  2. 截取$page第一个?之前的内容,如果在白名单中则返回 true
  3. $page进行一次 URL 解码后,再截取第一个?之前的内容,如果在白名单中则返回 true

mb_strpos会在$page的后面拼接一个?,并且会查询第一个问号的位置。而mb_substr会截取问号前的内容。只要问号前是白名单中的文件名(source.php/hint.php),就能通过第二个检查。

$_page = mb_substr( $page, 0, mb_strpos($page . '?', '?') );

所以我们只需要在参数的后面加个?就能通过检查,而代码里明确使用了$_REQUEST['file']来获取用户输入,所以:

?file=source.php?

这里有两个完全不同作用的问号

  1. 第一个?:URL 标准的参数分隔符,作用是把域名和 GET 参数分开,告诉服务器 "后面的是参数"
  2. 第二个?:我们精心构造用来绕过白名单的核心

ffffllllaaaagggg有什么用呢?

因为我们不清楚ffffllllaaaagggg是在哪层目录,而PHP 的include函数默认从当前脚本所在目录查找文件,而不是直接从系统根目录查找

几乎所有 CTF Web 靶机都采用 Linux 系统的标准 Web 目录结构:

/ ← 系统根目录 └── var/ └── www/ └── html/ ← 网站根目录(当前脚本所在目录) ├── index.php ├── source.php └── hint.php

所以我们要对payload进行向上的目录穿越,也就是要加4个../:

?file=source.php?/../../../../ffffllllaaaagggg

为什么第一个../前还要多加个正斜杠呢?

include遇到这样的路径:

source.php?/../../../../ffffllllaaaagggg
  1. PHP 首先会尝试找一个字面意义上叫source.php?的文件,这个文件当然不存在
  2. 找不到文件时,PHP 会退而求其次,把整个字符串当作目录路径来解析
  3. 这时候?就变成了文件名的一部分,而/是标准的目录分隔符
  4. 所以source.php?/会被解析成:一个名为source.php?的目录
  5. 后面的../就会正常执行向上穿越目录的操作

最后拆解一下执行过程:

//payload source.php?/../../../../ffffllllaaaagggg
第一步:执行mb_strpos($page . '?', '?')
  • 先拼接字符串:$page . '?'source.php?/../../../../ffffllllaaaagggg?
  • 查找第一个?的位置:source.php正好是 10 个字符,所以返回10
第二步:执行mb_substr($page, 0, 10)
  • 从第 0 个字符开始,截取 10 个字符
  • 结果:$_page = "source.php"
第三步:白名单检查
if (in_array($_page, $whitelist)) { return true; }
  • in_array("source.php", ["source.php", "hint.php"])→ 匹配成功
  • 函数直接返回true,绕过白名单检查

把payload放在靶机的地址后面:

flag出来了

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/4 15:31:42

3步终极指南:用椰羊cocogoat工具箱告别原神圣遗物手动管理烦恼

3步终极指南&#xff1a;用椰羊cocogoat工具箱告别原神圣遗物手动管理烦恼 【免费下载链接】cocogoat-client A toolbox for Genshin Impact to export artifacts automatically. 支持圣遗物全自动导出的原神工具箱&#xff0c;保证每一行代码都是熬夜加班打造。 项目地址: h…

作者头像 李华
网站建设 2026/6/4 15:29:39

图神经网络在乌尔都文学作者识别中的应用

1. 项目概述&#xff1a;当图神经网络遇见乌尔都文学在数字人文研究的实验室里&#xff0c;我正面对着一摞泛黄的乌尔都语小说扫描件。这些承载着南亚次大陆文化记忆的文本&#xff0c;正经历着从纸质到数字、从线性叙事到网络结构的奇妙转变。传统作者识别方法依赖于词汇统计和…

作者头像 李华
网站建设 2026/6/4 15:28:01

小白必看|OpenClaw Windows 一键安装教程,告别依赖缺失难题

✨ OpenClaw 一键安装包&#xff5c;一键部署&#xff0c;告别复杂环境配置 ✨ 适配系统&#xff1a;Windows10/11 64 位 当前版本&#xff1a;v2.7.8 核心优势&#xff1a;全程可视化操作&#xff0c;无需命令行、无需手动配置 Python/Node.js&#xff0c;内置所有运行依赖&a…

作者头像 李华
网站建设 2026/6/4 15:26:37

利用Agent 基础、ReAct、planning、memory做tool-based agent,利用 JSON Schema做structured output extraction从 从文本提取

一、整体系统架构┌──────────────────┐│ User │└────────┬─────────┘│▼┌─────────────────┐│ Agent ││ ReAct Planner │└────────┬────────┘│┌───────…

作者头像 李华
网站建设 2026/6/4 15:24:36

【RT-DETR实战】133、神经网络架构搜索(NAS)与RT-DETR结合展望

从一次深夜调参说起 上周在部署RT-DETR到边缘设备时,又遇到了老问题:模型在Jetson Orin上跑起来帧率只有23FPS,离实时检测的30FPS还差一截。 尝试了各种剪枝量化手段,要么精度掉得厉害,要么速度提升有限。盯着TensorRT的profiler输出,突然意识到——我们是不是在错误的…

作者头像 李华
网站建设 2026/6/4 15:24:35

请收下这些软件测试学习干货,不看后悔一辈子

学习软件测试的过程中会遇到很多很多的困难和挑战&#xff0c;只有跨过这些困难和挑战&#xff0c;才有机会挑战软件测试领域的高薪offer。今天我们就来梳理一下&#xff0c;学习软件测试的过程中&#xff0c;我们一般都会遇到哪些困难&#xff0c;我们又当如何克服这些困难。 …

作者头像 李华