Sep 2, 2026·6 min read·3 visits
An IDOR vulnerability in Sulu CMS allows low-privileged users with edit rights on at least one collection to steal restricted media files by moving them into accessible folders.
Sulu CMS, an open-source PHP content management system based on the Symfony framework, is affected by an Insecure Direct Object Reference (IDOR) vulnerability within its media relocation API. Authenticated users with restricted edit permissions can relocate media out of secure, unauthorized collections into folders they control, bypassing access controls entirely. This security issue is tracked under CVE-2026-82395 and GHSA-h6cx-gjxx-v25c.
Sulu CMS organizes media assets such as images, documents, and videos within logical directory structures known as Collections. Each collection is governed by granular Access Control Lists (ACLs) designed to prevent unauthorized users from viewing, editing, or downloading sensitive files. This restriction is enforced globally by the application's security framework.
The vulnerability, identified as CVE-2026-82395 (GHSA-h6cx-gjxx-v25c), represents an Insecure Direct Object Reference (IDOR) and an incorrect authorization flaw. It resides in the media relocation mechanism exposed via the administrative API. Specifically, the backend fails to validate access permissions against the media asset's historical source collection when processing a move action.
Because the authorization engine evaluates permission based on user-supplied request parameters rather than database state, authenticated attackers can circumvent ACL restrictions. An attacker with edit permissions on a single, benign collection can relocate restricted assets from unauthorized collections into their own. This actions effectively exposes those files to unauthorized read, modification, and extraction.
The architectural flaw is located within the decoupled design of Sulu's security interception and service layers. During a typical media move operation, a central security listener intercepts the HTTP request to authorize the action. This listener inspects the client-provided HTTP query or POST parameter, specifically looking at the collection variable to assess permissions.
If the requesting user possesses EDIT permissions for the collection specified in the request parameter, the security listener permits the transaction. The request is then passed directly to the MediaManager::move() method within src/Sulu/Bundle/MediaBundle/Media/Manager/MediaManager.php. This architectural flow relies on the implicit assumption that the security listener has fully validated the complete state of the transaction.
However, the backend service layer does not verify whether the user has authorization over the media's original source collection. The move() function retrieves the target destination collection entity, modifies the database-backed association on the media entity, and commits the transaction. This logic allows an attacker to manipulate the request variables to bypass ACL checks on the restricted source collection.
To understand the mechanics, analyze the difference between the vulnerable implementation and the patched codebase. The original MediaManager::move() method updated the media collection relationship without calling the internal security checker. It accepted the $destCollection argument and mapped it directly to the entity.
// Vulnerable Implementation
public function move($id, $locale, $destCollection)
{
// ...
// The entity's collection relationship is re-assigned
// without validating rights on the source collection.
$collection = $this->em->getReference(CollectionInterface::class, $destCollection);
$mediaEntity->setCollection($collection);
// ...
}The patch addresses this logical gap by integrating direct security checks inside MediaManager::move(). It explicitly queries the security checker against both the source collection ($previousCollectionId) and the target destination collection ($destCollection).
// Patched Implementation
public function move($id, $locale, $destCollection)
{
// ...
$previousCollectionId = $mediaEntity->getCollection()->getId();
if (null !== $this->securityChecker) {
// Check permissions on the actual database-backed source collection
$this->securityChecker->checkPermission(
new SecurityCondition('sulu.media.collections', null, Collection::class, $previousCollectionId),
PermissionTypes::EDIT
);
// Check permissions on the target destination collection
$this->securityChecker->checkPermission(
new SecurityCondition('sulu.media.collections', null, Collection::class, $destCollection),
PermissionTypes::EDIT
);
}
$collection = $this->em->getReference(CollectionInterface::class, $destCollection);
$mediaEntity->setCollection($collection);
// ...
}This change creates a robust security barrier that does not rely on transient client-supplied parameters. By querying the database for the active $previousCollectionId and running it through checkPermission(), the application prevents lateral movement of assets across different permission boundaries. This modification completely resolves the specific IDOR variant identified.
Exploitation of this vulnerability requires an authenticated session with at least low-level backend privileges. Specifically, the attacker must have EDIT rights over a minimum of one collection, which is a common privilege level for content editors. The attacker also needs to identify or guess the integer ID of a restricted media asset.
The attacker initiates the attack by sending a crafted HTTP POST request to the media move endpoint. They set both the security-evaluated collection parameter and the destination parameters to the ID of the collection they control. The target media asset ID is supplied in the URI path or post body.
Because the security listener evaluates permission based on the parameter collection=12 (the allowed collection), it permits the request. The underlying MediaManager receives the instruction to move media 42 (originally in restricted collection 99) to collection 12. Because the manager does not verify the user's rights on collection 99, the database is updated, and the asset is relocated to the attacker's territory.
The impact of CVE-2026-82395 is categorized primarily as a loss of confidentiality and integrity of digital assets. While the vulnerability does not directly lead to remote code execution (RCE) on the server, it allows unauthorized users to extract sensitive internal documentation, confidential images, and proprietary media.
The severity is quantified with a CVSS v4.0 base score of 5.3 (Medium). The attack vector is Network (AV:N), and the attack complexity is Low (AC:L), meaning it requires no specialized techniques or network positioning. Low privileges are required (PR:L), as the attacker must have an active backend user account.
In corporate environments, content management systems often host unreleased marketing material, financial spreadsheets, or personal identifiable information (PII). By exploiting this vulnerability, internal actors or compromised low-privileged accounts can systematically exfiltrate these files. Additionally, the relocation of files disrupts operational organization, representing an integrity impact on system structure.
The primary remediation path is upgrading the Sulu CMS installation to a fixed version. System administrators must identify their active branch and apply the corresponding update. For environments running the 2.x branch, upgrade to version 2.6.25 or higher. For environments on the 3.x branch, upgrade to version 3.0.8 or higher.
In scenarios where immediate patching is unfeasible, temporary mitigation can be implemented through strict endpoint monitoring or custom web application firewall (WAF) rules. Administrators can configure security appliances to inspect requests containing the URL query string action=move and log any cross-collection references.
Furthermore, security teams should execute database audits to detect unauthorized file movements. Querying the transaction logs or checking for media assets whose current collection belongs to users with historically limited permissions can reveal previous exploitation attempts. Implementing comprehensive auditing on the sulu_media tables is highly recommended.
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N| Product | Affected Versions | Fixed Version |
|---|---|---|
Sulu CMS Sulu GmbH | < 2.6.25 | 2.6.25 |
Sulu CMS Sulu GmbH | >= 3.0.0-alpha1, < 3.0.8 | 3.0.8 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-639 / CWE-863 |
| Attack Vector | Network |
| CVSS v4.0 Score | 5.3 (Medium) |
| EPSS Score | 0.00246 |
| EPSS Percentile | 15.73% |
| Impact | Partial Confidentiality & Integrity Loss |
| Exploit Status | PoC (Functional Integration Test Available) |
| KEV Status | Not Listed |
The system utilizes user-controlled parameters to perform permissions checking, allowing users to interact with unauthorized objects.
A host confusion vulnerability exists in the fast-uri Node.js library when parsing scheme-relative URI references. Due to inconsistent domain name canonicalization, applications validating resolved hosts can be bypassed by downstream WHATWG-compliant parsers, facilitating Server-Side Request Forgery (SSRF).
An incomplete sanitization fix for CVE-2026-35536 in Tornado allowed cookie attribute injection. The framework's validation loop checked lowercase keyword arguments but neglected legacy case-insensitive parameters passed through arbitrary keyword arguments, which Python's underlying library parses case-insensitively.
GHSA-8423-8FGW-73VQ is a pre-authentication denial of service vulnerability in the Tornado web server's handling of multipart/form-data. The flaw allows an unauthenticated remote attacker to cause memory exhaustion and CPU starvation by transmitting a crafted HTTP request containing a high density of boundary delimiters. Because Tornado splits the entire request body in memory prior to enforcing the max_parts validation threshold, the Python interpreter attempts to materialize a massive list of byte segments. This triggers an immediate memory exhaustion (OOM) crash or server-wide CPU starvation before the payload can be validated and rejected.
The league/commonmark library is subject to multiple denial of service vulnerabilities. These stem from three independent algorithmic complexity weaknesses in Markdown parsing: regular expression backtracking, reference link normalization, and delimiter processing. Remote, unauthenticated attackers can exploit these flaws by submitting crafted Markdown input to exhaust CPU execution resources, leading to application-wide thread exhaustion.
An inconsistency in whitespace handling between the PCRE regex engine, PHP's native trim function, and web browsers allows unauthenticated attackers to bypass XSS protections in the league/commonmark AttributesExtension by injecting a Form Feed (U+000C) control character.
GHSA-JJV6-8J6V-6J52 details multiple algorithmic complexity issues in the SmartPunct and Attributes extensions of the league/commonmark PHP library, leading to high CPU consumption and Denial of Service (DoS) when parsing pathological Markdown inputs.