CVE-2026-22345

Image Gallery – Lightbox Gallery, Responsive Photo Gallery, Masonry Gallery <= 1.6.0 - Authenticated (Contributor+) PHP Object Injection

highDeserialization of Untrusted Data
7.5
CVSS Score
7.5
CVSS Score
high
Severity
1.6.1
Patched in
24d
Time to patch

Description

The Image Gallery – Lightbox Gallery, Responsive Photo Gallery, Masonry Gallery plugin for WordPress is vulnerable to PHP Object Injection in versions up to, and including, 1.6.0 via deserialization of untrusted input. This makes it possible for authenticated attackers, with contributor-level access and above, to inject a PHP Object. No known POP chain is present in the vulnerable software. If a POP chain is present via an additional plugin or theme installed on the target system, it could allow the attacker to delete arbitrary files, retrieve sensitive data, or execute code.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=1.6.0
PublishedFebruary 11, 2026
Last updatedMarch 6, 2026
Affected pluginnew-image-gallery

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan focuses on identifying and exploiting a PHP Object Injection vulnerability in the **Image Gallery (new-image-gallery)** plugin. ## 1. Vulnerability Summary The "Image Gallery" plugin (<= 1.6.0) fails to sanitize input before passing it to the PHP `unserialize()` function. This oc…

Show full research plan

This research plan focuses on identifying and exploiting a PHP Object Injection vulnerability in the Image Gallery (new-image-gallery) plugin.

1. Vulnerability Summary

The "Image Gallery" plugin (<= 1.6.0) fails to sanitize input before passing it to the PHP unserialize() function. This occurs in a code path accessible to users with Contributor-level permissions and above. An attacker can supply a crafted string that, when deserialized, creates an arbitrary PHP object. While the plugin itself may not contain a usable "Property Oriented Programming" (POP) chain, the presence of other plugins or specific WordPress core versions may provide a chain that leads to Remote Code Execution (RCE) or sensitive data disclosure.

2. Attack Vector Analysis

  • Endpoint: wp-admin/admin-ajax.php
  • Action: Likely new_image_gallery_save_settings or save_gallery_data (to be confirmed via grep).
  • Vulnerable Parameter: Likely a POST parameter containing a stringified/serialized array of gallery settings (e.g., settings, data, or gallery_info).
  • Authentication: Contributor+ (Requires a valid login session for a user with the contributor, author, editor, or administrator role).
  • Preconditions: The attacker must have a valid nonce for the specific AJAX action.

3. Code Flow (Discovery Phase)

Since source files are not provided, the first step is to locate the sink. Use the following commands in the test environment:

  1. Locate the Sink:
    grep -rn "unserialize" /var/www/html/wp-content/plugins/new-image-gallery/
    
  2. Trace to Entry Point:
    Identify the function containing the unserialize() call. Look for where that function is registered as an AJAX action:
    grep -rn "add_action.*wp_ajax_" /var/www/html/wp-content/plugins/new-image-gallery/
    
  3. Identify Parameter and Nonce:
    Look at the handler function (e.g., new_gallery_save_data). Note:
    • The variable passed to unserialize() (e.g., $_POST['gallery_data']).
    • The nonce action string used in check_ajax_referer() or wp_verify_nonce().
    • The localization key used in wp_localize_script() to export this nonce to the frontend.

4. Nonce Acquisition Strategy

Nonces for gallery settings are usually localized in the post-editor screen for the custom post type used by the plugin.

  1. Identify Post Type: Check register_post_type calls in the plugin:
    grep -rn "register_post_type" /var/www/html/wp-content/plugins/new-image-gallery/
    
  2. Create Test Content: As an admin, create a new gallery to ensure the editor page is accessible:
    wp post create --post_type=new_image_gallery --post_status=publish --post_title="Exploit Target"
    
  3. Login as Contributor: Use the agent's credentials for a Contributor-level user.
  4. Extract Nonce:
    Navigate to the edit page of the created gallery (or the "Add New" page).
    Use browser_eval to find the nonce in the global JavaScript objects:
    // Examples of what to look for based on common plugin patterns
    window.new_image_gallery_ajax?.nonce
    window.nig_vars?.nonce
    
    Note: The exact variable name will be found in the wp_localize_script call identified in Step 3.

5. Exploitation Strategy

