Skip to content
Permalink
Browse files Browse the repository at this point in the history
Security fix for open redirect vulnerability
git-svn-id: https://plugins.svn.wordpress.org/freshdesk-support/trunk@1175214 b8457f37-d9ea-0310-8a92-e5e31aec5664
  • Loading branch information
shreyasns committed Jun 5, 2015
1 parent ad5a386 commit 2aaecd4
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 40 deletions.
106 changes: 71 additions & 35 deletions freshdesk-ext.php
@@ -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/
*/

Expand All @@ -20,6 +20,7 @@
#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
Expand All @@ -45,21 +46,41 @@ 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();
}
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' );
Expand All @@ -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' );
Expand All @@ -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>';
Expand Down Expand Up @@ -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'] );
Expand All @@ -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;
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
}
Expand All @@ -252,30 +308,21 @@ 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();
}
}
}
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();
}
}
Expand All @@ -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.
Expand Down
11 changes: 6 additions & 5 deletions readme.txt
Expand Up @@ -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

Expand Down Expand Up @@ -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.
Expand All @@ -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.
Expand Down

0 comments on commit 2aaecd4

Please sign in to comment.