CVE-2026-15361
Executive Summary
CVE-2026-15361 is a critical SQL injection vulnerability discovered in the Content Views WordPress plugin, affecting all versions prior to 4.5. The flaw resides in an unauthenticated AJAX action that lacks proper capability checks, combined with insufficient sanitization of user-supplied data before it is used in a SQL query. This allows any authenticated user—including those with Subscriber-level privileges—to execute arbitrary SQL commands against the underlying WordPress database. Successful exploitation can lead to complete data exfiltration, credential theft, privilege escalation to administrator, and in severe cases, remote code execution via MySQL file-write operations. All WordPress installations running Content Views versions below 4.5 are at risk.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Technical Analysis
The root cause of CVE-2026-15361 lies in an insecure implementation of an AJAX handler within the Content Views plugin. WordPress provides two hooks for AJAX requests: wp_ajax_ (for authenticated users) and wp_ajax_nopriv_ (for unauthenticated users). The vulnerable plugin registers an AJAX action but fails to invoke the necessary nonce verification and capability checks (e.g., current_user_can()). This oversight permits any logged-in user, regardless of their assigned role, to invoke the AJAX endpoint. A Subscriber account—which normally holds the lowest privilege level—is therefore sufficient to trigger the vulnerable code path.
The second component of the vulnerability is the lack of input sanitization and parameterized queries. The AJAX handler retrieves a user-controlled parameter (e.g., an ID, category, or sort field) and directly concatenates it into a SQL query without using WordPress's $wpdb->prepare() method or equivalent escaping functions. This allows an attacker to inject arbitrary SQL syntax. The unsanitized parameter is likely embedded in a WHERE, ORDER BY, or LIMIT clause, providing ample surfaces for classic UNION SELECT payloads, boolean-based blind injection, or time-based blind injection.
From a code perspective, the vulnerable function may resemble:
add_action('wp_ajax_cv_get_posts', 'cv_ajax_get_posts');
function cv_ajax_get_posts() {
$id = $_POST['id'];
global $wpdb;
$results = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}posts WHERE ID = $id");
// ...
}
The absence of check_ajax_referer() and current_user_can() allows the function to be reached, and the direct interpolation of $id into the SQL string introduces the injection vector.
The attack surface is the WordPress admin AJAX endpoint (admin-ajax.php), which is publicly accessible. While the attack requires authentication, the fact that Subscriber accounts are sufficient dramatically expands the target pool—any user who has ever been granted a low-privilege account on a WordPress site can exploit this vulnerability. Additionally, on many WordPress installations, user registration is open, allowing an attacker to create a Subscriber account and immediately exploit the flaw without requiring any prior access.
Exploitation Scenarios
A realistic attack chain for CVE-2026-15361 proceeds as follows:
Step 1: Reconnaissance and Target Identification
The attacker first identifies WordPress sites running the Content Views plugin. This can be achieved via Shodan searching for the plugin's typical page elements (http.component:"WordPress" combined with directories such as /wp-content/plugins/content-views-query-and-display-post-page/), by scanning for its JavaScript or CSS handles in page source, or by using WordPress-specific enumeration tools like WPScan against a target URL.
Step 2: Low-Privilege Account Creation or Compromise
Next, the attacker obtains a legitimate low-privilege account. If the site allows open user registration (a common default when Membership is enabled), the attacker registers a new Subscriber account in seconds. Alternatively, the attacker may attempt credential stuffing using leaked credential databases, targeting common email/password pairs against the site's wp-login.php. Given the scale of credential breaches, obtaining a valid Subscriber account is often trivial.
Step 3: Triggering the Vulnerable AJAX Action
The attacker authenticates to the WordPress admin dashboard and crafts a POST request to /wp-admin/admin-ajax.php. The request includes a valid action parameter matching the vulnerable endpoint (e.g., action=cv_get_posts) and carries the attacker-controlled parameter. Since the plugin lacks a nonce check, the attacker does not need to extract a valid nonce from the plugin UI; they simply include the raw payload in the POST body.
Step 4: SQL Injection Payload Weaponization
The attacker injects a UNION SELECT payload to extract data. For instance:
POST /wp-admin/admin-ajax.php HTTP/1.1
Host: target.com
Cookie: wordpress_logged_in_xxxxx=attacker_session;
action=cv_get_posts&id=0 UNION SELECT user_login, user_pass, user_email, user_nicename, 0, 0, 0, 0, 0 FROM wp_users--
The wp_users table contains login names and password hashes (MD5- or phpass-encrypted). A successful injection returns these credentials in the AJAX response. Alternatively, the attacker can use time-based blind injection (SLEEP(5)) to confirm the vulnerability and enumerate data when output is not directly reflected.
Step 5: Data Exfiltration and Privilege Escalation
With the dumped password hashes, the attacker proceeds offline to crack weak hashes or, for phpass-encrypted passwords, uses GPU-accelerated cracking tools like Hashcat. In parallel, the attacker can inject additional SQL to create a new administrator account by inserting a row into wp_users and wp_usermeta, gaining immediate full administrative access to the WordPress management console.
Step 6: Post-Exploitation — Full Site Compromise
With administrator access, the attacker installs a malicious plugin or modifies an existing theme's functions.php file to upload a web shell, achieving remote code execution on the underlying server. This allows the attacker to pivot into the hosting environment, access other sites on the same server, steal the wp-config.php database credentials, and potentially use the compromised server's outbound connectivity to launch further attacks against internal infrastructure.
Impact Assessment
The business impact of CVE-2026-15361 is severe, primarily because the access requirement is minimal. Any authenticated user, regardless of role, can trigger the vulnerability, which makes the likely attack path one of low friction for adversaries. A Subscriber account is effectively equivalent to an unauthenticated attacker in environments with open registration.
The confidentiality impact is total. SQL injection allows the attacker to read any table in the WordPress database, including wp_options (which stores secret keys and settings), wp_users (credentials), and custom tables that may contain business-critical data such as customer records, order histories, and personally identifiable information. For sites selling products or services, this constitutes a direct data breach under regulations like GDPR, CCPA, or PCI DSS.
Integrity is equally compromised. The attacker can alter or delete data, deface the site, inject malicious JavaScript (stored XSS), or modify the site's active plugins and themes—all within the database layer.
At the availability level, the attacker can use heavy queries (e.g., large UNION SELECT sets combined with BENCHMARK or SLEEP) to degrade database performance. In the most severe case, they could issue a DROP TABLE statement, causing a complete site outage.
The blast radius extends beyond the WordPress installation itself. The wp_options table often stores the AUTH_KEY, SECURE_AUTH_KEY, and LOGGED_IN_KEY salts. With these, an attacker can forge authentication cookies for any user without needing the password hash. Furthermore, if MySQL runs with FILE privilege (common in permissive shared-hosting configurations), the attacker can use SELECT ... INTO OUTFILE to write a PHP web shell to a web-accessible directory, converting database access into full remote code execution and total server compromise.
Detection Guidance
Sigma Rule
title: WordPress Content Views SQL Injection Attempt
id: 7c3f1e7d-5ff2-4d5a-8f2c-9b0a2e1c9d45
status: experimental
description: Detects SQL injection patterns in AJAX requests targeting the Content Views plugin before version 4.5.
author: Valtersit Threat Intel Team
date: 2026/06/15
logsource:
category: webserver
product: apache
definition: 'Requires access log or server request log for WordPress site'
detection:
selection:
cs-method: 'POST'
c-uri|contains:
- '/wp-admin/admin-ajax.php'
cs-uri-query|contains:
- 'action=cv_'
- 'action=content-views'
cs-uri-query|contains|all:
- 'UNION'
- 'SELECT'
cs-uri-query|contains:
- 'sleep('
- 'benchmark('
- 'information_schema'
- 'wp_users'
- '0x' # hex-encoded payload
condition: selection
level: high
falsepositives:
- Legitimate plugin functionality that includes 'SELECT' or 'UNION' in the query string is extremely unlikely.
- Some WAFs may rewrite URLs, causing false positives; correlate with WAF logs.
fields:
- src_ip
- c-uri
- cs-uri-query
YARA Rule
rule WordPress_Content_Views_SQLi_2026
{
meta:
author = "Valtersit Threat Intel Team"
description = "Detects SQL injection payloads targeting the Content Views WordPress plugin"
date = "2026-06-15"
cve = "CVE-2026-15361"
strings:
$admin_ajax = "/wp-admin/admin-ajax.php"
$action_param = "action=cv_" ascii wide
$action_param2 = "action=content-views" ascii wide
$sqli_union = "UNION SELECT" ascii wide nocase
$sqli_sleep = "SLEEP(" ascii wide
$sqli_bench = "BENCHMARK(" ascii wide
$sqli_error = "extractvalue(" ascii wide
$sqli_hex = "0x" ascii wide
$wp_tables = "wp_users" ascii wide nocase
$wp_tables2 = "wp_options" ascii wide nocase
$wp_meta = "wp_usermeta" ascii wide nocase
condition:
any of ($action_param*) and
(any of ($sqli_*)) and
(any of ($wp_tables*) or any of ($wp_meta) or any of ($sqli_hex))
}
Suricata IDS Rule
alert http any any -> any any (msg:"ET WEB_SPECIFIC_APPS WordPress Content Views Plugin SQL Injection Attempt (CVE-2026-15361)"; flow:established,to_server; content:"/wp-admin/admin-ajax.php"; http_uri; nocase; content:"action="; http_uri; nocase; content:"cv_"; http_uri; nocase; pcre:"/action=cv_[a-z0-9_-]+/i"; pcre:"/(UNION[\s]+SELECT|SLEEP\(|BENCHMARK\(|extractvalue\(|updatexml\(|information_schema|wp_users)/i"; sid:202615361; rev:1; reference:cve,2026-15361; reference:url,valtersit.com/cve-2026-15361; metadata:created_at 2026_06_15, updated_at 2026_06_15, cve 2026_15361;)
Elastic Detection
// EQL query for Elastic Security SIEM
// Detects SQL injection keywords in web requests to admin-ajax.php with Content Views action
sequence by process.entity_id with maxspan=5s
[network where dns.question.name : "*" and process.executable : "httpd*" or "nginx*"]
[http where http.request.method == "POST" and
url.path == "/wp-admin/admin-ajax.php" and
url.query : "*action=cv_*" and
(url.query : "*UNION*" or url.query : "*SELECT*" or url.query : "*sleep(*" or
url.query : "*benchmark(*" or url.query : "*information_schema*" or
url.query : "*wp_users*")
]
Splunk SPL Query
index=web sourcetype=access_combined OR sourcetype=iis
| where like(form_data, "%action=cv_%") OR like(form_data, "%action=content-views%")
| search (form_data="*UNION*" OR form_data="*SELECT*" OR form_data="*sleep(*" OR form_data="*benchmark(*" OR form_data="*information_schema*" OR form_data="*wp_users*")
| stats count by src_ip, uri_path, form_data, _time
| sort - count
| table _time, src_ip, uri_path, form_data, count
| rename uri_path AS "Request Path", src_ip AS "Source IP", form_data AS "POST Body", count AS "Hit Count"
Wazuh OSSEC Rule
<group name="wordpress, sql_injection,">
<rule id="100361" level="12">
<if_sid>100300</if_sid> <!-- parent rule for Apache/modsec -->
<match>admin-ajax\.php</match>
<regex>action=cv_|action=content-views</regex>
<regex>UNION SELECT|SLEEP\(|BENCHMARK\(|information_schema|wp_users|extractvalue\(</regex>
<description>WordPress Content Views SQL Injection attempt detected (CVE-2026-15361)</description>
<group>attack,sql_injection,web_application_attack,</group>
<mitre>
<id>T1190</id>
</mitre>
<options>no_full_log</options>
</rule>
</group>
Mitigation & Patch Guidance
Patch Confidence: 2/4 (CLAIMED — single source (NVD) claims patch, not independently confirmed. Exercise due diligence before deploying.)
Immediate Mitigations (Do this now):
- Temporarily disable AJAX for the plugin: If feasible, add a server-level rule (e.g., in
.htaccessfor Apache or alocationblock for Nginx) to block POST requests to/wp-admin/admin-ajax.phpthat containaction=cv_in the request body. This sacrifices plugin functionality but closes the hole instantly. - Restrict Subscriber registration: Immediately disable open user registration in WordPress (
Settings → General → Membership). Revoke or audit existing Subscriber accounts that are not strictly necessary. - Deploy a WAF rule: If using a Web Application Firewall (Cloudflare, AWS WAF, ModSecurity), add a custom rule that blocks requests to
admin-ajax.phpcontaining SQL keywords (UNION,SELECT,SLEEP,BENCHMARK) in the body, especially when paired with anaction=cv_parameter.
- Temporarily disable AJAX for the plugin: If feasible, add a server-level rule (e.g., in
Patch/Upgrade Steps:
- UPDATE THE PLUGIN: Upgrade Content Views to version 4.5 or later immediately. The NVD description explicitly states the fix is available in version 4.5. The patch introduces proper capability checks (
current_user_can()) and uses WordPress prepared statements to mitigate SQL injection. - Verify the update: After updating, navigate to
wp-admin/plugins.phpand confirm the plugin version. Check the plugin changelog for any mentions of "security fix" or "SQL injection" to confirm the patch is applied. - Test critical workflows: Since a security patch often changes request validation, retest the plugin's core display functionality to ensure no legitimate AJAX calls are blocked by the new security checks.
- UPDATE THE PLUGIN: Upgrade Content Views to version 4.5 or later immediately. The NVD description explicitly states the fix is available in version 4.5. The patch introduces proper capability checks (
Long-Term Hardening:
- Audit the database for compromise: If you suspect exploitation may have already occurred, review
wp_usersfor rogue administrator accounts and inspectwp_optionsfor suspiciousactive_plugins. Use a tool likewp-clito enumerate users with elevated roles. - Rotate credentials: Reset all WordPress admin passwords and rotate any API keys or secrets stored in
wp-config.php. If MySQLFILEprivilege was enabled, assume the worst and treat the server as fully compromised—restore from a clean backup and re-image the host if possible. - Enforce least privilege: Review and remove unnecessary Subscriber accounts. Enable two-factor authentication (2FA) for all accounts.
- Apply a principle of defense-in-depth: Rely on more than plugin fixes. Use WordPress security plugins (e.g., Wordfence, Solid Security) to add login rate limiting, file integrity monitoring, and brute-force protection.
- Audit the database for compromise: If you suspect exploitation may have already occurred, review
References
- NVD Entry: CVE-2026-15361 — National Vulnerability Database — https://nvd.nist.gov/vuln/detail/CVE-2026-15361 (Primary source; patch claim and description.)
- WordPress Plugin Directory: Content Views — Query and Display Post Page — https://wordpress.org/plugins/content-views-query-and-display-post-page/ (Official plugin page; check changelog for version 4.5.)
- OWASP SQL Injection Prevention Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html (Reference for remediation best practices.)
- WPScan Vulnerability Database: (if published) — https://wpscan.com/ (Search for Content Views or CVE-2026-15361 for additional researcher analysis.)
Threat Actor Campaigns: As of the analysis date (July 2026), no known in-the-wild exploitation or specific threat actor campaigns have been publicly attributed to CVE-2026-15361. Given the criticality of the flaw and the ease of exploitation (requiring only a Subscriber account), it is highly likely that automated scanning and exploitation will commence rapidly once public exploit details are released. Defenders should prioritize patching within 48 hours. The CVE is not listed on the CISA Known Exploited Vulnerabilities (KEV) catalog at the time of writing.
What is this? Security researchers use these exact search queries on Shodan.io (a search engine for internet-connected devices) to find vulnerable systems globally. You can copy these dorks to see if your organization's IP space is exposed.
💣 PoC CODE AVAILABLE
Exploit code for this CVE is tracked in our database.
Access poc_code via API Pro.