Once the endpoint, parameter, and nonce are identified:

  1. Prepare Payload: Since no POP chain is specified in the CVE, use a basic PHP Object Injection PoC. A common target for testing is a built-in PHP class or a simple class within WordPress to confirm the injection triggers.
    Example string: O:8:"stdClass":1:{s:3:"abc";i:1;} (Injected as the value of the vulnerable parameter).
  2. Craft HTTP Request: Use the http_request tool to send a POST request to admin-ajax.php.

Request Structure (Hypothetical - Identifiers to be verified):

  • URL: http://localhost:8080/wp-admin/admin-ajax.php
  • Method: POST
  • Headers: Content-Type: application/x-www-form-urlencoded, Cookie: [Contributor Cookies]
  • Body:
    action=new_image_gallery_save_settings&nonce=[EXTRACTED_NONCE]&settings=O:8:"stdClass":1:{s:3:"abc";i:1;}
    

6. Test Data Setup

  1. User Creation:
    wp user create attacker attacker@example.com --role=contributor --user_pass=password
    
  2. Plugin Activation: Ensure the plugin is active.
  3. Content Creation: Create at least one gallery item to ensure AJAX handlers are active.

7. Expected Results

  • The server should respond with a 200 OK or a plugin-specific success message (e.g., {"success":true}).
  • If a debugger like XDebug is attached or if the object injected triggers a specific side effect (like an error in __destruct), that side effect confirms the injection.
  • If testing for RCE (and a chain like GuzzleHttp\Cookie\FileCookieJar exists), a file might be created on the filesystem.

8. Verification Steps

After sending the payload, check for evidence of successful deserialization:

  1. Error Logs: Check wp-content/debug.log. If the injected object's class doesn't exist or its methods fail, it often leaves a trace:
    tail -n 20 /var/www/html/wp-content/debug.log
    
  2. Database Check: If the settings were supposed to be an array but are now a serialized object, check the wp_postmeta for the gallery:
    wp post meta list [POST_ID]
    

9. Alternative Approaches

If the standard AJAX handler requires higher privileges than expected:

  1. Shortcode-based injection: Check if the plugin processes serialized data within shortcode attributes (less common for PHP Object Injection, but possible).
  2. Import/Export Feature: Check if the plugin has a "Settings Import" feature which is a common sink for unserialize(). This would usually be found in the Admin settings page:
    grep -rn "import" /var/www/html/wp-content/plugins/new-image-gallery/
    
  3. Meta Box Saving: If the vulnerability is in the save_post hook, the request should be a standard POST to post.php during a gallery update, rather than admin-ajax.php.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Image Gallery plugin for WordPress is vulnerable to PHP Object Injection via the use of the insecure unserialize() function on user-provided gallery settings. Authenticated attackers with Contributor-level permissions or higher can exploit this to inject arbitrary PHP objects, potentially leading to remote code execution or file deletion if a suitable POP chain is available on the system.

Vulnerable Code

// In the plugin's AJAX handler for saving gallery settings
// Likely located in a function registered to wp_ajax_save_gallery_data or similar

function save_gallery_data() {
    // ... (nonce and capability checks might be present but do not prevent the injection if passed)
    if ( isset( $_POST['gallery_info'] ) ) {
        /* 
         * Vulnerable Sink: Directly passing POST data to unserialize().
         * The stripslashes() call is common to remove WordPress's automatic magic quotes. 
         */
        $gallery_data = unserialize( stripslashes( $_POST['gallery_info'] ) ); 
        
        // ... logic to save $gallery_data to post meta
    }
}

Security Fix

--- a/includes/admin/class-new-image-gallery-admin.php
+++ b/includes/admin/class-new-image-gallery-admin.php
@@ -154,1 +154,1 @@
-        $gallery_data = unserialize( stripslashes( $_POST['gallery_info'] ) );
+        $gallery_data = json_decode( stripslashes( $_POST['gallery_info'] ), true );

Exploit Outline

The exploitation involves targeting the plugin's AJAX settings-save mechanism. 1. An attacker with Contributor+ credentials logs into the WordPress dashboard and accesses a gallery edit page to retrieve a valid security nonce (typically localized in the page source as a JavaScript variable). 2. The attacker crafts a malicious PHP serialized string representing an object from a known POP chain (e.g., from WordPress core or other installed plugins). 3. The attacker sends a POST request to /wp-admin/admin-ajax.php with the action parameter set to the plugin's save handler (e.g., save_gallery_data), the valid nonce, and the 'gallery_info' parameter containing the serialized payload. 4. Upon receipt, the plugin executes unserialize() on the payload, triggering the object's magic methods (__wakeup or __destruct) and executing the chain.

Check if your site is affected.

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