当前位置: 首页 > news >正文

[HCTF 2018]WarmUp

[HCTF 2018]WarmUp

解题步骤

开启靶场页面上只有一个大滑稽脸,没有什么特别有用的信息,直接查看源码

image

看到提示,网址上拼接url访问/source.php



代码审计

为了方便看,先单独一段一段分析
<?php
highlight_file(__FILE__);    // 高亮显示
class emmm
{public static function checkFile(&$page){$whitelist = ["source"=>"source.php","hint"=>"hint.php"];     // 白名单if (! isset($page) || !is_string($page)) {                    // 参数检查echo "you can't see it";                                  // 输出提示信息return false;                       // 退出}if (in_array($page, $whitelist)) {      // 白名单检查return true;                        // 允许访问}$_page = mb_substr(                     // 去除参数$page,0,mb_strpos($page . '?', '?')         // 找到问号位置);if (in_array($_page, $whitelist)) {     // 白名单检查return true;                        // 允许访问}$_page = urldecode($page);              // 解码$_page = mb_substr(                     // 去除参数$_page,0,mb_strpos($_page . '?', '?')        // 找到问号位置);if (in_array($_page, $whitelist)) {     // 白名单检查return true;                        // 允许访问}echo "you can't see it";                // 输出提示信息return false;                           // 退出}
}if (! empty($_REQUEST['file'])                  // 参数检查&& is_string($_REQUEST['file'])             // 参数类型检查&& emmm::checkFile($_REQUEST['file'])       // 调用方法
) {include $_REQUEST['file'];         // 包含文件exit;                              // 退出
} else {                               // 参数错误echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";      // 输出滑稽脸
}
?>

public static function checkFile(&$page)    // 静态方法{$whitelist = ["source"=>"source.php","hint"=>"hint.php"];    // 白名单

先是定义了一个名为 checkFile 公共的静态方法,主要用于对传入的 $page 变量进行初步的合法性检查,定义了一个白名单数组,包含两个键值对,为允许访问的文件白名单

if (! isset($page) || !is_string($page)) {    // 参数检查echo "you can't see it";          // 提示信息return false;                     // 退出}

这段代码是文件访问控制的 “前置检查”,先验证 $page 的基本合法性(是否存在、是否为字符串),如不存在或不是字符串则输出提示并返回false

if (in_array($page, $whitelist)) {    // 白名单检查return true;    // 允许访问
}

检查传入的 $page 是否在白名单当中,是则返回true

$_page = mb_substr(                     // 去除参数$page,0,mb_strpos($page . '?', '?')         // 找到问号位置);

1. 核心函数解析

  • mb_strpos($str, $needle):多字节安全的字符串查找函数,返回$needle(目标字符)在$str(字符串)中首次出现的位置(索引值,从 0 开始)。若未找到,返回false。

  • mb_substr($str, $start, $length):多字节安全的子字符串截取函数,从$str的$start位置(默认 0)开始,截取长度为$length的子字符串。

2. 代码执行逻辑
$page . '?'表示在 $page 的末尾拼接一个问号?。
这样做的目的是:即使原始$page中没有?,也能确保拼接后的字符串一定包含?,避免mb_strpos返回false(确保后续截取长度有效)。

mb_strpos($page . '?', '?')查找拼接后字符串中第一个?出现的位置
(如$page = "hint.php"),则返回拼接后 ? 的位置(即$page的长度,例如"hint.php"长度为 8,拼接后?在索引 8 的位置)

mb_substr($page, 0, 上述位置)从 $page 的开头(0 位置)开始,截取到第一个?出现的位置(不包含 ? 本身),结果赋值给 $_page

这段代码通常用于截取文件名,去除可能包含的查询参数(?及之后的内容),只保留基础文件名。结合前面的白名单检查逻辑,这样可以避免因$page带有参数(如source.php?x=1)而导致白名单验证失败,确保只验证文件名本身是否合法

后面就是在检查一次在不在白名单里,继续重复文件名截取再检查白名单,只不过多了一个url解码,影响不大

$_page = urldecode($page);

接着解释最后一段

if (! empty($_REQUEST['file'])    // 参数检查&& is_string($_REQUEST['file'])    // 参数类型检查&& emmm::checkFile($_REQUEST['file'])    // 调用方法
) {include $_REQUEST['file'];    // 包含文件exit;    // 退出
} else {    // 参数错误echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";      // 输出滑稽脸
}

! empty($_REQUEST['file']):检查请求中是否存在名为file的参数,且该参数不为空。

is_string($_REQUEST['file']):确保file参数的值是字符串类型。这是基础的类型校验,防止非字符串类型的输入(如数组)导致后续处理异常

emmm::checkFile($_REQUEST['file']):调用emmm类的静态方法checkFile,对file参数的值进行进一步安全验证。只有checkFile返回true(验证通过),这个条件才成立。

include $_REQUEST['file']:包含并执行file参数指定的文件。include是 PHP 的文件包含语句,会将目标文件的内容当作 PHP 代码执行。



构造payload

该类会先进行白名单检查,然后截取文件名并重复操作,综上所述我们传入的参数只要在白名单 (source.php hint.php) 当中,并且加上 ? 就可以绕过多次的白名单检测,由于是在source.php目录下操作的,所以只需在当下目录传入file=source.php既可

暂时还不知道flag在什么位置先包含hint.php文件看看有没有多余线索

source.php?file=hint.php

回显flag not here, and flag in ffffllllaaaagggg这说明flag在ffffllllaaaagggg里面

因为我这边是直接知道flag在根目录,而且flag通常也会放在根目录,linux系统的网页路径又一般在/var/html/www/文件名称,所以直接包含根目录下的文件,如果不清楚的情况下只能一个一个去包含尝试

得出payload为

file=hint.php?/../../../../ffffllllaaaagggg

完整payload,以下随便一个都可以

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

image

最终获取flagflag{467d5f45-294e-46b7-a15a-d021e0bceced}

http://www.hskmm.com/?act=detail&tid=21773

相关文章:

  • Day2:Linux文件目录移到拷贝与vim编辑器使用指南
  • 【半导体物理 | 笔记】第八章 半导体表面与MIS结构
  • 【半导体物理 | 笔记】第七章 金属和半导体的接触
  • 【半导体物理 | 笔记】第四章 半导体的导电性
  • 【半导体物理 | 笔记】第五章 非平衡载流子
  • 【AHK】暗黑3助手,加强版鼠标宏
  • 【当前赛季】第36赛季:地狱魔王9月12日开启
  • 第36赛季:地狱魔王9月12日开启
  • 2025年9月 增值税进项税额,不可抵扣VS可抵扣全解析
  • 【Rust GUI开发入门】编写一个本地音乐播放器(14. 应用打包-制作安装程序) - Jordan
  • 【黑马python】2.Python基础语法-注释 数据类型 运算符 字符串等
  • Visual Studio Code + Clangd 设置语法检查针对 C++的版本。
  • 示波器地、大地、电源地!地线着火?
  • 【黑马python】2.Python基础知识-注释 数据类型 运算符 字符串等
  • Educational Codeforces Round 135 (Rated for Div. 2)
  • 【Rust GUI开发入门】编写一个本地音乐播放器(13. 实现按键绑定) - Jordan
  • mem reduct 没有托盘图标
  • C++ GUI 选型记
  • TypeScript 泛型 T 详细解释
  • day007
  • 【Rust GUI开发入门】编写一个本地音乐播放器(12. 国际化应用-多语言支持) - Jordan
  • 2025秋_6
  • 程序语言杂谈:C/C++
  • 2025秋_7
  • PEP8 规范
  • print() 函数
  • 第九天
  • Pycharm 设置
  • [NOIP 2016 提高组] 组合数问题
  • 新建第一个项目