Fenrisk is a security company specialized in offensive assessments (penetration tests, large scale engagements), security audits and trainings. It helps you secure your assets. Fenrisk strives to issue impactful security assessments.
Exploiting an unserialization vulnerability in WordPress never was a small issue. Unlike other PHP frameworks and until very recently, WordPress was not known for hosting gadget chains.
The first one was discovered 10 years ago, with a complex execution sequence.
Lately, the second one was discovered, its structure is quite complex too and it has been patched pretty quickly.
It was soon followed by a third one that depends on the presence of the WooCommerce plugin that is, of course, not guaranteed.
During a recent intrusion, we faced a wild unserialize and none of the above worked. Thus we decided to dig it up and discovered that a trivial chain had just been implemented in the core of WordPress. Let's take a look starting with the history.
The first interesting gadget chain on WordPress was found and presented in 2013 on versions below 3.6.1.
It is triggered using __toString PHP magic method of the WP_theme class. From this class, the execution flow finally execute make_plural_form_function method from translations module that evaluates a portion of code controlled by the user during the unserializing process.
This pivoting sequence is summarized in the schema below from Sam Thomas slides: https://fr.slideshare.net/_s_n_t/php-unserialization-vulnerabilities-what-are-we-missing.
This gadget chain is relatively difficult to find because of pivots and the interaction between each object class involved.
This gadget chain in WordPress code was described on october the 13th 2023 by WPScan team in the following article https://wpscan.com/blog/finding-a-rce-gadget-chain-in-wordpress-core.
This chain is also triggered using __toString PHP magic method of the WP_theme class. Then, from this class, the exploitation needed to pivot using the sequence summarized below:
This popchain is complex because of the amount of pivots needed to execute the interesting final code portion. The serialized payload exploiting this popchain speaks for itself:
This exploitation payload is available in the tool phpggc as WordPress/RCE1. This exploitation vector has been patched by WordPress since version 6.3.2 and is no more available in latest releases.
The second exploitation chain in WooCommerce plugin is clearly easier to understand. It is triggered using WC_Log_Handler_File WooCommerce class destructor and pivot via Requests_Utility_FilteredIterator WordPress class in order to execute a vulnerable portion of the code. This exploitation vector was patched in WordPress 5.5.2 but targets need WooCommerce plugin to be installed. This exploitation payload is available in the tool phpggc as WordPress/P/WooCommerce/RCE1 and WordPress/P/WooCommerce/RCE2.
To sum up, only complex gadget chains were present in WordPress, another easier to find and understand is available if the WooCommerce plugin is installed and none of them is available on latest versions 6.3.2, 6.4 and 6.4.1. Then, we started looking for gadget chains in WordPress and we found the simplest one.
WordPress defined in versions 6.4+ an internal class WP_HTML_Token used by the HTML processor during HTML parsing for referring to tokens in the input HTML string.
This class is defined in wp-includes/html-api/class-wp-html-token.php and implements a __destruct magic method that directly calls call_user_func method on the class variables without any pivot as shown below:
on_destroy and bookmark_name attributes are controled during the unserializing process which makes the exploitation quite trivial. The payload looks like:
Fortunately for us, this class is loaded by the WordPress class loader in wp-settings.php that makes the class WP_HTML_Token loaded and available in plugins and themes:
This exploitation vector is now available in the tool phpggc as WordPress/RCE2. Sometimes, simple exploitation vectors can be found in source code even in major projects such as WordPress. For now, the only version of WordPress that doesn't have a known gadget chain is 6.3.2.
Maxime Rinaudo is the co-founder of Fenrisk as well as one of its security experts. He's mostly involved in Web and applications security. After 10 years working in French Department of Defense and 3 years in security consulting in Paris, Maxime decided to join Julien to develop together their vision of security.