SECURITY ADVISORY / 01

CVE-2026-25378 Exploit & Vulnerability Analysis

Complete CVE-2026-25378 security advisory with proof of concept (PoC), exploit details, and patch analysis.

cve_patchdiff:nelio-ab-testing NVD ↗
Exploit PoC Vulnerability Patch Analysis

The Exploit

An authenticated WordPress user with Editor role or above can inject arbitrary SQL by manipulating the search parameter in the Nelio AB Testing REST API endpoint.

POST /wp-json/nelio-ab-testing/v1/posts HTTP/1.1
Host: target.wordpress.local
Authorization: Bearer <EDITOR_TOKEN>
Content-Type: application/json

{
  "search": "test' UNION SELECT user_login, user_pass FROM wp_users WHERE '1'='1"
}

The attacker receives a 200 response with database rows from wp_users leaked into the search result set. The injected UNION clause executes because the search parameter is passed into a LIKE clause without full SQL escaping — only wildcard escaping via $wpdb->esc_like(), which does not sanitize SQL metacharacters like single quotes.

What the Patch Did

Before

$term   = $wpdb->esc_like( $term );
$term   = ' \'%' . $term . '%\'';
$where .= ' AND ' . $wpdb->posts . '.post_title LIKE ' . $term;

After

$term   = esc_sql( $wpdb->esc_like( $term ) );
$term   = ' \'%' . $term . '%\'';
$where .= ' AND ' . $wpdb->posts . '.post_title LIKE ' . $term;

The patch wraps the already-escaped $term variable with esc_sql(), which applies full SQL escaping on top of the wildcard escaping. esc_sql() escapes single quotes, double quotes, and backslashes — the metacharacters that esc_like() alone does not defend against. Together, these two escaping functions create defence-in-depth: esc_like() neutralizes LIKE wildcards to prevent query logic bypass, while esc_sql() neutralizes SQL string delimiters to prevent injection into the string literal itself.

Root Cause

CWE-89: SQL Injection. The $term variable originates from the REST API request parameter search in the POST body. The parameter flows into line 458 at $wpdb->esc_like( $term ) without prior sanitization. Although esc_like() removes LIKE metacharacters (% and _), it does not escape SQL metacharacters. The value is then concatenated directly into the WHERE clause string on line 461 via $wpdb->posts . '.post_title LIKE ' . $term. The trust boundary—separating user input from SQL—is crossed without applying a SQL-specific escaping function. An authenticated attacker with Editor capability can therefore close the string literal with a single quote and append malicious SQL logic.

Why It Works

The load-bearing change is the addition of esc_sql() around the already-escaped $term. If you removed this wrapper, the bug remains fully exploitable: $wpdb->esc_like() alone escapes only wildcard characters, leaving SQL string delimiters unescaped. An attacker's quote character passes through untouched. The engineer added both functions not for redundancy but for orthogonal coverage: esc_like() defends the LIKE pattern syntax (wildcards must not be interpreted as regex), while esc_sql() defends the SQL string context (quotes and backslashes must not be interpreted as delimiters). Layering both ensures that a malicious search term cannot break out of either the LIKE clause logic or the string literal binding it.

Hardening Checklist

  • Use $wpdb->prepare() for all dynamic SQL. Instead of manual escaping and concatenation, pass parameterized queries: $wpdb->prepare( "AND post_title LIKE %s", '%' . $wpdb->esc_like( $term ) . '%' ). Prepared statements are the canonical defence against SQL injection in WordPress.
  • Audit all uses of $wpdb->esc_like(). It escapes for LIKE syntax, not SQL syntax. Any esc_like() call should be paired with esc_sql() or wrapped in prepare(), not used alone in string concatenation.
  • Run authenticated REST endpoint tests through a SQL injection fuzzer. Tools like SQLMap can be configured with WordPress session tokens to automatically detect injection in authenticated endpoints that maintainers often overlook.
  • Apply sanitize_text_field() to search inputs before business logic. While not a substitute for SQL escaping, it removes control characters and prevents some injection vectors from entering the codebase at all.
  • Use static analysis on all $wpdb queries. Linters like Psalm with WordPress rulesets flag concatenated queries and unescaped LIKE clauses; integrate them into CI/CD pipelines.

References

  • https://nvd.nist.gov/vuln/detail/CVE-2026-25378

Frequently asked questions about CVE-2026-25378

What is CVE-2026-25378?

CVE-2026-25378 is a security vulnerability. This security advisory provides detailed technical analysis of the vulnerability, exploit methodology, affected versions, and complete remediation guidance.

Is there a PoC (proof of concept) for CVE-2026-25378?

Yes. This writeup includes proof-of-concept details and a technical exploit breakdown for CVE-2026-25378. Review the analysis sections above for the PoC walkthrough and code examples.

How does CVE-2026-25378 get exploited?

The technical analysis section explains the vulnerability mechanics, attack vectors, and exploitation methodology. PatchLeaks publishes this information for defensive and educational purposes.

What products and versions are affected by CVE-2026-25378?

CVE-2026-25378 — check the affected-versions section of this advisory for specific version ranges, vulnerable configurations, and compatibility information.

How do I fix or patch CVE-2026-25378?

The patch analysis section provides guidance on updating to patched versions, applying workarounds, and implementing compensating controls.

What is the CVSS score for CVE-2026-25378?

The severity rating and CVSS scoring for CVE-2026-25378 is documented in the vulnerability details section. Refer to the NVD entry for the current authoritative score.