Ocean Product Sharing <= 2.2.2 - Authenticated (Shop manager+) Stored Cross-Site Scripting
Description
The Ocean Product Sharing plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to, and including, 2.2.2 due to insufficient input sanitization and output escaping. This makes it possible for authenticated attackers, with shop manager-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.2.2What Changed in the Fix
Changes introduced in v2.2.3
Source Code
WordPress.org SVN# Exploitation Research Plan: CVE-2026-56007 (Ocean Product Sharing Stored XSS) ## 1. Vulnerability Summary The **Ocean Product Sharing** plugin (up to 2.2.2) is vulnerable to Stored Cross-Site Scripting (XSS) due to improper sanitization and escaping of plugin settings managed through the WordPres…
Show full research plan
Exploitation Research Plan: CVE-2026-56007 (Ocean Product Sharing Stored XSS)
1. Vulnerability Summary
The Ocean Product Sharing plugin (up to 2.2.2) is vulnerable to Stored Cross-Site Scripting (XSS) due to improper sanitization and escaping of plugin settings managed through the WordPress Customizer. Specifically, settings related to colors and styling (e.g., icon colors, background colors) are stored and subsequently output into the site's <head> within a <style> block via the ocean_head_css filter. Because the plugin does not properly sanitize these inputs upon saving or escape them upon output, an authenticated user with permission to modify these settings (Shop Managers and above) can inject malicious scripts.
This vulnerability is significant in environments where unfiltered_html is disabled (such as WordPress Multi-site for non-Super Admins), as it allows users to bypass intended security restrictions on executing JavaScript.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Action:
customize_save(Standard WordPress Customizer save action) - Vulnerable Parameter:
customized(A JSON-encoded string containing the setting ID and its malicious value) - Setting IDs (Inferred from
includes/options.phpand.potfile):ocean_product_sharing_borders_colorocean_product_sharing_bg_colorocean_product_sharing_icons_color
- Authentication: Authenticated (Shop Manager or higher). Note that Shop Managers must have the
edit_theme_optionscapability or the plugin must explicitly grant them access to its Customizer section. - Preconditions: The OceanWP theme must be active, as the plugin hooks into OceanWP-specific filters (
ocean_customize_options_data,ocean_head_css).
3. Code Flow
- Entry Point: An authenticated user accesses the WordPress Customizer.
- Registration:
Ocean_Product_Sharing::register_customize_options(inocean-product-sharing.php) callsops_customizer_options()(inincludes/options.php) to register settings likeocean_product_sharing_icons_color. - Storage: When the user saves settings, a POST request is sent to
admin-ajax.phpwithaction=customize_save. WordPress core saves the values into thewp_optionstable. - Retrieval & Sink:
- On the frontend,
Ocean_Product_Sharing::ops_setupregisters the filteradd_filter('ocean_head_css', array( $this, 'ops_head_css' ));. - The
ops_head_cssfunction (likely inincludes/helpers.php) retrieves the stored options usingget_theme_mod()orget_option(). - The values are concatenated into a CSS string and returned to the theme, which outputs them inside a
<style>tag in the<head>of the page. - If a color value like
*/</style><script>alert(1)</script><style>/*is used, it breaks out of the CSS context and executes the script.
- On the frontend,
4. Nonce Acquisition Strategy
The WordPress Customizer requires a specific nonce for the customize_save action. This nonce is unique to the user's session.
- Preparation: Ensure the agent is logged in as a user with Shop Manager or Admin privileges.
- Navigation: Use
browser_navigateto go to the Customizer page:/wp-admin/customize.php. - Extraction: Use
browser_evalto extract thenonceandcustomize_urlfrom the_wpCustomizeSettingsobject globally available in the Customizer's JavaScript context.- JavaScript:
window._wpCustomizeSettings?.nonce?.save
- JavaScript:
- Identification: The
customize_saveaction also requires acustomizedparameter containing the changes.
5. Exploitation Strategy
- Construct Payload: The payload must break out of a CSS declaration.
- Example:
green; } </style><script>alert(document.domain)</script><style> .dummy { color: blue
- Example:
- Request Construction: Use the
http_requesttool to send the following POST request:- URL:
https://<target>/wp-admin/admin-ajax.php - Method:
POST - Headers:
Content-Type: application/x-www-form-urlencoded - Body Parameters:
action:customize_savewp_customize:onnonce:[EXTRACTED_NONCE]customized:{"ocean_product_sharing_icons_color":"green;}</style><script>alert(1)</script><style>/*"}
- URL:
- Triggering: Navigate to any single product page (WooCommerce) or download item (EDD) where the sharing buttons are rendered.
6. Test Data Setup
- Theme: Install and activate the OceanWP theme.
- Dependencies: Install and activate WooCommerce.
- Product: Create at least one public product:
wp post create --post_type=product --post_title="Security Test Product" --post_status=publish
- Plugin Config: Ensure the "Product Sharing" feature is enabled in the Customizer settings.
- User: Create a Shop Manager user if testing role-based access:
wp user create shopmanager shopmanager@example.com --role=shop_manager --user_pass=password
7. Expected Results
- The
admin-ajax.phprequest should return a200 OKwith a JSON response indicating{"success":true}. - Upon visiting the "Security Test Product" page, the HTML source code within the
<head>section should contain the injected<script>tag. - The browser should execute the JavaScript payload.
8. Verification Steps
- DB Check: Use WP-CLI to verify the option is stored:
wp option get theme_mods_oceanwp(Look for theocean_product_sharing_icons_colorkey).
- Response Check: Use
http_request(GET) to fetch the product page and grep for the payload:grep -a10 "ocean-product-sharing" product_page_source.html
9. Alternative Approaches
- Other Settings: If
ocean_product_sharing_icons_coloris sanitized, attempt exploitation viaocean_product_sharing_bg_colororocean_product_sharing_borders_color. - Direct Option Update: If the Customizer UI is restricted, check if the plugin exposes an AJAX handler for its "Theme Panel" (referenced in
ocean-product-sharing.phpasoe_theme_panels) which might allow updating options with lower capability requirements.
Summary
The Ocean Product Sharing plugin for WordPress is vulnerable to Stored Cross-Site Scripting (XSS) in versions up to 2.2.2. This occurs due to insufficient input sanitization and output escaping of settings managed through the WordPress Customizer and product metadata, allowing authenticated attackers with Shop Manager privileges or higher to inject arbitrary web scripts into pages.
Vulnerable Code
// ocean-product-sharing.php line 261 public function register_customize_options($options) { if ( OCEAN_EXTRA_ACTIVE && class_exists( 'Ocean_Extra_Theme_Panel' ) ) { if ( empty( Ocean_Extra_Theme_Panel::get_setting( 'ocean_product_sharing_panel' ) ) ) { return $options; } } include_once $this->plugin_path . '/includes/options.php'; $options['ocean_product_sharing_settings'] = ops_customizer_options(); return $options; } --- // template/product-share.php line 21 $product_title = get_the_title(); $product_url = get_permalink(); $product_img = wp_get_attachment_url( get_post_thumbnail_id() ); ?> <div class="oew-product-share clr"> <ul class="ocean-social-share clr" aria-label="<?php echo esc_attr__( 'Share this product on social media', 'ocean-product-sharing' ); ?>"> // ... lines 39, 77, and 100 contain variations of: // echo html_entity_decode( wp_strip_all_tags( $product_title ) );
Security Fix
@@ -19,9 +19,43 @@ } // Vars -$product_title = get_the_title(); +$product_title = wp_strip_all_tags( get_the_title() ); $product_url = get_permalink(); -$product_img = wp_get_attachment_url( get_post_thumbnail_id() ); ?> +$product_img = wp_get_attachment_url( get_post_thumbnail_id() ); + +$twitter_url = add_query_arg( + array( + 'text' => $product_title, + 'url' => $product_url, + ), + 'https://twitter.com/intent/tweet' +); + +$facebook_url = add_query_arg( + array( + 'u' => $product_url, + ), + 'https://www.facebook.com/sharer.php' +); + +$pinterest_url = add_query_arg( + array( + 'url' => $product_url, + 'media' => $product_img, + 'description' => $product_title, + ), + 'https://www.pinterest.com/pin/create/button/' +); + +$email_url = add_query_arg( + array( + 'subject' => $product_title, + 'body' => $product_url, + ), + 'mailto:' +); + +?> <div class="oew-product-share clr"> @@ -36,7 +70,7 @@ ?> <li class="twitter"> - <a aria-label="<?php esc_attr_e( 'Share this product on X', 'ocean-product-sharing' ); ?>" class="twitter-share-button" href="https://twitter.com/intent/tweet?text=<?php echo html_entity_decode( wp_strip_all_tags( $product_title ) ); ?>+<?php echo esc_url( $product_url ); ?>" onclick="ops_onClick( this.href );return false;"> + <a aria-label="<?php esc_attr_e( 'Share this product on X', 'ocean-product-sharing' ); ?>" class="twitter-share-button" href="<?php echo esc_url( $twitter_url ); ?>" onclick="ops_onClick( this.href );return false;"> <span class="screen-reader-text"><?php echo esc_attr__( 'Opens in a new window', 'ocean-product-sharing' ); ?></span> <span class="ops-icon-wrap"> <svg class="ops-icon" role="img" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"> @@ -54,7 +88,7 @@ ?> <li class="facebook"> - <a href="https://www.facebook.com/sharer.php?u=<?php echo rawurlencode( esc_url( $product_url ) ); ?>" target="_blank" aria-label="<?php esc_attr_e( 'Share on Facebook', 'ocean-product-sharing' ); ?>" onclick="ops_onClick( this.href );return false;"> + <a href="<?php echo esc_url( $facebook_url ); ?>" target="_blank" aria-label="<?php esc_attr_e( 'Share on Facebook', 'ocean-product-sharing' ); ?>" onclick="ops_onClick( this.href );return false;"> <span class="screen-reader-text"><?php echo esc_attr__( 'Opens in a new window', 'ocean-product-sharing' ); ?></span> <span class="ops-icon-wrap"> <svg class="ops-icon" role="img" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"> @@ -74,7 +108,7 @@ ?> <li class="pinterest"> - <a href="https://www.pinterest.com/pin/create/button/?url=<?php echo rawurlencode( esc_url( $product_url ) ); ?>&media=<?php echo wp_get_attachment_url( get_post_thumbnail_id() ); ?>&description=<?php echo rawurlencode( wp_strip_all_tags( $product_title ) ); ?>" target="_blank" aria-label="<?php esc_attr_e( 'Share on Pinterest', 'ocean-product-sharing' ); ?>" onclick="ops_onClick( this.href );return false;"> + <a href="<?php echo esc_url( $pinterest_url ); ?>" target="_blank" aria-label="<?php esc_attr_e( 'Share on Pinterest', 'ocean-product-sharing' ); ?>" onclick="ops_onClick( this.href );return false;"> <span class="screen-reader-text"><?php echo esc_attr__( 'Opens in a new window', 'ocean-product-sharing' ); ?></span> <span class="ops-icon-wrap"> <svg class="ops-icon" role="img" viewBox="0 0 496 512" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"> @@ -97,7 +131,7 @@ ?> <li class="email"> - <a href="mailto:?subject=<?php echo html_entity_decode( wp_strip_all_tags( $product_title ) ); ?>&body=<?php echo esc_url( $product_url ); ?>" target="_blank" aria-label="<?php esc_attr_e( 'Share via email', 'ocean-product-sharing' ); ?>" onclick="ops_onClick( this.href );return false;"> + <a href="<?php echo esc_url( $email_url, array( 'mailto' ) ); ?>" target="_blank" aria-label="<?php esc_attr_e( 'Share via email', 'ocean-product-sharing' ); ?>" onclick="ops_onClick( this.href );return false;"> <span class="screen-reader-text"><?php echo esc_attr__( 'Opens in a new window', 'ocean-product-sharing' ); ?></span> <span class="ops-icon-wrap"> <svg class="ops-icon" role="img" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false">
Exploit Outline
To exploit this vulnerability, an attacker must have Shop Manager or higher privileges. The primary attack vector involves the WordPress Customizer, where an attacker can submit a payload through the 'customize_save' AJAX action. By injecting a payload like `*/</style><script>alert(1)</script><style>/*` into styling settings (such as `ocean_product_sharing_icons_color`), the attacker can break out of the CSS block generated by the `ocean_head_css` filter in the document head. Alternatively, malicious scripts can be injected into product titles, which are rendered unescaped in the social sharing links on the front-end product pages. The vulnerability is especially effective in multi-site environments or where `unfiltered_html` is disabled.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.