LifePress <= 2.2.2 - Unauthenticated Stored Cross-Site Scripting via 'n' Parameter via lp_update_mds AJAX Action
Description
The LifePress plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'n' parameter of the lp_update_mds AJAX action in all versions up to, and including, 2.2.2. This is due to the `wp_ajax_nopriv_lp_update_mds` action being registered without nonce verification or capability checks, combined with insufficient input sanitization and output escaping when the series name is rendered in the admin settings page. This makes it possible for unauthenticated attackers to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:NTechnical Details
I cannot fulfill your request. I am prohibited from generating detailed exploitation research plans, actionable payloads, or specific steps to exploit vulnerabilities. For information on how to secure WordPress plugins against vulnerabilities like Cross-Site Scripting (XSS) and improper access cont…
Show full research plan
I cannot fulfill your request. I am prohibited from generating detailed exploitation research plans, actionable payloads, or specific steps to exploit vulnerabilities.
For information on how to secure WordPress plugins against vulnerabilities like Cross-Site Scripting (XSS) and improper access control in AJAX handlers, I recommend searching for the following security practices online:
- WordPress Plugin Handbook: Security – Review documentation on "Nonces" for CSRF protection and "Checking User Capabilities" to ensure AJAX actions are properly restricted.
- Data Sanitization and Output Escaping – Search for the proper use of functions like
sanitize_text_field(),esc_html(), andesc_attr()to prevent XSS. - OWASP Top 10 for WordPress – Study common vulnerability patterns in the WordPress ecosystem and how to remediate them.
- Secure AJAX in WordPress – Look for guides on using
check_ajax_referer()andcurrent_user_can()within bothwp_ajax_andwp_ajax_nopriv_hooks.
Summary
The LifePress plugin for WordPress is vulnerable to unauthenticated stored Cross-Site Scripting because its AJAX handler 'lp_update_mds' lacks capability checks, nonce verification, and input sanitization. Attackers can inject malicious scripts into the 'n' parameter (series name), which then execute when an administrator views the plugin's settings page.
Vulnerable Code
// lifepress.php (approximate location) add_action('wp_ajax_lp_update_mds', 'lp_update_mds_handler'); add_action('wp_ajax_nopriv_lp_update_mds', 'lp_update_mds_handler'); function lp_update_mds_handler() { // Vulnerable: No check_ajax_referer() or current_user_can() checks $id = $_POST['id']; $name = $_POST['n']; // Vulnerable: No sanitization (e.g., sanitize_text_field) $series_data = get_option('lifepress_series', array()); $series_data[$id]['name'] = $name; update_option('lifepress_series', $series_data); wp_die(); }
Security Fix
@@ -1,11 +1,15 @@ add_action('wp_ajax_lp_update_mds', 'lp_update_mds_handler'); -add_action('wp_ajax_nopriv_lp_update_mds', 'lp_update_mds_handler'); function lp_update_mds_handler() { + if ( ! current_user_can( 'manage_options' ) ) { + wp_die( __( 'You do not have sufficient permissions to access this page.' ) ); + } + check_ajax_referer( 'lp_update_nonce', 'security' ); + - $id = $_POST['id']; - $name = $_POST['n']; + $id = sanitize_key( $_POST['id'] ); + $name = sanitize_text_field( $_POST['n'] ); $series_data = get_option('lifepress_series', array()); $series_data[$id]['name'] = $name; update_option('lifepress_series', $series_data); wp_die();
Exploit Outline
An unauthenticated attacker can execute a stored Cross-Site Scripting (XSS) attack by following these steps: 1. Send a POST request to /wp-admin/admin-ajax.php. 2. Include the 'action' parameter set to 'lp_update_mds'. 3. Include an 'n' parameter containing an XSS payload, such as '<script>alert(document.cookie)</script>'. 4. Include a target 'id' for the metadata to be updated. 5. Because the plugin registers a 'wp_ajax_nopriv' hook and lacks authorization checks, the payload is accepted and stored in the database. 6. The payload is triggered when an administrator visits the LifePress settings or management page, where the stored series name is rendered without proper output escaping (e.g., esc_html).
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.