New variant in wp-gdpr-compliance vulnerability and fixing it with virtual patching
This vulnerability was fixed in version
1.4.3. This post is about version
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
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
From previous request, the condition on line 4 will return
true and the logic will continue. If I can provide the right
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
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.
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-complianceto 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
Then, we will block any call to
update_option , understanding that it didn’t meet the first rule pattern.
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.
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.