XWiki's REST API Under Siege: Unauthenticated SQL Injection (CVE-2025-32969) Lets Attackers Raid the Database
Alright folks, grab your coffee (or your preferred caffeinated beverage) because we're diving into a nasty vulnerability that hit the popular open-source wiki platform, XWiki. CVE-2025-32969 isn't just another bug; it's an unauthenticated SQL injection vulnerability lurking in the REST API. This means anyone on the network, without even needing to log in, could potentially tamper with or steal data directly from your wiki's database. Let's unpack this critical issue.
TL;DR / Executive Summary
What's the issue? CVE-2025-32969 is a critical SQL injection vulnerability in the XWiki Platform's REST API (/rest/wikis/{wikiName}/query
endpoint).
Who is affected? XWiki Platform versions from 1.8 up to (but not including) 15.10.16, 16.4.6, and 16.10.1.
What's the impact? Unauthenticated remote attackers can execute arbitrary SQL commands against the backend database. This allows for potential data theft (including password hashes), data modification, or deletion, even on wikis configured to restrict anonymous viewing/editing. The severity is high due to the unauthenticated nature and direct database access.
How do I fix it? Upgrade immediately to XWiki versions 16.10.1, 16.4.6, or 15.10.16. There are no known workarounds other than patching.
Introduction: When APIs Go Rogue
Application Programming Interfaces (APIs) are the unsung heroes of modern software, enabling different systems to talk to each other seamlessly. XWiki, a powerful Java-based wiki platform used for knowledge management and collaboration, relies heavily on its REST API for various functions. But what happens when an API endpoint, designed to provide data querying capabilities, becomes an open door for attackers?
That's precisely the scenario with CVE-2025-32969. Discovered by Sergey Anufrienko from the Kaspersky ICS-CERT vulnerability research team, this flaw allows attackers to bypass authentication and directly inject malicious SQL commands. Why is this particularly bad? Because XWiki often holds sensitive corporate knowledge, project details, and user information. An unauthenticated vulnerability means your first line of defense (login prompts) is completely bypassed, leaving the underlying database exposed. Even if you've meticulously configured permissions to prevent anonymous users from viewing pages, this vulnerability could still allow them to query the database directly. Ouch.
Technical Deep Dive: HQL Hijinks and SQL Sorcery
So, how does this attack actually work? It boils down to how XWiki's REST API handles queries using Hibernate Query Language (HQL).
The Vulnerable Endpoint: The issue lies within the /rest/wikis/{wikiName}/query
endpoint, specifically when using the type=hql
parameter. This endpoint is designed to allow querying wiki data using HQL.
HQL vs. SQL: Think of HQL as a more object-oriented way to query a database, abstracting away some of the raw SQL complexities. Hibernate, the underlying Object-Relational Mapping (ORM) tool, translates these HQL queries into actual SQL that the database understands. It's like ordering food using a menu (HQL) versus giving the chef specific, detailed cooking instructions (SQL).
The Root Cause: The vulnerability stems from insufficient validation and sanitization of the user-supplied HQL query string passed via the q
parameter. Attackers found ways to craft malicious input that "escapes" the intended HQL context. They could inject special characters and SQL commands that, when Hibernate translates the HQL into SQL, result in unintended SQL code being executed directly against the database.
Imagine telling the librarian (Hibernate) you want books "where the title contains 'XWiki' and also please run this extra command: DROP ALL TABLES
". A properly secured system would reject the second part, but here, clever formatting allowed the malicious command to sneak through the translation process.
Attack Vectors:
An unauthenticated attacker simply needs network access to the XWiki instance. They send a specially crafted HTTP GET request to the vulnerable endpoint. Because it's often a blind SQL injection (meaning the attacker doesn't see direct query results in the response), they typically use techniques like:
- Time-Based Injection: Injecting commands like
SLEEP(10)
and observing if the server takes 10 seconds longer to respond. This confirms successful SQL execution. - Boolean-Based Injection: Crafting queries that result in different responses (e.g., different page content or HTTP status) depending on whether a condition (like
SUBSTRING((SELECT password FROM users WHERE username='admin'), 1, 1) = 'a'
) is true or false. - Error-Based Injection (Less common here but possible): Forcing database errors that leak information.
Business Impact:
- Data Breach: Extraction of sensitive information like user credentials (password hashes), private wiki content, configuration details.
- Data Manipulation/Destruction: Modification or deletion of wiki pages, user accounts, or other critical data.
- Denial of Service: Overloading the database or corrupting data.
- Reputational Damage: Loss of trust from users and customers.
Proof of Concept: Seeing is Believing (and Patching!)
The advisory provides clear examples. These are simplified demonstrations; real attacks would be more sophisticated, likely using automated tools to exfiltrate data character by character.
Example 1: MySQL/MariaDB (Time-Based Blind SQLi)
# This command attempts to inject a SLEEP(10) command.
# If the server takes ~10 seconds longer than usual to respond, the injection worked.
time curl "http://<XWIKI_HOST>:8080/rest/wikis/xwiki/query?q=where%20doc.name=length('a')*org.apache.logging.log4j.util.Chars.SPACE%20or%201%3C%3E'1%5C''%20union%20select%201,2,3,sleep(10)%20%23'&type=hql&distinct=0"
- Breakdown: The URL-encoded query (
q=...
) uses HQL constructs combined with SQL injection techniques (' union select 1,2,3,sleep(10) #
). Thesleep(10)
is the payload, and the#
comments out the rest of the original HQL query. The initial part (where doc.name=... or 1<>'1\\''
) is crafted to manipulate the HQL parsing and allow theUNION SELECT
to be injected.
Example 2: PostgreSQL (Breaking out of HQL)
# This command uses PostgreSQL specific functions (chr, concat) to break out and inject SQL.
# The exact effect depends on the injected SQL (here, just 'select 1').
curl "http://<XWIKI_HOST>:8080/rest/wikis/xwiki/query?q=where%20%24%24='%24%24=concat(%20chr(%2061%20),(chr(%2039%20))%20)%20;select%201%20--%20comment'&type=hql&distinct=0"
- Breakdown: This uses dollar-quoting (
$$
) and character functions (chr
) common in PostgreSQL exploitation techniques (as detailed in the referenced SonarSource blog post) to terminate the HQL string prematurely and inject raw SQL (select 1 --
).
Disclaimer: Only run these commands against systems you own and have explicit permission to test. Unauthorized testing is illegal.
Mitigation and Remediation: Patch Now, Ask Questions Later!
Okay, enough scary stuff. How do we fix this?
-
Upgrade Immediately: This is the most crucial step. Update your XWiki instance to one of the patched versions:
- 16.10.1 or later
- 16.4.6 or later (if on the 16.4.x branch)
- 15.10.16 or later (if on the 15.10.x branch)
The XWiki team has addressed the root cause in these releases. According to the advisory, there are no other workarounds.
-
Verify the Fix: After upgrading, check your XWiki version in the administration interface. If possible (and safe!), try running the PoC commands against a non-production, patched instance. They should no longer cause delays (MySQL) or execute unintended SQL.
-
Long-Term Best Practices:
- Web Application Firewall (WAF): Implement a WAF with rulesets designed to detect and block common SQL injection patterns. This adds a valuable layer of defense but shouldn't replace patching.
- Database Permissions: Ensure the database user account XWiki uses has the minimum necessary privileges. It shouldn't be able to drop tables or access databases unrelated to XWiki if possible.
- Monitoring: Keep an eye on XWiki and database logs for unusual queries or errors, especially targeting the REST API endpoints.
Patch Analysis: How XWiki Fixed the Leak
The fix, primarily in commit 5c11a874bd24a581f534d283186e209bbccd8113
, focuses on improving query validation within the HqlQueryExecutor
.
- Problem: The original validation (
HqlQueryUtils.isSafe
) might not have correctly handled "short form" HQL statements (like those starting withwhere
ororder by
) or queries containing tricky escape sequences. Attackers could potentially craft input that looked safe in its partial form but became malicious when completed by XWiki. - Solution:
- Complete Before Validation: The
isSafeSelect
method now explicitly converts any short-form HQL statement into a complete one (e.g., prependingselect doc.fullName from XWikiDocument doc
) before passing it to theHqlQueryUtils.isSafe
validator. This ensures the validator analyzes the full query context. - Context Correction: The
checkAllowed
method, which verifies if the user has the right to execute the query, is now called after the code potentially switches the wiki context (getContext().setWikiId(...)
). This ensures permission checks happen within the context of the target wiki. - Improved Test Cases: New unit tests were added to
HqlQueryUtilsTest.java
specifically targetingUNION
based injections and escape character tricks (1<>'1\\'' union select ... #
). This confirms the strengthened validation catches these known attack patterns. - Secure Query Manager: In
AbstractDatabaseSearchSource.java
, the code now explicitly requests the@Named("secure")
version of theQueryManager
. This likely ensures that security constraints and validations associated with the "secure" manager are consistently applied to these REST API queries.
- Complete Before Validation: The
Essentially, the patch closes the loopholes by ensuring the entire, final query is validated within the correct security context, and adds tests to prove it catches previously successful injection techniques.
Timeline
- Discovery: Reported by Sergey Anufrienko (Kaspersky ICS-CERT). Date not specified in the advisory.
- Vendor Notification: Assumed shortly after discovery.
- Patch Availability: Patched versions 16.10.1, 16.4.6, 15.10.16 released. (Check XWiki release notes for specific dates if needed).
- Public Disclosure (CVE & Advisory): April 23, 2025
Lessons Learned: Trust No One (Especially API Inputs)
This vulnerability serves as a stark reminder of several key security principles:
- Input Validation is Non-Negotiable: Never trust data coming from external sources, especially user-controlled parameters in APIs. Sanitize, validate, and escape rigorously.
- ORMs Aren't Magic Shields: While ORMs like Hibernate help prevent some types of basic SQL injection, they can introduce their own complexities (like HQL injection). Developers need to understand how the ORM works and where potential injection points still exist. Parameterized queries are still the gold standard where applicable.
- Unauthenticated = Critical: Vulnerabilities that don't require login credentials have a much wider attack surface and potential impact. They should always be treated with the highest priority.
- Defense in Depth: Patching is primary, but WAFs, least privilege database users, and monitoring provide crucial backup layers.
Key Takeaway: Even sophisticated platforms using abstraction layers like HQL are susceptible to injection flaws if input isn't meticulously handled. Always assume API inputs are hostile until proven otherwise.
Have you encountered similar HQL injection issues? What are your go-to strategies for securing API endpoints? Share your thoughts in the comments below! And seriously, go patch your XWiki instances.
References and Further Reading
- GitHub Advisory: GHSA-f69v-xrj8-rhxf
- XWiki JIRA Ticket: XWIKI-22691
- Exploiting Hibernate Injections (SonarSource Blog): https://www.sonarsource.com/blog/exploiting-hibernate-injections/ (Provides context on HQL injection techniques)
- XWiki Downloads: https://www.xwiki.org/xwiki/bin/view/Download/
- Patch Commit: 5c11a874bd24a581f534d283186e209bbccd8113