GHSA-7X43-MPFG-R9WJ

Vulnerability from github – Published: 2026-03-03 20:38 – Updated: 2026-03-04 18:38
VLAI?
Summary
Craft CMS has IDOR via GraphQL @parseRefs
Details

The GraphQL directive @parseRefs, intended to parse internal reference tags (e.g., {user:1:email}), can be abused by both authenticated users and unauthenticated guests (if a Public Schema is enabled) to access sensitive attributes of any element in the CMS. The implementation in Elements::parseRefs fails to perform authorization checks, allowing attackers to read data they are not authorized to view.

Vulnerability Details

craft\services\Elements::parseRefs identifies reference tags and resolves them using _getRefTokenReplacement. This method fetches the referenced element and accesses the specified attribute via $element->$attribute.

  • Missing Auth Check: It bypasses canView() checks.
  • Polymorphic Access: getElementTypeByRefHandle allows referencing any element type (entry, asset, user, category).
  • Custom Field Access: Since Craft elements use __get() to resolve custom field handles, an attacker is not limited to core attributes. They can exfiltrate any custom field data by enumerating the field handle (e.g. {entry:123:privateNotes}).

Attack Vectors

  1. Privilege Escalation / User Data Leak

An attacker can enumerate sensitive attributes of administrators or other users.

  • Payload: {user:1:email} or {user:1:photoId}

  • Arbitrary Property Reflection & Server-Side Logic Execution

The vulnerability allows reflecting any accessible property of the underlying Element model.

  • Username/Admin Enumeration: {user:1:username} (Confirmed: returns admin), {user:1:admin}.
  • Internal Path Disclosure: Accessing methods that trigger errors (e.g., {user:1:authKey}) exposes full server stack traces in the GraphQL error response (e.g., Exception: No user session token exists with paths like /var/www/html/...).

  • IDOR on Private Entries & Assets (Polymorphism)

The vulnerability is not limited to Users. Reference tags can target any element type.

  • Payload: {entry:456:myConfidentialField} (Bypasses canView checks).
  • Asset Path Leakage: {volume:1:path} can expose internal file system paths.

  • Unauthenticated Exploitation (Public Schema)

Confirmed locally. The @parseRefs directive is active in the Public Schema. By injecting a payload into a public-facing field (e.g., a "News" entry title), an unauthenticated guest can trigger the resolution and retrieve the sensitive output.

Steps to Reproduce

  1. Setup (Admin Panel):
  2. Create a Section (e.g., "News") and an Entry Type.
  3. Create a new Entry in that section. Set the Title to the payload: {user:1:username} or {user:1:email}.
  4. Go to GraphQL > Schemas > Public Schema. Enable it, and ensure "Query for elements in the Site" and "News" section queries are checked.

  5. Execute Exploit (Unauthenticated):

  6. Send a POST request to http://localhost:8000/index.php?action=graphql/api:
curl -X POST \
-H "Content-Type: application/json" \
-d '{"query": "{ entries { title @parseRefs } }"}'
  1. Observation:
  2. The API returns {"data":{"entries":[{"title":"admin"}]}} (or the email).
  3. Using {user:1:authKey} triggers an internal server error that leaks the full server path in string format.

Impact

  • Critical Information Disclosure: Full PII enumeration (emails, usernames).
  • System Information Leakage: Absolute server paths via stack traces.
  • Authentication Bypass: Guest accounts can effectively query the database as the system user.

Recommended Fix

Modify Elements::parseRefs to enforce canView permissions on the resolved element before extracting attributes.

References

