{"id":"CVE-2026-44741","aliases":["EUVD-2026-57357","GHSA-h4ph-crvj-9h92"],"status":"published","title":"Pimcore Admin Classic Bundle Vulnerable to SQL Injection in Translation Grid Date Filter via Unsanitized Property Parameter","description":"Pimcore's Admin Classic Bundle provides a Backend UI for Pimcore. Versions prior to 2.3.6 and 1.7.18 have a SQL injection vulnerability in Pimcore's translation grid date filter — the user-supplied `property` field from the filter JSON is interpolated directly into a `UNIX_TIMESTAMP(DATE(FROM_UNIXTIME(...)))` SQL expression without parameterization or allowlist validation. Versiosn 2.3.6 and 1.7.18 fix the issue.","severity":{"version":"3.1","score":8.8,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H","level":"high","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-09","score":0.005,"percentile":0.43109,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-89"],"published":"2026-05-27T00:35:56Z","modified":"2026-10-28T02:30:59Z","fixes":[{"ecosystem":"Packagist","package":"pimcore/admin-ui-classic-bundle","fixed_in":["2.3.6","1.7.18"],"sources":["ghsa","osv"]}],"affected":[{"source":"ghsa","ecosystem":"Packagist","package":"pimcore/admin-ui-classic-bundle","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"2.0.0-RC1"},{"last_affected":"2.3.5"},{"fixed":"2.3.6"}]}]},{"source":"ghsa","ecosystem":"Packagist","package":"pimcore/admin-ui-classic-bundle","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"1.7.18"}]}]},{"source":"osv","ecosystem":"Packagist","package":"pimcore/admin-ui-classic-bundle","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"2.0.0-RC1"},{"fixed":"2.3.6"}]}],"versions":["2.0.0-RC2","v2.0.0","v2.0.0-RC1","v2.0.0-RC3","v2.0.0-RC4","v2.0.1","v2.0.2","v2.1.0","v2.1.1","v2.1.2","v2.1.3","v2.1.4","v2.2.0","v2.2.1","v2.2.2","v2.2.3","v2.3.0","v2.3.1","v2.3.2","v2.3.3","v2.3.4"]},{"source":"osv","ecosystem":"Packagist","package":"pimcore/admin-ui-classic-bundle","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"1.7.18"}]}],"versions":["1.4.0","v1.0.0","v1.0.0-BETA1","v1.0.0-RC1","v1.0.0-RC2","v1.0.1","v1.0.2","v1.0.3","v1.0.4","v1.0.5","v1.0.6","v1.1.0","v1.1.0-RC1","v1.1.1","v1.1.2","v1.1.3","v1.1.4","v1.2","v1.2.0-RC1","v1.2.1","v1.2.2","v1.2.3","v1.3.0","v1.3.0-RC1","v1.3.1","v1.3.2","v1.3.3","v1.3.4","v1.3.5","v1.4.1","v1.4.2","v1.4.3","v1.4.4","v1.4.5","v1.5.0","v1.5.0-RC1","v1.5.0-RC2","v1.5.1","v1.5.2","v1.5.3","v1.5.4","v1.5.5","v1.6.0","v1.6.0-RC1","v1.6.0-RC2","v1.6.1","v1.6.2","v1.6.3","v1.6.4","v1.6.5","v1.6.6","v1.7.0","v1.7.1","v1.7.10","v1.7.12","v1.7.13","v1.7.14","v1.7.15","v1.7.16","v1.7.2","v1.7.3","v1.7.4","v1.7.5","v1.7.6","v1.7.7","v1.7.8","v1.7.9"]}],"products":[{"vendor":"pimcore","product":"pimcore"}],"references":[{"url":"https://github.com/pimcore/pimcore/security/advisories/GHSA-h4ph-crvj-9h92","tags":["x_refsource_CONFIRM","exploit","advisory","web"]},{"url":"https://github.com/pimcore/admin-ui-classic-bundle/pull/1111","tags":["x_refsource_MISC","fix","web"]},{"url":"https://github.com/pimcore/admin-ui-classic-bundle/commit/80e57a23d9e19574eddfe9b08e8f26785b2b0d90","tags":["x_refsource_MISC","fix","web"]},{"url":"https://github.com/pimcore/admin-ui-classic-bundle/releases/tag/v2.3.6","tags":["x_refsource_MISC","web"]},{"url":"https://github.com/advisories/GHSA-h4ph-crvj-9h92"},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/44xxx/CVE-2026-44741.json","tags":["advisory"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-44741","tags":["advisory"]},{"url":"https://github.com/pimcore/pimcore","tags":["package"]}],"sources":{"cve":[{"id":"CVE-2026-44741","title":"Pimcore Admin Classic Bundle Vulnerable to SQL Injection in Translation Grid Date Filter via Unsanitized Property Parameter","description":"Pimcore's Admin Classic Bundle provides a Backend UI for Pimcore. Versions prior to 2.3.6 and 1.7.18 have a SQL injection vulnerability in Pimcore's translation grid date filter — the user-supplied `property` field from the filter JSON is interpolated directly into a `UNIX_TIMESTAMP(DATE(FROM_UNIXTIME(...)))` SQL expression without parameterization or allowlist validation. Versiosn 2.3.6 and 1.7.18 fix the issue.","status":"published","published":"2026-08-12T17:06:19.479Z","modified":"2026-08-12T17:56:20.692Z","cvss":[{"version":"3.1","score":8.8,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H","level":"high","assessor":"cna"}],"cwes":["CWE-89"],"updated_at":"2026-11-02T13:42:49.132798Z"}],"euvd":[{"id":"EUVD-2026-57357","description":"Pimcore's Admin Classic Bundle provides a Backend UI for Pimcore. Versions prior to 2.3.6 and 1.7.18 have a SQL injection vulnerability in Pimcore's translation grid date filter — the user-supplied `property` field from the filter JSON is interpolated directly into a `UNIX_TIMESTAMP(DATE(FROM_UNIXTIME(...)))` SQL expression without parameterization or allowlist validation. Versiosn 2.3.6 and 1.7.18 fix the issue.","status":"published","published":"2026-08-12T17:06:19Z","modified":"2026-08-12T17:56:20Z","cvss":[{"version":"3.1","score":8.8,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H","level":"high"}],"updated_at":"2026-11-02T18:01:57.953172Z"}],"ghsa":[{"id":"GHSA-h4ph-crvj-9h92","title":"Pimcore Admin Classic Bundle Vulnerable to SQL Injection in Translation Grid Date Filter via Unsanitized Property Parameter","description":"# GitHub Security Advisory Draft — GM-369\n\n## Summary\nSQL injection in Pimcore's translation grid date filter — the user-supplied `property` field from the filter JSON is interpolated directly into a `UNIX_TIMESTAMP(DATE(FROM_UNIXTIME(...)))` SQL expression without parameterization or allowlist validation.\n\n## Severity\nCVSS 3.1: 8.8 (High) — AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H\n\n## Affected Component\n- **Package:** `pimcore/admin-ui-classic-bundle`\n- **File:** `src/Controller/Admin/TranslationController.php`\n- **Lines:** 565 (input), 569 (inadequate sanitization), 593 (injection point)\n- **Endpoint:** `POST /admin/translation/translations`\n\n## Description\nThe translation grid endpoint processes JSON filter parameters. When a filter has `type: \"date\"`, the `property` field is extracted and used to construct a SQL expression:\n\n```php\n$fieldname = $filter[$propertyField];              // Line 565 — user input\n$fieldname = str_replace('--', '', $fieldname);    // Line 569 — trivially bypassable\n$fieldname = $tableName . '.' . $fieldname;        // Line 577\n$fieldname = \"UNIX_TIMESTAMP(DATE(FROM_UNIXTIME({$fieldname})))\";  // Line 593 — injection\n```\n\nThe `str_replace('--', '')` sanitization is trivially bypassable (use `/**/` comments or `----`). In non-language mode, `$fieldname` is concatenated directly into the SQL condition without quoting or parameterization.\n\n## Impact\nAuthenticated user with translations view permission can extract arbitrary database data via UNION-based or error-based SQL injection. Combined with GM-249 (unsafe unserialize), this enables an SQLi → deserialization → RCE chain.\n\n## Proof of Concept\n```\nPOST /admin/translation/translations\nfilter=[{\"property\":\"1))) UNION SELECT password FROM users WHERE ((1\",\"type\":\"date\",\"operator\":\"eq\",\"value\":\"2026-01-01\"}]\n```\n\n## Suggested Fix\nValidate `$fieldname` against an allowlist of valid column names before SQL interpolation:\n```php\n$allowedDateColumns = ['creationDate', 'modificationDate'];\nif (!in_array($fieldname, $allowedDateColumns, true)) {\n    continue;\n}\n```\n\n## References\n- CWE-89: SQL Injection\n- Related: CVE-2026-27461 (RLIKE injection in Dependency/Dao.php — different code path)\n\n\n---\n\n## Suggested Fix\n\nIn `TranslationController.php`: (1) Add allowlist check for non-language fieldnames before processing. (2) Replace raw string interpolation `UNIX_TIMESTAMP(DATE(FROM_UNIXTIME({$fieldname})))` with `$db-\u003equoteIdentifier($fieldname)` to prevent SQL injection in date filter expressions.\n\n```diff\n--- a/src/Controller/Admin/TranslationController.php\n+++ b/src/Controller/Admin/TranslationController.php\n@@ -569,7 +569,15 @@ class TranslationController extends AdminAbstractController\n                 $fieldname = str_replace('--', '', $fieldname);\n \n                 if (!$languageMode \u0026\u0026 in_array($fieldname, $validLanguages)\n                     || $languageMode \u0026\u0026 !in_array($fieldname, $validLanguages)) {\n                     continue;\n                 }\n \n+                // Allowlist non-language fieldnames to prevent SQL injection\n+                $allowedNonLanguageFields = ['key', 'type', 'creationDate', 'modificationDate'];\n+                if (!$languageMode \u0026\u0026 !in_array($fieldname, $allowedNonLanguageFields) \u0026\u0026 !in_array($fieldname, $validLanguages)) {\n+                    continue;\n+                }\n+\n                 if (!$languageMode) {\n                     $fieldname = $tableName . '.' . $fieldname;\n                 }\n@@ -582,7 +590,7 @@ class TranslationController extends AdminAbstractController\n                         } elseif ($filter[$operatorField] == 'eq') {\n                             $operator = '=';\n-                            $fieldname = \"UNIX_TIMESTAMP(DATE(FROM_UNIXTIME({$fieldname})))\";\n+                            // Use validated fieldname only — never interpolate raw user input into SQL functions\n+                            $fieldname = sprintf('UNIX_TIMESTAMP(DATE(FROM_UNIXTIME(%s)))', $db-\u003equoteIdentifier($fieldname));\n                         }\n\n```\n\n---\n\n## Proposed Fix\n\n```diff\n--- a/src/Controller/Admin/TranslationController.php\n+++ b/src/Controller/Admin/TranslationController.php\n@@ -569,7 +569,15 @@ class TranslationController extends AdminAbstractController\n                 $fieldname = str_replace('--', '', $fieldname);\n \n                 if (!$languageMode \u0026\u0026 in_array($fieldname, $validLanguages)\n                     || $languageMode \u0026\u0026 !in_array($fieldname, $validLanguages)) {\n                     continue;\n                 }\n \n+                // Allowlist non-language fieldnames to prevent SQL injection\n+                $allowedNonLanguageFields = ['key', 'type', 'creationDate', 'modificationDate'];\n+                if (!$languageMode \u0026\u0026 !in_array($fieldname, $allowedNonLanguageFields) \u0026\u0026 !in_array($fieldname, $validLanguages)) {\n+                    continue;\n+                }\n+\n                 if (!$languageMode) {\n                     $fieldname = $tableName . '.' . $fieldname;\n                 }\n@@ -582,7 +590,7 @@ class TranslationController extends AdminAbstractController\n                         } elseif ($filter[$operatorField] == 'eq') {\n                             $operator = '=';\n-                            $fieldname = \"UNIX_TIMESTAMP(DATE(FROM_UNIXTIME({$fieldname})))\";\n+                            // Use validated fieldname only — never interpolate raw user input into SQL functions\n+                            $fieldname = sprintf('UNIX_TIMESTAMP(DATE(FROM_UNIXTIME(%s)))', $db-\u003equoteIdentifier($fieldname));\n                         }\n```\n\nHappy to submit this as a PR against a private fork if that is the preferred workflow.","status":"published","published":"2026-05-27T00:35:56Z","modified":"2026-07-10T19:07:23Z","cvss":[{"version":"3.1","score":8.8,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H","level":"high"}],"cwes":["CWE-89"],"updated_at":"2026-11-02T14:40:42.703776Z"}],"nvd":[{"id":"CVE-2026-44741","description":"Pimcore's Admin Classic Bundle provides a Backend UI for Pimcore. Versions prior to 2.3.6 and 1.7.18 have a SQL injection vulnerability in Pimcore's translation grid date filter — the user-supplied `property` field from the filter JSON is interpolated directly into a `UNIX_TIMESTAMP(DATE(FROM_UNIXTIME(...)))` SQL expression without parameterization or allowlist validation. Versiosn 2.3.6 and 1.7.18 fix the issue.","status":"published","published":"2026-08-12T18:17:29.823Z","modified":"2026-09-16T13:42:43.377Z","cvss":[{"version":"3.1","score":8.8,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H","level":"high","assessor":"secondary"}],"cwes":["CWE-89"],"updated_at":"2026-11-02T14:12:37.217486Z"}],"osv":[{"id":"CVE-2026-44741","title":"Pimcore Admin Classic Bundle Vulnerable to SQL Injection in Translation Grid Date Filter via Unsanitized Property Parameter","description":"Pimcore's Admin Classic Bundle provides a Backend UI for Pimcore. Versions prior to 2.3.6 and 1.7.18 have a SQL injection vulnerability in Pimcore's translation grid date filter — the user-supplied `property` field from the filter JSON is interpolated directly into a `UNIX_TIMESTAMP(DATE(FROM_UNIXTIME(...)))` SQL expression without parameterization or allowlist validation. Versiosn 2.3.6 and 1.7.18 fix the issue.","status":"published","published":"2026-08-12T17:06:19.479Z","modified":"2026-10-28T02:30:59.105016433Z","cvss":[{"version":"3.1","score":8.8,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H","level":"high"}],"cwes":["CWE-89"],"updated_at":"2026-11-02T15:45:05.172514Z"},{"id":"GHSA-h4ph-crvj-9h92","title":"Pimcore Admin Classic Bundle Vulnerable to SQL Injection in Translation Grid Date Filter via Unsanitized Property Parameter","description":"# GitHub Security Advisory Draft — GM-369\n\n## Summary\nSQL injection in Pimcore's translation grid date filter — the user-supplied `property` field from the filter JSON is interpolated directly into a `UNIX_TIMESTAMP(DATE(FROM_UNIXTIME(...)))` SQL expression without parameterization or allowlist validation.\n\n## Severity\nCVSS 3.1: 8.8 (High) — AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H\n\n## Affected Component\n- **Package:** `pimcore/admin-ui-classic-bundle`\n- **File:** `src/Controller/Admin/TranslationController.php`\n- **Lines:** 565 (input), 569 (inadequate sanitization), 593 (injection point)\n- **Endpoint:** `POST /admin/translation/translations`\n\n## Description\nThe translation grid endpoint processes JSON filter parameters. When a filter has `type: \"date\"`, the `property` field is extracted and used to construct a SQL expression:\n\n```php\n$fieldname = $filter[$propertyField];              // Line 565 — user input\n$fieldname = str_replace('--', '', $fieldname);    // Line 569 — trivially bypassable\n$fieldname = $tableName . '.' . $fieldname;        // Line 577\n$fieldname = \"UNIX_TIMESTAMP(DATE(FROM_UNIXTIME({$fieldname})))\";  // Line 593 — injection\n```\n\nThe `str_replace('--', '')` sanitization is trivially bypassable (use `/**/` comments or `----`). In non-language mode, `$fieldname` is concatenated directly into the SQL condition without quoting or parameterization.\n\n## Impact\nAuthenticated user with translations view permission can extract arbitrary database data via UNION-based or error-based SQL injection. Combined with GM-249 (unsafe unserialize), this enables an SQLi → deserialization → RCE chain.\n\n## Proof of Concept\n```\nPOST /admin/translation/translations\nfilter=[{\"property\":\"1))) UNION SELECT password FROM users WHERE ((1\",\"type\":\"date\",\"operator\":\"eq\",\"value\":\"2026-01-01\"}]\n```\n\n## Suggested Fix\nValidate `$fieldname` against an allowlist of valid column names before SQL interpolation:\n```php\n$allowedDateColumns = ['creationDate', 'modificationDate'];\nif (!in_array($fieldname, $allowedDateColumns, true)) {\n    continue;\n}\n```\n\n## References\n- CWE-89: SQL Injection\n- Related: CVE-2026-27461 (RLIKE injection in Dependency/Dao.php — different code path)\n\n\n---\n\n## Suggested Fix\n\nIn `TranslationController.php`: (1) Add allowlist check for non-language fieldnames before processing. (2) Replace raw string interpolation `UNIX_TIMESTAMP(DATE(FROM_UNIXTIME({$fieldname})))` with `$db-\u003equoteIdentifier($fieldname)` to prevent SQL injection in date filter expressions.\n\n```diff\n--- a/src/Controller/Admin/TranslationController.php\n+++ b/src/Controller/Admin/TranslationController.php\n@@ -569,7 +569,15 @@ class TranslationController extends AdminAbstractController\n                 $fieldname = str_replace('--', '', $fieldname);\n \n                 if (!$languageMode \u0026\u0026 in_array($fieldname, $validLanguages)\n                     || $languageMode \u0026\u0026 !in_array($fieldname, $validLanguages)) {\n                     continue;\n                 }\n \n+                // Allowlist non-language fieldnames to prevent SQL injection\n+                $allowedNonLanguageFields = ['key', 'type', 'creationDate', 'modificationDate'];\n+                if (!$languageMode \u0026\u0026 !in_array($fieldname, $allowedNonLanguageFields) \u0026\u0026 !in_array($fieldname, $validLanguages)) {\n+                    continue;\n+                }\n+\n                 if (!$languageMode) {\n                     $fieldname = $tableName . '.' . $fieldname;\n                 }\n@@ -582,7 +590,7 @@ class TranslationController extends AdminAbstractController\n                         } elseif ($filter[$operatorField] == 'eq') {\n                             $operator = '=';\n-                            $fieldname = \"UNIX_TIMESTAMP(DATE(FROM_UNIXTIME({$fieldname})))\";\n+                            // Use validated fieldname only — never interpolate raw user input into SQL functions\n+                            $fieldname = sprintf('UNIX_TIMESTAMP(DATE(FROM_UNIXTIME(%s)))', $db-\u003equoteIdentifier($fieldname));\n                         }\n\n```\n\n---\n\n## Proposed Fix\n\n```diff\n--- a/src/Controller/Admin/TranslationController.php\n+++ b/src/Controller/Admin/TranslationController.php\n@@ -569,7 +569,15 @@ class TranslationController extends AdminAbstractController\n                 $fieldname = str_replace('--', '', $fieldname);\n \n                 if (!$languageMode \u0026\u0026 in_array($fieldname, $validLanguages)\n                     || $languageMode \u0026\u0026 !in_array($fieldname, $validLanguages)) {\n                     continue;\n                 }\n \n+                // Allowlist non-language fieldnames to prevent SQL injection\n+                $allowedNonLanguageFields = ['key', 'type', 'creationDate', 'modificationDate'];\n+                if (!$languageMode \u0026\u0026 !in_array($fieldname, $allowedNonLanguageFields) \u0026\u0026 !in_array($fieldname, $validLanguages)) {\n+                    continue;\n+                }\n+\n                 if (!$languageMode) {\n                     $fieldname = $tableName . '.' . $fieldname;\n                 }\n@@ -582,7 +590,7 @@ class TranslationController extends AdminAbstractController\n                         } elseif ($filter[$operatorField] == 'eq') {\n                             $operator = '=';\n-                            $fieldname = \"UNIX_TIMESTAMP(DATE(FROM_UNIXTIME({$fieldname})))\";\n+                            // Use validated fieldname only — never interpolate raw user input into SQL functions\n+                            $fieldname = sprintf('UNIX_TIMESTAMP(DATE(FROM_UNIXTIME(%s)))', $db-\u003equoteIdentifier($fieldname));\n                         }\n```\n\nHappy to submit this as a PR against a private fork if that is the preferred workflow.","status":"published","published":"2026-05-27T00:35:56Z","modified":"2026-07-10T19:15:11.856742087Z","cvss":[{"version":"3.1","score":8.8,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H","level":"high"}],"cwes":["CWE-89"],"updated_at":"2026-11-02T15:46:48.546324Z"}]}}
