Authenticated PHP Object Injection Vulnerability in Post Pay Counter
Through the proactive monitoring of changes in WordPress plugins for serious vulnerabilities we do, we have found some of those serious vulnerabilities, but we also have found less serious variants of some of those vulnerabilities. The latter is certainly the case with an authenticated PHP object injection vulnerability we found in the plugin Post Pay Counter.
On the plugin’s Options page there is a section title Import/Export Settings. When doing an import through that the function import_settings(), which began as follows in version 2.730, is utilized (in /classes/ppc_ajax_functions_class.php):
258 259 260 261 262 | static function import_settings() { global $ppc_global_settings; self::ppc_check_ajax_referer( 'ppc_import_settings' ); $to_import = unserialize( base64_decode( $_REQUEST['import_settings_content'] ) ); |
That code checked for a valid nonce, which prevents cross-site request forgery (CSRF), and then passed the value of the GET or POST input “import_settings_content” through the unserialize() function, which permitted PHP object injection.
The value of the nonce is only available on the plugin’s Options page. Normally that page is only available to Administrators, for who this really wouldn’t be a vulnerability since they can normally do the equivalent what this vulnerability could do. The plugin does provide the option to allow lower users level access to it and for them to exploit this it would be a vulnerability:
Before doing the importation of settings, the plugin should have also made sure the user is intended to be able to import settings by checking if their user role is one permitted to access the page.
Less than two days after we notified the developer of the issues they released version 2.731, which replaces the usage of unserialize():
262 | $to_import = json_decode( base64_decode( $_REQUEST['import_settings_content'] ), true ); |
and adds a capabilities check to the function that handles updating the settings, update_settings() (in the file /classes/ppc_save_options_class.php):
221 222 | if( ! current_user_can( $ppc_global_settings['cap_manage_options'] ) ) return new WP_Error( 'save_settings_error', __( 'Are you sure you want to do this?' ) ); |
Proof of Concept
With our plugin for testing for PHP object injection installed and activated, passing “TzoyMDoicGhwX29iamVjdF9pbmplY3Rpb24iOjA6e30=” through the Import Settings feature on /wp-admin/admin.php?page=ppc-options will cause the message “PHP object injection has occurred.” to be shown.
Timeline
- September 14, 2017 – Developer notified.
- September 15, 2017 – Developer responds.
- September 16, 2017 – Version 2.731, which fixes vulnerability.