This vulnerability was fixed in version 1.4.3 . This post is about version 1.4.2 .

On Tuesday, I wrote about a serialization vulnerability fixed in the last version of wp-gdpr-compliance plugin.

Its exploitation likely was low because it required that Request User Data page was enabled (disabled by default) and add that [wpgdprc_access_request_form] shortcode in some public post/page .

Diving into the the source code, that checkbox on the page is related to a Wordpress option created by the plugin called wpgdprc_settings_enable_access_request . Looking at the vulnerability disclosed by Wordfence, the vulnerable logic executed update_option and do_action at the end. Then, what if I enable Request User Data using that vulnerability? Yep, it works! Internally it executes update_option('wpgdprc_settings_enable_access_request', '1') .

Then, I have to find a way to inject the shortcode in some public post/page to be able to trigger my serialization vulnerability. That was a bit hard to achieve. Looking at the source code, the vulnerability by Wordfence considers type='save_setting' , which ends up hitting the vulnerable logic. However, this type variable is part of a switch clause, which handles other values too. What called my attention was delete_request case:

From previous request, the condition on line 4 will return true and the logic will continue. If I can provide the right session settings type value values, I could reach the unserialize() statement at line 31. The value to unserialize is fully under my control. Using the same PDO gadget mentioned in previous post, I was able to write a proof of concept:

In the server logs, we can see that we reached unserialize function.

wordpress_1 | [Thu Nov 15 15:13:10.245618 2018] [php7:error] [pid 52] [client 172.20.0.1:36834] PHP Fatal error: Uncaught PDOException: You cannot serialize or unserialize PDO instances in /var/www/html/wp-content/plugins/wp-gdpr-compliance/Includes/Ajax.php:181

Reading from Wordfence post, this would be a new variant not blocked by their firewall. Next, we’re going how to block the exploitation using virtual patching.

Introducing Snuffleupagus

Snuffleupagus is a PHP module that allows to do virtual patching. As its description says:

Snuffleupagus is a PHP7+ module designed to drastically raise the cost of attacks against websites. This is achieved by killing entire bug classes and providing a powerful virtual-patching system, allowing the administrator to fix specific vulnerabilities without having to touch the PHP code.

This year I attended PassTheSalt Conference and the creators of the project did a presentation about it. I found it cool and I think it’s a good case to apply the magic of virtual patching.

First, as mentioned in Wordfence post conclusion, it’s probable to see more new variants in the future and that means that the list of firewall rules grow. It’s like a blacklist approach, what about a whitelist approach?

Looking at the source code, the vulnerable endpoint is used by wp-gdpr-compliance to register options related to integrations. wp-gdpr-compliance plugin integrates with other plugins like ContactForm7, GForms, etc.

Looking at the format of the request body when you modify settings related to integrations, we can see a pattern:

All these options start with wpgdprc_integrations_ . Then, why you’re accepting users_can_register option if it doesn’t start with wpgdprc_integrations_ ? That could be solved at code level, but we’re going to fix it using Snuffleupagus.

Virtual patching the vulnerability

Snuffleupagus works based on rules and they’re easy to create. As the affected code resides in file Includes/Ajax.php we’re going to work specifically over that file. update_option is only used in the vulnerable logic, that’s the reason why we aren’t more specific on the scope and last reminder, the order of the rules is important!

Our first rule will allow calls to update_option only if the first argument option starts with wpgdprc_integrations_ .

sp.disable_function.function(“update_option”).param(“option”).filename_r(“Includes/Ajax.php$”).value_r(“^wpgdprc_integrations_.*$”).allow()

Then, we will block any call to update_option , understanding that it didn’t meet the first rule pattern.

sp.disable_function.function(“update_option”).filename_r(“Includes/Ajax.php$”).drop()

That way, the plugin continue to work as always and Snuffleupagus blocks my new variant exploit.

wordpress_1 | [Thu Nov 15 15:49:08.039023 2018] [php7:error] [pid 49] [client 172.20.0.1:37818] PHP Fatal error: [snuffleupagus][disabled_function] Aborted execution on call of the function ‘update_option’ in /var/www/html/wp-includes/option.php on line 285

I’ve reproduced the case discovered by Wordfence and it’s blocked too.

Conclusions

It’s an interesting case for developers since vulnerability chaining makes possible to exploit logic parts that could seem unreachable and unconnected, then there’s no reason to not patch unsafe use of functions.

At alertot we do early vulnerability notification but also provide network and host mitigations based on open source software like Snuffleupagus. Contact us if you want to know more about what we do!