Feb 25, 2026·6 min read·6 visits
Pimcore versions prior to 12.3.3 contain a classic SQL Injection flaw in the `Dependency Dao` class. Authenticated admins can exploit the `filter` parameter to dump the entire database, including password hashes, despite the application using an ORM.
A critical SQL Injection vulnerability in the Pimcore platform allows authenticated administrators to execute arbitrary SQL commands via the dependency listing feature. By manipulating JSON filter parameters, attackers can bypass sanitization and inject malicious payloads directly into `RLIKE` clauses.
Pimcore is one of those massive, 'do-it-all' platforms. It handles Product Information Management (PIM), Digital Asset Management (DAM), and Customer Data Platforms (CDP). It’s the digital equivalent of a Swiss Army knife that also tries to be a toaster. When software tries to do everything, the attack surface expands exponentially.
In this episode of 'Why is my database leaking?', we're looking at a feature designed to help administrators track dependencies. For example, if you want to delete an image, Pimcore checks if that image is used in a product page. Useful? Absolutely. Safe? Well, usually.
But in CVE-2026-27461, this innocent dependency checker becomes a gateway to the database's soul. The vulnerability lies deep within the Data Access Object (DAO) layer—specifically where the application tries to filter these dependencies using regular expressions. Spoiler alert: mixing SQL, Regex, and user input without a condom (parameterization) is a bad idea.
You would think that by 2026, direct string concatenation in SQL queries would be an extinct species, like the Dodo or a printer that works on the first try. Unfortunately, it’s alive and well in models/Dependency/Dao.php.
The flaw occurs in two methods: getFilterRequiresByPath and getFilterRequiredByPath. These functions accept a $value parameter, which comes from a JSON-decoded query string sent by the frontend. The developer intended to let users filter the list of dependencies using a search string.
Instead of passing this search string to a prepared statement, the code takes the raw value and drops it directly into a SQL RLIKE clause. The RLIKE operator in MySQL/MariaDB checks if a string matches a regular expression. The logic looked something like this:
... AND column RLIKE '" . $value . "'
See the problem? If $value contains a single quote, the string terminates, and the SQL parser starts interpreting the rest of the input as commands. It’s the oldest trick in the book, and it still works because developers often forget that 'Search Filters' are just as dangerous as 'Login Forms'.
Let's look at the crime scene. In the vulnerable version of models/Dependency/Dao.php, the query construction was reckless. Here is the simplified vulnerable code:
// VULNERABLE CODE
$query = "SELECT ... FROM dependencies d ...
WHERE ... AND LOWER(CONCAT(o.path, o.key)) RLIKE '" . $value . "'";
// Execution (No parameter binding for $value)
$this->db->fetchAllAssociative($query);There is zero sanitation here. If $value is admin, the query is safe. If $value is admin' OR '1'='1, the query becomes a logic bomb.
The fix, introduced in version 12.3.3, is a textbook example of how to do it right. The developers switched to Doctrine DBAL's prepared statements:
// PATCHED CODE
$query = "SELECT ... FROM dependencies d ...
WHERE ... AND LOWER(CONCAT(o.path, o.key)) RLIKE :value";
$params = [
'value' => preg_quote((string) $value) // Double protection!
];
$types = ['value' => ParameterType::STRING];
$this->db->fetchAllAssociative($query, $params, $types);Notice two things here. First, the use of :value placeholder ensures the database driver handles the escaping. Second, they wrapped the value in preg_quote(). This is clever—since RLIKE expects a regex, a malicious user could potentially inject a "Regular Expression Denial of Service" (ReDoS) payload even if they couldn't inject SQL. By quoting the regex characters, they neutralized both the SQL injection and the regex complexity attack.
Now for the fun part. How do we weaponize this? The vulnerability requires authentication, specifically as an administrator with access to the dependency tab. While this sounds like a high barrier, consider the insider threat or a scenario where an attacker compromises a low-level admin account via XSS or phishing.
The Setup:
filter parameter.The Attack:
The filter parameter is a JSON object. It looks like this: {"value": "search_term"}. We can intercept this request and inject our SQL payload.
Payload Construction:
We need to break out of the single quotes inside the RLIKE.
{
"value": "') OR (SELECT SLEEP(5)) -- "
}When the backend processes this, the SQL becomes:
... RLIKE '') OR (SELECT SLEEP(5)) -- 'If the server hangs for 5 seconds, we have confirmed blind SQL injection. From here, we can use tools like sqlmap or manual enumeration to extract the users table. Since we are already an admin, why do we care? Because we might be a restricted admin, and this vulnerability allows us to dump the hashes of the super admins, or access tables containing customer PII that our specific user role shouldn't see.
A common dismissal for vulnerabilities like this is, "But you need admin access!" This is true, and it does lower the CVSS score (hence the 6.9 Medium). However, in the real world, the perimeter is often soft.
If an attacker gains initial access to the Pimcore backend—perhaps through a weak password or a leaked session cookie—they are usually confined to specific permissions. Pimcore has a granular permission system (Object-level security). This SQL Injection blows that wide open.
With this vulnerability, a user who is only supposed to edit "Blog Posts" can execute SELECT * FROM payment_gateways or SELECT * FROM users. It is a vertical privilege escalation from "Content Editor" to "Database God." Furthermore, if this Pimcore instance is connected to other internal systems via database links, the attacker could pivot laterally across the infrastructure.
The remediation is straightforward: Update Pimcore to version 12.3.3 or later. The patch effectively closes the hole by enforcing strict typing and parameter binding.
If you cannot upgrade immediately (perhaps you're stuck on a legacy 11.x build), you can manually patch models/Dependency/Dao.php. You must replace the string concatenation with Doctrine's placeholders.
Developer Takeaway:
Never trust input, even if it comes from an 'Admin'. Just because a user is authenticated doesn't mean they aren't malicious (or compromised). Also, treat RLIKE, REGEXP, and ORDER BY clauses with extreme suspicion—they are often overlooked by automatic scanners and ORMs, making them prime targets for manual code review.
CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N| Product | Affected Versions | Fixed Version |
|---|---|---|
Pimcore Pimcore | <= 11.5.14.1 | 12.3.3 |
Pimcore Pimcore | >= 12.0.0, < 12.3.3 | 12.3.3 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-89 (SQL Injection) |
| CVSS v4.0 | 6.9 (Medium) |
| Attack Vector | Network (Authenticated Admin) |
| Vulnerable Parameter | JSON 'filter' -> 'value' |
| Sink | SQL RLIKE clause |
| Exploit Maturity | Proof of Concept (High Probability) |
The software constructs all or part of an SQL command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended SQL command when it is sent to a downstream component.