Fix CSRF security issue.
This commit is contained in:
davidcallizaya
2017-10-13 07:57:22 -04:00
parent 592ab76c01
commit 086cc31982
12 changed files with 112 additions and 68 deletions

View File

@@ -323,8 +323,7 @@ class PmBootstrap extends Bootstrap
require_once 'classes/model/Users.php'; require_once 'classes/model/Users.php';
$oUser = new Users(); $oUser = new Users();
$aUser = $oUser->load($aSession['USR_UID']); $aUser = $oUser->load($aSession['USR_UID']);
$_SESSION['USER_LOGGED'] = $aUser['USR_UID']; initUserSession($aUser['USR_UID'], $aUser['USR_USERNAME']);
$_SESSION['USR_USERNAME'] = $aUser['USR_USERNAME'];
$bRedirect = false; $bRedirect = false;
$RBAC->initRBAC(); $RBAC->initRBAC();
$RBAC->loadUserRolePermission( $RBAC->sSystem, $_SESSION['USER_LOGGED'] ); $RBAC->loadUserRolePermission( $RBAC->sSystem, $_SESSION['USER_LOGGED'] );

View File

@@ -182,14 +182,12 @@ try {
$oPluginRegistry->executeTriggers ( PM_LOGIN , $loginInfo ); $oPluginRegistry->executeTriggers ( PM_LOGIN , $loginInfo );
} }
EnterpriseClass::enterpriseSystemUpdate($loginInfo); EnterpriseClass::enterpriseSystemUpdate($loginInfo);
$_SESSION['USER_LOGGED'] = $uid; initUserSession($uid, $usr);
$_SESSION['USR_USERNAME'] = $usr;
} else { } else {
setcookie("singleSignOn", '1', time() + (24 * 60 * 60), '/'); setcookie("singleSignOn", '1', time() + (24 * 60 * 60), '/');
$uid = $RBAC->userObj->fields['USR_UID']; $uid = $RBAC->userObj->fields['USR_UID'];
$usr = $RBAC->userObj->fields['USR_USERNAME']; $usr = $RBAC->userObj->fields['USR_USERNAME'];
$_SESSION['USER_LOGGED'] = $uid; initUserSession($uid, $usr);
$_SESSION['USR_USERNAME'] = $usr;
} }
//Set default Languaje //Set default Languaje

View File

