$5,500 Bounty Awarded for Unauthenticated SQL Injection Vulnerability Patched in LayerSlider WordPress Plugin

On March 25th, 2024, during our second Bug Bounty Extravaganza, we received a submission for an unauthenticated SQL Injection vulnerability in LayerSlider, a WordPress plugin with more than 1,000,000 estimated active installations. This vulnerability can be leveraged to extract sensitive data from the database, such as password hashes.

Props to 1337_wannabe who discovered and responsibly reported this vulnerability through the Wordfence Bug Bounty Program. This researcher earned a bounty of $5,500.00 for this discovery during our Bug Bounty Program Extravaganza, our highest bounty yet! Our mission is to Secure the Web, 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, which ultimately makes the entire web more secure.

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 contacted the Kreatura Team on March 25, 2024, and received a response on the next day. After providing full disclosure details, the developer released a patch on March 27, 2024. We would like to commend the Kreatura Team for their prompt response and timely patch.

We urge users to update their sites with the latest patched version of LayerSlider, which is version 7.10.1, as soon as possible.

Vulnerability Summary from Wordfence Intelligence

Description: LayerSlider 7.9.11 – 7.10.0 – Unauthenticated SQL Injection
Affected Plugin: LayerSlider
Plugin Slug: LayerSlider
Affected Versions: 7.9.11 – 7.10.0
CVE ID: CVE-2024-2879
CVSS Score: 9.8 (Critical)
CVSS Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Researcher/s: 1337_wannabe
Fully Patched Version: 7.10.1
Bounty Award: $5,500.00

The LayerSlider plugin for WordPress is vulnerable to SQL Injection via the ls_get_popup_markup action in versions 7.9.11 and 7.10.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 unauthenticated attackers to append additional SQL queries into already existing queries that can be used to extract sensitive information from the database.

Technical Analysis

Unfortunately, insecure implementation of the plugin’s slider popup markup query functionality allows for SQL injection. Examining the code reveals that the plugin uses the ls_get_popup_markup() function to query sliders markup for popup, where the id can be specified with the ‘id’ parameter.

function ls_get_popup_markup() {

	$id 	= is_numeric( $_GET['id'] ) ? (int) $_GET['id'] : $_GET['id'];
	$popup = LS_Sliders::find( $id );

	if( $popup ) {
		$GLOBALS['lsAjaxOverridePopupSettings'] = true;
		$parts 	= LS_Shortcode::generateSliderMarkup( $popup );
		die( $parts['container'].$parts['markup'].'<script>'.$parts['init'].'</script>' );
	}

	die();
}

If the ‘id’ parameter is not a number, it is passed without sanitization to the find() function in the LS_Sliders class, which queries the sliders as follows, if $args is neither a number nor a string, nor a special integer array:

public static function find( $args = [] ) {

$userArgs = $args;

// Find by slider ID
if(is_numeric($args) && intval($args) == $args) {
	return self::_getById( (int) $args );

// Random slider
} elseif($args === 'random') {
	return self::_getRandom();

// Find by slider slug
} elseif(is_string($args)) {
	return self::_getBySlug($args);

// Find by list of slider IDs
} elseif(is_array($args) && isset($args[0]) && is_numeric($args[0])) {
	return self::_getByIds($args);

// Find by query
} else {


	// Defaults
	$defaults = [
		'columns' => '*',
		'where' => '',
		'exclude' => ['removed'],
		'orderby' => 'date_c',
		'order' => 'DESC',
		'limit' => 30,
		'page' => 1,
		'groups' => false,
		'data' => true,
		'drafts' => false
	];
	
	// Merge user data with defaults
	foreach( $defaults as $key => $val ) {
		if( ! isset( $args[ $key ] ) ) {
			$args[ $key ] = $val;
		}
	}
	
	// Escape user data
	foreach( $args as $key => $val ) {
		if( $key !== 'where' ) {
			$args[ $key ] = esc_sql( $val );
		}
	}

All $args values are escaped with the esc_sql() function, except for the ‘where’ value.

// Where
$where = '';
if(!empty($args['where']) && !empty($args['exclude'])) {
	$where = "WHERE ({$args['exclude']}) AND ({$args['where']}) ";

} elseif(!empty($args['where'])) {
	$where = "WHERE {$args['where']} ";

} elseif(!empty($args['exclude'])) {
	$where = "WHERE {$args['exclude']} ";
}
$sliders = $wpdb->get_results("
	SELECT SQL_CALC_FOUND_ROWS {$args['columns']}
	FROM $table
	$where
	ORDER BY `{$args['orderby']}` {$args['order']}, name ASC
	LIMIT {$args['limit']}

", ARRAY_A);

The WHERE statement is added to the query without the WordPress wpdb prepare() function. The prepare() function would parameterize and escape the SQL query for safe execution in WordPress, thereby providing protection against SQL injection attacks.

Since Union-Based SQL injection is not possible due to the structure of the query, an attacker would need to use a time-based blind approach to extract information from the database. This means that they would need to use SQL CASE statements along with the SLEEP() command while observing the response time of each request to steal information from the database. This is an intricate, yet frequently successful method to obtain information from a database when exploiting SQL Injection vulnerabilities.

Wordfence Firewall

The following graphic demonstrates the steps to exploitation an attacker might take and at which point the Wordfence firewall blocks an attacker from successfully exploiting the vulnerability.

The Wordfence firewall rule detects the malicious SQL query and blocks the request.

Disclosure Timeline

March 25, 2024 – We receive the submission for the SQL Injection vulnerability in LayerSlider via the Wordfence Bug Bounty Program.
March 25, 2024 – We validate the report and confirm the proof-of-concept exploit.
March 25, 2024 – We initiate contact with the plugin vendor asking that they confirm the inbox for handling the discussion.
March 26, 2024 – The vendor confirms the inbox for handling the discussion.
March 26, 2024 – We send over the full disclosure details. The vendor acknowledges the report and begins working on a fix.
March 27, 2024 – The fully patched version of the plugin, 7.10.1, is released.

Conclusion

In this blog post, we detailed an SQL Injection vulnerability within the LayerSlider plugin affecting versions 7.9.11 and 7.10.0. This vulnerability allows unauthenticated threat actors to inject malicious SQL queries to steal sensitive information from the database. The vulnerability has been fully addressed in version 7.10.1 of the plugin.

We encourage WordPress users to verify that their sites are updated to the latest patched version of LayerSlider.

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.

Did you enjoy this post? Share it!

Comments

2 Comments
  • Is there a patch available that doesn't require the user to either purchase/subscribe via the creators themselves or rely on the theme creators to include the new version?

    The Wordfence rule is really helpful here, and I appreciate it having been made immediately available to users of the free version too. However, it's still a sticking plaster for something that remains dangerous- particularly if WF is turned off for whatever reason- and which should be patched regardless.

    (After checking, I notice that our installed version is 7.9.5- ironically too old to be one of the apparently affected versions (7.9.11 to 7.10.0)- but I'll post this anyway as I suspect having an answer already available would be helpful to others who *are* in that boat).

    • Hi Steven, we are not sure if there is a patch available for users that does not require purchasing/subscribing directly through the vendor. I would recommend reaching out directly to the vendor to see if they can provide you with a patched copy of the plugin considering this is a critical security issue.