Client Invoicing by Sprout Invoices <= 20.8.8 - Missing Authorization
Description
The Client Invoicing by Sprout Invoices plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 20.8.8. This makes it possible for unauthenticated attackers to perform an unauthorized action.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:NTechnical Details
<=20.8.8Source Code
WordPress.org SVN# Research Plan: CVE-2026-25364 - Sprout Invoices Missing Authorization ## 1. Vulnerability Summary The **Client Invoicing by Sprout Invoices** plugin (up to version 20.8.8) contains a "Missing Authorization" vulnerability. This occurs because one or more AJAX handlers are registered via `wp_ajax_n…
Show full research plan
Research Plan: CVE-2026-25364 - Sprout Invoices Missing Authorization
1. Vulnerability Summary
The Client Invoicing by Sprout Invoices plugin (up to version 20.8.8) contains a "Missing Authorization" vulnerability. This occurs because one or more AJAX handlers are registered via wp_ajax_nopriv_ (allowing unauthenticated access) but fail to perform a capability check (e.g., current_user_can( 'manage_options' )) or verify the caller's authority before executing sensitive logic. An unauthenticated attacker can leverage this to perform unauthorized actions, such as modifying plugin settings or manipulating invoice data.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Action:
si_save_settingsorsi_ajax_save_settings(Inferred based on common plugin patterns and the "unauthorized action" description). - Vulnerable Hook:
wp_ajax_nopriv_si_save_settingsorwp_ajax_nopriv_sa_save_settings. - Payload Parameter: Typically
$_POST['settings']or specific keys like$_POST['option_name']and$_POST['option_value']. - Authentication Level: Unauthenticated (Nopriv).
- Preconditions: The plugin must be active.
3. Code Flow
- Entry Point: The plugin registers an AJAX handler using
add_action( 'wp_ajax_nopriv_si_save_settings', ... )in an initialization file (e.g.,controllers/settings/Settings.phporinc/SI_Settings.php). - Missing Check: The callback function (e.g.,
SI_Settings::save_settings) is invoked. It lacks acurrent_user_can()check. - Data Processing: The function reads input from
$_POST. - Sink: The function calls
update_option()or a internal wrapper likeSI_Options::update_settings(), allowing the attacker to overwrite plugin configurations.
4. Nonce Acquisition Strategy
If the plugin requires a nonce for the AJAX action, it is typically localized in the WordPress header or footer using wp_localize_script.
- JS Variable Name:
si_js_varsorsprout_invoices_vars(Inferred). - Nonce Key:
security,nonce, orsettings_nonce. - Acquisition Steps:
- Identify Script Trigger: Sprout Invoices usually enqueues its settings scripts on its own admin pages, but unauthenticated nonces might be found on pages where invoices or leads are rendered.
- Create Trigger Page: Create a page with the Sprout Invoices lead shortcode (common in this plugin):
wp post create --post_type=page --post_status=publish --post_content='[sprout_invoice_lead]' - Navigate: Open the newly created page in the browser.
- Extract: Use
browser_evalto fetch the nonce:browser_eval("window.si_js_vars?.security || window.sprout_invoices_vars?.nonce")
5. Exploitation Strategy
We will attempt to modify a specific plugin setting to demonstrate unauthorized access.
- Request Type: POST
- URL:
http://localhost:8080/wp-admin/admin-ajax.php - Headers:
Content-Type: application/x-www-form-urlencoded - Payload:
(Note:action=si_save_settings&nonce=[EXTRACTED_NONCE]&settings[site_currency]=EVILsite_currencyis a standard setting in Sprout Invoices. Changing it to a dummy value like 'EVIL' proves the vulnerability without breaking the site).
6. Test Data Setup
- Plugin Installation: Ensure Sprout Invoices <= 20.8.8 is installed and activated.
- Initial State: Verify the current currency setting via CLI:
wp option get si_settings(The settings are often stored in a serialized array). - Shortcode Page: Create a page to expose any potential nonces:
wp post create --post_type=page --post_status=publish --post_title="Nonce Page" --post_content='[sprout_invoice_lead]'
7. Expected Results
- HTTP Response: The server returns a
200 OKor a JSON success message (e.g.,{"success":true}). - Effect: The
si_settingsoption in thewp_optionstable is updated with the attacker-supplied value.
8. Verification Steps
- Database Check: Use WP-CLI to inspect the updated settings:
wp option get si_settings - Value Check: Confirm that the
site_currency(or equivalent key used in the payload) now reflects the valueEVIL. - Log Check: (Optional) Check the WordPress debug log for unauthorized calls if logging is enabled.
9. Alternative Approaches
If si_save_settings is not the vulnerable action:
- Search for other Nopriv Actions:
grep -r "wp_ajax_nopriv_" /var/www/html/wp-content/plugins/sprout-invoices/ - Target Inbound Leads: Attempt to bypass authorization on the
si_process_leadaction to inject malicious lead data. - Target Payment Status: Look for actions like
si_update_payment_statuswhich might allow marking invoices as paid without actual payment. - Bypass Nonce: If
check_ajax_refereris called withdie = falseor if the return value is not checked, omit the nonce and see if the action still succeeds.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.