JavaScript Notifier <= 1.2.8 - Authenticated (Administrator+) Stored Cross-Site Scripting via Plugin Settings
Description
The JavaScript Notifier plugin for WordPress is vulnerable to Stored Cross-Site Scripting via plugin settings in all versions up to, and including, 1.2.8. This is due to insufficient input sanitization and output escaping on user-supplied attributes in the `wp_footer` action. This makes it possible for authenticated attackers, with administrator-level access, 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:H/PR:H/UI:N/S:C/C:L/I:L/A:NTechnical Details
<=1.2.8This research plan outlines the steps to exploit a Stored Cross-Site Scripting (XSS) vulnerability in the **JavaScript Notifier** plugin for WordPress (versions <= 1.2.8). ## 1. Vulnerability Summary The **JavaScript Notifier** plugin fails to properly sanitize and escape settings saved by an admin…
Show full research plan
This research plan outlines the steps to exploit a Stored Cross-Site Scripting (XSS) vulnerability in the JavaScript Notifier plugin for WordPress (versions <= 1.2.8).
1. Vulnerability Summary
The JavaScript Notifier plugin fails to properly sanitize and escape settings saved by an administrator. These settings are subsequently retrieved and rendered directly into the site's footer via the wp_footer action hook. An attacker with administrator-level privileges can inject arbitrary JavaScript, which will execute in the context of any user (including other administrators) who visits the site's frontend.
2. Attack Vector Analysis
- Vulnerable Endpoint: WordPress Admin Settings (
/wp-admin/options.php). - Vulnerable Action:
wp_footer(frontend rendering). - Vulnerable Parameters: The specific setting fields registered by the plugin (likely
js_notifier_textor similar). - Preconditions:
- Authenticated user with
administratorprivileges (required to access the settings page). - Plugin version <= 1.2.8 installed and active.
- Authenticated user with
3. Code Flow (Inferred)
- Entry Point (Admin): The administrator navigates to the plugin's settings page, usually registered via
add_options_page()in a function hooked toadmin_menu. - Storage: Settings are registered via
register_setting(). When the form is submitted tooptions.php, WordPress callsupdate_option(). The plugin fails to provide asanitize_callbackduring registration, or the callback is insufficient. - Sink (Frontend): The plugin registers a function to the
wp_footerhook:add_action('wp_footer', 'javascript_notifier_display'); - Rendering: Inside
javascript_notifier_display(), the plugin retrieves the stored option:$options = get_option('javascript_notifier_settings'); echo $options['notifier_text']; // VULNERABLE: No esc_html() or esc_attr()
4. Nonce Acquisition Strategy
To update the settings via options.php, a valid settings nonce and the option_page identifier are required.
- Identify the Page: Navigate to the JavaScript Notifier settings page (likely
wp-admin/options-general.php?page=javascript-notifier). - Identify the Option Group: Look for the hidden input field
option_page. - Extract Nonce:
- Action:
browser_navigateto the settings page. - Action:
browser_evalto extract the nonce:({ nonce: document.querySelector('input[name="_wpnonce"]')?.value, option_page: document.querySelector('input[name="option_page"]')?.value })
- Action:
5. Exploitation Strategy
Step 1: Discover Setting Parameters
Since source files are not provided, we first need to identify the exact key used in the options.php request.
- Navigate to the settings page.
- Inspect the
nameattributes of the input fields (e.g.,javascript_notifier_options[message]).
Step 2: Inject Payload
Submit a POST request to options.php as an administrator.
- URL:
https://<target>/wp-admin/options.php - Method:
POST - Headers:
Content-Type: application/x-www-form-urlencoded - Body (Example):
option_page=javascript_notifier_settings& _wpnonce=<EXTRACTED_NONCE>& action=update& javascript_notifier_options[message]=<script>alert(document.domain)</script>
Step 3: Trigger Execution
Navigate to any frontend page of the WordPress site. The wp_footer hook executes on every frontend page load.
6. Test Data Setup
- Install Plugin: Ensure
javascript-notifierversion 1.2.8 is installed. - User: Create an administrator user.
- Plugin Config: Navigate to the settings page once to ensure the option is initialized in the database.
7. Expected Results
- The
options.phprequest should return a302 Redirectback to the settings page withsettings-updated=true. - Viewing the frontend source code (near the closing
</body>tag) should show the raw payload:<script>alert(document.domain)</script>. - A JavaScript alert box should appear when visiting the site's homepage.
8. Verification Steps
After the exploit, use wp-cli to verify the state of the database:
# Check the stored option value
wp option get javascript_notifier_options
Verify that the message (or relevant key) contains the unescaped <script> tag.
9. Alternative Approaches
If the plugin uses a custom AJAX handler instead of the Options API:
- Search for
wp_ajax_hooks in the plugin code:grep -r "wp_ajax_" .. - Locate the saving function and check for nonce verification:
check_ajax_referer('...', '...'). - Construct an AJAX POST request to
wp-admin/admin-ajax.php.
If the XSS is rendered inside an existing <script> block rather than directly in HTML:
- Payload:
";alert(document.domain);// - Check for
wp_add_inline_scriptorwp_localize_scriptcalls that might be the sink.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.