31 Jul 2017

Planet Zuda’s False Claim of a Cross-Site Request Forgery (CSRF) Vulnerability in Caldera Forms

If you have read either of our previous posts about the security company Planet Zuda you won’t be surprised to hear that they are selling a “fixed” version of another WordPress plugin where the vulnerability they claim to have fixed doesn’t exist. This time it is with the plugin Caldera Forms, which has 90,000+ active installs, and for which they want 29.99 for the “fixed” version.

In reading the first part of their post with the claim about this plugin it really seems that people behind this company are not all together with it, which makes deciphering what the vulnerability is supposed to be harder. Here is the main portion of the claim about the vulnerability:

It saddens us that the developer misunderstood the wp_create_nonce as a way to actually create a secure nonce. You can just maliciously remove this from the form creating  csrf where you can add new forms on a site you don’t own  . Unfortunately, the forms suffer from stored XSS, which means we can put in malicious code if an admin clicks on a link, looks at a picture that is malicious online, etc thus exploiting the CSRF issue.

The function wp_create_nonce() is in fact exactly the way to create a secure nonce in WordPress, so it seems like Planet Zuda doesn’t understand what they are talking about at all. Amazingly in the post they mention the following:

Our advisor told us that Caldera forms would be a great candidate for our Help A Code Author program, where we contact a developer who needs help and offer our services free of charge.

If you remove the nonce from a request then the other half of the cross-site request forgery (CSRF) protection should prevent the request from being successful. Planet Zuda’s post doesn’t even mention that part of the code, instead the next paragraph in the post is this:

Here is the code that is flawed that leads to the CSRF

Then it shows this image :

The post them moves on without showing the code that should be checking for a valid nonce.

When requesting to create a new form the function create_form() in the file /classes/admin.php is run. The first part of it checks for a valid nonce and here is how it looks in the current version of the pluign, 1.5.3.1 (and how it has looked for some time):

1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
public static function create_form(){
	$nonce_validated = false;
	if(  isset( $_POST[ 'nonce' ] ) &&  wp_verify_nonce( $_POST[ 'nonce'], 'cf_create_form' ) ){
		$nonce_validated = true;
	}
 
	parse_str( $_POST['data'], $newform );
 
 
	if( ! $nonce_validated ){
		if( isset( $newform, $newform[ 'nonce' ] ) ) {
			if( wp_verify_nonce( $newform[ 'nonce' ], 'cf_create_form' ) ){
				$nonce_validated = true;
			}
		}
 
	}
 
	if( ! $nonce_validated ){
		status_header(500);
		wp_send_json_error( );
	}

The code uses wp_verify_nonce() correctly to check if a valid nonce is included with the request. Just to double check that we didn’t misread the code, we tried creating a new form using a request that include an invalid or no nonce and they both failed. So the plugins actual does include valid protection against CSRF.

What looks to have happen is that Planet Zuda confused an unneeded nonce generated in the line shown in code in the image show above, with the line where the actual nonce used when creating a new form is generated, which occurs on line 374 of the file /classes/admin.php in version 1.5.3.1:

data-nonce=<?php echo wp_create_nonce( 'cf_create_form' ); ?>

Either proper testing and properly reviewing the code would have avoided improperly identifying that there was a vulnerability here.

Without the CSRF there isn’t a vulnerability here, as creating a new form is usually limited to Administrator level users who have normally the ability to use the equivalent of cross-site scripting (XSS) through the unfiltered_html capability. Though it looks like the form name doesn’t need to include HTML, so it would probably be best to sanitize the value. It would also be best to do a capabilities check along with checking for a valid nonce. (Update 8/1/2017: The developer pointed out to us that the capabilities check is already in place, it just occurs when before registering the AJAX function for creating a form.) We have contacted the developer to let them know of Planet’s Zuda claims and suggest those improvements to the plugin.

Leave a Reply

Your email address will not be published.