06 Nov

Full Disclosure of Authenticated PHP Object Injection Vulnerability in WordPress Plugin with 100,000+ Installs

The WordPress plugin plugin OptionTree recently came on to our radar through our monitoring of indications that changes made to plugins have fixed security issues, as it was included in another plugin and this plugin’s last changelog indicated a security issue had been fixed in the latest version (the relevant vulnerability was already had in our data set). Including this plugin in another plugin seems to be of some concern considering the plugin hasn’t been updated in two and half years. We did a little checking over the plugin and found that it has an authenticated PHP object injection vulnerability that is not only exploitable when using the plugin directly but also with the other plugin it shipped with.

The plugin makes the function add_list_item() available to anyone logged in to WordPress:

add_action( 'wp_ajax_add_list_item', array( $this, 'add_list_item' ) );

That function checks for a nonce to prevent cross-site request forgery (CSRF) and then passes user input, in the form of the GET or POST input “settings” through the unserialize function, which could permit PHP object injection:

public function add_list_item() {
  check_ajax_referer( 'option_tree', 'nonce' );
  ot_list_item_view( $_REQUEST['name'], $_REQUEST['count'], array(), $_REQUEST['post_id'], $_REQUEST['get_option'], unserialize( ot_decode( $_REQUEST['settings'] ) ), $_REQUEST['type'] );

Before it passes the value to unserialize() though it passes it through ot_decode(), which it turns out just base64 decodes the value (which can remove an impediment to PHP object injection being successful with user input like this):

function ot_decode( $value ) {
  $func = 'base64' . '_decode';
  return $func( $value );

So whether this could be exploited depends on who can get access to a valid nonce. The nonce is generated in the function ot_admin_scripts():

'nonce'                 => wp_create_nonce( 'option_tree' ),

That function runs when accessing the page to create or edit posts:

add_action( 'admin_print_scripts-post-new.php', 'ot_admin_scripts', 11 );
add_action( 'admin_print_scripts-post.php', 'ot_admin_scripts', 11 );

So normally any user with the Contributor or a higher role can get access to a valid nonce and exploit this.

Due to the moderators of the WordPress Support Forum’s continued inappropriate behavior we are full disclosing vulnerabilities in protest until WordPress gets that situation cleaned up, so we are releasing this post and then only trying to notify the developer through the WordPress Support Forum. You can notify the developer of this issue as well. Hopefully the moderators will finally see the light and clean up their act soon, so these full disclosures will no longer be needed (we hope they end soon).

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, when logged in to WordPress.

Make sure to replace “[path to WordPress]” with the location of WordPress and “[nonce]” with a valid nonce. The valid nonce can be found in the source code of the page to create or edit a post on the line that starts “var option_tree”.

http://[path to WordPress]/wp-admin/admin-ajax.php?action=add_list_item&nonce=[nonce]&settings=TzoyMDoicGhwX29iamVjdF9pbmplY3Rpb24iOjA6e30=

Concerned About The Security of the Plugins You Use?

When you are a paying customer of our service, you can suggest/vote for the WordPress plugins you use to receive a security review from us. You can start using the service for free when you sign up now. We also offer security reviews of WordPress plugins as a separate service.