https://github.com/craftcms/cms/commit/4d98a07e47580f1712095825d3e3c4d67bc9f8b9

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "craftcms/cms"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "4.0.0-RC1"
            },
            {
              "fixed": "4.17.0-beta.1"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "craftcms/cms"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "5.0.0-RC1"
            },
            {
              "fixed": "5.9.0-beta.1"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-28696"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-639",
      "CWE-862"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-03-03T20:38:55Z",
    "nvd_published_at": "2026-03-04T17:16:21Z",
    "severity": "HIGH"
  },
  "details": "The GraphQL directive `@parseRefs`, intended to parse internal reference tags (e.g., `{user:1:email}`), can be abused by both authenticated users and unauthenticated guests (if a Public Schema is enabled) to access sensitive attributes of any element in the CMS. The implementation in `Elements::parseRefs` fails to perform authorization checks, allowing attackers to read data they are not authorized to view.\n\n## Vulnerability Details\n\n`craft\\services\\Elements::parseRefs` identifies reference tags and resolves them using `_getRefTokenReplacement`. This method fetches the referenced element and accesses the specified attribute via $element-\u003e$attribute.\n\n- Missing Auth Check: It bypasses `canView()` checks.\n- Polymorphic Access: `getElementTypeByRefHandle` allows referencing any element type (entry, asset, user, category).\n- Custom Field Access: Since Craft elements use `__get()` to resolve custom field handles, an attacker is not limited to core attributes. They can exfiltrate any custom field data by enumerating the field handle (e.g. `{entry:123:privateNotes}`).\n\n## Attack Vectors\n\n1. Privilege Escalation / User Data Leak\n\nAn attacker can enumerate sensitive attributes of administrators or other users.\n\n- Payload: `{user:1:email}` or `{user:1:photoId}`\n\n2. Arbitrary Property Reflection \u0026 Server-Side Logic Execution\n\nThe vulnerability allows reflecting any accessible property of the underlying Element model.\n\n- Username/Admin Enumeration: `{user:1:username}` (Confirmed: returns admin), {user:1:admin}.\n- Internal Path Disclosure: Accessing methods that trigger errors (e.g., `{user:1:authKey}`) exposes full server stack traces in the GraphQL error response (e.g., Exception: No user session token exists with paths like `/var/www/html/...`).\n\n3. IDOR on Private Entries \u0026 Assets (Polymorphism)\n\nThe vulnerability is not limited to Users. Reference tags can target any element type.\n\n- Payload: `{entry:456:myConfidentialField}` (Bypasses canView checks).\n- Asset Path Leakage: `{volume:1:path}` can expose internal file system paths.\n\n4. Unauthenticated Exploitation (Public Schema)\n\nConfirmed locally. The `@parseRefs` directive is active in the Public Schema. By injecting a payload into a public-facing field (e.g., a \"News\" entry title), an unauthenticated guest can trigger the resolution and retrieve the sensitive output.\n\n## Steps to Reproduce\n\n1. Setup (Admin Panel):\n- Create a Section (e.g., \"News\") and an Entry Type.\n- Create a new Entry in that section. Set the Title to the payload: {user:1:username} or {user:1:email}.\n- Go to GraphQL \u003e Schemas \u003e Public Schema. Enable it, and ensure \"Query for elements in the Site\" and \"News\" section queries are checked.\n\n2. Execute Exploit (Unauthenticated):\n- Send a POST request to http://localhost:8000/index.php?action=graphql/api:\n```\ncurl -X POST \\\n-H \"Content-Type: application/json\" \\\n-d \u0027{\"query\": \"{ entries { title @parseRefs } }\"}\u0027\n```\n\n3. Observation:\n- The API returns `{\"data\":{\"entries\":[{\"title\":\"admin\"}]}}` (or the email).\n- Using `{user:1:authKey}` triggers an internal server error that leaks the full server path in string format.\n\n## Impact\n\n- Critical Information Disclosure: Full PII enumeration (emails, usernames).\n- System Information Leakage: Absolute server paths via stack traces.\n- Authentication Bypass: Guest accounts can effectively query the database as the system user.\n\n## Recommended Fix\n\nModify `Elements::parseRefs` to enforce `canView` permissions on the resolved element before extracting attributes.\n\n## References\n\nhttps://github.com/craftcms/cms/commit/4d98a07e47580f1712095825d3e3c4d67bc9f8b9",
  "id": "GHSA-7x43-mpfg-r9wj",
  "modified": "2026-03-04T18:38:55Z",
  "published": "2026-03-03T20:38:55Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/craftcms/cms/security/advisories/GHSA-7x43-mpfg-r9wj"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-28696"
    },
    {
      "type": "WEB",
      "url": "https://github.com/craftcms/cms/commit/4d98a07e47580f1712095825d3e3c4d67bc9f8b9"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/craftcms/cms"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N",
      "type": "CVSS_V4"
    }
  ],
  "summary": "Craft CMS has IDOR via GraphQL @parseRefs"
}


Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Sightings

Author Source Type Date

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or observed by the user.
  • Confirmed: The vulnerability has been validated from an analyst's perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
  • Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
  • Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
  • Not confirmed: The user expressed doubt about the validity of the vulnerability.
  • Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.


Loading…

Detection rules are retrieved from Rulezet.

Loading…

Loading…