05 Oct

The Continued Inappropriate Behavior of WordPress Has Lead to This Disclosure of an Exploitable Vulnerability in a Plugin with 30,000+ Active Installs

A lot has been going on for us recently. One of those things is that we have made a big improvement to our ability to detect the possibility of vulnerabilities being fixed in plugins, so that we can add more of them to our data set. That has lead to us reviewing code changes in more plugins and finding more vulnerabilities, which are more serious than the possible issues that might have already been fixed. That today lead to us noticing that there is a PHP object injection vulnerability, which is the type of vulnerability has been the type that more advanced hackers are likely to try exploit, in the plugin WP DSGVO Tools, which has 30,000+ active installs.

Another thing that has gone on is that due to the continued inappropriate behavior by the moderators of the WordPress Support Forum we have started full disclosing vulnerabilities in WordPress plugins until such time that they stop acting inappropriately. They could have already done that and the full disclosures would have stopped, instead so far they have just decide to compound their bad behavior with more of it. What that means is that instead of contacting the developer and letting them know about the vulnerabilities, offering assistance in fixing them, and only after they have had a chance to do, disclosing them, we are just disclosing them. We then try to notify the developers of the full disclosure through the Support Forum. That isn’t a good thing, but the inappropriate behavior of the moderators of the Support Forum is much more of a problem and it needs to finally stop.

What lead us to spot the PHP object injection vulnerability in WP DSGVO Tools was this line in the code changed in the latest version of the plugin:

48
setcookie('sp_dsgvo_user_permissions', serialize($meta), (time()+(365*24*60*60)), '/');

What that seemed to indicate is that the plugin might pass the value of a cookie through the unserialize() function, which would lead to PHP object injection. That type of issue with the passing of the value of cookies through unserialize() is something that we have seen over and over leading to this type of vulnerability in plugins, unfortunately something being common doesn’t mean that there is any concerted effort to make sure that plugins are not vulnerable (WordPress seems uninterested in taking even more basic steps to improve the security of plugins).

A quick check of the code lead us to the function hasUserGivenPermissionFor(), which is located in the file /includes/helpers.php. That function will in fact pass the value of a cookie through the unserialize() function as long as two conditions are met:

111
112
113
114
115
116
117
118
119
120
121
122
123
function hasUserGivenPermissionFor($slug)
{
	//error_log('hasUserGivenPermissionFor: '.$slug);
	$user = wp_get_current_user();
 
	if ($slug === 'cookies') {
		$cnAccepted = sp_dsgvo_cn_cookies_accepted();
 
		if ($user instanceof WP_User && $user->ID) {
			$userPermissions = get_user_meta($user->ID, 'sp_dsgvo_user_permissions', TRUE);
		} else {
			$userPermissions = @$_COOKIE['sp_dsgvo_user_permissions'];
			$userPermissions = unserialize(stripslashes($userPermissions));

The first condition is that the value of the variable $slug that is passed to function must be “cookies” and the second is that request is not coming from someone logged in to WordPress.

To find out if this could be exploited we needed to find out if there was code elsewhere in the plugin that met the first condition. One such place is the function cookieNotice():

143
144
145
146
147
148
public function cookieNotice()
{
	/* i592995 */
	if (SPDSGVOSettings::get('cookie_notice_display') == 'cookie_notice') :
		/* i592995 */
		if (hasUserGivenPermissionFor('cookies') === FALSE) :

That will meet the condition with the default settings of the plugin.

That function in turn will run when the function writeFooterScripts() runs:

439
440
441
public function writeFooterScripts()
{
	$this->cookieNotice();

And that in turn runs when the footer of a frontend page is being generated:

285
$this->loader->add_action('wp_footer', 					$public, 'writeFooterScripts', 1000);

All together that means that this can easily be exploited by just having the value of the cookie “sp_dsgvo_user_permissions” set to something that causes a malicious action to occur when unserialized and visiting a frontend page of the website when not logged in. Limiting exploitation is that you need to know a value that will cause a malicious action to happen, which looks to limit who can exploit this type of issue.

If it were not for the moderators of the Support Forum deciding that their ability to continue act inappropriately is more important than everyone else in the WordPress community this would not be being disclosed this way, so we hope this will finally be the wakeup call they desperately need (but we are not holding our breath on that).

Worth noting is that there are a couple of plugins in the Plugin Directory that have a combined 15,000+ active installations that have this type of vulnerability, which were disclosed over six months and over a year respectively, and yet they remain in the directory because the people on the WordPress side of things don’t actually seem to care all that much about security (or do other security companies). In the past we would made sure those got removed, but we suspended doing that last year as part of our more limited previous effort to try to get changes made to the handling of things by WordPress. People using our service would have been warned if they were using those at the time they were disclosed (we also happened to be the ones that discovered and disclosed them).

Proof of Concept

With our plugin for testing for PHP object injection installed and activated, set the value of the cookie “sp_dsgvo_user_permissions” to “O:20:”php_object_injection”:0:{}” and then when visiting a frontend page the message “PHP object injection has occurred.” will be shown.

Leave a Reply

Your email address will not be published. Required fields are marked *