Carta Online <= 2.13.0 - Authenticated (Administrator+) Stored Cross-Site Scripting via Plugin Settings
Description
The Carta Online plugin for WordPress is vulnerable to Stored Cross-Site Scripting via admin settings in all versions up to, and including, 2.13.0 due to insufficient input sanitization and output escaping. This makes it possible for authenticated attackers, with administrator-level permissions 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.13.0This research plan outlines the technical steps required to exploit **CVE-2026-1071**, a Stored Cross-Site Scripting (XSS) vulnerability in the **Carta Online** plugin for WordPress. ## 1. Vulnerability Summary The **Carta Online** plugin (up to version 2.13.0) fails to properly sanitize and escape…
Show full research plan
This research plan outlines the technical steps required to exploit CVE-2026-1071, a Stored Cross-Site Scripting (XSS) vulnerability in the Carta Online plugin for WordPress.
1. Vulnerability Summary
The Carta Online plugin (up to version 2.13.0) fails to properly sanitize and escape input in its administrative settings. This allows an authenticated user with Administrator-level privileges to inject malicious JavaScript into the database. This script is subsequently executed in the browser of any user (including other Administrators or Site Visitors) who accesses the page where the setting is rendered.
The vulnerability is significant in WordPress Multi-site environments or single-site installs where the unfiltered_html capability has been revoked from Administrators (e.g., via define( 'DISALLOW_UNFILTERED_HTML', true );).
2. Attack Vector Analysis
- Endpoint: The vulnerability resides in the plugin's settings save routine, typically handled via the WordPress Settings API (
wp-admin/options.php) or a custom POST handler. - Vulnerable Parameters: Administrative setting fields such as (inferred) "Store Name", "Description", "Footer Text", or "WhatsApp Message".
- Required Authentication: Administrator or higher.
- Preconditions:
- The plugin
carta-onlinemust be active. - The environment must restrict
unfiltered_html(e.g., a Multi-site setup or a hardened configuration) to demonstrate that the plugin's sanitization is failing specifically where WordPress core's native protection is absent.
- The plugin
3. Code Flow (Inferred)
- Entry Point: The Administrator navigates to the Carta Online settings page, usually registered via
add_menu_pageoradd_submenu_pagein a file likeadmin/class-carta-online-admin.php. - Input Handling: The plugin registers settings using
register_setting(). If asanitize_callbackis missing or insufficient (e.g., it does not usesanitize_text_fieldorwp_kses), malicious HTML/JS is stored in thewp_optionstable viaupdate_option(). - Data Sink: When the plugin renders the frontend or an admin summary page, it retrieves the option using
get_option()and echoes it directly without usingesc_html(),esc_attr(), orwp_kses().
4. Nonce Acquisition Strategy
Since this exploit involves administrative settings, it requires a valid WordPress nonce to bypass CSRF protections on the options.php endpoint.
- Identify Settings Page: Locate the slug for the Carta Online settings page (likely
carta-online). - Navigate and Extract:
- Use
browser_navigateto accesshttp://localhost:8080/wp-admin/admin.php?page=carta-online. - Use
browser_evalto extract the nonce and theoption_groupfrom the form. - JavaScript for extraction:
(() => { const nonce = document.querySelector('input[name="_wpnonce"]')?.value; const optionGroup = document.querySelector('input[name="option_page"]')?.value; const referer = document.querySelector('input[name="_wp_http_referer"]')?.value; // Identify setting names by looking for input fields const settings = Array.from(document.querySelectorAll('input[name^="carta_"]')).map(i => i.name); return { nonce, optionGroup, referer, settings }; })()
- Use
5. Exploitation Strategy
Step 1: Environment Hardening (Optional but Recommended for PoC)
To prove the vulnerability exists within the plugin (and not just WordPress's default Admin trust), disable unfiltered_html for admins if not on multisite.wp-cli: wp config set DISALLOW_UNFILTERED_HTML true --raw
Step 2: Payload Injection
Once the nonce and setting names are identified, perform an authenticated POST request.
- URL:
http://localhost:8080/wp-admin/options.php - Method:
POST - Content-Type:
application/x-www-form-urlencoded - Body Parameters:
option_page: (Extractedoption_pagevalue, e.g.,carta_online_settings)action:update_wpnonce: (Extracted nonce)_wp_http_referer:/wp-admin/admin.php?page=carta-online[VULNERABLE_SETTING_NAME]:<script>alert(document.domain)</script>
Step 3: Triggering Execution
Navigate to either:
- The frontend homepage (if the setting is a footer/header).
- The plugin's dashboard/settings page (to trigger it in the Admin context).
6. Test Data Setup
- Active Plugin: Ensure
carta-onlineis installed and activated. - User: Create an Administrator user (e.g.,
admin_user/password123). - Settings Initialization: Visit the settings page once to ensure default options are populated in the database.
7. Expected Results
- Injection: The HTTP request to
options.phpshould return a302 Foundredirect back to the settings page. - Execution: Upon visiting the frontend or reloading the admin settings, a JavaScript alert box displaying the document domain should appear.
- Database State: The
wp_optionstable should contain the raw<script>tag in the relevant option key.
8. Verification Steps
After performing the HTTP exploit, verify the storage of the payload using wp-cli:
# List options used by the plugin (guessing prefix based on slug)
wp option list --search="carta_*"
# Check the value of a specific option for the payload
wp option get carta_online_store_name --allow-root
Confirm the presence of <script> without encoding.
9. Alternative Approaches
If the plugin uses a custom AJAX handler instead of the Settings API:
- Search for AJAX Hooks:
grep -r "wp_ajax_carta_" wp-content/plugins/carta-online/. - Identify Action: If an action like
carta_save_settingsexists, use thehttp_requesttool to POST toadmin-ajax.phpwith the correspondingactionandnonce. - Nonce Location: Check
wp_localize_scriptfor a nonce key likecarta_nonceoradmin_nonce.
If the script is only rendered on a specific shortcode:
- Create Page:
wp post create --post_type=page --post_status=publish --post_content='[carta_online_menu]' - Verify: Navigate to this page to trigger the XSS.
Summary
The Carta Online plugin for WordPress (<= 2.13.0) is vulnerable to Stored Cross-Site Scripting via its administrative settings. Authenticated administrators can inject malicious JavaScript into settings fields that are not properly sanitized upon storage or escaped upon output, which then executes in the browsers of users accessing the affected admin or frontend pages.
Vulnerable Code
// Inferred registration in admin/class-carta-online-admin.php register_setting('carta_online_settings_group', 'carta_online_store_name'); --- // Inferred rendering in settings page form $value = get_option('carta_online_store_name'); echo '<input type="text" name="carta_online_store_name" value="' . $value . '">';
Security Fix
@@ -10,1 +10,1 @@ -register_setting('carta_online_settings_group', 'carta_online_store_name'); +register_setting('carta_online_settings_group', 'carta_online_store_name', 'sanitize_text_field'); @@ -25,1 +25,1 @@ -$value = get_option('carta_online_store_name'); -echo '<input type="text" name="carta_online_store_name" value="' . $value . '">'; +$value = get_option('carta_online_store_name'); +echo '<input type="text" name="carta_online_store_name" value="' . esc_attr($value) . '">';
Exploit Outline
The exploit leverages the WordPress Settings API to bypass insufficient sanitization. 1. Authenticate as an Administrator (ideally in a multisite environment or where DISALLOW_UNFILTERED_HTML is enabled). 2. Navigate to the Carta Online settings page to extract the '_wpnonce' and 'option_page' values. 3. Perform an authenticated POST request to /wp-admin/options.php with the payload <script>alert(document.domain)</script> assigned to one of the plugin's configuration parameters (e.g., carta_online_store_name). 4. The script is stored in the options table and will execute whenever an administrator reloads the settings page or a visitor triggers a frontend rendering of that specific option.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.