4 Jan 2017

Tip For Security Researchers: Make Sure The Developer Has Actually Fixed The Vulnerability You Found

When reviewing a report of a vulnerability in a WordPress plugin while preparing to add it our service’s dataset we test out the vulnerability. We do that to help us to do a number of things, including making sure the vulnerability actually exists and to determine what versions are vulnerable. Through that we often find that the vulnerabilities have only been partially fixed or have not been fixed at all, despite the discover of the vulnerability stating that it has been fixed.

If the vulnerability is likely to be exploited that can be a big issue, since hackers are unlikely to check what version of the plugin is in use, instead they will just try to exploit it. So people that have updated won’t be protected by keeping up to date and they even may think they are if the run across a source claiming it has been fixed (we seem to be the only ones that do that sort of checking with WordPress plugins, so if someone else is telling you a vulnerability has been fixed they likely don’t know if that is true or not).

What looks to be a common cause of this is that discoverer of the vulnerability gets told by the developer of the plugin that it has been fixed and assumes that to be the case. Considering how many vulnerabilities involve failures to do security basics in the first place, it wouldn’t be surprising that the plugin’s developer wouldn’t actually know if it has been fixed. In other cases with more complicated issues it is understandable that the developer might not fully grasp the issue at first and what needs to be done to fully fix it.

In our experience, when we get in touch with the plugin’s developer to let them know that the vulnerability hasn’t been fixed and offer help on getting it resolved, the issue is often quickly fixed. So checking if the vulnerability has in fact been fixed before disclosing it will make a big difference towards better security.

A Partial Fix

To give you an example of the need to make sure the vulnerability has been fixed let’s take a look at a recently disclosed server side request forgery (SSRF) vulnerability in the plugin Nelio AB Testing discovered by Yeo Quan Yang.

A server side request forgery vulnerability involves a request being made by the server, which could allow an attacker to send request to systems that are accessible by the server, but not publicly accessible. The request could also allow them increased access to publicly accessible systems than they normally would have.

In the case of the Nelio AB testing when a request was to sent to the file /ajax/iesupport.php in version 4.5.8 the value of the POST input “originalRequestUrl” was used for the value of the variable “$url”:

23
24
25
26
if ( isset( $_POST['originalRequestUrl'] ) ) {
	$url = $_POST['originalRequestUrl'];
	$url = preg_replace( '/^\/\//', '', $url );
}

That value of that variable then is used as the URL to be requested by a curl request sent from the server:

57
curl_setopt( $ch, CURLOPT_URL, $url );

In the discoverer’s post they mention that they were told the vulnerability was fixed:

I’ve since reported this to the plugin author and was told it has been fixed!

That appears to be in reference to version 4.5.9, which adds a restriction to what the POST input “originalRequestUrl” could be set to:

23
24
25
26
27
28
29
if ( isset( $_POST['originalRequestUrl'] ) ) {
	$url = $_POST['originalRequestUrl'];
	$url = preg_replace( '/^\/\//', '', $url );
	if ( ! preg_match( '/^https?:/', $url ) ) {
		return;
	}//end if
}

So now the URL to be requested has to either be the HTTP or HTTPS protocol, which does limit things since curl supports:

DICT, FILE, FTP, FTPS, Gopher, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, POP3, POP3S, RTMP, RTSP, SCP, SFTP, SMB, SMTP, SMTPS, Telnet and TFTP.

But that doesn’t resolve the issue entirely since it would still allow an attacker to requests to arbitrary HTTP or HTTPS URLs.

When we reviewed the vulnerability we noticed the issue and notified the developer of the issue. In less than a day they had put in place a fix and replied to us asking us to review it before the released it.

That fix involved taking the domain that requests from this file are intended to be sent to:

5
6
define( 'NELIOAB_BACKEND_NAME', 'nelioabtesting' );
define( 'NELIOAB_BACKEND_DOMAIN', NELIOAB_BACKEND_NAME . '.appspot.com' );

If the URL to be requested isn’t from that domain then the file exits before the request would be made:

37
38
39
40
41
42
43
44
45
46
$url = $_POST['originalRequestUrl'];
$url = preg_replace( '/^\/\//', '', $url );
$data = $_POST['data'];
 
// If the URL isn't the one we expect, leave.
if ( strpos( $url, NELIOAB_BACKEND_DOMAIN . '/' ) !== 0 ) {
	// Silence is gold
	header( 'HTTP/1.1 400 Bad Request' );
	return;
}

That change resolved the issue.

Leave a Reply

Your email address will not be published.