CVE-2015-10102 (published 2023-04-17T18:15Z)

A vulnerability, which was classified as critical, has been found in Freshdesk Plugin 1.7 on WordPress. Affected by this issue is some unknown functionality. The manipulation leads to open redirect. The attack may be launched remotely. Upgrading to version 1.8 is able to address this issue. The patch is identified as 2aaecd4e0c7c6c1dc4e6a593163d5f7aa0fa5d5b. It is recommended to upgrade the affected component. VDB-226118 is the identifier assigned to this vulnerability.

CVSS v3 base score: 6.1, MEDIUM (CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N)

Weakness information:
cwe_id: CWE-601
cwe_name: URL Redirection to Untrusted Site ('Open Redirect')
description: A web application accepts a user-controlled input that specifies a link to an external site, and uses that link in a Redirect. This simplifies phishing attacks.
extended_description: An http parameter may contain a URL value and could cause the web application to redirect the request to the specified URL. By modifying the URL value to a malicious site, an attacker may successfully launch a phishing scam and steal user credentials. Because the server name in the modified link is identical to the original site, phishing attempts have a more trustworthy appearance. Whether this issue poses a vulnerability will be subject to the intended behavior of the application. For example, a search engine might intentionally provide redirects to arbitrary URLs.
         

Fix information:
repo_url: https://github.com/wp-plugins/freshdesk-support
commit_details: repo_url: https://github.com/wp-plugins/freshdesk-support
author: shreyasns
author_date: 2015-06-05 12:07:27+00:00
msg: Security fix for open redirect vulnerability

git-svn-id: https://plugins.svn.wordpress.org/freshdesk-support/trunk@1175214 b8457f37-d9ea-0310-8a92-e5e31aec5664
repository: repo_url: https://github.com/wp-plugins/freshdesk-support
repo_name: wp-plugins/freshdesk-support
description: WordPress.org Plugin Mirror
repo_language: PHP
owner: wp-plugins
file_changes: filename: freshdesk-ext.php
change_type: ModificationType.MODIFY
diff: @@ -1,14 +1,14 @@
 <?php
 /*
   @package Freshdesk Official
-  @version 1.7
+  @version 1.8
 */
 /*
   Plugin Name: Freshdesk Official
   Plugin URI: 
   Description: Freshdesk Official is a seamless way to add your helpdesk account to your website. Supports various useful functions.
   Author: hjohnpaul,sathishfreshdesk,balakumars,shreyasns
-  Version: 1.7
+  Version: 1.8
   Author URI: http://freshdesk.com/
 */
 