@@ -129,9 +129,10 @@ try {
setcookie('singleSignOn', '1', time() + (24 * 60 * 60), '/'); setcookie('singleSignOn', '1', time() + (24 * 60 * 60), '/');
$_SESSION['USER_LOGGED'] = $_SESSION['__USER_LOGGED_SSO__']; initUserSession(
$_SESSION['USR_USERNAME'] = $_SESSION['__USR_USERNAME_SSO__']; $_SESSION['__USER_LOGGED_SSO__'],
$_SESSION['__USR_USERNAME_SSO__']
);
unset($_SESSION['__USER_LOGGED_SSO__'], $_SESSION['__USR_USERNAME_SSO__']); unset($_SESSION['__USER_LOGGED_SSO__'], $_SESSION['__USR_USERNAME_SSO__']);
G::header('Location: ' . $location); G::header('Location: ' . $location);

View File

@@ -4,7 +4,6 @@ ini_set("max_execution_time", 0);
$filter = new InputFilter(); $filter = new InputFilter();
$_FILES = $filter->xssFilterHard($_FILES); $_FILES = $filter->xssFilterHard($_FILES);
$_SESSION['USER_LOGGED'] = $filter->xssFilterHard($_SESSION['USER_LOGGED']);
if (isset($_FILES["PROCESS_FILENAME"]) && if (isset($_FILES["PROCESS_FILENAME"]) &&
pathinfo($_FILES["PROCESS_FILENAME"]["name"], PATHINFO_EXTENSION) == "bpmn" pathinfo($_FILES["PROCESS_FILENAME"]["name"], PATHINFO_EXTENSION) == "bpmn"

View File

@@ -24,8 +24,7 @@ try {
throw new \Exception('WebEntry User not found'); throw new \Exception('WebEntry User not found');
} }
$_SESSION['USER_LOGGED'] = $userUid; initUserSession($userUid, $userInfo['username']);
$_SESSION['USR_USERNAME'] = $userInfo['username'];
$result = [ $result = [
'user_logged' => $userUid, 'user_logged' => $userUid,

View File

@@ -129,6 +129,7 @@ switch ($_POST['action']) {
case 'saveUser': case 'saveUser':
case 'savePersonalInfo': case 'savePersonalInfo':
try { try {
verifyCsrfToken($_POST);
$user = new \ProcessMaker\BusinessModel\User(); $user = new \ProcessMaker\BusinessModel\User();
$form = $_POST; $form = $_POST;
$permissionsToSaveData = $user->getPermissionsForEdit(); $permissionsToSaveData = $user->getPermissionsForEdit();

View File

@@ -261,9 +261,11 @@ class SkinEngine
$template = new TemplatePower($templateFile); $template = new TemplatePower($templateFile);
$template->prepare(); $template->prepare();
$header = '<meta name="csrf-token" content="'. csrfToken().'" />' . "\n" . $header;
$template->assign('header', $header); $template->assign('header', $header);
$template->assign('styles', $styles); $template->assign('styles', $styles);
$template->assign('bodyTemplate', $body); $template->assign('bodyTemplate', $body);
$template->assign('csrf_token', csrfToken());
$doctype = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">"; $doctype = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">";
$meta = null; $meta = null;
@@ -569,6 +571,7 @@ class SkinEngine
$smarty->cache_dir = PATH_SMARTY_CACHE; $smarty->cache_dir = PATH_SMARTY_CACHE;
$smarty->config_dir = PATH_THIRDPARTY . 'smarty/configs'; $smarty->config_dir = PATH_THIRDPARTY . 'smarty/configs';
$smarty->register_function('translate', 'translate'); $smarty->register_function('translate', 'translate');
$smarty->register_function('csrf_token', 'csrfToken');
$viewVars = $oHeadPublisher->getVars(); $viewVars = $oHeadPublisher->getVars();

View File

@@ -1,4 +1,8 @@
<?php <?php
use Illuminate\Session\TokenMismatchException;
use Illuminate\Support\Str;
/** /**
* We will send a case note in the actions by email * We will send a case note in the actions by email
* @param object $httpData * @param object $httpData
@@ -361,3 +365,33 @@ function eprintln ($s = "", $c = null)
print "$s\n"; print "$s\n";
} }
} }
/**
* Initialize the user logged session
*/
function initUserSession($usrUid, $usrName)
{
$_SESSION['USER_LOGGED'] = $usrUid;
$_SESSION['USR_USERNAME'] = $usrName;
$_SESSION['USR_CSRF_TOKEN'] = Str::random(40);
}
function verifyCsrfToken($request)
{
$headers = getallheaders();
$token = isset($request['_token'])
? $request['_token']
: (isset($headers['X-CSRF-TOKEN'])
? $headers['X-CSRF-TOKEN']
: null);
$match = is_string($_SESSION['USR_CSRF_TOKEN'])
&& is_string($token)
&& hash_equals($_SESSION['USR_CSRF_TOKEN'], $token);
if (!$match) {
throw new TokenMismatchException();
}
}
function csrfToken()
{
return isset($_SESSION['USR_CSRF_TOKEN']) ? $_SESSION['USR_CSRF_TOKEN'] : '';
}

View File

@@ -810,6 +810,12 @@ Ext.onReady(function () {
] ]
}); });
var csrfToken = {
xtype : 'hidden',
name : '_token',
value : document.querySelector('meta[name="csrf-token"]').content
};
frmDetails = new Ext.FormPanel({ frmDetails = new Ext.FormPanel({
id : 'frmDetails', id : 'frmDetails',
labelWidth : 250, labelWidth : 250,
@@ -828,6 +834,7 @@ Ext.onReady(function () {
align : 'center' align : 'center'
}, },
items : [ items : [
csrfToken,
informationFields, informationFields,
/*----------------------------------********---------------------------------*/ /*----------------------------------********---------------------------------*/
costByHour, costByHour,

View File

@@ -644,8 +644,7 @@ use ProcessMaker\Plugins\PluginRegistry;
require_once 'classes/model/Users.php'; require_once 'classes/model/Users.php';
$oUser = new Users(); $oUser = new Users();
$aUser = $oUser->load($aSession['USR_UID']); $aUser = $oUser->load($aSession['USR_UID']);
$_SESSION['USER_LOGGED'] = $aUser['USR_UID']; initUserSession($aUser['USR_UID'], $aUser['USR_USERNAME']);
$_SESSION['USR_USERNAME'] = $aUser['USR_USERNAME'];
$bRedirect = false; $bRedirect = false;
if (PHP_VERSION < 5.2) { if (PHP_VERSION < 5.2) {
setcookie(session_name(), session_id(), time() + $timelife, '/', '; HttpOnly'); setcookie(session_name(), session_id(), time() + $timelife, '/', '; HttpOnly');

View File

@@ -15,7 +15,7 @@ $server = isset($_GET['server']) ? $_GET['server'] : '';
//We do need the server to continue. //We do need the server to continue.
if( !isset($_GET['server']) || $server == "" ){ if( !isset($_GET['server']) || $server == "" ){
throw new \Exception(Bootstrap::LoadTranslation( 'ID_GMAIL_NEED_SERVER' )); throw new \Exception(Bootstrap::LoadTranslation( 'ID_GMAIL_NEED_SERVER' ));
} }
//First check if the feature is enabled in the license. //First check if the feature is enabled in the license.
@@ -53,75 +53,77 @@ curl_close($curl);
$decodedResp = G::json_decode($curl_response); $decodedResp = G::json_decode($curl_response);
if(!is_object($decodedResp) || property_exists($decodedResp,'error')) { if(!is_object($decodedResp) || property_exists($decodedResp,'error')) {
die($decodedResp->error->message); die($decodedResp->error->message);
} }
//getting the enviroment //getting the enviroment
$enviroment = $decodedResp->enviroment; $enviroment = $decodedResp->enviroment;
if(count($decodedResp->user) > 1){ if(count($decodedResp->user) > 1){
echo Bootstrap::LoadTranslation( 'ID_EMAIL_MORE_THAN_ONE_USER' ); echo Bootstrap::LoadTranslation( 'ID_EMAIL_MORE_THAN_ONE_USER' );
die; die;
} else if(count($decodedResp->user) < 1){ } else if(count($decodedResp->user) < 1){
echo Bootstrap::LoadTranslation( 'ID_USER_NOT_FOUND' ); echo Bootstrap::LoadTranslation( 'ID_USER_NOT_FOUND' );
die; die;
} }
//validationg if there is an actual PM session //validationg if there is an actual PM session
if( !isset($_SESSION['USER_LOGGED']) || $_SESSION['USER_LOGGED'] != $decodedResp->user['0']->USR_UID){ if( !isset($_SESSION['USER_LOGGED']) || $_SESSION['USER_LOGGED'] != $decodedResp->user['0']->USR_UID){
$url = 'https://www.googleapis.com/oauth2/v1/tokeninfo?access_token='.$gmailToken; $url = 'https://www.googleapis.com/oauth2/v1/tokeninfo?access_token='.$gmailToken;
// init curl object // init curl object
$ch = curl_init(); $ch = curl_init();
// define options // define options
$optArray = array( $optArray = array(
CURLOPT_URL => $url, CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true, CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSL_VERIFYPEER => false, CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false CURLOPT_SSL_VERIFYHOST => false
); );
// apply those options // apply those options
curl_setopt_array($ch, $optArray); curl_setopt_array($ch, $optArray);
// execute request and get response // execute request and get response
$result = curl_exec($ch); $result = curl_exec($ch);
$response = (G::json_decode($result)); $response = (G::json_decode($result));
curl_close($ch); curl_close($ch);
//First validate if this user (mail) corresponds to a PM user //First validate if this user (mail) corresponds to a PM user
if(isset($response->email) && ($gmail == $response->email)){ if(isset($response->email) && ($gmail == $response->email)){
//If the email corresponds I get the username and with the gmail user_id the session is created. //If the email corresponds I get the username and with the gmail user_id the session is created.
if($decodedResp->user['0']->USR_STATUS == "ACTIVE"){ if($decodedResp->user['0']->USR_STATUS == "ACTIVE"){
//User Active! lets create the Session //User Active! lets create the Session
@session_destroy(); @session_destroy();
session_start(); session_start();
session_regenerate_id(); session_regenerate_id();
if (PHP_VERSION < 5.2) { if (PHP_VERSION < 5.2) {
setcookie("workspaceSkin", $enviroment, time() + (24 * 60 * 60), "/sys" . $enviroment, "; HttpOnly"); setcookie("workspaceSkin", $enviroment, time() + (24 * 60 * 60), "/sys" . $enviroment, "; HttpOnly");
} else { } else {
setcookie("workspaceSkin", $enviroment, time() + (24 * 60 * 60), "/sys" . $enviroment, null, false, true); setcookie("workspaceSkin", $enviroment, time() + (24 * 60 * 60), "/sys" . $enviroment, null, false, true);
} }
$_SESSION = array(); $_SESSION = array();
$_SESSION['__EE_INSTALLATION__'] = 2; $_SESSION['__EE_INSTALLATION__'] = 2;
$_SESSION['__EE_SW_PMLICENSEMANAGER__'] = 1; $_SESSION['__EE_SW_PMLICENSEMANAGER__'] = 1;
$_SESSION['phpLastFileFound'] = ''; $_SESSION['phpLastFileFound'] = '';
$_SESSION['USERNAME_PREVIOUS1'] = $decodedResp->user['0']->USR_USERNAME; $_SESSION['USERNAME_PREVIOUS1'] = $decodedResp->user['0']->USR_USERNAME;
$_SESSION['USERNAME_PREVIOUS2'] = $decodedResp->user['0']->USR_USERNAME; $_SESSION['USERNAME_PREVIOUS2'] = $decodedResp->user['0']->USR_USERNAME;
$_SESSION['WORKSPACE'] = $pmws; $_SESSION['WORKSPACE'] = $pmws;
$_SESSION['USER_LOGGED'] = $decodedResp->user['0']->USR_UID; $_SESSION['USR_FULLNAME'] = $decodedResp->user['0']->USR_FIRSTNAME. ' ' .$decodedResp->user['0']->USR_LASTNAME;
$_SESSION['USR_USERNAME'] = $decodedResp->user['0']->USR_USERNAME; $_SESSION['__sw__'] = 1;
$_SESSION['USR_FULLNAME'] = $decodedResp->user['0']->USR_FIRSTNAME. ' ' .$decodedResp->user['0']->USR_LASTNAME; initUserSession(
$_SESSION['__sw__'] = 1; $decodedResp->user['0']->USR_UID,
//session created $decodedResp->user['0']->USR_USERNAME
} else { );
echo Bootstrap::LoadTranslation( 'ID_USER_NOT_ACTIVE' ); //session created
die; } else {
} echo Bootstrap::LoadTranslation( 'ID_USER_NOT_ACTIVE' );
} else { die;
echo Bootstrap::LoadTranslation( 'ID_USER_DOES_NOT_CORRESPOND' ); }
die; } else {
} echo Bootstrap::LoadTranslation( 'ID_USER_DOES_NOT_CORRESPOND' );
die;
}
} }
$_SESSION['server'] = 'https://' . $server . '/sys'. $pmws .'/en/'.$enviroment.'/'; $_SESSION['server'] = 'https://' . $server . '/sys'. $pmws .'/en/'.$enviroment.'/';

View File

@@ -979,8 +979,10 @@ if (! defined( 'EXECUTE_BY_CRON' )) {
require_once 'classes/model/Users.php'; require_once 'classes/model/Users.php';
$oUser = new Users(); $oUser = new Users();
$aUser = $oUser->load( $aSession['USR_UID'] ); $aUser = $oUser->load( $aSession['USR_UID'] );
$_SESSION['USER_LOGGED'] = $aUser['USR_UID']; initUserSession(
$_SESSION['USR_USERNAME'] = $aUser['USR_USERNAME']; $_SESSION['USER_LOGGED'],
$aUser['USR_USERNAME']
);
$bRedirect = false; $bRedirect = false;
if ((preg_match("/msie/i", $_SERVER ['HTTP_USER_AGENT']) != 1 || if ((preg_match("/msie/i", $_SERVER ['HTTP_USER_AGENT']) != 1 ||
$config['ie_cookie_lifetime'] == 1) && $config['ie_cookie_lifetime'] == 1) &&