Aug 5, 2026·7 min read·51 visits
Authenticated staff-level users can exploit insecure nested filter mapping in the Ghost Admin API to extract bcrypt password hashes of other users, including administrators, via boolean-based blind SQL side-channel queries.
An authenticated staff-level user can perform a side-channel, boolean-based blind database query attack through the Ghost Admin API to systematically extract the hashed passwords (bcrypt) of other staff users, including administrators, due to insecure filter mapping.
CVE-2026-70590 defines a security vulnerability in the administrative API of the Ghost content management system, specifically involving unauthorized exposure of sensitive information (CWE-200). The vulnerability surfaces in the query dynamic-filtering mechanism used within Ghost's Admin API. An authenticated attacker possessing staff-level privileges can query API resources, such as posts or pages, and instruct the application engine to evaluate comparisons against arbitrary backend database columns.
While the application layer actively filters and sanitizes API JSON payloads before they are returned to clients, it does not prevent the database execution engine from evaluating these comparative filters. Consequently, the API serves as an unintentional side-channel oracle. If the specified filter evaluates to true, the query succeeds and returns valid entries. If the filter evaluates to false, the system yields empty results.
This behavior allows a malicious actor with API access to iteratively reconstruct the bcrypt password hashes of administrative and other staff accounts. Although the hashes are stored using the computationally intensive bcrypt algorithm, they remain subject to offline brute-force and dictionary attacks. Complete compromise of target accounts becomes a secondary consequence if the offline cracking attempt succeeds.
The root cause of this vulnerability lies in the implementation of the Node Query Language (NQL / GQL) translation layer in Ghost. Ghost uses NQL to compile high-level filter query parameters, such as ?filter=status:published, directly into database queries via the Bookshelf.js and Knex.js query builders. When compiling these filters, the API prior to version 6.54.1 failed to validate the path depth and column names when traversing nested relations.
When a staff-level user requests a resource like /posts or /pages, they can supply a custom nested filter parameter, such as authors.password:~'a%'. The query translation logic parses the query and generates a SQL statement that joins the users (authors) table and executes a LIKE comparison against the password field. The Bookshelf model correctly excludes the password field from the final JSON serialization context, but the underlying database query execution has already occurred.
The exploitability of this side channel depends heavily on the underlying database engine and collation settings. On MySQL, which defaults to case-insensitive collations such as utf8mb4_general_ci, character comparisons using the LIKE operator (~ in NQL) are case-insensitive, returning positive matches for both uppercase and lowercase characters. On PostgreSQL or SQLite, exact binary matches are evaluated, allowing full-fidelity extraction of the precise case-sensitive bcrypt hash directly. This engine dependency dictates the complexity of the subsequent offline processing phase.
To mitigate this issue, the Ghost development team implemented a unified filtering transformer within the query options execution path. The fix commit 63c31fad7e473caa62d8fbb4651a04a2a62b5d00 enforces the rejectAdminApiRestrictedFieldsTransformer across multiple endpoint controllers including posts, pages, and their associated export engines.
In the vulnerable implementation of the pages endpoint controller, the query parameters passed directly to models.Post.findPage(frame.options) without filtering or intercepting client-supplied AST fields. The patch inserts the mongoTransformer property into the options object:
// ghost/core/core/server/api/endpoints/pages.js
const {rejectAdminApiRestrictedFieldsTransformer} = require('./utils/api-filter-utils');
// ...
query(frame) {
const options = {
...frame.options,
mongoTransformer: rejectAdminApiRestrictedFieldsTransformer
};
return models.Post.findPage(options);
}This structural modification prevents the query builder from mapping forbidden database columns. The transformer recursively sweeps the AST structure parsed from the NQL expression. If a restricted field such as password is detected within the query path, the transformer blocks or normalizes the filter payload before Knex.js compiles it to raw SQL. This prevents the execution of arbitrary comparisons on administrative credential tables, closing the boolean oracle side-channel entirely.
Exploiting CVE-2026-70590 requires a valid administrative or staff-level session token to interact with the Ghost Admin API. The attacker leverages the dynamic filter parameter exposed on endpoints like /ghost/api/admin/posts/ or /ghost/api/admin/pages/. An attack starts by querying a post associated with the target author while appending a wildcard comparison matching the expected prefix of a bcrypt hash.
Because bcrypt hashes start with a predictable prefix, such as $2b$12$, the attacker can verify the oracle function by requesting /ghost/api/admin/posts/?filter=authors.password:~'$2b$'. A successful match confirms the target hash structure. The attacker then builds an automated script to systematically cycle through the base64 character set ([a-zA-Z0-9./$]) for each character index of the hash.
Character 1: $ -> True
Character 2: 2 -> True
Character 3: b -> True
Character 4: $ -> True
Character 5: 1 -> True
Character 6: 2 -> True
Character 7: $ -> True
Character 8: [Iterate through a-z, A-Z, 0-9] -> Match: a
This serial lookup yields the target's complete bcrypt hash. In a MySQL environment, the resulting extracted hash is case-insensitive. The attacker must feed the case-insensitive hash into an offline cracking tool like Hashcat or John the Ripper, configured to mutate alphabetical positions. Under PostgreSQL or SQLite, the exact hash is retrieved, enabling a direct dictionary attack against the clean bcrypt string.
The concrete impact of CVE-2026-70590 is unauthorized access to sensitive credential material, leading to potential account takeover. The CVSS score for this vulnerability is assessed at 4.8 (Medium). The score reflects the requirement for high-privilege access (PR:H) and high attack complexity (AC:H) due to the need for a staff session, collation issues, and the necessity of offline brute-forcing.
Importantly, Ghost includes a security control called Device Verification. If an attacker successfully cracks an administrator's bcrypt hash and attempts to authenticate from an unrecognized device or IP address, Ghost prompts for a verification code sent to the owner's registered email. This verification step serves as a secondary line of defense that prevents immediate, direct account takeover unless the attacker also compromises the user's email inbox.
Furthermore, the requirement of high privileges limits the attack surface primarily to trusted users or compromised staff credentials. However, in multi-author publications, a rogue junior writer could exploit this vulnerability to elevate their privileges to a full administrator. This scenario bypasses role-based access controls entirely, presenting a severe risk to large-scale, collaborative editorial teams.
The primary remediation path is upgrading the Ghost instance to version 6.54.1 or higher. This update applies the necessary NQL transformer filters across all post and page API controllers, preventing unauthorized SQL comparisons. Administrators running self-hosted installations can update their environments using the Ghost-CLI command:
ghost updateIf patching cannot be executed immediately, administrators should implement defensive configuration controls. Deploying a Web Application Firewall (WAF) rule to intercept and inspect URI queries targeting the Admin API is highly recommended. The following ModSecurity rule blocks requests containing references to restricted fields within query parameters:
SecRule ARGS:filter "(?i)\bpassword\b" "id:100001,phase:2,deny,status:400,msg:'Insecure filter mapping attempt detected'"Additionally, security teams should audit the Admin API access logs for anomalous, high-frequency requests targeting /ghost/api/admin/posts/ or /ghost/api/admin/pages/ containing complex filter query structures. Standard operational traffic rarely requires highly nested relational password comparisons, making these patterns highly visible indicators of compromise.
CVSS:3.1/AV:N/AC:H/PR:H/UI:R/S:U/C:L/I:H/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
Ghost TryGhost | < 6.54.1 | 6.54.1 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-200 |
| Attack Vector | Network (AV:N/AC:H/PR:H/UI:R/S:U/C:L/I:H/A:N) |
| CVSS Score | 4.8 |
| EPSS Score | 0.0 |
| Impact | Information Disclosure (Password Hashes) |
| Exploit Status | None (No public weaponized exploit) |
| KEV Status | Not Listed |
Exposure of Sensitive Information to an Unauthorized Actor
CVE-2026-107718 is a medium-severity Open Redirect vulnerability in the core HTTP server package of the AdonisJS Node.js framework. Prior to versions 8.2.3 and 9.3.0, the framework built route paths by directly interpolating dynamic parameters and wildcard segments without URI encoding. If an application routes attacker-controlled input directly to a dynamic first path segment and uses the generated route URL as a redirect destination, a leading slash can produce a scheme-relative external URL. Modern web browsers process scheme-relative URLs by redirecting the client to the specified external domain, exposing users to credential harvesting, social engineering, and session hijacking. This vulnerability affects all applications running unpatched configurations where input validation is not explicitly implemented before generating paths.
CVE-2026-107725 is a critical security bypass in Hazelcast where missing authorization checks in the MapPermission class permit unprivileged clients to issue queries containing aggregators or projections. This architectural oversight allows attackers to run arbitrary code on the cluster servers under the privileges of the active Hazelcast process.
A stored Cross-Site Scripting (XSS) vulnerability was identified in Indico, an open-source event management system developed at CERN, prior to version 3.3.13. The vulnerability stems from weak URL validation in custom link fields and lack of HTML sanitization during Marshmallow serialization of event notes. This allows authenticated attackers with event modification privileges to inject malicious payloads that execute in the browser of users viewing the event pages or collaborating on notes.
A technical analysis of CVE-2026-107397, a stored Cross-Site Scripting (XSS) vulnerability in Indico's collaborative notes editor and custom link generation fields. Prior to version 3.3.13, Marshmallow serialization schemas omitted HTML sanitization during conflict resolution, and form validators failed to enforce strict URI schemes, enabling authenticated low-privilege attackers to execute arbitrary JavaScript.
An authorization bypass vulnerability exists in the legacy session export API of Indico, an open-source event management system developed at CERN. Due to a missing object-level access check, authenticated users can bypass configuration-level restrictions to extract private session metadata (including session titles, descriptions, and list of conveners) from events that they are otherwise authorized to view.
An incomplete Server-Side Request Forgery (SSRF) validation check in Indico prior to version 3.3.13 allows authenticated event organizers to bypass outbound network restrictions. By utilizing backslash characters within crafted URLs, attackers can exploit a parser differential between the application's validator and the downstream HTTP client library to access internal network resources.