Our Proactive Monitoring Caught a PHP Object Injection Vulnerability in a Fairly Popular Plugin
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 again has lead to us catching a vulnerability in a fairly popular plugin, of a type that hackers are likely to exploit if they know about it. 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).
In the plugin WP Support Plus Responsive Ticket System, which has 10,000+ active installations according to wordpress.org, as of version 9.0.3, the value of cookies were passed through the unserialize() function, which could lead to PHP object injection. Two of the instances that occurred were in the function get_current_user_session() (in the file /includes/class-wpsp-functions.php):
1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 | public function get_current_user_session(){ global $current_user; $wpsp_user_session = array(); if( is_user_logged_in() ){ $wpsp_user_session = array( 'type' => 1, 'name' => $current_user->display_name, 'email' => $current_user->user_email ); if (isset($_COOKIE['wpsp_user_session'])){ $wpsp_user_session_temp = unserialize(base64_decode($_COOKIE['wpsp_user_session'])); if($wpsp_user_session_temp['email'] != $wpsp_user_session['email'] ){ @setcookie("wpsp_user_session", base64_encode(serialize($wpsp_user_session)), 0, COOKIEPATH); } } else { @setcookie("wpsp_user_session", base64_encode(serialize($wpsp_user_session)), 0, COOKIEPATH); } } else if (isset($_COOKIE['wpsp_user_session'])) { $wpsp_user_session = unserialize(base64_decode($_COOKIE['wpsp_user_session'])); |
When not logged in, if the cookie “wpsp_user_session” exists it will be unserialized after being base64 decoded.
That function is called numerous times including in the function check_login() (in the file /includes/frontend/class-wpsp-frontend.php):
86 87 88 89 90 | function check_login(){ global $wpdb, $wpsupportplus, $current_user; $wpsp_user_session = $wpsupportplus->functions->get_current_user_session(); |
That in turns is called anytime WordPress is loaded due to it running during init():
22 | add_action( 'init', array($this,'check_login') ); |
So by simply visiting any page on the website with a cookie set a value that causes PHP object injection this vulnerability could have been exploited.
After we notified the developer, they initially responded five days later that the vulnerability had been fixed in version 9.0.3, which had been released five days before we contacted them. Four days later they released version 9.0.4, which resolve the vulnerability by replacing the usage of unserialize() with json_decode() (and related usage of serialize() with json_encode()).
The Plugin Security Checker has flagged other possible issues in the plugin, so those using the plugin may want to have someone do a thorough review of the plugin’s security.
Proof of Concept
With our plugin for testing for PHP object injection installed and activated, set the value of the cookie “wpsp_user_session” to “TzoyMDoicGhwX29iamVjdF9pbmplY3Rpb24iOjA6e30=” and then when you visit any page on the website the message “PHP object injection has occurred.” will be shown.
Timeline
- February 7, 2018 – Developer notified.
- February 12, 2018 – Developer responds that the vulnerability had been fixed in version 9.0.3 (which was released five days before we contacted the developer).
- February 16, 2018 – Version 9.0.4 released, which fixes vulnerability.