CVE-2026-23492

Pimcore SQLi: When a 'Fix' is Just a Band-Aid

Amit Schendel
Amit Schendel
Senior Security Researcher

Jan 15, 2026·6 min read

Executive Summary (TL;DR)

Pimcore tried to fix an SQL injection in 2023 by deleting double dashes (`--`) and hiding error messages. It didn't work. CVE-2026-23492 is the result: a high-severity Blind SQL Injection in the Admin Search Find API that allows attackers to exfiltrate the entire database using time-based payloads. If you run Pimcore < 11.5.14 or < 12.3.1, patch immediately.

A critical Blind SQL Injection vulnerability in Pimcore's Admin Search API caused by a failed attempt to patch a previous vulnerability (CVE-2023-30848). Developers relied on a blacklist approach—stripping SQL comments—and error suppression, leaving the core injection flaw wide open to authenticated attackers.

The Hook: Searching for Trouble

Every complex web application needs a search bar, and in the world of Content Management Systems (CMS), the Admin Search is the nerve center. It allows administrators to query users, assets, objects, and documents. In Pimcore, this functionality is handled by the Admin Search Find API at /admin/search/search/find. It’s a powerful endpoint designed to take complex filters and return precise data.

However, power often breeds fragility. When you allow users to define how the database is queried—specifying fields, filters, and structures—you are walking a tightrope over the pit of SQL injection. The developers knew this. They had already been bitten by this exact endpoint in the past (CVE-2023-30848). But as we'll see, recognizing a problem and actually fixing it are two very different disciplines.

This vulnerability isn't just a coding error; it's a lesson in why "mitigation" is not a synonym for "remediation." The feature meant to help admins find content is now the perfect tool for attackers to find your secrets.

The Flaw: A History of Bad Ideas

To understand CVE-2026-23492, we have to look at the ghost of vulnerabilities past. In CVE-2023-30848, attackers found they could inject SQL via the fields[] parameter. The development team's response was... optimistic. They implemented two specific defenses: a blacklist sanitizer and error suppression.

First, they added str_replace('--', '', $fields). This logic assumes that if you remove the SQL comment syntax (--), an attacker can't construct a valid malicious query. This is akin to removing the firing pin from a gun but leaving the loaded chamber and hammer intact. SQL injection does not require comments; they are just a convenience for attackers to ignore the rest of the original query.

Second, they wrapped the execution in a try/catch block that suppressed SyntaxErrorException. This stopped the application from vomiting stack traces (which prevents Error-Based SQLi), but it did absolutely nothing to stop the database from executing a query that didn't cause a syntax error. If the query runs—even slowly—we have a vulnerability.

The Code: The Smoking Gun

Let's look at the PHP code responsible for this logic. This snippet from SearchController.php shows exactly how the incomplete patch was implemented. It essentially scrubs the input for one specific character sequence and then feeds it into the query builder.

// Pimcore\Bundle\AdminBundle\Controller\Searchadmin\SearchController.php
 
$fields = $allParams['fields'];
 
// The "Fix": remove sql comments (useless against advanced injection)
$fields = str_replace('--', '', $fields);
 
foreach ($fields as $f) {
    // The input is split, but the first part is still raw user data
    $parts = explode('~', $f);
    
    // $parts[0] is eventually concatenated into the SQL query
    // ...
}
 
try {
    // The query executes. If it's valid SQL, it runs.
    $hits = $searcherList->load();
} catch (SyntaxErrorException $syntaxErrorException) {
    // Hiding the evidence doesn't stop the crime
    throw new \InvalidArgumentException('Check your arguments.');
}

The fundamental issue here is concatenation. The variable $parts[0] (derived from the GET parameter) is treated as a column name or expression in the generated SQL. Because the developers only stripped --, we can still inject spaces, quotes, logic operators (AND, OR), and functions (SLEEP, BENCHMARK).

The Exploit: Sleeping on the Job

Since the application suppresses errors, we can't use standard error-based techniques. We also can't easily see the output of our injection in the JSON response because the query logic is complex. This forces us into Blind SQL Injection territory.

The most reliable way to prove existence is a Time-Based attack. We ask the database a question: "Is the first letter of the database version '5'?" If the answer is YES, we tell the database to sleep for 5 seconds. If NO, it returns immediately.

Here is the attack flow:

The Payload: We inject a logical test into the fields[] array. Note that we don't need -- to make this valid SQL if we carefully balance our parentheses.

GET /admin/search/search/find?query=2&
fields[]=field1 AND IF(1=1,SLEEP(5),0)~field2&
filter=[{"property":"value"}]&
class=classname

If the server hangs for 5 seconds, we have confirmed RCE (Remote Code Execution) on the database context. An attacker would script this to extract the admin password hash character by character.

The Impact: Total Recall

Why should you panic? Because this is the Admin interface. While the vulnerability requires authentication, in many organizations, "Admin" access is tiered. A lower-privileged user with access to the search function (e.g., a content editor) could use this to elevate privileges to Super Admin by dumping the users table.

Furthermore, the database user backing a Pimcore instance often has significant privileges. An attacker could:

  1. Exfiltrate Customer Data: Dump the entire customer database via blind extraction.
  2. Read Files: If the DB user has FILE privileges, they could read /etc/passwd or configuration files.
  3. Lateral Movement: Use the database access to pivot to other systems connected to the same DB cluster.

This isn't just about reading data; it's about owning the platform's foundation.

The Fix: Do It Right This Time

The remediation is straightforward but requires a shift in mindset. You cannot sanitize SQL injection with str_replace. You must use Parameterization or strictly allow-list the input.

Pimcore has released versions 11.5.14 and 12.3.1 to address this. The fix involves refactoring the Searcher class to validate that the input provided in fields corresponds to actual existing columns in the data definition, rejecting any input that contains SQL logic or unknown identifiers.

If you cannot patch immediately, you can attempt to block these requests at the WAF level, but be warned: WAF rules for SQLi are notoriously easy to bypass with obfuscation. The only real fix is the patch.

Fix Analysis (1)

Technical Appendix

CVSS Score
8.8/ 10
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
EPSS Probability
0.04%
Top 100% most exploited

Affected Systems

Pimcore < 11.5.14Pimcore >= 12.0.0-RC1, < 12.3.1

Affected Versions Detail

Product
Affected Versions
Fixed Version
Pimcore
Pimcore
< 11.5.1411.5.14
Pimcore
Pimcore
>= 12.0.0-RC1, < 12.3.112.3.1
AttributeDetail
CWECWE-89 (SQL Injection)
CVSS v3.18.8 (High)
Attack VectorNetwork (Authenticated)
Vulnerability TypeBlind SQL Injection (Boolean/Time-based)
Previous FailIncomplete fix for CVE-2023-30848
StatusPatched
CWE-89
Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')

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.

Vulnerability Timeline

Original incomplete fix (CVE-2023-30848) committed
2023-04-25
CVE-2026-23492 Disclosed
2026-01-14
Patches released for v11 and v12
2026-01-14

Subscribe to updates

Get the latest CVE analysis reports delivered to your inbox.