16 Feb

Our Proactive Monitoring Caught a PHP Object Injection Vulnerability in a Fairly Popular Plugin

One of the ways we help to improve the security of WordPress plugins, not just for our customers, but for everyone using them, is the proactive monitoring of changes made to plugins in the Plugin Directory to try to catch serious vulnerabilities. That again has lead to us catching a vulnerability in a fairly popular plugin, of a type that hackers are likely to exploit if they know about it. Since the check used to spot this is also included in our Plugin Security Checker (which  is now accessible through a WordPress plugin of its own), it is another of reminder of how that can help to indicate which plugins are in greater need of security review (for which we do as part of our service as well as separately).

In the plugin WP Support Plus Responsive Ticket System, which has 10,000+ active installations according to wordpress.org, as of  version 9.0.3, the value of cookies were passed through the unserialize() function, which could lead to PHP object injection. Two of the instances that occurred were in the function get_current_user_session() (in the file /includes/class-wpsp-functions.php):

1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
public function get_current_user_session(){
 
	global $current_user;
				$wpsp_user_session = array();
				if( is_user_logged_in() ){
						$wpsp_user_session = array(
								'type'  => 1,
								'name'  => $current_user->display_name,
								'email' => $current_user->user_email
						);
 
						if (isset($_COOKIE['wpsp_user_session'])){
			$wpsp_user_session_temp = unserialize(base64_decode($_COOKIE['wpsp_user_session']));
			if($wpsp_user_session_temp['email'] != $wpsp_user_session['email'] ){
				@setcookie("wpsp_user_session", base64_encode(serialize($wpsp_user_session)), 0, COOKIEPATH);
			}
		} else {
			@setcookie("wpsp_user_session", base64_encode(serialize($wpsp_user_session)), 0, COOKIEPATH);
		}
 
				} else if (isset($_COOKIE['wpsp_user_session'])) {
						$wpsp_user_session = unserialize(base64_decode($_COOKIE['wpsp_user_session']));

When not logged in, if the cookie “wpsp_user_session” exists it will be unserialized after being base64 decoded.

That function is called numerous times including in the function check_login() (in the file /includes/frontend/class-wpsp-frontend.php):

86
87
88
89
90
function check_login(){
 
		global $wpdb, $wpsupportplus, $current_user;
 
		$wpsp_user_session = $wpsupportplus->functions->get_current_user_session();

That in turns is called anytime WordPress is loaded due to it running during init():

22
add_action( 'init', array($this,'check_login') );

So by simply visiting any page on the website with a cookie set a value that causes PHP object injection this vulnerability could have been exploited.

After we notified the developer, they initially responded five days later that the vulnerability had been fixed in version 9.0.3, which had been released five days before we contacted them. Four days later they released version 9.0.4, which resolve the vulnerability by replacing the usage of unserialize() with json_decode() (and related usage of serialize() with json_encode()).

The Plugin Security Checker has flagged other possible issues in the plugin, so those using the plugin may want to have someone do a thorough review of the plugin’s security.

Proof of Concept

With our plugin for testing for PHP object injection installed and activated, set the value of the cookie “wpsp_user_session” to “TzoyMDoicGhwX29iamVjdF9pbmplY3Rpb24iOjA6e30=” and then when you visit any page on the website the message “PHP object injection has occurred.” will be shown.

Timeline

  • February 7, 2018 – Developer notified.
  • February 12, 2018 – Developer responds that the vulnerability had been fixed in version 9.0.3 (which was released five days before we contacted the developer).
  • February 16, 2018 –  Version 9.0.4 released, which fixes vulnerability.
15 Feb

Our Proactive Monitoring Caught a PHP Object Injection Vulnerability in Swift Help Desk Support Software Ticketing System

One of the ways we help to improve the security of WordPress plugins, not just for our customers, but for everyone using them, is the proactive monitoring of changes made to plugins in the Plugin Directory to try to catch serious vulnerabilities. That again has lead to us catching a vulnerability of a type that hackers are likely to exploit if they know about it. Since the check used to spot this is also included in our Plugin Security Checker (which  is now accessible through a WordPress plugin of its own), it is another of reminder of how that can help to indicate which plugins are in greater need of security review (for which we do as part of our service as well as separately).

In the plugin Swift Help Desk Support Software Ticketing System (Help Desk & Knowledgebase Software) the value of a cookie is passed through the unserialize() function, which could lead to PHP object injection. That occurs in two shortcodes accessed functions in the plugin. One of them being swift_helpdesk_support_callback(), which is located in the file /sections/shd-shortcodes.php. Some ways into the function it checks if the cookie “sc_lead_scoring” exists and then unserializes its value:

164
165
if (isset($_COOKIE['sc_lead_scoring']) && !empty($_COOKIE['sc_lead_scoring'])) {
	$sc_lead_scoring_cookie = unserialize(stripslashes($_COOKIE['sc_lead_scoring']));

Even if the shortcodes that cause those functions to run are not used on the website, any one logged in to WordPress could access them, like they can shortcodes in general, through WordPress AJAX functionality and the vulnerability is also exploitable that way as well.

We notified the developer of the issue a week ago. We haven’t heard back from them and no new version has been released to fix the issue. 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.

The Plugin Security Checker has flagged other possible issues in the plugin, so those using the plugin may want to have someone do a thorough review of the plugin’s security.

Proof of Concept

With our plugin for testing for PHP object injection installed and activated, set the value of the cookie “sc_lead_scoring” to “O:20:”php_object_injection”:0:{}” and then when you visit a page on the website using the “swift_helpdesk_support” shortcode the message “PHP object injection has occurred.” will be shown.

Timeline

  • February 8, 2017 – Developer notified.
14 Feb

Our Proactive Monitoring Caught a PHP Object Injection Vulnerability Returning to a Fairly Popular Plugin

One of the ways we help to improve the security of WordPress plugins, not just for our customers, but for everyone using them, is the proactive monitoring of changes made to plugins in the Plugin Directory to try to catch serious vulnerabilities. That again has lead to us catching a vulnerability in a fairly popular plugin, of a type that hackers are likely to exploit if they know about it. In this case the vulnerability is much worse because it was previously fixed, so some hacker could still be trying to exploit it based on the previous instance of it. Since the check used to spot this is also included in our Plugin Security Checker (which  is now accessible through a WordPress plugin of its own), it is another of reminder of how that can help to indicate which plugins are in greater need of security review (for which we do as part of our service as well as separately).

Back in September we noticed that PHP object injection vulnerability had been fixed the plugin Welcart e-Commerce, which has 10,000+ active installations according to wordpress.org (who had discovered vulnerability that wasn’t disclosed). That had been fixed by replacing the usage of unserialze() with json_decode() in version 1.9.4. The relevant line had previously looked like this (in the file /classes/usceshop.class.php):

$values = isset($_COOKIE[$key]) ? unserialize(stripslashes($_COOKIE[$key])) : NULL;

And was replaced with this:

$values = isset($_COOKIE[$key]) ? json_decode(stripslashes($_COOKIE[$key]), true) : NULL;

Then in version 1.9.5 it got changed to:

$values = isset($_COOKIE[$key]) ? usces_unserialize(stripslashes($_COOKIE[$key])) : NULL;

That function usces_unserialize() used there is as follows:

2498
2499
2500
2501
2502
2503
2504
2505
2506
function usces_unserialize( $data ) {
	if( is_serialized( $data ) ) {
		return @unserialize( $data );
	}
	if( is_array( $data ) ) {
		return $data;
	}
	return @json_decode( $data, true );
}

With that, if the value passed to the function is serialized then the value is unserialized. Since PHP object injection involves untrusted serialized data being unserialized, that code allows for PHP object injection again. This can easily be exploited because that code runs when visiting any frontend page of the website.

Since the vulnerability could be already be being exploited due to the previous instance of it, we are disclosing this without giving the developer a chance to fix it first, since we have a responsibility to warn our customers as soon as possible (and we don’t want to leave others without the ability to know about this and we don’t want to allow hackers to use our service to become aware of otherwise undisclosed vulnerabilities).

Proof of Concept

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

Timeline

  • February 14, 2018 – Developer notified.
29 Jan

PHP Object Injection Vulnerability in WordPress Forms

Over at our main business we clean up a lot of hacked websites. Based on how often we are brought in to re-clean websites after another company (including many well known names) has failed to even attempt to properly clean things up, our service in general is much better than many other options out there. But when cleaning up hacked WordPress websites we throw in a couple of extras related to this service. The first being a free lifetime subscription to this service and the second being that we check over all the installed plugins using same checks we do as part of our proactive monitoring of changes made to plugins in the Plugin Directory to try to catch serious vulnerabilities.

Recently, While looking into a possible arbitrary file upload vulnerability flagged in the plugin WordPress Forms we noticed what looked to be a PHP object injection vulnerability in the same function in the plugin and a quick test using our plugin for testing for those confirmed it was in fact exploitable.

The plugin can process form submissions through WordPress’ AJAX functionality:

274
275
add_action( "wp_ajax_wp_forms_submit_form", array( &$this, "process_submition" ) );
add_action( "wp_ajax_nopriv_wp_forms_submit_form", array( &$this, "process_submition" ) );

The function that handles that, process_submition(), passes the GET or POST input “field_keys” through the function unserialize(), which permits PHP object injection:

334
$field_keys = unserialize( str_replace('\\', '', html_entity_decode($_REQUEST['field_keys'])) );

While this type of vulnerability is fairly likely to be exploited if hackers are aware of it, in the case of the website we were cleaning, the plugin was deactivated, so the vulnerability could not have been exploited.

That plugin was removed from the Plugin Directory by the developer five years ago, but the plugin is still installed on 500+ websites.

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 and “[form ID]” with the ID for one of the forms created by the plugin.

<html>
<body>
<form action="http://[path to WordPress]/wp-admin/admin-ajax.php" method="POST">
<input type="hidden" name="action" value="wp_forms_submit_form" />
<input type="hidden" name="post" value="[form ID]" />
<input type="hidden" name="field_keys" value='O:20:"php_object_injection":0:{}' />
<input type="submit" value="Submit" />
</form>
</body>
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://[path to WordPress]/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 half off (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 WordPress plugin 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 half off (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 WordPress plugin security researcher please contact us to get free access to all of our Vulnerability Details posts.