CVE-2026-39510

Image Photo Gallery Final Tiles Grid <= 3.6.11 - Authenticated (Author+) Insecure Direct Object Reference

mediumAuthorization Bypass Through User-Controlled Key
4.3
CVSS Score
4.3
CVSS Score
medium
Severity
3.6.12
Patched in
84d
Time to patch

Description

The Image Photo Gallery Final Tiles Grid plugin for WordPress is vulnerable to Insecure Direct Object Reference in all versions up to, and including, 3.6.11 due to missing validation on a user controlled key. This makes it possible for authenticated attackers, with Author-level access and above, to perform an unauthorized action.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=3.6.11
PublishedFebruary 11, 2026
Last updatedMay 5, 2026

What Changed in the Fix

Changes introduced in v3.6.12

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan - CVE-2026-39510 ## 1. Vulnerability Summary The **Image Photo Gallery Final Tiles Grid** plugin (<= 3.6.11) is vulnerable to an **Insecure Direct Object Reference (IDOR)**. The vulnerability exists in the plugin's AJAX handlers—specifically those responsible for galler…

Show full research plan

Exploitation Research Plan - CVE-2026-39510

1. Vulnerability Summary

The Image Photo Gallery Final Tiles Grid plugin (<= 3.6.11) is vulnerable to an Insecure Direct Object Reference (IDOR). The vulnerability exists in the plugin's AJAX handlers—specifically those responsible for gallery management actions like deletion or cloning—because they lack a verification step to ensure the requesting user owns the object (gallery) specified by the ID.

While the plugin enforces an Author level capability check for access to the gallery management interface, it fails to perform object-level authorization. An authenticated user with Author privileges can perform unauthorized actions (like deleting or modifying) on galleries created by administrators or other users by manipulating the id parameter.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Vulnerable Action: ftg_delete_gallery (inferred as the most likely "unauthorized action" for this IDOR).
  • HTTP Method: POST
  • Parameter: id (the ID of the target gallery).
  • Required Authentication: Authenticated user with Author role or higher.
  • Preconditions: A gallery must exist that is owned by a different user (e.g., an Administrator).

3. Code Flow

  1. Registration: The plugin registers AJAX actions in the main class (likely FinalTiles_Gallery) or an admin-specific class during init or admin_init.
    add_action('wp_ajax_ftg_delete_gallery', array($this, 'delete_gallery'));
    
  2. Callback: The delete_gallery function is invoked.
  3. Vulnerable Processing:
    • The function retrieves the gallery ID from $_POST['id'].
    • It verifies the request nonce (e.g., ftg_nonce).
    • It checks if the user has the general capability to manage galleries (e.g., current_user_can('publish_posts')).
    • Vulnerability: It proceeds to call the database deletion method (e.g., FinalTilesdb::deleteGallery($id)) without checking if the $current_user_id matches the author_id associated with that gallery record in the wp_ftg_galleries table.

4. Nonce Acquisition Strategy

The plugin enqueues a script and localizes gallery configuration variables, including a nonce, on the plugin's admin dashboard.

  1. Identify Trigger: The scripts are loaded on the main gallery admin page: /wp-admin/admin.php?page=ftg-lite-gallery-admin.
  2. Creation: No special shortcode is needed as the dashboard is accessible to any user with Author privileges (who can "publish posts").
  3. Extraction:
    • Navigate to the dashboard.
    • Use browser_eval to extract the nonce from the ftg_vars (or ftg_lite_vars) object.
    • JS Key: window.ftg_vars?.nonce or window.ftg_lite_vars?.nonce.

5. Exploitation Strategy

Step 1: Discover Target Gallery ID

The attacker needs the ID of a gallery they do not own. Gallery IDs are often sequential or visible in the frontend source code of pages displaying galleries.

  • Method: Check the homepage or any post for the shortcode: [finaltilesgallery id='X'].

Step 2: Obtain Nonce as Author

Log in as an Author and retrieve the nonce from the localized script.

Step 3: Trigger Unauthorized Deletion

Send a POST request to the AJAX endpoint targeting the Administrator's gallery ID.

Request Body (URL-encoded):

POST /wp-admin/admin-ajax.php HTTP/1.1
Content-Type: application/x-www-form-urlencoded

action=ftg_delete_gallery&id=[TARGET_ID]&_wpnonce=[EXTRACTED_NONCE]

6. Test Data Setup

  1. Administrator: Create a gallery named "Admin Private Gallery" via the Final Tiles Gallery menu. Note its ID (e.g., 1).
  2. Author: Create a user with the Author role.
  3. Verification Record: Ensure the gallery exists in the database.
    wp db query "SELECT id, name FROM wp_ftg_galleries"
    

7. Expected Results

  • The server should respond with a 200 OK and likely a success indicator (e.g., 1, true, or a JSON success message).
  • The "Admin Private Gallery" record should be removed from the wp_ftg_galleries table.
  • All associated image records in wp_ftg_images linked to that gallery ID should be deleted or orphaned.

