CVE-2021-45040
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 and 2.x through 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”.
Finally, we can access the webshell and run arbitrary command as the user of web service.
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:
We will also discuss another approach for each problem, but you need to do more customization:
Unauthenticated upload
Do not use Route macro, and add “auth:api” middleware. You may refer to the 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 the non-predictable path. One thing to note is that you cannot generate random paths or filenames.
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.
Updated on 21 Mar 2022:
Laravel Media Library Pro teams released v.2.1.11 & v1.17.12 which fixed all our reported issues, and we have validated the results. We would like to appreciate the effort and their commitment to security.
Updated on 19 Mar 2022:
Laravel Media Library Pro teams released v.2.1.8 which fix the issues, and we will work with them to validate the result and provide our feedback.
Updated on 18 Mar 2022:
We have received tons of replies regarding the file upload best practices and concerns. So, we are preparing additional materials including blog posts and youtube for this topic. Stay tuned!
Updated on 16 Mar 2022:
Laravel Media Library Pro teams are working on a fix, and the new changes introduce the following new features:
- Configurable upload file types using both mime types and file extension as validation
- Generate random paths using TemporaryUploadPathGenerator
- Recommend “use S3 for file uploads” as a best practice in documentation
Official CVE Link:
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-45040
Full Disclosure Link: