CVEReports
Reports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Reports
  • Sitemap
  • RSS Feed

Company

  • About
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Powered by Google Gemini & CVE Feed

|
•

CVE-2025-32969
CVSS 9.8|EPSS 25.20%

HQL Hell: Breaking XWiki with a Single Quote and a Dream

Alon Barad
Alon Barad
Software Engineer•January 3, 2026•7 min read
Weaponized

Executive Summary (TL;DR)

XWiki exposed a REST endpoint that accepts HQL queries. Due to a flaw in how 'short-form' queries were validated versus how they were executed, attackers can escape the HQL context. This results in unauthenticated Blind SQL Injection, leading to full database compromise and potential RCE. Rated CVSS 9.8.

A critical unauthenticated HQL injection vulnerability in XWiki's REST API allows attackers to break out of the Hibernate Query Language abstraction and execute raw SQL on the underlying database.

The Hook: When Abstractions Leak

We all love ORMs (Object-Relational Mappers). They are the warm, fuzzy blanket that protects developers from the cold, hard reality of raw SQL. They promise us that if we just stick to their objects and methods, SQL injection will be a thing of the past. But here's the dirty little secret of the Java ecosystem: Hibernate Query Language (HQL) is just another language, and like any language, if you let user input dictate the syntax, you are going to have a bad time.

In this episode of "Why did you expose that endpoint?", we are looking at XWiki, a popular open-source enterprise wiki. XWiki is complex, powerful, and apparently, very trusting of anonymous internet strangers. The vulnerability lies within xwiki-platform-rest-server, specifically in how it handles search queries via the REST API.

The developers provided a handy feature: a REST endpoint (/rest/wikis/xwiki/query) that allows you to search the wiki using HQL. To make life easier, they support "short-form" queries. Instead of writing a full SELECT statement, you can just write where doc.title like '%search%', and XWiki kindly prepends the SELECT clause for you. It's syntactic sugar. And like actual sugar, too much of it will rot your teeth—or in this case, your database security posture.

The Flaw: A Tale of Two Parsers

The root cause of CVE-2025-32969 is a classic case of "Check-Then-Act" disparity. The vulnerability exists because the validation logic checked one string, but the execution engine ran another.

Here is the logic flow that doomed the implementation:

  1. The user sends a query string, e.g., where doc.name = 'foo'.
  2. The HqlQueryExecutor#isSafeSelect method inspects this string. It looks for dangerous keywords like UPDATE or DELETE at the start of the query. Since the user's string starts with where, it passes the check.
  3. After the check, the system realizes this is a short-form query and prepends select doc.fullName from XWikiDocument doc.
  4. The combined query is sent to Hibernate, and subsequently, the database.

The flaw is obvious in hindsight: The security check was performed on the partial query, not the final query. This gap allowed attackers to construct a payload that looked innocent to the validator but became a monster once expanded.

Furthermore, there was a secondary failure in the authorization logic. The checkAllowed(query) permission check was performed before the context switch to the target wiki. This means the application checked if Anonymous had permission to search the current context, rather than the target wiki defined in the query. This Race Condition-esque logic allowed unauthenticated users to bypass view restrictions even when "Prevent unregistered users from viewing pages" was strictly enabled.

The Code: The Smoking Gun

Let's dissect the patch. The fix was pushed in commit 5c11a874bd24a581f534d283186e209bbccd8113. It reveals exactly where the logic failed.

The Fix in HqlQueryExecutor.java

The developers realized that validating the raw input string was insufficient. The patch introduces a crucial step: normalizing the query before validation.

// BEFORE (Vulnerable Logic)
// The code checked 'statement' directly, which might be just "where ..."
if (!isSafeSelect(statement)) {
    throw new IllegalArgumentException("Illegal query");
}
 
// AFTER (Fixed Logic)
// Expand the short-form query FIRST, then validate the result
String completeStatement = toCompleteShortForm(statement);
if (!isSafeSelect(completeStatement)) {
    throw new IllegalArgumentException("Illegal query");
}

By converting where ... into select doc.fullName from ... where ... before the check, the validator now sees the full picture.

The Authorization Shift

They also moved the permission check inside the wiki context block. Previously, the check happened too early:

// Vulnerable Flow
checkAllowed(query); // Checked against wrong context
try {
    getContext().setWikiId(query.getWiki());
    // execute query
}
 
// Fixed Flow
try {
    getContext().setWikiId(query.getWiki());
    checkAllowed(query); // Checked against the ACTUAL target wiki context
    // execute query
}

This subtle shift ensures that even if you bypass the HQL check, you still need valid permissions on the target wiki data to see the result. But since this is a blind SQLi, the permission check is largely a secondary defense layer.

The Exploit: Escaping the Matrix

So, how do we weaponize this? We need to trick the HQL parser into thinking we are still writing HQL, while simultaneously tricking the underlying SQL engine into executing a new command. This is achieved through specific character escaping.

