Headline
CVE-2021-45040: CVE-2021-45040
The Spatie media-library-pro library through 1.17.10 and 2.x through 2.1.6 for Laravel allows remote attackers to upload executable files via the uploads route.
On 14 Dec 2021, we have reported a vulnerability (CVE-2021-45040) for the Spatie media-library-pro library. In short, the Spatie media-library-pro library through 1.17.10 & 2.1.6 for Laravel allows remote attackers to upload executable files via the uploads route.
Introduction
Media Library Pro is a paid add-on package for Spatie Laravel Media Library. Laravel Media Library Pro intended to solve file upload challenges for PHP developers by providing a convenient “Temporary Upload” function and frontend package for Blade, Livewire, React, and Vue.
The “Temporary Upload” function of Media Library Pro also provides a route macro “Route::mediaLibrary()” which will register a route at “media-library-pro/uploads”. This is the default URI endpoint but can be changed by the developer. It accepts POST requests to upload files and store the uploaded files inside a temporary directory. However, this route Marco has NO authentication enabled by default for Laravel API-style design.
This temporary upload route accepts 3 POST parameters including uuid, name, and file:
- uuid is a random string in this format: c46c4540-5803-11ec-970b-00155d4e8236, and it is possible to generate a random uuid using Linux command “uuid”
- name represents the file name which is an arbitrary string
- file is the actual file to be upload.
Unauthenticated Arbitrary File Upload concern (CVE-2021-45040)
After a successful POST request to the route “media-library-pro/uploads”, a JSON payload including “original_url” string will be returned. Therefore, the user can directly access this file. If the server is not hardened properly, this approach opened up the possibilities and lets the attacker upload a web shell because there is no filtering of file type/extension at the temporary upload stage.
Other concerns
In addition to the above “unauthenticated arbitrary file upload” issue, there is a lack of file name length protection and rate-limiting which may also open possibilities of DDoS attack or other potential issues.
Furthermore, the Media Library Pro library is a PHP software library that may be included by the other software or website, it may impact some of the website or other software packages. Therefore, it can also be classified as Supply–Chain vulnerability.
Simulation environment for CVE-2021-45040
Below are some components to simulate a vulnerable environment (CVE-2021-45040):
- Laradock / XAMPP
- composer – PHP package management tools
- Laravel Media Library
- Subscription of Laravel Media Library Pro
- Postman
- A PHP Webshell (e.g. wwwolf’s PHP web shell) – wwwolf’s PHP web shell is certaintly a good one, but Windows Defender treat it as malware. You can also try our modified version of PHP webshell here, which can evade Window Defender as of this writing.
Below are instructions to setup the simulate a vulnerable environment. Firstly, we need to create a basic project skeleton:
composer create-project --prefer-dist laravel/laravel laravel8_medialibrarypro
Then, we need to install Laravel media Library, generate corresponding configuration and perform database migration. A complete documentation is available here.
cd laravel8_medialibrarypro/
composer require "spatie/laravel-medialibrary:^9.0.0"
php artisan vendor:publish --provider="Spatie\MediaLibrary\MediaLibraryServiceProvider" --tag="migrations"
php artisan migrate
php artisan vendor:publish --provider="Spatie\MediaLibrary\MediaLibraryServiceProvider" --tag="config"
Before proceed the following instructions, we need to configure the repository and add license, you can refer to the documentation here. Then, we can proceed to install Laravel media library pro and generate its configuration.
composer require spatie/laravel-medialibrary-pro
php artisan vendor:publish --provider="Spatie\MediaLibraryPro\MediaLibraryProServiceProvider" --tag="media-library-pro-migrations"
Next, we can add the route and run the service:
echo 'Route::mediaLibrary();' to routes/web.php
php artisan serve
If everything is setup correctly, you will be able to upload webshell PHP file to the server, and able to check the value of “original_url”.
CVE-2021-45040 Postman upload screen
Finally, we can access the webshell and run arbitrary command as the user of web service.
CVE-2021-45040 webshell screen
Solution
In this section, we will cover some possible solutions for CVE-2021-45040.
If you are using Apache or Nginx, you can limit attacker execute the PHP webshell using configuration directives:
- Nginx Location directives
- Apache Directory/Location directives
We will also discuss a another approach for each problems, but you need to do more customization:
Unauthenticated upload
Do not use Route macro, and add “auth:api” middleware. You may refer to following sample:
Route::post('media-library/uploads', TemporaryUpload::class)
->name('media-library-uploads')
->middleware(['auth:api'])
User able to upload any kind of files
Adapt your new controller class, and perform validation.
User can directly access the original file
Extend TemporaryUpload model, force image conversion, and delete the original file.
Original file name is returned in Json response
Extend Media model, and override the getOriginalUrlAttribute function to return converted file.
Predicatable path may allow brute-forcing
Extend the file_namer & path_generator class to generate non-predictable path. One thing to note is that you cannot generate random path or filename.
Rate-Limiting
Add a new middleware using RateLimiter.
Summary
To summarize, the default implementation and documentation of Laravel medialibrary-pro allow “Unauthenticated Arbitrary File Upload” which may lead to uploading a PHP web shell, and potentially take over the entire system. We have discussed some possible solutions, and some best practices when designing file upload functions for a web application.
Full Disclosure URL:
https://seclists.org/fulldisclosure/2022/Mar/15
Updated on 16 Mar 2022:
Laravel Media Library Pro teams are working on a fix.