400,000 WordPress Sites Affected by Unauthenticated SQL Injection Vulnerability in Ally WordPress Plugin

On February 4th, 2026, we received a submission for an SQL Injection vulnerability in Ally, a WordPress plugin estimated to have more than 400,000 active installations. This vulnerability can be leveraged to extract sensitive data from the database, such as password hashes.

Props to Drew Webber (mcdruid) who discovered and responsibly reported this vulnerability through the Wordfence Bug Bounty Program. This vulnerability was reported to our program just five days after it was introduced. This researcher earned a bounty of $800.00 for this discovery. Our mission is to secure WordPress through defense in depth, which is why we are investing in quality vulnerability research and collaborating with researchers of this caliber through our Bug Bounty Program. We are committed to making the WordPress ecosystem more secure through the detection and prevention of vulnerabilities, which is a critical element to our multi-layered approach to security.

All Wordfence Premium, Wordfence Care, and Wordfence Response customers, as well as those using the free version of our plugin, are protected against any exploits targeting this vulnerability by the Wordfence firewall’s built-in SQL Injection protection.

We provided full disclosure details to the Elementor team on February 13, 2026. The vendor acknowledged the report on February 15, 2026, and released the patch on February 23, 2026. We would like to commend the Elementor team for their prompt response and timely patch.

We urge users to update their sites with the latest patched version of Ally, version 4.1.0 at the time of this publication, as soon as possible.


🔥🔥🔥 Triple Threat Bug Bounty Challenge 🔥🔥🔥
Hunt High Threat vulnerabilities and earn triple the incentives!

Now through April 6, 2026, earn three stacked bonuses on all valid submissions from our ‘High Threat Vulnerabilities’ list:

  • 💰 2x all high threat vulnerability bounties (excluding 5,000,000+ installs)
  • 📈 +30% bonus for high threat vulnerabilities in software with 30,000+ active installs (excluding 5,000,000+ installs)
  • 🎯 $300 extra for every 3 High Threat vulnerabilities submitted (minimum of 1,000 installs)

Use the Bounty Estimator to see what rewards are possible through the promotion.

Submit through our Bug Bounty Program today to maximize your impact and your payout.


Vulnerability Summary from Wordfence Intelligence

CVSS Rating
7.5 (High)
Affected Version(s)
<= 4.0.3
Patched Version
4.1.0
Bounty
$800.00
Affected Software
The Ally – Web Accessibility & Usability plugin for WordPress is vulnerable to SQL Injection via the URL path in all versions up to, and including, 4.0.3. This is due to insufficient escaping on the user-supplied URL parameter in the `get_global_remediations()` method, where it is directly concatenated into an SQL JOIN clause without proper sanitization for SQL context. While `esc_url_raw()` is applied for URL safety, it does not prevent SQL metacharacters (single quotes, parentheses) from being injected. 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 via time-based blind SQL injection techniques. The Remediation module must be active, which requires the plugin to be connected to an Elementor account.

Technical Analysis

Unfortunately, insecure implementation of the plugin’s subscribers query functionality allows for SQL injection. Examining the code reveals that the plugin uses the get_global_remediations() function in the Remediation_Entry class to query global remediations for the page url.

public static function get_global_remediations( string $url ) : array {
	$excluded_table = Global_Remediation_Relationship_Table::table_name();
	$remediation_table = Remediation_Table::table_name();
	$global_where = [
		[
			'column' => "$remediation_table.global",
			'value' => 1,
			'operator' => '=',
		],
	];
	$join = "LEFT JOIN $excluded_table ON $remediation_table.id = $excluded_table.remediation_id AND $excluded_table.page_url = '$url'";
	return Remediation_Table::select( "$remediation_table.*, COALESCE($excluded_table.active, $remediation_table.active) AS active_for_page", $global_where, null, null, $join );
}

Although the esc_url_raw() function is used in the Utils::get_current_page_url() function, it does not protect against SQL injection.

The JOIN statement is added to the query without the WordPress wpdb prepare() function. The prepare() function parameterizes and escapes SQL queries for safe execution in WordPress, thereby providing protection against SQL injection attacks. When this function is missing, it is possible to break out of SQL queries and inject new custom queries that will also be executed.

An attacker can use a Time-Based blind SQL injection approach to extract information from the database. This involves the use of SQL CASE statements in combination with the SLEEP() function while observing the response time of each request to exfiltrate information from the database. This is an intricate, yet frequently successful method to obtain information from a database when exploiting blind SQL Injection vulnerabilities.

The Patch

The vendor patched this issue by using the wpdb prepare() function in the JOIN statement.

public static function get_global_remediations( string $url ) : array {
	$excluded_table = Global_Remediation_Relationship_Table::table_name();
	$remediation_table = Remediation_Table::table_name();
	$global_where = [
		[
			'column' => "$remediation_table.global",
			'value' => 1,
			'operator' => '=',
		],
	];
	// Use prepare() to safely bind the URL; never concatenate user input into SQL.
	$join = Remediation_Table::db()->prepare(
		"LEFT JOIN $excluded_table ON $remediation_table.id = $excluded_table.remediation_id AND $excluded_table.page_url = %s",
		$url
	);
	return Remediation_Table::select( "$remediation_table.*, COALESCE($excluded_table.active, $remediation_table.active) AS active_for_page", $global_where, null, null, $join );
}

Disclosure Timeline

February 4, 2026 – We received the submission for the SQL Injection vulnerability in Ally via the Wordfence Bug Bounty Program.
February 13, 2026 – We validated the report and confirmed the proof-of-concept exploit.
February 13, 2026 – We sent over the full disclosure details.
February 15, 2026 –The vendor acknowledged the report and began working on a fix.
February 23, 2026 – The fully patched version of the plugin, 4.1.0, was released.

Conclusion

In this blog post, we detailed a SQL Injection vulnerability within the Ally plugin affecting versions 4.0.3 and earlier. This vulnerability allows unauthenticated threat actors to inject malicious SQL queries to steal sensitive information from the database. The vulnerability has been addressed in version 4.1.0 of the plugin.

We encourage WordPress users to verify that their sites are updated to the latest patched version of Ally as soon as possible considering the critical nature of this vulnerability.

All Wordfence users, including those running Wordfence Premium, Wordfence Care, and Wordfence Response, as well as sites running the free version of Wordfence, are fully protected against this vulnerability.

If you know someone who uses this plugin on their site, we recommend sharing this advisory with them to ensure their site remains secure, as this vulnerability poses a significant risk.

The post 400,000 WordPress Sites Affected by Unauthenticated SQL Injection Vulnerability in Ally WordPress Plugin appeared first on Wordfence.

Leave a Comment