8. Verification Steps

  1. Database Check: Run a query via WP-CLI to verify the target gallery no longer exists.
    wp db query "SELECT count(*) FROM wp_ftg_galleries WHERE id = [TARGET_ID]"
    
    Expected Output: 0
  2. Admin UI Check: Log in as Administrator and verify the gallery is missing from the list at /wp-admin/admin.php?page=ftg-lite-gallery-admin.

9. Alternative Approaches

If ftg_delete_gallery is not the vulnerable action, try the following IDOR-prone actions:

  • ftg_save_gallery: Attempt to rename the Admin's gallery.
    • Body: action=ftg_save_gallery&id=[TARGET_ID]&name=DefacedByAuthor&_wpnonce=[NONCE]
  • ftg_duplicate_gallery: Attempt to clone an Admin's gallery to see if the cloned version becomes owned by the Author, allowing information disclosure.
    • Body: action=ftg_duplicate_gallery&id=[TARGET_ID]&_wpnonce=[NONCE]
  • ftg_shortcode_editor: Check if the picker allows viewing the configuration of non-owned galleries.
    • URL: /wp-admin/admin-ajax.php?action=ftg_shortcode_editor&id=[TARGET_ID] (GET)
Research Findings
Static analysis — not yet PoC-verified

Summary

The Image Photo Gallery Final Tiles Grid plugin is vulnerable to an Insecure Direct Object Reference (IDOR) via its AJAX handlers due to a lack of ownership verification on the requested gallery object. Authenticated attackers with Author-level permissions can access or manipulate gallery configurations belonging to other users, including administrators, by providing a specific gallery ID in requests to the 'ftg_shortcode_editor' action.

Vulnerable Code

// FinalTilesGalleryLite.php lines 493-497
public function ftg_shortcode_editor() {
    if ( !current_user_can( 'edit_posts' ) ) {
        wp_die( 'Unauthorized', 401 );
    }
    // ... following logic uses a user-supplied 'id' without ownership validation

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/final-tiles-grid-gallery-lite/3.6.11/admin/scripts/editor-plugin.js /home/deploy/wp-safety.org/data/plugin-versions/final-tiles-grid-gallery-lite/3.6.12/admin/scripts/editor-plugin.js
--- /home/deploy/wp-safety.org/data/plugin-versions/final-tiles-grid-gallery-lite/3.6.11/admin/scripts/editor-plugin.js	2026-01-28 12:43:14.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/final-tiles-grid-gallery-lite/3.6.12/admin/scripts/editor-plugin.js	2026-03-04 14:01:26.000000000 +0000
@@ -6,7 +6,7 @@
 			{
 				ed.windowManager.open(
 				{
-					file: ajaxurl + '?action=ftg_shortcode_editor',
+					file: ajaxurl + '?action=ftg_shortcode_editor&nonce=' + (typeof ftgEditorData !== 'undefined' ? ftgEditorData.nonce : ''),
 					width : 900 + parseInt(ed.getLang('button.delta_width', 0)),
 					height : 500 + parseInt(ed.getLang('button.delta_height', 0)),
 					inline : 1
diff -ru /home/deploy/wp-safety.org/data/plugin-versions/final-tiles-grid-gallery-lite/3.6.11/FinalTilesGalleryLite.php /home/deploy/wp-safety.org/data/plugin-versions/final-tiles-grid-gallery-lite/3.6.12/FinalTilesGalleryLite.php
--- /home/deploy/wp-safety.org/data/plugin-versions/final-tiles-grid-gallery-lite/3.6.11/FinalTilesGalleryLite.php	2026-01-28 12:43:14.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/final-tiles-grid-gallery-lite/3.6.12/FinalTilesGalleryLite.php	2026-03-04 14:01:26.000000000 +0000
@@ -491,6 +492,7 @@
         }
 
         public function ftg_shortcode_editor() {
+            check_ajax_referer( 'ftg_shortcode_editor_nonce', 'nonce' );
             if ( !current_user_can( 'edit_posts' ) ) {
                 wp_die( 'Unauthorized', 401 );
             }

Exploit Outline

1. Authenticate as a user with the 'Author' role or any role possessing the 'edit_posts' capability. 2. Identify a target gallery ID belonging to another user (e.g., an Administrator's gallery ID found via front-end shortcodes like [finaltilesgallery id='1']). 3. Send an HTTP GET request to the AJAX endpoint: /wp-admin/admin-ajax.php?action=ftg_shortcode_editor&id=[TARGET_ID]. 4. Observe that the plugin returns the configuration interface or data for the requested gallery because it lacks an ownership check verifying the gallery belongs to the requester, and in version 3.6.11, it lacks a nonce to prevent unauthorized direct requests.

Check if your site is affected.

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