KeystoneJS, Access Control Bypass, CVE-2023-XXXX (Medium)

How the CVE Works

The vulnerability arises when KeystoneJS processes `update` and `delete` mutations with multiple unique filters in the `where` clause. Despite `isFilterable` or `defaultIsFilterable` restrictions, the system incorrectly evaluates combined filters (e.g., `id` + email), allowing attackers to infer restricted field values. For example, if `email` is not filterable, an attacker can still probe its existence by pairing it with a valid `id` in a mutation. Successful execution confirms the email’s presence, effectively bypassing access controls. This flaw stems from incomplete validation in mutation operations, whereas `findMany` queries correctly enforce filtering restrictions.

DailyCVE Form

Platform: KeystoneJS
Version: <6.5.0
Vulnerability: Filter bypass
Severity: Medium
Date: 2023-XX-XX

What Undercode Say:

Exploitation:

  1. Probing Fields: Craft a GraphQL mutation with multiple unique filters (e.g., where: { id: "1", email: "[email protected]" }).
  2. Oracle Technique: Observe mutation success/failure to deduce restricted field values.
  3. Automation: Script repeated mutations to enumerate sensitive data.

Example Attack Query:

mutation {
updateUser(where: { id: "1", email: "[email protected]" }, data: { name: "hacked" }) {
id
}
}

Protection:

1. Patch: Upgrade to `@keystone-6/[email protected]`.

2. Workaround Code:

// Disable filtering on sensitive fields
User: list({
fields: {
email: text({ isFilterable: false }),
},
defaultIsFilterable: false,
})

3. Schema Hardening:

// Omit fields from GraphQL reads
email: text({ graphql: { omit: { read: true } } })

4. Access Control:

// Disable mutations entirely
access: { operation: { update: false, delete: false } }

Detection Commands:

  • Audit Dependencies:
    npm list @keystone-6/core
    
  • Log Suspicious Mutations: Monitor GraphQL logs for multi-filter update/delete operations.

Mitigation Script:

// Pre-mutation hook to validate filters
hooks: {
validateInput: ({ resolvedData, context }) => {
if (Object.keys(resolvedData.where).length > 1) throw new Error("Filter bypass attempt");
},
}

References:

  • KeystoneJS 6.5.0 Changelog
  • GraphQL Security Best Practices

Sources:

Reported By: github.com
Extra Source Hub:
Undercode

Join Our Cyber World:

💬 Whatsapp | 💬 TelegramFeatured Image

Scroll to Top