@@ -20,6 +20,7 @@ if ( ! defined( 'ABSPATH' ) ) {
 #include freshdesk api class.
 define( 'FD_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
 define( 'FD_PAGE_BASENAME', 'freshdesk-menu-handle' );
+define( 'DOMAIN_REGEX', '/\bhttps?:\/\/([-a-z0-9+&@#\/%?=~_|!:,.;]*[-a-z0-9+&@#\/%=~_|])/i' );
 require_once( plugin_dir_path( __FILE__ ) . 'freshdesk-plugin-api.php' );
 
 add_action( 'init', 'fd_login' ); //Sso handler and comment action handler
@@ -45,14 +46,17 @@ function fd_login_redirect( $url, $request, $user ) {
 	if ( ! $fd_redirect_to ) {
 		return $url;
 	}
+	$redirect_url = get_redirect_url( $fd_redirect_to );
+
 	// For handling Redirect to Freshdesk on login.
-	if ( $_REQUEST['wp-submit'] == "Log In" && is_a( $user, 'WP_User' ) ) {
+	if ( $_REQUEST['wp-submit'] == "Log In" && is_a( $user, 'WP_User' ) && $redirect_url ) {
+		$freshdesk_options = get_option( 'freshdesk_options' );		
+		
 		$user_name = $user->data->display_name;
-		$freshdesk_options = get_option( 'freshdesk_options' );
 		$secret = $freshdesk_options['freshdesk_sso_key'];
 		$data = $user_name.$user->data->user_email.time();
 		$hash_key = hash_hmac("md5", $data, $secret);
-		$ssl_url = $fd_redirect_to."/login/sso?name=".urlencode($user->data->display_name)."&email=".urlencode($user->data->user_email)."&timestamp=".time()."&hash=".urlencode($hash_key);
+		$ssl_url = $redirect_url."/login/sso?name=".urlencode($user->data->display_name)."&email=".urlencode($user->data->user_email)."&timestamp=".time()."&hash=".urlencode($hash_key);
 		sleep(1); // holding a bit so that it falls within FD 30 mins bar.
 		header("Location: ".$ssl_url);
 		die();
@@ -60,6 +64,23 @@ function fd_login_redirect( $url, $request, $user ) {
 	return  $request;
 }
 
+function get_redirect_url($host_url) {
+	$freshdesk_options = get_option( 'freshdesk_options' );
+
+	//Stripping protocols from urls to match the host url correctly.
+	$host_url = preg_replace( DOMAIN_REGEX, "$1", trim($host_url) );
+	$domains = split( ",", $freshdesk_options['freshdesk_cname'] );
+	array_push( $domains, $freshdesk_options['freshdesk_domain_url'] );
+
+	//Checking the host url against the provided helpdesk/portal url to avoid Open-redirect vulnerability
+	foreach ( $domains as $domain ) {
+		$domain = trim($domain);
+		$url = preg_replace( DOMAIN_REGEX, "$1", $domain);
+		if ( $url == $host_url ) {
+			return $domain;
+		}
+	}
+}
 function freshdesk_plugin_menu() {
 	add_menu_page( 'Freshdesk Settings', 'Freshdesk', 'manage_options', 'freshdesk-menu-handle', 'freshdesk_settings_page');
 	add_action( 'admin_init', 'freshdesk_settings_init' );
@@ -83,6 +104,8 @@ function freshdesk_settings_init() {
 	add_settings_section( 'freshdesk_settings_section', '', '', 'freshdesk-menu-handle' );
 	//Domain url.
 	add_settings_field( 'freshdesk_domain_url', __('Helpdesk URL'), 'freshdesk_domain_callback' ,'freshdesk-menu-handle', 'freshdesk_settings_section' );
+	//Host url
+	add_settings_field( 'freshdesk_cname', __('Portal URLs'), 'freshdesk_cname_callback' ,'freshdesk-menu-handle', 'freshdesk_settings_section' );
 	
 	//Freshdesk Api Key.
 	add_settings_field( 'freshdesk_api_key', 'API Key', 'freshdesk_api_callback' , 'freshdesk-menu-handle', 'freshdesk_settings_section' );
@@ -102,6 +125,12 @@ function freshdesk_domain_callback() {
 	echo '<div class="info-data fd_ui_element">Eg: https://yourcompany.freshdesk.com</div>';
 }
 
+function freshdesk_cname_callback() {
+	$options = get_option( 'freshdesk_options' );
+	echo "<input class='fd_ui_element' id='freshdesk_cname' name='freshdesk_options[freshdesk_cname]' size='72' type='text' value='{$options['freshdesk_cname']}' />";
+	echo '<div class="info-data fd_ui_element">Eg: https://support.yourdomain.com,https://support2.yourdomain.com</div>';
+}
+
 function freshdesk_enable_sso_callback() {
 	$options = get_option( 'freshdesk_options' );
 	echo '<tr><td colspan="2"><ul class="fd-form-table"><li><div><label><input class="fd_button" type="checkbox" name="freshdesk_options[freshdesk_enable_sso]" id="freshdesk_enable_sso" '.$options['freshdesk_enable_sso'].' /><span class="fd_ui_element fd-bold">Enable SSO Login </span></label><div><div class="info-data fd_lmargin">Enabling this will let your users to login using their wordpress credentials</div></li>';
@@ -157,9 +186,31 @@ function validate_freshdesk_settings( $input ) {
 	$freshdesk_options = get_option( 'freshdesk_options' );
 	$error = 0;
 	$url=trim($input['freshdesk_domain_url']);
-	if ( ! preg_match("/\b(?:(?:https?):\/\/|www\.)[-a-z0-9+&@#\/%?=~_|!:,.;]*[-a-z0-9+&@#\/%=~_|]/i", $url ) ) {
-		$url ='';
+	if ( $url && ! preg_match( DOMAIN_REGEX, $url )  ) {
+		add_settings_error(
+			'freshdesk_domain_url', // setting title
+			'fd_invalid_domain', // error ID
+			"$url is an invalid  Helpdesk url", // error message
+			'error' // type of message
+		);
+		$error=1;
+	}
+	$cnames = split( ",", trim($input['freshdesk_cname'] ) );
+	foreach ( $cnames as $cname ) {
+		$cname = trim($cname);
+		if ( ! preg_match( DOMAIN_REGEX, $cname ) && $cname ) {
+			add_settings_error(
+				'freshdesk_cname', // setting title
+				'fd_cname_invalid_domain', // error ID
+				"$cname is an invalid  domain url", // error message
+				'error' // type of message
+			);
+			$error=1;
+			break;
+		}
 	}
+	$cname = trim($input['freshdesk_cname'] );
+	
 	$sso_secret = $input['freshdesk_sso_key'];
 	$api_key = $input['freshdesk_api_key'];
 	$enable_feedback = validate_checkbox( $input['freshdesk_enable_feedback'] );
@@ -169,7 +220,7 @@ function validate_freshdesk_settings( $input ) {
 		add_settings_error(
 			'freshdesk_domain_url', // setting title
 			'fd_domain_url_not_present', // error ID
-			'Domain url cannot be blank', // error message
+			'Helpdesk url cannot be blank', // error message
 			'error' // type of message
 		);
 		$error=1;
@@ -198,7 +249,7 @@ function validate_freshdesk_settings( $input ) {
 	if ( $error ) {
 		return $freshdesk_options;
 	}
-	$settings = array( 'freshdesk_domain_url' => $url, 'freshdesk_enable_sso' => $enable_sso, 'freshdesk_sso_key' => $sso_secret, 'freshdesk_api_key' => $api_key, 'freshdesk_enable_feedback' => $enable_feedback );
+	$settings = array( 'freshdesk_domain_url' => $url, 'freshdesk_cname' => $cname, 'freshdesk_enable_sso' => $enable_sso, 'freshdesk_sso_key' => $sso_secret, 'freshdesk_api_key' => $api_key, 'freshdesk_enable_feedback' => $enable_feedback );
 	
 	return $settings;	
 }
@@ -238,9 +289,14 @@ function freshdesk_comment_action( $actions, $comment ) {
 function fd_login() {
 	global $pagenow, $display_name , $user_email;
 	if ( 'wp-login.php' == $pagenow ){
+		$freshdesk_options = get_option( 'freshdesk_options' );
+		$domain = get_redirect_url($_REQUEST['host_url']);
+		error_log("Domain : $domain ");
+		if( ! $domain ) {
+			return;
+		}
 		if ( $_GET['action'] == 'freshdesk-login' ) {
 			// NOTE: is_user_logged_in dont't work during  [wp-submit] => Log In
-			$freshdesk_options = get_option( 'freshdesk_options' );
 			if( $freshdesk_options['freshdesk_enable_sso'] != 'checked' ){
 				return;
 			}
@@ -252,12 +308,12 @@ function fd_login() {
 				$user_email = $current_user->user_email;
 				$data = $user_name.$user_email.time();
 				$hash_key = hash_hmac( "md5", $data, $secret );
-				$url = freshdesk_sso_login_url( $user_name, $user_email ,$hash_key );
+				$url = freshdesk_sso_login_url( $domain, $user_name, $user_email ,$hash_key );
 				header( 'Location: '.$url ) ;	
 				die();
 			}
 			else{ // if wordpress is not logged in.
-				$domain = ( $_REQUEST['host_url'] ) ? get_domain_protocol()."://".$_REQUEST['host_url'] : $freshdesk_options['freshdesk_domain_url']; // Redirect to the host url if host url option is present with the request.
+				
 				if (isset($domain)){
 					header( "Location: " .wp_login_url()."?redirect_to=fd_redirect_to=".$domain );
 					die();
@@ -265,17 +321,8 @@ function fd_login() {
 		 	}
 		}
 		if ( $_GET['action'] == 'freshdesk-logout' ) {
-			$redirect_url = wp_login_url();
-			// Sometimes we get the http referer and some times don't so to find if it is coming from Freshdesk we do a two condition check and if one is satisfied then Freshdesk is the referer.
-			// Condition-1) Host url is a substring of http referer
-			// Condition-2) Host url exists and the http_referer is empty because request from within wordpress seems to always have a referer.
-			$condition_one = ( strpos($_SERVER['HTTP_REFERER'], $_REQUEST['host_url']) !== FALSE ) ? TRUE : FALSE;
-			$condition_two = ( $_REQUEST['host_url'] && empty( $_SERVER['HTTP_REFERER'] ) );
-			if ( $condition_one || $condition_two ) {
-				$redirect_url = get_domain_protocol()."://".$_REQUEST['host_url'];
-			}
 			wp_logout();
-			header( 'Location: '.$redirect_url );
+			header( 'Location: '.$domain );
 			die();
 		}
 	}
@@ -302,19 +349,8 @@ function freshdesk_handshake_secret() {
 	
 }
 
-function get_domain_protocol() {
-	$freshdesk_options= get_option( 'freshdesk_options' );
-	$domain_url = $freshdesk_options['freshdesk_domain_url'];
-	$temp_array = explode( ":", $domain_url );
-	$protocol = $temp_array[0];
-	return $protocol;
-}
-
-function freshdesk_sso_login_url($user_name,$email,$hash_key){
-	$host_url = $_GET['host_url'];
-	$protocol = get_domain_protocol()."://";
-	$domain = (empty($host_url) === true) ? $domain_url : $host_url; // Take the domain_url if host_url is null.
-	return $protocol.$domain."/login/sso?name=".urlencode($user_name)."&email=".urlencode($email)."&timestamp=".time()."&hash=".urlencode($hash_key);
+function freshdesk_sso_login_url($domain, $user_name, $email, $hash_key){
+	return $domain."/login/sso?name=".urlencode($user_name)."&email=".urlencode($email)."&timestamp=".time()."&hash=".urlencode($hash_key);
 }
 
 //Ajax Action handler. Freshdesk Ticket creation handled here.

programming_language: PHP
filename: readme.txt
change_type: ModificationType.MODIFY
diff: @@ -4,7 +4,7 @@ Donate link:
 Tags: freshdesk, helpdesk, support tool
 Requires at least: 3.4
 Tested up to: 4.1.5
-Stable tag: 1.7
+Stable tag: 1.8
 License: GPLv2 or later
 License URI: http://www.gnu.org/licenses/gpl-2.0.html
 
@@ -66,6 +66,8 @@ Manual Installation:
 4. This shows the comment link in the ticket description.
 
 == Changelog ==
+= 1.8 =
+  Security fix for open redirect vulnerablity. Now users are required to configure all the portal urls in the settings page.
 = 1.7 =
   Added option to enable/disable sso.
   Logging out of wordpress no longer logs out the Freshdesk session.
@@ -90,10 +92,9 @@ Bug Fix:
 First Release Version.
 
 == Upgrade Notice ==
-  Added option to enable/disable sso.
-  Logging out of wordpress will no longer logout the Freshdesk session.
-  Added validations for the settings page.
-  Fixed the error showing up on the plugin settings page.
+  Security fix for open redirect vulnerablity. Now users are required to configure all the portal urls in the settings page.
+= 1.8 =
+  Security fix for open redirect vulnerablity. Now users are required to configure all the portal urls in the settings page.  
 == 1.7 ==
   Added option to enable/disable sso.
   Logging out of wordpress will no longer logout the Freshdesk session.

programming_language: Markdown