Headline
CVE-2023-4773: wsl.auth.widgets.php in wordpress-social-login/tags/3.0.4/includes/widgets – WordPress Plugin Repository
The WordPress Social Login plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the ‘wordpress_social_login_meta’ shortcode in versions up to, and including, 3.0.4 due to insufficient input sanitization and output escaping on user supplied attributes. This makes it possible for authenticated attackers with contributor-level and above permissions to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page.
1<?php2/*!3* WordPress Social Login4*5* https://miled.github.io/wordpress-social-login/ | https://github.com/miled/wordpress-social-login6* © 2011-2020 Mohamed Mrassi and contributors | https://wordpress.org/plugins/wordpress-social-login/7*/89/**10* Authentication widgets generator11*12* http://miled.github.io/wordpress-social-login/widget.html13* http://miled.github.io/wordpress-social-login/themes.html14* http://miled.github.io/wordpress-social-login/developer-api-widget.html15*/1617// Exit if accessed directly18if( !defined( ‘ABSPATH’ ) ) exit;1920// --------------------------------------------------------------------2122/**23* Generate the HTML content of WSL Widget24*25* Note:26* WSL shortcode arguments are still experimental and might change in future versions.27*28* [wordpress_social_login29* auth_mode="login"30* caption="Connect with"31* enable_providers="facebook|google"32* restrict_content="wsl_user_logged_in"33* assets_base_url="http://example.com/wp-content/uploads/2022/01/"34* ]35*36* Overall, WSL widget work with these simple rules :37* 1. Shortcode arguments rule over the defaults38* 2. Filters hooks rule over shortcode arguments39* 3. Bouncer rules over everything40*/41function wsl_render_auth_widget( $args = array() )42{43 $auth_mode = isset( $args[‘mode’] ) && $args[‘mode’] ? $args[‘mode’] : 'login’;4445 // validate auth-mode46 if( ! in_array( $auth_mode, array( 'login’, 'link’, ‘test’ ) ) )47 {48 return;49 }5051 // auth-mode eq ‘login’ => display wsl widget only for NON logged in users52 // > this is the default mode of wsl widget.53 if( $auth_mode == ‘login’ && is_user_logged_in() )54 {55 return;56 }5758 // auth-mode eq ‘link’ => display wsl widget only for LOGGED IN users59 // > this will allows users to manually link other social network accounts to their WordPress account60 if( $auth_mode == ‘link’ && ! is_user_logged_in() )61 {62 return;63 }6465 // auth-mode eq ‘test’ => display wsl widget only for LOGGED IN users only on dashboard66 // > used in Authentication Playground on WSL admin dashboard67 if( $auth_mode == ‘test’ && ! is_user_logged_in() && ! is_admin() )68 {69 return;70 }7172 // Bouncer :: Allow authentication?73 if( get_option( ‘wsl_settings_bouncer_authentication_enabled’ ) == 2 )74 {75 return;76 }7778 // HOOKABLE: This action runs just before generating the WSL Widget.79 do_action( ‘wsl_render_auth_widget_start’ );8081 GLOBAL $WORDPRESS_SOCIAL_LOGIN_PROVIDERS_CONFIG;8283 ob_start();8485 // Icon set. If eq 'none’, we show text instead86 $social_icon_set = get_option( ‘wsl_settings_social_icon_set’ );8788 // wpzoom icons set, is shown by default89 if( empty( $social_icon_set ) )90 {91 $social_icon_set = “wpzoom/";92 }9394 $assets_base_url = WORDPRESS_SOCIAL_LOGIN_PLUGIN_URL . ‘assets/img/32x32/’ . $social_icon_set . '/’;9596 $assets_base_url = isset( $args[‘assets_base_url’] ) && $args[‘assets_base_url’] ? $args[‘assets_base_url’] : $assets_base_url;9798 // HOOKABLE:99 $assets_base_url = apply_filters( 'wsl_render_auth_widget_alter_assets_base_url’, $assets_base_url );100101 // get the current page url, which we will use to redirect the user to,102 // unless Widget::Force redirection is set to 'yes’, then this will be ignored and Widget::Redirect URL will be used instead103 $redirect_to = wsl_get_current_url();104105 // Use the provided redirect_to if it is given and this is the login page.106 if ( in_array( $GLOBALS[“pagenow”], array( “wp-login.php", “wp-register.php” ) ) && !empty( $_REQUEST[“redirect_to”] ) )107 {108 $redirect_to = $_REQUEST[“redirect_to”];109 }110111 // build the authentication url which will call for wsl_process_login() : action=wordpress_social_authenticate112 $authenticate_base_url = add_query_arg(113 array(114 ‘action’ => 'wordpress_social_authenticate’,115 ‘mode’ => 'login’,116 ),117 site_url( 'wp-login.php’, ‘login_post’ )118 );119120 // if not in mode login, we overwrite the auth base url121 // > admin auth playground122 if( $auth_mode == ‘test’ )123 {124 $authenticate_base_url = add_query_arg(125 array(126 ‘action’ => 'wordpress_social_authenticate’,127 ‘mode’ => 'test’,128 ),129 home_url()130 );131 }132133 // > account linking134 elseif( $auth_mode == ‘link’ )135 {136 $authenticate_base_url = add_query_arg(137 array(138 ‘action’ => 'wordpress_social_authenticate’,139 ‘mode’ => 'link’,140 ),141 home_url()142 );143 }144145 // Connect with caption146 $connect_with_label = _wsl__( get_option( ‘wsl_settings_connect_with_label’ ), ‘wordpress-social-login’ );147148 $connect_with_label = isset( $args[‘caption’] ) ? $args[‘caption’] : $connect_with_label;149150 // HOOKABLE:151 $connect_with_label = apply_filters( 'wsl_render_auth_widget_alter_connect_with_label’, $connect_with_label );152?>153154<!–155 wsl_render_auth_widget156 WordPress Social Login <?php echo wsl_get_version(); ?>.157 http://wordpress.org/plugins/wordpress-social-login/158–>159<?php160 // Widget::Custom CSS161 $widget_css = get_option( ‘wsl_settings_authentication_widget_css’ );162163 // HOOKABLE:164 $widget_css = apply_filters( 'wsl_render_auth_widget_alter_widget_css’, $widget_css, $redirect_to );165166 // show the custom widget css if not empty167 if( ! empty( $widget_css ) )168 {169?>170171<style type="text/css">172<?php173 echo174 preg_replace(175 array( '%/\*(?:(?!\*/).)*\*/%s’, '/\s{2,}/’, “/\s*([;{}])[\r\n\t\s]/", '/\\s*;\\s*/’, '/\\s*{\\s*/’, ‘/;?\\s*}\\s*/’ ),176 array( '’, ' ', '$1’, ';’, '{’, ‘}’ ),177 $widget_css );178?>179</style>180<?php181 }182?>183184<div class="wp-social-login-widget">185186 <div class="wp-social-login-connect-with"><?php echo $connect_with_label; ?></div>187188 <div class="wp-social-login-provider-list">189<?php190 // Widget::Authentication display191 $wsl_settings_use_popup = get_option( ‘wsl_settings_use_popup’ );192193 // if a user is visiting using a mobile device, WSL will fall back to more in page194 $wsl_settings_use_popup = function_exists( ‘wp_is_mobile’ ) ? wp_is_mobile() ? 2 : $wsl_settings_use_popup : $wsl_settings_use_popup;195196 $no_idp_used = true;197198 // display provider icons199 foreach( $WORDPRESS_SOCIAL_LOGIN_PROVIDERS_CONFIG AS $item )200 {201 $provider_id = isset( $item[“provider_id”] ) ? $item[“provider_id”] : ‘’ ;202 $provider_name = isset( $item[“provider_name”] ) ? $item[“provider_name”] : ‘’ ;203204 // provider enabled?205 if( get_option( ‘wsl_settings_’ . $provider_id . ‘_enabled’ ) )206 {207 // restrict the enabled providers list208 if( isset( $args[‘enable_providers’] ) )209 {210 $enable_providers = explode( '|’, $args[‘enable_providers’] ); // might add a couple of pico seconds211212 if( ! in_array( strtolower( $provider_id ), $enable_providers ) )213 {214 continue;215 }216 }217218 // build authentication url219 $authenticate_url = add_query_arg(220 array(221 ‘provider’ => $provider_id,222 ‘redirect_to’ => urlencode( $redirect_to ),223 ),224 $authenticate_base_url225 );226227 // http://codex.wordpress.org/Function_Reference/esc_url228 $authenticate_url = esc_url( $authenticate_url );229230 // in case, Widget::Authentication display is set to 'popup’, then we overwrite 'authenticate_url’231 // > /assets/js/connect.js will take care of the rest232 if( $wsl_settings_use_popup == 1 && $auth_mode != ‘test’ )233 {234 $authenticate_url= “javascript:void(0);";235 }236237 // HOOKABLE: allow user to rebuilt the auth url238 $authenticate_url = apply_filters( 'wsl_render_auth_widget_alter_authenticate_url’, $authenticate_url, $provider_id, $auth_mode, $redirect_to, $wsl_settings_use_popup );239240 // HOOKABLE: allow use of other icon sets241 $provider_icon_markup = apply_filters( 'wsl_render_auth_widget_alter_provider_icon_markup’, $provider_id, $provider_name, $authenticate_url );242243 if( $provider_icon_markup != $provider_id )244 {245 echo $provider_icon_markup;246 }247 else248 {249?>250251 <a rel="nofollow” href="<?php echo $authenticate_url; ?>” title="<?php echo sprintf( _wsl__(“Connect with %s", ‘wordpress-social-login’), $provider_name ) ?>” class="wp-social-login-provider wp-social-login-provider-<?php echo strtolower( $provider_id ); ?>” data-provider="<?php echo $provider_id ?>” role="button">252 <?php if( $social_icon_set == ‘none’ ){ echo apply_filters( 'wsl_render_auth_widget_alter_provider_name’, $provider_name ); } else { ?><img alt="<?php echo $provider_name ?>" src="<?php echo $assets_base_url . strtolower( $provider_id ) . ‘.png’ ?>" aria-hidden="true" /><?php } ?>253254 </a>255<?php256 }257258 $no_idp_used = false;259 }260 }261262 // no provider enabled?263 if( $no_idp_used )264 {265?>266 <p style="background-color: #FFFFE0;border:1px solid #E6DB55;padding:5px;">267 <?php _wsl_e( '<strong>WordPress Social Login is not configured yet</strong>.<br />Please navigate to <strong>Settings > WP Social Login</strong> to configure this plugin.<br />For more information, refer to the <a rel="nofollow" href="http://miled.github.io/wordpress-social-login">online user guide</a>.’, ‘wordpress-social-login’) ?>.268 </p>269 <style>#wp-social-login-connect-with{display:none;}</style>270<?php271 }272?>273274 </div>275276 <div class="wp-social-login-widget-clearing"></div>277278</div>279280<?php281 // provide popup url for hybridauth callback282 if( $wsl_settings_use_popup == 1 )283 {284?>285<input type="hidden" id="wsl_popup_base_url" value="<?php echo esc_url( $authenticate_base_url ) ?>" />286<input type="hidden" id="wsl_login_form_uri" value="<?php echo esc_url( site_url( 'wp-login.php’, ‘login_post’ ) ); ?>" />287288<?php289 }290291 // HOOKABLE: This action runs just after generating the WSL Widget.292 do_action( ‘wsl_render_auth_widget_end’ );293?>294<!-- wsl_render_auth_widget -->295296<?php297 // Display WSL debugging area bellow the widget.298 // wsl_display_dev_mode_debugging_area(); // ! keep this line commented unless you know what you are doing :)299300 return ob_get_clean();301}302303// --------------------------------------------------------------------304305/**306* WSL wordpress_social_login action307*308* Ref: http://codex.wordpress.org/Function_Reference/add_action309*/310function wsl_action_wordpress_social_login( $args = array() )311{312 echo wsl_render_auth_widget( $args );313}314315add_action( 'wordpress_social_login’, ‘wsl_action_wordpress_social_login’ );316317// --------------------------------------------------------------------318319/**320* WSL wordpress_social_login shortcode321*322* Note:323* WSL shortcode arguments are still experimental and might change in future versions.324*325* Ref: http://codex.wordpress.org/Function_Reference/add_shortcode326*/327function wsl_shortcode_wordpress_social_login( $args = array(), $content = null )328{329 $restrict_content = isset( $args[‘restrict_content’] ) && $args[‘restrict_content’] ? true : false;330331 if( ‘wp_user_logged_in’ == $restrict_content && is_user_logged_in() )332 {333 return do_shortcode( $content );334 }335336 if( ‘wsl_user_logged_in’ == $restrict_content && wsl_get_stored_hybridauth_user_profiles_by_user_id( get_current_user_id() ) )337 {338 return do_shortcode( $content );339 }340341 return wsl_render_auth_widget( $args );342}343344add_shortcode( 'wordpress_social_login’, ‘wsl_shortcode_wordpress_social_login’ );345346// --------------------------------------------------------------------347348/**349* WSL wordpress_social_login_meta shortcode350*351* Note:352* This shortcode is experimental and might change in future versions.353*354* [wordpress_social_login_meta355* user_id="215"356* meta="wsl_current_user_image"357* display="html"358* css_class="my_style_is_better"359* ]360*/361function wsl_shortcode_wordpress_social_login_meta( $args = array() )362{363 // wordpress user id default to current user connected364 $user_id = isset( $args[‘user_id’] ) && $args[‘user_id’] ? $args[‘user_id’] : get_current_user_id();365366 // display default to plain text367 $display = isset( $args[‘display’] ) && $args[‘display’] ? $args[‘display’] : 'plain’;368369 // when display is set to html, css_class will be used for the main dom el370 $css_class = isset( $args[‘css_class’] ) && $args[‘css_class’] ? $args[‘css_class’] : '’;371372 // wsl user meta to display373 $meta = isset( $args[‘meta’] ) && $args[‘meta’] ? $args[‘meta’] : null;374375 if( ! is_numeric( $user_id ) )376 {377 return;378 }379380 if( ! $meta )381 {382 return;383 }384385 $assets_base_url = WORDPRESS_SOCIAL_LOGIN_PLUGIN_URL . 'assets/img/16x16/’;386387 $assets_base_url = isset( $args[‘assets_base_url’] ) && $args[‘assets_base_url’] ? $args[‘assets_base_url’] : $assets_base_url;388389 $return = '’;390391 if( ‘current_avatar’ == $meta )392 {393 if( ‘plain’ == $display )394 {395 $return = wsl_get_user_custom_avatar( $user_id );396 }397 else398 {399 $return = '<img class="wordpress_social_login_meta_user_avatar ' . $css_class . ‘" src="’ . wsl_get_user_custom_avatar( $user_id ) . '" />’;400 }401 }402403 if( ‘current_provider’ == $meta )404 {405 $provider = get_user_meta( $user_id, 'wsl_current_provider’, true );406407 if( ‘plain’ == $display )408 {409 $return = $provider;410 }411 else412 {413 $return = '<img class="wordpress_social_login_meta_user_provider ' . $css_class . ‘" src="’ . $assets_base_url . strtolower( $provider ) . '.png"> ' . $provider;414 }415 }416417 if( ‘user_identities’ == $meta )418 {419 ob_start();420421 $linked_accounts = wsl_get_stored_hybridauth_user_profiles_by_user_id( $user_id );422423 if( $linked_accounts )424 {425 ?><table class="wp-social-login-linked-accounts-list <?php echo $css_class; ?>"><?php426427 foreach( $linked_accounts AS $item )428 {429 $identity = $item->profileurl;430 $photourl = $item->photourl;431432 if( ! $identity )433 {434 $identity = $item->identifier;435 }436437 ?><tr><td><?php if( $photourl ) { ?><img style="vertical-align: top;width:16px;height:16px;" src="<?php echo $photourl ?>"> <?php } else { ?><img src="<?php echo $assets_base_url . strtolower( $item->provider ) . ‘.png’ ?>" /> <?php } ?><?php echo ucfirst( $item->provider ); ?> </td><td><?php echo $identity; ?></td></tr><?php438439 echo "\n";440 }441442 ?></table><?php443 }444445 $return = ob_get_clean();446447 if( ‘plain’ == $display )448 {449 $return = strip_tags( $return );450 }451 }452453 return $return;454}455456add_shortcode( 'wordpress_social_login_meta’, ‘wsl_shortcode_wordpress_social_login_meta’ );457458// --------------------------------------------------------------------459460/**461* Display on comment area462*/463function wsl_render_auth_widget_in_comment_form()464{465 $wsl_settings_widget_display = get_option( ‘wsl_settings_widget_display’ );466467 if( comments_open() )468 {469 if(470 ! $wsl_settings_widget_display471 ||472 $wsl_settings_widget_display == 1473 ||474 $wsl_settings_widget_display == 2475 )476 {477 echo wsl_render_auth_widget();478 }479 }480}481482add_action( ‘comment_form_top’ , ‘wsl_render_auth_widget_in_comment_form’ );483add_action( 'comment_form_must_log_in_after’, ‘wsl_render_auth_widget_in_comment_form’ );484485// --------------------------------------------------------------------486487/**488* Display on login form489*/490function wsl_render_auth_widget_in_wp_login_form()491{492 $wsl_settings_widget_display = get_option( ‘wsl_settings_widget_display’ );493494 if( $wsl_settings_widget_display == 1 || $wsl_settings_widget_display == 3 )495 {496 echo wsl_render_auth_widget();497 }498}499500add_action( ‘login_form’ , ‘wsl_render_auth_widget_in_wp_login_form’ );501add_action( 'bp_before_account_details_fields’, ‘wsl_render_auth_widget_in_wp_login_form’ );502add_action( ‘bp_before_sidebar_login_form’ , ‘wsl_render_auth_widget_in_wp_login_form’ );503504// --------------------------------------------------------------------505506/**507* Display on login & register form508*/509function wsl_render_auth_widget_in_wp_register_form()510{511 $wsl_settings_widget_display = get_option( ‘wsl_settings_widget_display’ );512513 if( $wsl_settings_widget_display == 1 || $wsl_settings_widget_display == 3 )514 {515 echo wsl_render_auth_widget();516 }517}518519add_action( ‘register_form’ , ‘wsl_render_auth_widget_in_wp_register_form’ );520add_action( 'after_signup_form’, ‘wsl_render_auth_widget_in_wp_register_form’ );521522// --------------------------------------------------------------------523524/**525* Enqueue WSL CSS file526*/527function wsl_add_stylesheets()528{529 if( ! wp_style_is( 'wsl-widget’, ‘registered’ ) )530 {531 wp_register_style( "wsl-widget", WORDPRESS_SOCIAL_LOGIN_PLUGIN_URL . “assets/css/style.css” );532 }533534 wp_enqueue_style( “wsl-widget” );535}536537add_action( ‘wp_enqueue_scripts’ , ‘wsl_add_stylesheets’ );538add_action( 'login_enqueue_scripts’, ‘wsl_add_stylesheets’ );539540// --------------------------------------------------------------------541542/**543* Enqueue WSL Javascript, only if we use popup544*/545function wsl_add_javascripts()546{547 $wsl_settings_use_popup = get_option( ‘wsl_settings_use_popup’ );548549 // if a user is visiting using a mobile device, WSL will fall back to more in page550 $wsl_settings_use_popup = function_exists( ‘wp_is_mobile’ ) ? wp_is_mobile() ? 2 : $wsl_settings_use_popup : $wsl_settings_use_popup;551552 if( $wsl_settings_use_popup != 1 )553 {554 return null;555 }556557 if( ! wp_script_is( 'wsl-widget’, ‘registered’ ) )558 {559 wp_register_script( "wsl-widget", WORDPRESS_SOCIAL_LOGIN_PLUGIN_URL . “assets/js/widget.js” );560 }561562 wp_enqueue_script( “jquery” );563 wp_enqueue_script( “wsl-widget” );564}565566add_action( ‘wp_enqueue_scripts’ , ‘wsl_add_javascripts’ );567add_action( 'login_enqueue_scripts’, ‘wsl_add_javascripts’ );568569// --------------------------------------------------------------------