02 Oct

Vulnerability Details: PHP Object Injection Vulnerability in Flickr Gallery

From time to time a vulnerability is fixed in a plugin without the discoverer putting out a report on the vulnerability and we will put out a post detailing the vulnerability so that we can provide our customers with more complete information on the vulnerability.

Since June we have been doing proactive monitoring of changes made to plugins to try to catch serious vulnerabilities. So far that has lead to identifying a couple of dozen vulnerabilities. For the fourth time it has lead to us identifying a PHP object injection vulnerability being fixed in a plugin, this time in the plugin Flickr Gallery.

Before getting in to the details of that it is worth noting that the description of the plugin was change in the latest version to state “This plugin is deprecated, please remove it from your WordPress install.”

There is no changelog for the plugin and no information that indicates who discovered the vulnerability.

The plugin runs the function init() during init, which occurs when WordPress is loading a page (in the file /flickr-gallery.php):

1121
add_action('init', array('DC_FlickrGallery', 'init'));

In that function, as of version 1.5.2, the function ajax_pagination() would run if the POST input “action” was set to “flickr-gallery-page”:

107
108
} elseif ( $_POST['action'] == 'flickr-gallery-page' ) {
	DC_FlickrGallery::ajax_pagination();

That function will unserialize the value of the POST input “page”, which permits PHP object injection to occur:

174
175
176
function ajax_pagination() {
	global $phpFlickr;
	$pager = unserialize(stripslashes($_POST['pager']));

Version 1.5.3 removes that function and the code in the function init() that would call it.

Proof of Concept

With our plugin for testing for PHP object injection installed and activated, the following proof of concept will cause the message “PHP object injection has occurred.” be shown.

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

<html>
<body>
<form action="http://[path to WordPress]" method="POST">
<input type="hidden" name="action" value="flickr-gallery-page" />
<input type="hidden" name="pager" value='O:20:"php_object_injection":0:{}' />
<input type="submit" name="submit" value="Submit" />
</form>
</body>
</html>
22 Sep

Vulnerability Details: PHP Object Injection Vulnerability in Appointments

From time to time a vulnerability is fixed in a plugin without the discoverer putting out a report on the vulnerability and we will put out a post detailing the vulnerability so that we can provide our customers with more complete information on the vulnerability.

Since June we have been doing proactive monitoring of changes made to plugins to try to catch serious vulnerabilities. So far that has lead to identifying a couple of dozen vulnerabilities. For the third time it has lead to identifying a PHP object injection vulnerability being fixed in a plugin, this time in the plugin Appointments.

In this instance though what we also noticed was that the new version of the plugin put out to fix the vulnerability still contained the vulnerable code, though it is not accessible through the plugin. What makes that situation stand out is that two companies that put out WordPress security plugins were involved in fixing this vulnerability and appear to have missed that remaining vulnerable code.

In version 2.2.2 of the plugin, two lines that pass the value of cookies to the maybe_unserialize() function, which would have permitted to PHP objection to occur, were removed. They are the following lines in the file /includes/class-app-sessions.php:

27
$apps = maybe_unserialize( stripslashes( $_COOKIE['wpmudev_appointments'] ) );
83
$data = maybe_unserialize( stripslashes( $_COOKIE['wpmudev_appointments_userdata'] ) );

Our monitoring picked up their removal, but at the same time that picked up the following two lines in the file being included in the file /includes/class_app_shortcodes.php in that version:

871
$apps = unserialize( stripslashes( $_COOKIE["wpmudev_appointments"] ) );
1699
$data = unserialize( stripslashes( $_COOKIE["wpmudev_appointments_userdata"] ) );

Those are almost exactly the same as the first two. With the only difference being use of the WordPress function maybe_unserialize() versus the PHP function unserialize() and single quotes versus double quotes.

In looking over the situation we found that the file /includes/class_app_shortcodes.php wasn’t being used, what looks to have happened is that the contents of that file were split in to different files and then that file was never removed.

This risk of that vulnerable code is limited since on its own the file can’t do anything. The risks we could think of is if someone was able to use some other code to cause this file to be loaded or that someone might reuse the vulnerable code from this file. The latter is something we recently saw happen with another plugin, though in that case the code was being utilized in the plugin it was copied from.

When the vulnerability existed in the plugin it was exploitable through several locations, including on pages using several shortcodes.

Security Companies Missed the Remaining Vulnerable Code

Normally a developer missing other instances where vulnerable code is still in the plugin isn’t something that we would be too concerned about, but in this case the developer is WPMU DEV, which also makes the Defender security plugin. We would expect that a company that provides a security plugin to be more careful about the security of their plugins.

In a look over how they promote that security plugin we didn’t get the feeling that they really have the level of concern for security that they should have when producing a security plugin. No where do they present any evidence of the effectiveness of the plugin overall or the effectiveness of its various features. One area where we know that what they are providing has limitations, is their checking for known vulnerabilities in plugins, as the source of plugin vulnerability data is WPScan Vulnerability Database, which has serious limitations, as we have discussed in previous posts. They really should be disclosing the source of the data in the marketing material and making it clear that the data they provide has serious limitations.

Something else that stuck out to us in how the plugin is promoted is this:

Brute force attacks are no match for Defender. Limit login attempts to stop users trying to guess passwords. Permanently ban IPs or trigger a timed lockout after a set number of failed login attempts.

Brute force attacks against WordPress admin passwords are not happening, what is happening, dictionary attacks, can be prevented by simply using a strong password, which WordPress does a good job of helping to people use. Protections meant to protect against brute force attacks would not always be effective against dictionary attacks and can lead to unnecessary complications.

In the changelog for version 2.2.2, one the entries seemed to be possibly referring to this vulnerability:

  • Fixed security issue (vulnerability) with data stored on a browser. Thanks to Matt Barry @ Wordfence

When we contacted the developer of the plugin about the remaining vulnerable code, they confirmed that did in fact refer to this vulnerability.

That Wordfence missed the remaining vulnerable code isn’t all that surprising based on their track record. Last year they disclosed several vulnerabilities in plugins and we found that three related vulnerabilities had not been fixed. The problem then wasn’t as much that they missed them, but that they were not providing the normal level of detail on the vulnerabilities they found that would have allowed someone to check things over and spot those related issues easily. Their providing limited details was not due to a concern about that being misused, but so they could market that they provided protection against the vulnerabilities that other firewall providers did not. In explaining why they were handling things they way they did they claimed that “At Wordfence the security of our customers and the greater WordPress community is of paramount importance to us.”,  which seems untrue when you consider that it was only because we figured out the details they didn’t provide that we could work to get the other vulnerabilities fixed. If they release information on this vulnerability, it will be interesting to see if they handle things better than they did last year.

File Removed

After we notified the developer of the remaining issue, the file /includes/class_app_shortcodes.php was removed. If you already updated to version 2.2.2 though you will still have the file. In normal circumstances that is harmless, but if you want to be extra careful you could delete the file or reinstall the plugin to get rid of the file.

Proof of Concept

With our plugin for testing for PHP object injection installed and activated, set the value of the cookie “wpmudev_appointments_userdata” to “O:20:”php_object_injection”:0:{}” and then when you visit a page with the shortcode “app_confirmation” (with a “title” attribute) the message “PHP object injection has occurred.” will be shown.

22 Sep

PHP Object Injection Vulnerability in DS.DownloadList

For the second time through our proactive monitoring of changes in WordPress plugins for serious vulnerabilities we have found a vulnerability not just as it is added to a plugin, but as the plugin was introduced into the Plugin Directory.

There is a manual review done of plugins before they are approved for the Plugin Directory and that appears to be intended to involve some check of the security of the plugins as it is stated that:

 Then someone will manually review your code. If we find no issues with the security, documentation, or presentation, your plugin will be approved.

There is nothing beyond that, which explains what, if anything, is actually checked for security wise, which is concerning, Unfortunately that isn’t just an issue with that process, everything to do with handling security by the Plugin Directory is very opaque and maybe not unrelated to that, there are a lot of problems with their handling of security as well.

In the case of the plugin DS.DownloadList, what drew our attention to it was a PHP object injection vulnerability, which is a type of vulnerability that hackers have exploited widely in the last year. But during a review of the plugin the whole concept should have been concerning due to what it is described as doing, “A lightweight plugin to download files and browse folders”.

While the plugin has some protection against abuse what we found was that it could be used by anyone to view the contents of directories inside the /wp-content/ directory. That could for example, allow someone to find the names and then download backup files, which would otherwise be protected by the use of non-easily guessable file and directory names.

The PHP object injection vulnerability occurs at the beginning the function wp_ajax_dsdl(), which is located in the file /classes/Action.class.php:

21
22
23
24
public static function wp_ajax_dsdl()
{
 
	$atts = @unserialize(base64_decode($_REQUEST['atts']));

The value of the GET or POST input “atts” will be unserialized, which permits PHP object injection to occur.

From the name of the function you can probably guess that it is accessed through WordPress’ AJAX functionality. In this case it is made accessible whether logged in or not:

32
33
add_action('wp_ajax_dsdl', array('\dsdl\Action', 'wp_ajax_dsdl'));
add_action('wp_ajax_nopriv_dsdl', array('\dsdl\Action', 'wp_ajax_dsdl'));

We contacted the developer about the vulnerability a week ago, but have not heard back from them. In line with our disclosure policy, which is based on the need to provide our customers with information on vulnerabilities on a timely basis, we are now disclosing this vulnerability.

Proof of Concept

With our plugin for testing for PHP object injection installed and activated, visiting the following URL will cause the message “PHP object injection has occurred.” to be shown.

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

http://localhost/wp-admin/admin-ajax.php?action=dsdl&atts=TzoyMDoicGhwX29iamVjdF9pbmplY3Rpb24iOjA6e30=

Timeline

  • September 15, 2017 – Developer notified.
22 Sep

PHP Object Injection Vulnerability in TAKETIN To WP Membership

Through the proactive monitoring of changes in WordPress plugins for serious vulnerabilities we do, we recently found a PHP object injection vulnerability in the TAKETIN To WP Membership plugin.

In the file /classes/taketin-mp-utils.php the function getMessage() as of version 1.2.7 would unserialize the value of the cookie “taketin_mp_error”, which permitted PHP object injection:

346
347
348
349
350
public static function getMessage(){
	if(!isset($_COOKIE[TMP_ERR_MSG_COOKIE_KEY])){
		return false;
	}
	$mess = unserialize(base64_decode($_COOKIE[TMP_ERR_MSG_COOKIE_KEY]));

One of the places that function is called is in the file /views/forgot_password.php:

10
$msg = TaketinMpUtils::getMessage();

That file is included by the function reset() (in the file /classes/taketin-mp-membership.php):

403
404
405
406
407
408
409
410
411
public function reset() {
	//$succeeded = $this->notices();
	//if ($succeeded) {
	//    return '';
	//}
	ob_start();
	//Load the forgot password template
	$template_files = TMP_MEM_PATH . 'views/forgot_password.php';
	require( $template_files );

That function is called when the shortcode “tmp_reset_form” is used:

20
add_shortcode('tmp_reset_form', array(&$this, 'reset'));

Less than day after we notifying the developer of the vulnerability they released version 1.2.8, which fixes the vulnerability by replacing usage of unserialize() with json_decode() (as well as replacing a connected usage of serialize() with json_encode()):

352
$mess = json_decode(base64_decode($_COOKIE[TMP_ERR_MSG_COOKIE_KEY]), true);

Proof of Concept

With our plugin for testing for PHP object injection installed and activated, set the value of the cookie “taketin_mp_error” to “TzoyMDoicGhwX29iamVjdF9pbmplY3Rpb24iOjA6e30=” and then when you visit a post or page with the shortcode “tmp_reset_form” on it the message “PHP object injection has occurred.” will be shown.

Timeline

  • September 21, 2017 – Developer notified.
  • September 21, 2017 – Developer responds.
  • September 21, 2017 – Version 1.2.8 released, which fixes vulnerability.
21 Sep

Vulnerability Details: PHP Object Injection Vulnerability in Invite Anyone

From time to time a vulnerability is fixed in a plugin without the discoverer putting out a report on the vulnerability and we will put out a post detailing the vulnerability so that we can provide our customers with more complete information on the vulnerability.

Since June we have been doing proactive monitoring of changes made to plugins to try to catch serious vulnerabilities. So ...


To read the rest of this post you need to have an active account with our service.

For existing customers, please log in to your account to view the rest of the post.

If you are not currently a customer, when you sign up now you can try the service for free for the first month (there are a lot of other reason that you will want to sign up beyond access to posts like this one).

If you are a security researcher please contact us to get free access to all of our Vulnerability Details posts.

14 Sep

Vulnerability Details: PHP Object Injection Vulnerability in Welcart e-Commerce

From time to time a vulnerability is fixed in a plugin without the discoverer putting out a report on the vulnerability and we will put out a post detailing the vulnerability so that we can provide our customers with more complete information on the vulnerability.

Since June we have been doing proactive monitoring of changes made to plugins to try to catch serious vulnerabilities. ...


To read the rest of this post you need to have an active account with our service.

For existing customers, please log in to your account to view the rest of the post.

If you are not currently a customer, when you sign up now you can try the service for free for the first month (there are a lot of other reason that you will want to sign up beyond access to posts like this one).

If you are a security researcher please contact us to get free access to all of our Vulnerability Details posts.

05 Sep

PHP Object Injection Vulnerability in Booster for WooCommerce

We recently started proactively monitoring for evidence of some high risk vulnerabilities when changes are made to WordPress plugins and if we had more customers we could expand the proactive monitoring to more types of vulnerabilities. One of the types of vulnerabilities we are looking for are PHP object injection vulnerabilities since those are likely to be exploited if hackers become aware of them. Through that we came across a PHP object injection vulnerability in the Email Verification module of the plugin Booster for WooCommerce.

When the Email Verification modules is enabled (it and all of the other modules are disabled by default) the function process_email_verification() in the file /includes/class-wcj-emails-verification.php is run during init:

32
add_action( 'init',                              array( $this, 'process_email_verification' ),                      PHP_INT_MAX );

That function will unserialize the value of the GET input “wcj_verify_email”, which can be abused to cause PHP object injection to occur:

111
112
113
function process_email_verification(){
	if ( isset( $_GET['wcj_verify_email'] ) ) {
		$data = unserialize( base64_decode( $_GET['wcj_verify_email'] ) );

The developer put in fix for the vulnerability in the development version of the plugin six days after we notified them of it, but a new version still has yet to be released a month later. In line with our disclosure policy, which is based on the need to provide our customers with information on vulnerabilities on a timely basis, we are now disclosing this vulnerability.

Proof of Concept

With our plugin for testing for PHP object injection installed and activated, visiting the following URL while logged in to WordPress will cause the message “PHP object injection has occurred.” to be shown.

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

http://[path to WordPress]/?wcj_verify_email=TzoyMDoicGhwX29iamVjdF9pbmplY3Rpb24iOjA6e30=

Timeline

  • August 4, 2017 – Developer notified.
  • August 10, 2017 – Developer responds.
  • September 11, 2017 – Version 3.1.0 released, which fixes vulnerability.
01 Sep

PHP Object Injection Vulnerability in VideoWhisper Live Streaming

Recently we found that the plugin VideoWhisper Live Streaming contained a PHP object injection vulnerability.

The plugin makes the function vwls_calls() available through WordPress’ AJAX functionality whether the requester is logged in to WordPress or not (in the file /videowhisper_streaming.php ):

94
95
add_action( 'wp_ajax_vwls', array('VWliveStreaming','vwls_calls'));
add_action( 'wp_ajax_nopriv_vwls', array('VWliveStreaming','vwls_calls'));

In that function the value of the GET input “task” is used for a switch statement:

6767
switch ($_GET['task'])

As of version 4.67.8, when that is set to “rtmp_status” the value of the POST input “users” is unserialized, which permits PHP object injection to occur:

7962
7963
7964
case 'rtmp_status':
 
	$users = unserialize(stripslashes($_POST['users']));

After we notified the developer they made changes that at least limit the ability to exploit this. Here is the relevant code as version 4.67.12:

80111
80112
80113
80114
80115
80116
80117
80118
80119
80120
80121
80122
80123
80124
80125
80126
80127
80128
case 'rtmp_status':
 
	$options = get_option('VWliveStreamingOptions');
 
	//allow such requests only if feature is enabled (by default is not)
	if ($options['webStatus'] != 'enabled') VWliveStreaming::rexit('denied=webStatusNotEnabled-' . $options['webStatus']);
 
	//allow only status updates from configured server IP
	if ($options['rtmp_restrict_ip'])
	{
		if (VWliveStreaming::get_ip_address() != trim($options['rtmp_restrict_ip'])) VWliveStreaming::rexit('denied=NotFromAllowedIP');
	} else VWliveStreaming::rexit('denied=StatusServerIPnotConfigured');
 
	$userdata = stripslashes($_POST['users']);
 
	if (version_compare(phpversion(), '7.0', '&lt;'))
		$users = unserialize($userdata);  //request is from trusted server
	else $users = unserialize($userdata, false);

Before getting to unserialization, a feature needs to be enabled and the request needs to appear to come from an permitted IP address (there is the possibility that the IP address could be spoofed, but you would need to guess or know the IP address when doing that). For those running at least PHP 7.0, the option to not accept any classes when unserializing should also at least limit PHP object injection from occurring if you could get past the two previous restrictions.

Proof of Concept

With our plugin for testing for PHP object injection installed and activated, the following proof of concept will cause the message “PHP object injection has occurred.” to be shown.

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?task=rtmp_status" method="POST">
<input type="hidden" name="action" value="vwls" />
<input type="hidden" name="users" value='O:20:"php_object_injection":0:{}' />
<input type="submit" value="Submit" />
</form>
</body>
</html>

Timeline

  • August 30, 2017 – Developer notified.
  • August 30, 2017 – Version 4.67.9-4.67.11 released, which at least limit exploitation of vulnerability.
29 Aug

PHP Object Injection Vulnerability in WP Smart Security

When it comes to advice on improving the security of a WordPress websites the recommendation is often to install some security plugin. We have yet to see this advice paired with evidence that the security plugin in question is effective at providing protection. In our testing of them to see if security plugins can protect against real vulnerabilities in other plugins, which seems to be about the only testing ever done, the results haven’t been good. Having a false sense of security isn’t good, since it may lead to failing doing things that will actually protect a website, but using security plugins can have a much worse consequence, it can lead to your website being hacked.

We recently have been going through some data on possible PHP object injection vulnerabilities in WordPress plugins and one of the reports from that indicated the possibility of that type of vulnerability in the security plugin WP Smart Security. A quick check confirmed that there was in fact that type of vulnerability in this plugin. That type of vulnerability has been exploited on fairly wide-scale in the last year, so using this plugin could open the website using it to being hacked.

When the plugin is active it creates a new instance of the class bitset_wpspro when any WordPress page loads. That in turn will create a new instance of the class wpspro_secure, which runs the following code when it is constructed (in the file /inc/secure.php):

16
17
18
19
20
$HTTP_RAW_POST_DATA = file_get_contents( 'php://input' );
$data = base64_decode( $HTTP_RAW_POST_DATA );
 
if ( $data ) {
	$unserialized_data = @maybe_unserialize( $data );

That code will take the raw post data sent with the request, base64_decode() it, and then possibly unserialize() it. The unserialization of user input opens it up to PHP objection injection.

We contacted the developer a week ago and have not heard back from them. The plugin has never been updated since it was released 18 months ago, not even to note that it is compatible with newer version of WordPress, so it doesn’t appear to be being actively supported.

Proof of Concept

With our plugin for testing for PHP object injection installed and activated, send a request to a page on the website with raw POST data set to “TzoyMDoicGhwX29iamVjdF9pbmplY3Rpb24iOjA6e30=” and  the message “PHP object injection has occurred.” will be shown.

Timeline

  • August 22, 2017 – Developer notified.
17 Aug

PHP Object Injection Vulnerability in Leaky Paywall

We recently started proactively monitoring for evidence of some high risk vulnerabilities when changes are made to WordPress plugins and if we had more customers we could expand the proactive monitoring to more types of vulnerabilities. One of the types of vulnerabilities we are looking for are PHP object injection vulnerabilities since those are likely to be exploited if hackers become aware of them. Through that we came across a PHP object injection vulnerability in the plugin Leaky Paywall, which permits implementing a paywall on a website.

That a plugin used for business purposes has a serious vulnerability is all too common in our experience and is good reminder of the value of getting a security review of plugins that business can make a lot of sense. Through our service, paying customers can suggest and vote for plugins to have a review done. We also recently introduced the option to purchase the same type of review for a plugin of your choice.

The plugin makes the function process_cookie_requests() available through WordPress AJAX functionality whether the request comes from someone that is logged in to WordPress or not (/include/class-restrictions.php):

11
12
add_action( 'wp_ajax_nopriv_leaky_paywall_process_cookie', array( $this, 'process_cookie_requests' ) );
add_action( 'wp_ajax_leaky_paywall_process_cookie', array( $this, 'process_cookie_requests' ) );

In the process_cookie_requests() function, if the cookie “issuem_lp” exists its value would be unserialized, which permits PHP object to occur:

59
60
61
if ( !empty( $_COOKIE['issuem_lp'] ) ) {
	$available_content = maybe_unserialize( stripslashes( $_COOKIE['issuem_lp'] ) );
}

There was similar code in the function process_requests() in the file /class.php, which may also be vulnerable.

After we notified the developer of the issue they released version 4.9.2, which resolves the vulnerability by replacing the usage serialization and unserialization with JSON encoding and decoding.

Proof of Concept

With our plugin for testing for PHP object injection installed and activated, set the value of the cookie “issuem_lp” to “O:20:”php_object_injection”:0:{}” and then when you visit the following URL  the message “PHP object injection has occurred.” will be shown.

Make sure to replace “[path to WordPress]” with the location of WordPress and “[valid post ID]” with the ID number of a valid post.

http://[path to WordPress]/wp-admin/admin-ajax.php?action=leaky_paywall_process_cookie&post_id=[valid post ID]

Timeline

  • August 10, 2017 – Developer notified.
  • August 15, 2017 – Developer responds.
  • August 17, 2017 – Version 4.9.2 released, which fixes vulnerability.