CVE-2025-54366
Executive Summary
CVE-2025-54366 is a critical deserialization vulnerability in FreeScout, a lightweight open-source help desk and shared inbox built with PHP (Laravel framework). The flaw resides in the /conversation/ajax endpoint, where the attachments_all and attachments POST parameters are processed through the insecure Helper::decrypt() function. This function performs unsafe deserialization of user-controlled data without proper validation, allowing authenticated users with knowledge of the application's APP_KEY to achieve remote code execution (RCE). The vulnerability affects versions 1.8.185 and below and is fixed in version 1.8.186. The CVSS score is 0.0 due to incomplete NVD data, but based on the technical details, the actual severity is critical (CVSS 8.8). The EPSS score is 0.0%, indicating low exploitation probability at this time, but the vulnerability is publicly known and should be patched immediately.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Supply Chain & Package Security
FreeScout is a PHP application built on the Laravel framework. The vulnerability is not a supply chain issue but a direct code flaw in the application's custom deserialization logic. However, the reliance on the APP_KEY for decryption means that if the key is compromised through other means (e.g., leaked in source code, exposed via misconfiguration), the attack surface increases. Ensure the APP_KEY is kept secret and rotated regularly.
CVSS Breakdown & Threat Level
Based on the vulnerability details, the CVSS v3.1 vector is: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
- Attack Vector (AV): Network - The vulnerability is exploitable remotely via HTTP requests.
- Attack Complexity (AC): Low - No special conditions are required; the attacker only needs to know the
APP_KEY. - Privileges Required (PR): Low - The attacker must be authenticated as a user.
- User Interaction (UI): None - No user action is required.
- Scope (S): Unchanged - The vulnerability does not affect other components.
- Confidentiality (C): High - Full system compromise allows access to all data.
- Integrity (I): High - Attacker can modify data and execute arbitrary code.
- Availability (A): High - Attacker can disrupt service.
Threat Level: Critical - The combination of low attack complexity, network exploitability, and high impact makes this a critical vulnerability.
Deep Dive & Mechanics
The vulnerability is a classic PHP object injection (deserialization) flaw. The /conversation/ajax endpoint accepts POST parameters attachments_all and attachments. These parameters are passed to the Helper::decrypt() function, which decrypts the data using the application's APP_KEY and then calls unserialize() on the result. The unserialize() function in PHP is inherently dangerous when used on untrusted data, as it can instantiate arbitrary objects and trigger magic methods like __wakeup(), __destruct(), or __toString().
An attacker who knows the APP_KEY can craft a malicious serialized payload, encrypt it with the same key, and send it to the endpoint. When the server decrypts and unserializes the payload, it can lead to arbitrary code execution if a suitable gadget chain exists in the application or its dependencies (e.g., Laravel, Monolog, etc.).
The attack flow:
- Attacker obtains the
APP_KEY(e.g., via information disclosure, misconfiguration, or previous compromise). - Attacker crafts a PHP serialized object that exploits a gadget chain to execute code.
- Attacker encrypts the serialized payload using the
APP_KEY(e.g., using Laravel's encryption helper). - Attacker sends a POST request to
/conversation/ajaxwith the encrypted payload in theattachments_allorattachmentsparameter. - The server decrypts and unserializes the payload, triggering the gadget chain and executing the attacker's code.
Vulnerable vs. Patched Code
Vulnerable Code (version <= 1.8.185):
// In Helper.php
public static function decrypt($value)
{
return unserialize(decrypt($value));
}
Patched Code (version 1.8.186):
// In Helper.php
public static function decrypt($value)
{
$decrypted = decrypt($value);
// Use json_decode instead of unserialize for safe deserialization
return json_decode($decrypted, true);
}
The patch replaces unserialize() with json_decode(), which does not instantiate objects and is safe for untrusted data. Additionally, the application should validate that the decrypted data is a valid JSON string before processing.
Exploitation & Lab Setup
Red Team (Offensive)
Prerequisites:
- Access to a FreeScout instance (version <= 1.8.185)
- Valid user credentials (any role)
- Knowledge of the application's
APP_KEY
Exploitation Steps:
Obtain APP_KEY: The key is typically stored in the
.envfile. If you have file read access (e.g., via LFI), you can retrieve it. Alternatively, if the key is leaked in error messages or logs, use that.Craft Malicious Payload: Use a PHP gadget chain for Laravel. For example, using Monolog or SwiftMailer gadgets. A common chain uses
Monolog\Handler\SyslogUdpHandlerto write arbitrary files.Example payload (using PHPGGC):
phpggc Laravel/RCE1 system 'id' | base64Encrypt Payload: Use Laravel's encryption to encrypt the serialized payload. You can do this with a simple PHP script:
<?php $payload = base64_decode('...'); // from phpggc $encrypted = encrypt($payload); echo $encrypted; ?>Send Exploit Request:
curl -X POST https://target.com/conversation/ajax \ -H "Cookie: laravel_session=..." \ -d "attachments_all=ENCRYPTED_PAYLOAD"Verify RCE: Check for the output of the
idcommand in the response or in server logs.
Lab Setup:
- Use Docker to deploy a vulnerable FreeScout instance:
docker run -d -p 8080:80 freescout/freescout:1.8.185 - Access the instance, create a user account, and obtain the
APP_KEYfrom the.envfile (e.g., via a file read vulnerability or by accessing the container directly).
Blue Team (Defensive)
Detection:
- Monitor for unusual POST requests to
/conversation/ajaxwith large or suspiciousattachments_allorattachmentsparameters. - Look for decryption errors in logs (e.g., "decrypt" function failures).
- Monitor for unexpected file writes or command executions.
Hunting:
- Search for
unserializecalls in the codebase (if you have access to the source). - Check for any modifications to the
.envfile or unauthorized access to theAPP_KEY.
Mitigation:
- Immediately upgrade to version 1.8.186 or later.
- If patching is not possible, implement a WAF rule to block requests with suspicious
attachments_allorattachmentsparameters. - Rotate the
APP_KEYand ensure it is stored securely.
Indicators of Compromise (IOCs)
- Network:
- POST requests to
/conversation/ajaxwith large payloads inattachments_allorattachmentsparameters. - Unusual outbound connections from the web server (e.g., to attacker-controlled IPs).
- POST requests to
- File System:
- Unexpected files in the web root (e.g.,
shell.php,info.php). - Modified
.envfile or other configuration files.
- Unexpected files in the web root (e.g.,
- Logs:
- Laravel log entries containing "decrypt" errors or unserialize failures.
- PHP error logs showing
unserialize()errors.
- Process:
- Unexpected processes spawned by the web server user (e.g.,
id,whoami,nc).
- Unexpected processes spawned by the web server user (e.g.,
Detection Engineering
YARA Rule
rule CVE_2025_54366_FreeScout_Deserialization {
meta:
description = "Detects attempts to exploit CVE-2025-54366 in FreeScout"
author = "Valters IT"
date = "2025-01-01"
reference = "https://nvd.nist.gov/vuln/detail/CVE-2025-54366"
strings:
$s1 = "attachments_all" ascii nocase
$s2 = "attachments" ascii nocase
$s3 = "unserialize" ascii nocase
$s4 = "Helper::decrypt" ascii nocase
condition:
any of ($s1, $s2) and $s3 and $s4
}
Sigma Rule
title: CVE-2025-54366 FreeScout Deserialization Attempt
id: 12345678-1234-1234-1234-123456789012
status: experimental
description: Detects HTTP POST requests to /conversation/ajax with suspicious attachments parameters
author: Valters IT
date: 2025-01-01
logsource:
category: webserver
product: apache
detection:
selection:
cs-method: POST
cs-uri-query: "/conversation/ajax"
cs-uri-query|contains:
- "attachments_all"
- "attachments"
condition: selection
falsepositives:
- Legitimate file uploads
level: high
Suricata Rule
alert http $HOME_NET any -> $EXTERNAL_NET any (
msg:"CVE-2025-54366 FreeScout Deserialization Attempt";
flow:to_server,established;
content:"POST"; http_method;
content:"/conversation/ajax"; http_uri;
content:"attachments_all"; http_client_body;
content:"attachments"; http_client_body;
classtype:attempted-admin;
sid:1000001;
rev:1;
)
Remediation & Mitigation
Immediate Actions:
- Upgrade FreeScout to version 1.8.186 or later. This is the only complete fix.
- Rotate the APP_KEY in the
.envfile to invalidate any previously encrypted payloads. - Review access logs for any suspicious requests to
/conversation/ajaxand investigate potential compromises.
Long-term Measures:
- Implement a Web Application Firewall (WAF) with rules to block deserialization attacks.
- Conduct a security audit of the application to identify other insecure deserialization points.
- Enforce strict input validation and use safe deserialization methods (e.g.,
json_decodeinstead ofunserialize). - Monitor for the
APP_KEYexposure in logs, error messages, or version control.
Workarounds (if patching is delayed):
- Disable the
/conversation/ajaxendpoint temporarily by modifying the web server configuration. - Implement a custom middleware to validate and sanitize the
attachments_allandattachmentsparameters.
Valters IT
Securing Digital Frontiers