The attack vector targets the /rest/wikis/xwiki/query endpoint. We inject a payload into the q parameter that uses a backslash and single quote combination (\') to desynchronize the HQL parser and the SQL parser.

The Payload Anatomy

Consider this payload found in the wild:

GET /rest/wikis/xwiki/query?type=hql&distinct=0&q=where%20doc.name=length(%27a%27)*org.apache.logging.log4j.util.Chars.SPACE%20or%201%3C%3E%271%5C%27%27%20union%20select%201,2,3,sleep(7)%20%23%27 HTTP/1.1

Let's break down the URL-decoded HQL injection:

  1. where doc.name=...: Satisfies the "short-form" requirement. It looks like a valid property check.
  2. 1<>'1\'': This is the magic. The backslash escapes the quote in a way that Hibernate processes differently than the database. To Hibernate, it might look like a string literal. To the database, it closes the string and opens up the command line.
  3. union select 1,2,3,sleep(7): The standard SQL injection payload. We use UNION to append our own result set. Since we can't easily see the output (blind), we use sleep(7) to pause the database execution. If the server hangs for 7 seconds, we have a hit.
  4. #: The comment character kills whatever valid SQL XWiki tries to append after our injection.

This is a Time-Based Blind SQL Injection. It's slow, it's noisy, but it works without authentication.

The Impact: Why You Should Care

This is rated CVSS 9.8 (Critical) for a reason. It requires zero authentication (PR:N), zero user interaction (UI:N), and can be launched remotely (AV:N).

1. Data Exfiltration Even though the injection is blind, an attacker can extract data bit-by-bit. They can dump the xwikidoc table, extract user password hashes, or read confidential wiki pages. In a corporate environment, a wiki often holds the "keys to the kingdom"—network diagrams, credentials, and architectural secrets.

2. Lateral Movement By extracting the hashed credentials of the XWiki administrator, an attacker can crack the hash (or pass-the-hash if the architecture allows) to log in as an admin. From there, XWiki allows execution of scripts (Groovy, Python, Velocity) in wiki pages. This turns SQL Injection into Remote Code Execution (RCE).

3. Database Manipulation Depending on the database user's privileges, the attacker could theoretically UPDATE records to inject XSS payloads into pages served to other users, or DELETE entire tables to cause a Denial of Service.

The Fix: Shutting the Door

If you are running XWiki, stop reading and start patching. The vulnerability affects a massive range of versions, effectively everything from version 1.8 up to recently patched releases.

Patched Versions

  • 15.10.16
  • 16.4.6
  • 16.10.1

Mitigation Strategy

There is no viable configuration workaround. You cannot simply "turn off" the REST API without breaking significant functionality of the XWiki platform. The fix requires updating the JARs.

If immediate patching is impossible, you should block access to /rest/wikis/*/query at your WAF or reverse proxy level for all unauthenticated IP addresses. However, given the query endpoint is fundamental to how XWiki front-ends often fetch data, this might break public-facing features.

Official Patches

XWikiGitHub Commit fixing the vulnerability
XWikiJira Issue Tracking

Fix Analysis (1)

Technical Appendix

CVSS Score
9.8/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
EPSS Probability
25.20%
Top 4% most exploited
5,000
Estimated exposed hosts via Shodan

Affected Systems

XWiki Platform < 15.10.16XWiki Platform 16.0.0-rc-1 to < 16.4.6XWiki Platform 16.5.0-rc-1 to < 16.10.1

Affected Versions Detail

ProductAffected VersionsFixed Version
XWiki Platform
XWiki
1.8 - < 15.10.1615.10.16
XWiki Platform
XWiki
16.0.0 - < 16.4.616.4.6
XWiki Platform
XWiki
16.5.0 - < 16.10.116.10.1
AttributeDetail
CWE IDCWE-89 (SQL Injection)
Attack VectorNetwork (REST API)
CVSS v3.19.8 (Critical)
CVSS v4.09.3 (Critical)
EPSS Score25.20%
EPSS Percentile96th Percentile
Exploit StatusPoC Available
ImpactConfidentiality, Integrity, Availability

MITRE ATT&CK Mapping

MITRE ATT&CK Mapping

T1190Exploit Public-Facing Application
Initial Access
T1059Command and Scripting Interpreter
Execution
T1505Server Software Component
Persistence
CWE-89
SQL Injection

Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')

Exploit Resources

Known Exploits & Detection

NucleiTime-based SQL injection template utilizing the sleep function
NucleiDetection Template Available

Vulnerability Timeline

Vulnerability Timeline

Fix committed to GitHub repository
2024-12-06
Public Disclosure / GHSA Published
2025-04-23
Nuclei Template Verified
2025-08-28

References & Sources

  • [1]GHSA Advisory
  • [2]NVD Detail

Subscribe to updates

Get the latest CVE analysis reports delivered to your inbox.

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.