From 6afc876d199362624d03cc3a6f907f6e0d68205b Mon Sep 17 00:00:00 2001 From: xisi Date: Thu, 16 Jan 2014 07:52:52 -0500 Subject: [PATCH 01/47] Merge changes from TheSerapher's pull/1404 Added re-Captcha to Login Page --- public/include/config/global.inc.dist.php | 2 +- public/include/pages/login.inc.php | 10 ++++++++++ public/include/version.inc.php | 2 +- public/templates/mpos/global/header.tpl | 1 + 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/public/include/config/global.inc.dist.php b/public/include/config/global.inc.dist.php index 7c9eebba..677a4619 100644 --- a/public/include/config/global.inc.dist.php +++ b/public/include/config/global.inc.dist.php @@ -7,7 +7,7 @@ if (!defined('SECURITY')) die('Hacking attempt'); * This is used in the version check to ensure you run the latest version of the configuration file. * Once you upgraded your config, change the version here too. **/ -$config['version'] = '0.0.4'; +$config['version'] = '0.0.5'; // Our include directory for additional features define('INCLUDE_DIR', BASEPATH . 'include'); diff --git a/public/include/pages/login.inc.php b/public/include/pages/login.inc.php index 7122d22b..7e43ae5a 100644 --- a/public/include/pages/login.inc.php +++ b/public/include/pages/login.inc.php @@ -26,6 +26,16 @@ if ($setting->getValue('maintenance') && !$user->isAdmin($user->getUserId($_POST $_SESSION['POPUP'][] = array('CONTENT' => 'You are not allowed to login during maintenace.', 'TYPE' => 'info'); } else if (!empty($_POST['username']) && !empty($_POST['password'])) { $nocsrf = 1; + $recaptchavalid = 0; + if ($setting->getValue('recaptcha_enabled') && $setting->getValue('recaptcha_enabled_logins') && $rsp->is_valid) { + if ($rsp->is_valid) { + // recaptcha is enabled and valid + $recaptchavalid = 1; + } else { + // error out, invalid captcha + $_SESSION['POPUP'][] = array('CONTENT' => 'Unable to login: The captcha you entered was incorrect', 'TYPE' => 'errormsg'); + } + } if ($config['csrf']['enabled'] && $config['csrf']['forms']['login']) { if ((isset($_POST['ctoken']) && $_POST['ctoken'] !== $user->getCSRFToken($_SERVER['REMOTE_ADDR'], 'login')) || (!isset($_POST['ctoken']))) { // csrf protection is on and this token is invalid, error out -> time expired diff --git a/public/include/version.inc.php b/public/include/version.inc.php index 21dd0010..e132eb5e 100644 --- a/public/include/version.inc.php +++ b/public/include/version.inc.php @@ -5,7 +5,7 @@ if (!defined('SECURITY')) die('Hacking attempt'); define('MPOS_VERSION', '0.0.2'); define('DB_VERSION', '0.0.3'); -define('CONFIG_VERSION', '0.0.4'); +define('CONFIG_VERSION', '0.0.5'); // Fetch installed database version $db_version = $setting->getValue('DB_VERSION'); diff --git a/public/templates/mpos/global/header.tpl b/public/templates/mpos/global/header.tpl index ecc997c1..493147dd 100644 --- a/public/templates/mpos/global/header.tpl +++ b/public/templates/mpos/global/header.tpl @@ -2,3 +2,4 @@

{$GLOBAL.website.name|default:"Unknown Pool"}

{if $smarty.request.action|escape|default:""}{$smarty.request.action|escape|capitalize}{else}{$smarty.request.page|escape|default:"home"|capitalize}{/if}

+ {if $GLOBAL.config.recaptcha_enabled|default:"0" != 1 || $GLOBAL.config.recaptcha_enabled_logins|default:"0" != 1}{nocache}{include file="login/small.tpl"}{/nocache}{/if} \ No newline at end of file From 19a0945be24b668e2443b3afa51d534f908f29a3 Mon Sep 17 00:00:00 2001 From: xisi Date: Thu, 16 Jan 2014 07:57:52 -0500 Subject: [PATCH 02/47] no config version inc --- public/include/config/global.inc.dist.php | 2 +- public/include/version.inc.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/public/include/config/global.inc.dist.php b/public/include/config/global.inc.dist.php index 677a4619..7c9eebba 100644 --- a/public/include/config/global.inc.dist.php +++ b/public/include/config/global.inc.dist.php @@ -7,7 +7,7 @@ if (!defined('SECURITY')) die('Hacking attempt'); * This is used in the version check to ensure you run the latest version of the configuration file. * Once you upgraded your config, change the version here too. **/ -$config['version'] = '0.0.5'; +$config['version'] = '0.0.4'; // Our include directory for additional features define('INCLUDE_DIR', BASEPATH . 'include'); diff --git a/public/include/version.inc.php b/public/include/version.inc.php index e132eb5e..21dd0010 100644 --- a/public/include/version.inc.php +++ b/public/include/version.inc.php @@ -5,7 +5,7 @@ if (!defined('SECURITY')) die('Hacking attempt'); define('MPOS_VERSION', '0.0.2'); define('DB_VERSION', '0.0.3'); -define('CONFIG_VERSION', '0.0.5'); +define('CONFIG_VERSION', '0.0.4'); // Fetch installed database version $db_version = $setting->getValue('DB_VERSION'); From a56140ca8479307b78345feaeab74bd8a84a93e8 Mon Sep 17 00:00:00 2001 From: xisi Date: Thu, 16 Jan 2014 22:31:04 -0500 Subject: [PATCH 03/47] Moved csrftoken stuff into a class added getCurrentIP method to user class added config option for sitewide csrf protection --- public/include/autoloader.inc.php | 1 + public/include/classes/base.class.php | 3 ++ public/include/classes/csrftoken.class.php | 45 +++++++++++++++++++++ public/include/classes/user.class.php | 47 +++++++++++++--------- public/include/config/global.inc.dist.php | 7 +++- public/include/pages/home.inc.php | 2 +- public/include/pages/login.inc.php | 5 +-- 7 files changed, 85 insertions(+), 25 deletions(-) create mode 100644 public/include/classes/csrftoken.class.php diff --git a/public/include/autoloader.inc.php b/public/include/autoloader.inc.php index 1c8dba45..5bf2652f 100644 --- a/public/include/autoloader.inc.php +++ b/public/include/autoloader.inc.php @@ -53,6 +53,7 @@ require_once(CLASS_DIR . '/bitcoinwrapper.class.php'); require_once(CLASS_DIR . '/monitoring.class.php'); require_once(CLASS_DIR . '/notification.class.php'); require_once(CLASS_DIR . '/user.class.php'); +require_once(CLASS_DIR . '/csrftoken.class.php'); require_once(CLASS_DIR . '/invitation.class.php'); require_once(CLASS_DIR . '/share.class.php'); require_once(CLASS_DIR . '/worker.class.php'); diff --git a/public/include/classes/base.class.php b/public/include/classes/base.class.php index d3dd18c1..d8bb23bb 100644 --- a/public/include/classes/base.class.php +++ b/public/include/classes/base.class.php @@ -73,6 +73,9 @@ class Base { public function setTokenType($tokentype) { $this->tokentype = $tokentype; } + public function setCSRFToken($token) { + $this->CSRFToken = $token; + } public function setShare($share) { $this->share = $share; } diff --git a/public/include/classes/csrftoken.class.php b/public/include/classes/csrftoken.class.php new file mode 100644 index 00000000..e061e2e3 --- /dev/null +++ b/public/include/classes/csrftoken.class.php @@ -0,0 +1,45 @@ +salty; + $lead = $this->config['csrf']['options']['leadtime']; + if ($lead >= 11) { $lead = 10; } + if ($lead <= 0) { $lead = 3; } + if ($minute == 59 && $second > (60-$lead)) { + $minute = 0; + $fhour = ($hour == 23) ? $hour = 0 : $hour+=1; + } + $seed = $seed.$month.$day.$user.$type.$year.$hour.$minute.$seed; + return $this->getHash($seed); + } + + private function getHash($string) { + return hash('sha256', $this->salty.$string.$this->salt); + } +} + +$csrftoken = new CSRFToken(); +$csrftoken->setDebug($debug); +$csrftoken->setMysql($mysqli); +$csrftoken->setSalt(SALT); +$csrftoken->setSalty(SALTY); +$csrftoken->setMail($mail); +$csrftoken->setUser($user); +$csrftoken->setToken($oToken); +$csrftoken->setConfig($config); +$csrftoken->setErrorCodes($aErrorCodes); +?> \ No newline at end of file diff --git a/public/include/classes/user.class.php b/public/include/classes/user.class.php index 80cc346a..a9fe3f97 100644 --- a/public/include/classes/user.class.php +++ b/public/include/classes/user.class.php @@ -794,26 +794,36 @@ class User extends Base { } /** - * Gets the current CSRF token for this user/type setting and time chunk - * @param string User; for hash seed, if username isn't available use IP - * @param string Type of token; for hash seed, should be unique per page/use - * @return string CSRF token + * Convenience function to get IP address, no params is the same as REMOTE_ADDR + * @param trustremote bool must be FALSE to checkclient or checkforwarded + * @param checkclient bool check HTTP_CLIENT_IP for a valid ip first + * @param checkforwarded bool check HTTP_X_FORWARDED_FOR for a valid ip first + * @return string IP address */ - public function getCSRFToken($user, $type) { - $date = date('m/d/y/H/i/s'); - $data = explode('/', $date); - $month = $data[0]; $day = $data[1]; $year = $data[2]; - $hour = $data[3]; $minute = $data[4]; $second = $data[5]; - $seed = $this->salty; - $lead = $this->config['csrf']['options']['leadtime']; - if ($lead >= 11) { $lead = 10; } - if ($lead <= 0) { $lead = 3; } - if ($minute == 59 && $second > (60-$lead)) { - $minute = 0; - $fhour = ($hour == 23) ? $hour = 0 : $hour+=1; + public function getCurrentIP($trustremote=true, $checkclient=false, $checkforwarded=false) { + $client = (isset($_SERVER['HTTP_CLIENT_IP'])) ? $_SERVER['HTTP_CLIENT_IP'] : false; + $fwd = (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : false; + $remote = (isset($_SERVER['REMOTE_ADDR'])) ? $_SERVER['REMOTE_ADDR'] : @$_SERVER['REMOTE_ADDR']; + // shared internet + if (filter_var($client, FILTER_VALIDATE_IP) && !$trustremote && $checkclient) { + return $client; + } else if (strpos($fwd, ',') !== false && !$trustremote && $checkforwarded) { + // multiple proxies + $ips = explode(',', $fwd); + $path = array(); + foreach ($ips as $ip) { + if (filter_var($ip, FILTER_VALIDATE_IP)) { + $path[] = $ip; + } + } + return array_pop($path); + } else if (filter_var($fwd, FILTER_VALIDATE_IP) && !$trustremote && $checkforwarded) { + // single + return $fwd; + } else { + // as usual + return $remote; } - $seed = $seed.$month.$day.$user.$type.$year.$hour.$minute.$seed; - return $this->getHash($seed); } } @@ -822,7 +832,6 @@ $user = new User(); $user->setDebug($debug); $user->setMysql($mysqli); $user->setSalt(SALT); -$user->setSalty(SALTY); $user->setSmarty($smarty); $user->setConfig($config); $user->setMail($mail); diff --git a/public/include/config/global.inc.dist.php b/public/include/config/global.inc.dist.php index 7c9eebba..b5e1ef0d 100644 --- a/public/include/config/global.inc.dist.php +++ b/public/include/config/global.inc.dist.php @@ -135,15 +135,18 @@ $config['twofactor']['options']['changepw'] = true; * * Options: * enabled = Whether or not we will generate/check for valid CSRF tokens - * leadtime = Length of time in seconds to give as leeway, 1-10s - * login = Use and check CSRF tokens for the login forms + * sitewide = Require a valid CSRF token for all forms, does not override specific form settings + * leadtime = Length of time in seconds to give as leeway between minute switches + * login = Use and check login-specific CSRF token * * Default: * enabled = true + * sitewide = true * leadtime = 3 * login = true */ $config['csrf']['enabled'] = true; +$config['csrf']['sitewide'] = true; $config['csrf']['options']['leadtime'] = 3; $config['csrf']['forms']['login'] = true; diff --git a/public/include/pages/home.inc.php b/public/include/pages/home.inc.php index 4dffeb8a..861e24be 100644 --- a/public/include/pages/home.inc.php +++ b/public/include/pages/home.inc.php @@ -25,7 +25,7 @@ if (!$smarty->isCached('master.tpl', $smarty_cache_key)) { // csrf token - update if it's enabled $token = ''; if ($config['csrf']['enabled'] && $config['csrf']['forms']['login']) { - $token = $user->getCSRFToken($_SERVER['REMOTE_ADDR'], 'login'); + $token = $csrftoken->getBasic($user->getCurrentIP(), 'login'); } // Load news entries for Desktop site and unauthenticated users $smarty->assign("CONTENT", "default.tpl"); diff --git a/public/include/pages/login.inc.php b/public/include/pages/login.inc.php index 7e43ae5a..9442d10f 100644 --- a/public/include/pages/login.inc.php +++ b/public/include/pages/login.inc.php @@ -3,7 +3,6 @@ // Make sure we are called from index.php if (!defined('SECURITY')) die('Hacking attempt'); - // ReCaptcha handling if enabled if ($setting->getValue('recaptcha_enabled') && $setting->getValue('recaptcha_enabled_logins')) { require_once(INCLUDE_DIR . '/lib/recaptchalib.php'); @@ -37,7 +36,7 @@ if ($setting->getValue('maintenance') && !$user->isAdmin($user->getUserId($_POST } } if ($config['csrf']['enabled'] && $config['csrf']['forms']['login']) { - if ((isset($_POST['ctoken']) && $_POST['ctoken'] !== $user->getCSRFToken($_SERVER['REMOTE_ADDR'], 'login')) || (!isset($_POST['ctoken']))) { + if ((isset($_POST['ctoken']) && $_POST['ctoken'] !== $csrftoken->getBasic($user->getCurrentIP(), 'login')) || (!isset($_POST['ctoken']))) { // csrf protection is on and this token is invalid, error out -> time expired $nocsrf = 0; } @@ -61,7 +60,7 @@ if ($setting->getValue('maintenance') && !$user->isAdmin($user->getUserId($_POST // csrf token - update if it's enabled $token = ''; if ($config['csrf']['enabled'] && $config['csrf']['forms']['login']) { - $token = $user->getCSRFToken($_SERVER['REMOTE_ADDR'], 'login'); + $token = $csrftoken->getBasic($user->getCurrentIP(), 'login'); } // Load login template From 42d93f5bebb63cad8cb600a98246d8435151342b Mon Sep 17 00:00:00 2001 From: xisi Date: Thu, 16 Jan 2014 23:04:29 -0500 Subject: [PATCH 04/47] specific timing for csrf tokens --- public/include/classes/csrftoken.class.php | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/public/include/classes/csrftoken.class.php b/public/include/classes/csrftoken.class.php index e061e2e3..0f4f8820 100644 --- a/public/include/classes/csrftoken.class.php +++ b/public/include/classes/csrftoken.class.php @@ -6,16 +6,18 @@ if (!defined('SECURITY')) die('Hacking attempt'); class CSRFToken Extends Base { /** * Gets a basic CSRF token for this user/type and time chunk - * @param string User; for hash seed, if username isn't available use IP - * @param string Type of token; for hash seed, should be unique per page/use + * @param string user User; for hash seed, if username isn't available use IP + * @param string type Type of token; for hash seed, should be unique per page/use + * @param string timing Which date() chars we add to the seed; month day year hour minute default + * @param string seedExtra Extra information to add to the seed * @return string CSRF token */ - public function getBasic($user, $type) { + public function getBasic($user, $type, $timing='mdyHi', $seedExtra='') { $date = date('m/d/y/H/i/s'); $data = explode('/', $date); - $month = $data[0]; $day = $data[1]; $year = $data[2]; - $hour = $data[3]; $minute = $data[4]; $second = $data[5]; - $seed = $this->salty; + $month = $data[0]; $day = $data[1]; $year = $data[2]; + $hour = $data[3]; $minute = $data[4]; $second = $data[5]; + $salt1 = $this->salt; $salt2 = $this->salty; $seed = $salt1; $lead = $this->config['csrf']['options']['leadtime']; if ($lead >= 11) { $lead = 10; } if ($lead <= 0) { $lead = 3; } @@ -23,7 +25,13 @@ class CSRFToken Extends Base { $minute = 0; $fhour = ($hour == 23) ? $hour = 0 : $hour+=1; } - $seed = $seed.$month.$day.$user.$type.$year.$hour.$minute.$seed; + $seed.= (strpos($timing, 'm') !== false) ? $month : ''; + $seed.= (strpos($timing, 'd') !== false) ? $day : ''; + $seed.= (strpos($timing, 'y') !== false) ? $year : ''; + $seed.= (strpos($timing, 'H') !== false) ? $hour : ''; + $seed.= (strpos($timing, 'i') !== false) ? $minute : ''; + $seed.= (strpos($timing, 's') !== false) ? $second : ''; + $seed.= ($seedExtra !== '') ? $seedExtra.$salt2 : $salt2; return $this->getHash($seed); } From 6da551003576fc8fa736acd37759bbb3d4a28e92 Mon Sep 17 00:00:00 2001 From: xisi Date: Thu, 16 Jan 2014 23:19:25 -0500 Subject: [PATCH 05/47] clean up pages that use csrftokens --- public/include/classes/csrftoken.class.php | 2 +- public/include/pages/home.inc.php | 11 +++++------ public/include/pages/login.inc.php | 12 +++++------- public/include/pages/register.inc.php | 6 ++++++ 4 files changed, 17 insertions(+), 14 deletions(-) diff --git a/public/include/classes/csrftoken.class.php b/public/include/classes/csrftoken.class.php index 0f4f8820..6c32b8ca 100644 --- a/public/include/classes/csrftoken.class.php +++ b/public/include/classes/csrftoken.class.php @@ -8,7 +8,7 @@ class CSRFToken Extends Base { * Gets a basic CSRF token for this user/type and time chunk * @param string user User; for hash seed, if username isn't available use IP * @param string type Type of token; for hash seed, should be unique per page/use - * @param string timing Which date() chars we add to the seed; month day year hour minute default + * @param string timing Which date() chars we add to the seed; default month day year hour minute ie same minute only * @param string seedExtra Extra information to add to the seed * @return string CSRF token */ diff --git a/public/include/pages/home.inc.php b/public/include/pages/home.inc.php index 861e24be..85e550dc 100644 --- a/public/include/pages/home.inc.php +++ b/public/include/pages/home.inc.php @@ -22,12 +22,11 @@ if (!$smarty->isCached('master.tpl', $smarty_cache_key)) { } else { $debug->append('Using cached page', 3); } -// csrf token - update if it's enabled -$token = ''; -if ($config['csrf']['enabled'] && $config['csrf']['forms']['login']) { - $token = $csrftoken->getBasic($user->getCurrentIP(), 'login'); -} // Load news entries for Desktop site and unauthenticated users $smarty->assign("CONTENT", "default.tpl"); -$smarty->assign('CTOKEN', $token); +// csrf token +if ($config['csrf']['enabled'] && $config['csrf']['forms']['login']) { + $token = $csrftoken->getBasic($user->getCurrentIP(), 'login'); + $smarty->assign('CTOKEN', $token); +} ?> diff --git a/public/include/pages/login.inc.php b/public/include/pages/login.inc.php index 9442d10f..8559fa7d 100644 --- a/public/include/pages/login.inc.php +++ b/public/include/pages/login.inc.php @@ -57,13 +57,11 @@ if ($setting->getValue('maintenance') && !$user->isAdmin($user->getUserId($_POST $_SESSION['POPUP'][] = array('CONTENT' => "Login token expired, please try again $img", 'TYPE' => 'info'); } } -// csrf token - update if it's enabled -$token = ''; -if ($config['csrf']['enabled'] && $config['csrf']['forms']['login']) { - $token = $csrftoken->getBasic($user->getCurrentIP(), 'login'); -} - // Load login template $smarty->assign('CONTENT', 'default.tpl'); -$smarty->assign('CTOKEN', $token); +// csrf token +if ($config['csrf']['enabled'] && $config['csrf']['forms']['login']) { + $token = $csrftoken->getBasic($user->getCurrentIP(), 'login'); + $smarty->assign('CTOKEN', $token); +} ?> diff --git a/public/include/pages/register.inc.php b/public/include/pages/register.inc.php index 692c3e42..e05ffa7b 100644 --- a/public/include/pages/register.inc.php +++ b/public/include/pages/register.inc.php @@ -14,6 +14,12 @@ if ($setting->getValue('lock_registration') && $setting->getValue('disable_invit require_once(INCLUDE_DIR . '/lib/recaptchalib.php'); $smarty->assign("RECAPTCHA", recaptcha_get_html($setting->getValue('recaptcha_public_key'), null, true)); } + // Load news entries for Desktop site and unauthenticated users $smarty->assign("CONTENT", "default.tpl"); + // csrf token + if ($config['csrf']['enabled'] && $config['csrf']['forms']['register']) { + $token = $csrftoken->getBasic($user->getCurrentIP(), 'register'); + $smarty->assign('CTOKEN', $token); + } } ?> From 58529547e0d050648186d66523ce74fbddafbbe4 Mon Sep 17 00:00:00 2001 From: xisi Date: Thu, 16 Jan 2014 23:48:38 -0500 Subject: [PATCH 06/47] Cleaned up logic of login page csrf protection added csrf protection to register page --- public/include/config/global.inc.dist.php | 3 +++ public/include/pages/login.inc.php | 8 +++++--- public/include/pages/register.inc.php | 2 +- .../include/pages/register/register.inc.php | 19 +++++++++++++++++-- public/templates/mpos/register/default.tpl | 1 + 5 files changed, 27 insertions(+), 6 deletions(-) diff --git a/public/include/config/global.inc.dist.php b/public/include/config/global.inc.dist.php index b5e1ef0d..faf09b19 100644 --- a/public/include/config/global.inc.dist.php +++ b/public/include/config/global.inc.dist.php @@ -138,17 +138,20 @@ $config['twofactor']['options']['changepw'] = true; * sitewide = Require a valid CSRF token for all forms, does not override specific form settings * leadtime = Length of time in seconds to give as leeway between minute switches * login = Use and check login-specific CSRF token + * register = Use and check register-specific CSRF token * * Default: * enabled = true * sitewide = true * leadtime = 3 * login = true + * register = true */ $config['csrf']['enabled'] = true; $config['csrf']['sitewide'] = true; $config['csrf']['options']['leadtime'] = 3; $config['csrf']['forms']['login'] = true; +$config['csrf']['forms']['register'] = true; /** * Lock account after maximum failed logins diff --git a/public/include/pages/login.inc.php b/public/include/pages/login.inc.php index 8559fa7d..57005c7d 100644 --- a/public/include/pages/login.inc.php +++ b/public/include/pages/login.inc.php @@ -21,6 +21,11 @@ if ($setting->getValue('recaptcha_enabled') && $setting->getValue('recaptcha_ena } } +// csrf if enabled +if ($config['csrf']['enabled'] && $config['csrf']['forms']['login']) { + $nocsrf = ($csrftoken->getBasic($user->getCurrentIP(), 'login') == @$_POST['ctoken']) ? 1 : 0; +} + if ($setting->getValue('maintenance') && !$user->isAdmin($user->getUserId($_POST['username']))) { $_SESSION['POPUP'][] = array('CONTENT' => 'You are not allowed to login during maintenace.', 'TYPE' => 'info'); } else if (!empty($_POST['username']) && !empty($_POST['password'])) { @@ -52,9 +57,6 @@ if ($setting->getValue('maintenance') && !$user->isAdmin($user->getUserId($_POST } else { $_SESSION['POPUP'][] = array('CONTENT' => 'Unable to login: '. $user->getError(), 'TYPE' => 'errormsg'); } - } else if ($nocsrf == 0) { - $img = ""; - $_SESSION['POPUP'][] = array('CONTENT' => "Login token expired, please try again $img", 'TYPE' => 'info'); } } // Load login template diff --git a/public/include/pages/register.inc.php b/public/include/pages/register.inc.php index e05ffa7b..4ae62a6a 100644 --- a/public/include/pages/register.inc.php +++ b/public/include/pages/register.inc.php @@ -18,7 +18,7 @@ if ($setting->getValue('lock_registration') && $setting->getValue('disable_invit $smarty->assign("CONTENT", "default.tpl"); // csrf token if ($config['csrf']['enabled'] && $config['csrf']['forms']['register']) { - $token = $csrftoken->getBasic($user->getCurrentIP(), 'register'); + $token = $csrftoken->getBasic($user->getCurrentIP(), 'register', 'mdyH'); $smarty->assign('CTOKEN', $token); } } diff --git a/public/include/pages/register/register.inc.php b/public/include/pages/register/register.inc.php index 7090a1c4..30f088ec 100644 --- a/public/include/pages/register/register.inc.php +++ b/public/include/pages/register/register.inc.php @@ -14,6 +14,12 @@ if ($setting->getValue('recaptcha_enabled') && $setting->getValue('recaptcha_ena ); $smarty->assign("RECAPTCHA", recaptcha_get_html($setting->getValue('recaptcha_public_key'), $rsp->error, true)); if (!$rsp->is_valid) $_SESSION['POPUP'][] = array('CONTENT' => 'Invalid Captcha, please try again.', 'TYPE' => 'errormsg'); + $recaptcha = ($rsp->isvalid) ? 1 : 0; +} + +// csrf if enabled +if ($config['csrf']['enabled'] && $config['csrf']['forms']['register']) { + $nocsrf = ($csrftoken->getBasic($user->getCurrentIP(), 'register', 'mdyH') == $_POST['ctoken']) ? 1 : 0; } if ($setting->getValue('disable_invitations') && $setting->getValue('lock_registration')) { @@ -21,8 +27,12 @@ if ($setting->getValue('disable_invitations') && $setting->getValue('lock_regist } else if ($setting->getValue('lock_registration') && !$setting->getValue('disable_invitations') && !isset($_POST['token'])) { $_SESSION['POPUP'][] = array('CONTENT' => 'Only invited users are allowed to register.', 'TYPE' => 'errormsg'); } else { - // Check if recaptcha is enabled, process form data if valid or disabled - if ($setting->getValue('recaptcha_enabled') != 1 || $setting->getValue('recaptcha_enabled_registrations') != 1 || $rsp->is_valid) { + // Check if csrf is enabled and fail if token is invalid + if (!$nocsrf && $config['csrf']['enabled'] && $config['csrf']['forms']['register']) { + $img = ""; + $_SESSION['POPUP'][] = array('CONTENT' => "Register token expired, please try again $img", 'TYPE' => 'info'); + } else if ($setting->getValue('recaptcha_enabled') != 1 || $setting->getValue('recaptcha_enabled_registrations') != 1 || $rsp->is_valid) { + // Check if recaptcha is enabled, process form data if valid or disabled isset($_POST['token']) ? $token = $_POST['token'] : $token = ''; if ($user->register(@$_POST['username'], @$_POST['password1'], @$_POST['password2'], @$_POST['pin'], @$_POST['email1'], @$_POST['email2'], @$_POST['tac'], $token)) { ! $setting->getValue('accounts_confirm_email_disabled') ? $_SESSION['POPUP'][] = array('CONTENT' => 'Please check your mailbox to activate this account') : $_SESSION['POPUP'][] = array('CONTENT' => 'Account created, please login'); @@ -34,4 +44,9 @@ if ($setting->getValue('disable_invitations') && $setting->getValue('lock_regist // We load the default registration template instead of an action specific one $smarty->assign("CONTENT", "../default.tpl"); +// csrf token +if ($config['csrf']['enabled'] && $config['csrf']['forms']['register']) { + $token = $csrftoken->getBasic($user->getCurrentIP(), 'register', 'mdyH'); + $smarty->assign('CTOKEN', $token); +} ?> diff --git a/public/templates/mpos/register/default.tpl b/public/templates/mpos/register/default.tpl index d60f2209..2eb2b984 100644 --- a/public/templates/mpos/register/default.tpl +++ b/public/templates/mpos/register/default.tpl @@ -7,6 +7,7 @@ {if $smarty.request.token|default:""} {/if} +{if $GLOBAL.csrf.enabled && $GLOBAL.csrf.forms.register}{/if}
From d83542e03e93fbd9d5b5fcd5f588997d6cb6389c Mon Sep 17 00:00:00 2001 From: xisi Date: Fri, 17 Jan 2014 01:15:28 -0500 Subject: [PATCH 07/47] Added method to get description image of csrf token with name moved sitewide into options portion of the config option csrf protection for contact form under sitewide config option changed register to 1 hour token --- public/include/classes/csrftoken.class.php | 13 +++++++ public/include/config/global.inc.dist.php | 4 +- public/include/pages/contactform.inc.php | 6 ++- .../pages/contactform/contactform.inc.php | 38 ++++++++++++++----- .../include/pages/register/register.inc.php | 2 +- .../mpos/contactform/contactform/default.tpl | 31 ++++++++++++++- public/templates/mpos/contactform/default.tpl | 1 + 7 files changed, 81 insertions(+), 14 deletions(-) diff --git a/public/include/classes/csrftoken.class.php b/public/include/classes/csrftoken.class.php index 6c32b8ca..21e8b5f7 100644 --- a/public/include/classes/csrftoken.class.php +++ b/public/include/classes/csrftoken.class.php @@ -35,6 +35,19 @@ class CSRFToken Extends Base { return $this->getHash($seed); } + /** + * + * @param unknown $dowhat + * @return string + */ + public static function getDescriptionImageHTML($dowhat="try") { + $string = "salty.$string.$this->salt); } diff --git a/public/include/config/global.inc.dist.php b/public/include/config/global.inc.dist.php index faf09b19..3b7562c9 100644 --- a/public/include/config/global.inc.dist.php +++ b/public/include/config/global.inc.dist.php @@ -135,7 +135,7 @@ $config['twofactor']['options']['changepw'] = true; * * Options: * enabled = Whether or not we will generate/check for valid CSRF tokens - * sitewide = Require a valid CSRF token for all forms, does not override specific form settings + * sitewide = Require a valid CSRF token for all forms, does not override form specific settings * leadtime = Length of time in seconds to give as leeway between minute switches * login = Use and check login-specific CSRF token * register = Use and check register-specific CSRF token @@ -148,7 +148,7 @@ $config['twofactor']['options']['changepw'] = true; * register = true */ $config['csrf']['enabled'] = true; -$config['csrf']['sitewide'] = true; +$config['csrf']['options']['sitewide'] = true; $config['csrf']['options']['leadtime'] = 3; $config['csrf']['forms']['login'] = true; $config['csrf']['forms']['register'] = true; diff --git a/public/include/pages/contactform.inc.php b/public/include/pages/contactform.inc.php index ad4a54c7..9b46c4db 100644 --- a/public/include/pages/contactform.inc.php +++ b/public/include/pages/contactform.inc.php @@ -14,7 +14,11 @@ if ($setting->getValue('disable_contactform')) { require_once(INCLUDE_DIR . '/lib/recaptchalib.php'); $smarty->assign("RECAPTCHA", recaptcha_get_html($setting->getValue('recaptcha_public_key'))); } - + // csrf token + if ($config['csrf']['enabled'] && $config['csrf']['options']['sitewide']) { + $token = $csrftoken->getBasic($user->getCurrentIP(), 'contact'); + $smarty->assign('CTOKEN', $token); + } // Tempalte specifics $smarty->assign("CONTENT", "default.tpl"); } diff --git a/public/include/pages/contactform/contactform.inc.php b/public/include/pages/contactform/contactform.inc.php index 28425bfd..5fadba39 100644 --- a/public/include/pages/contactform/contactform.inc.php +++ b/public/include/pages/contactform/contactform.inc.php @@ -15,19 +15,31 @@ if ($setting->getValue('recaptcha_enabled')) { ); } +// csrf if enabled +if ($config['csrf']['enabled'] && $config['csrf']['options']['sitewide']) { + $nocsrf = ($csrftoken->getBasic($user->getCurrentIP(), 'contact', 'mdyH') == $_POST['ctoken']) ? 1 : 0; +} + if ($setting->getValue('disable_contactform')) { $_SESSION['POPUP'][] = array('CONTENT' => 'Contactform is currently disabled. Please try again later.', 'TYPE' => 'errormsg'); } else if ($setting->getValue('disable_contactform') && !$user->isAuthenticated(false)) { $_SESSION['POPUP'][] = array('CONTENT' => 'Contactform is disabled for guests.', 'TYPE' => 'errormsg'); } else { - // Check if recaptcha is enabled, process form data if valid - if($setting->getValue('recaptcha_enabled') && $_POST["recaptcha_response_field"] && $_POST["recaptcha_response_field"]!=''){ + if ($setting->getValue('recaptcha_enabled') && $_POST["recaptcha_response_field"] && $_POST["recaptcha_response_field"]!=''){ + // Check if recaptcha is enabled, process form data if valid if ($rsp->is_valid) { - $smarty->assign("RECAPTCHA", recaptcha_get_html($setting->getValue('recaptcha_public_key'))); - if ($mail->contactform($_POST['senderName'], $_POST['senderEmail'], $_POST['senderSubject'], $_POST['senderMessage'])) { - $_SESSION['POPUP'][] = array('CONTENT' => 'Thanks for sending your message! We will get back to you shortly'); + // Check if csrf is enabled and fail if token is invalid + if (!$nocsrf && $config['csrf']['enabled'] && $config['csrf']['forms']['register']) { + $img = $csrftoken->getDescriptionImageHTML(); + $_SESSION['POPUP'][] = array('CONTENT' => "Contact token expired, please try again $img", 'TYPE' => 'info'); } else { - $_SESSION['POPUP'][] = array('CONTENT' => 'There was a problem sending your message. Please try again.' . $user->getError(), 'TYPE' => 'errormsg'); + // csrf is valid or disabled, send + $smarty->assign("RECAPTCHA", recaptcha_get_html($setting->getValue('recaptcha_public_key'))); + if ($mail->contactform($_POST['senderName'], $_POST['senderEmail'], $_POST['senderSubject'], $_POST['senderMessage'])) { + $_SESSION['POPUP'][] = array('CONTENT' => 'Thanks for sending your message! We will get back to you shortly'); + } else { + $_SESSION['POPUP'][] = array('CONTENT' => 'There was a problem sending your message. Please try again.' . $user->getError(), 'TYPE' => 'errormsg'); + } } } else { $smarty->assign("RECAPTCHA", recaptcha_get_html($setting->getValue('recaptcha_public_key'), $rsp->error)); @@ -39,9 +51,13 @@ if ($setting->getValue('disable_contactform')) { $_SESSION['POPUP'][] = array('CONTENT' => 'Empty Captcha, please try again.', 'TYPE' => 'errormsg'); // Captcha disabled } else { - if ($mail->contactform($_POST['senderName'], $_POST['senderEmail'], $_POST['senderSubject'], $_POST['senderMessage'])) { + // Check if csrf is enabled and fail if token is invalid + if (!$nocsrf && $config['csrf']['enabled'] && $config['csrf']['options']['sitewide']) { + $img = $csrftoken->getDescriptionImageHTML(); + $_SESSION['POPUP'][] = array('CONTENT' => "Contact token expired, please try again $img", 'TYPE' => 'info'); + } else if ($mail->contactform($_POST['senderName'], $_POST['senderEmail'], $_POST['senderSubject'], $_POST['senderMessage'])) { $_SESSION['POPUP'][] = array('CONTENT' => 'Thanks for sending your message! We will get back to you shortly'); - } else { + } else { $_SESSION['POPUP'][] = array('CONTENT' => 'There was a problem sending your message. Please try again. ' . $user->getError(), 'TYPE' => 'errormsg'); } } @@ -49,5 +65,9 @@ if ($setting->getValue('disable_contactform')) { // Tempalte specifics $smarty->assign("CONTENT", "default.tpl"); - +// csrf token +if ($config['csrf']['enabled'] && $config['csrf']['options']['sitewide']) { + $token = $csrftoken->getBasic($user->getCurrentIP(), 'contact', 'mdyH'); + $smarty->assign('CTOKEN', $token); +} ?> diff --git a/public/include/pages/register/register.inc.php b/public/include/pages/register/register.inc.php index 30f088ec..cb262546 100644 --- a/public/include/pages/register/register.inc.php +++ b/public/include/pages/register/register.inc.php @@ -29,7 +29,7 @@ if ($setting->getValue('disable_invitations') && $setting->getValue('lock_regist } else { // Check if csrf is enabled and fail if token is invalid if (!$nocsrf && $config['csrf']['enabled'] && $config['csrf']['forms']['register']) { - $img = ""; + $img = $csrftoken->getDescriptionImageHTML('register'); $_SESSION['POPUP'][] = array('CONTENT' => "Register token expired, please try again $img", 'TYPE' => 'info'); } else if ($setting->getValue('recaptcha_enabled') != 1 || $setting->getValue('recaptcha_enabled_registrations') != 1 || $rsp->is_valid) { // Check if recaptcha is enabled, process form data if valid or disabled diff --git a/public/templates/mpos/contactform/contactform/default.tpl b/public/templates/mpos/contactform/contactform/default.tpl index 8b137891..8e4785c2 100644 --- a/public/templates/mpos/contactform/contactform/default.tpl +++ b/public/templates/mpos/contactform/contactform/default.tpl @@ -1 +1,30 @@ - +
+ + + {if $GLOBAL.csrf.enabled && $GLOBAL.csrf.options.sitewide}{/if} +
+

Contact Us

+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
{nocache}{$RECAPTCHA|default:""}{/nocache}
+
+
+ +
+
+
diff --git a/public/templates/mpos/contactform/default.tpl b/public/templates/mpos/contactform/default.tpl index a086e69b..ee4ef607 100644 --- a/public/templates/mpos/contactform/default.tpl +++ b/public/templates/mpos/contactform/default.tpl @@ -1,6 +1,7 @@
+ {if $GLOBAL.csrf.enabled && $GLOBAL.csrf.options.sitewide}{/if}

Contact Us

From 9ccb5e15bc2383c30e160b0fd3a71b84e6b14acb Mon Sep 17 00:00:00 2001 From: xisi Date: Fri, 17 Jan 2014 01:45:08 -0500 Subject: [PATCH 08/47] refactored old token usage in account edit page --- public/include/classes/csrftoken.class.php | 7 ++--- public/include/pages/account/edit.inc.php | 30 +++++++--------------- 2 files changed, 13 insertions(+), 24 deletions(-) diff --git a/public/include/classes/csrftoken.class.php b/public/include/classes/csrftoken.class.php index 21e8b5f7..380b78cc 100644 --- a/public/include/classes/csrftoken.class.php +++ b/public/include/classes/csrftoken.class.php @@ -36,9 +36,10 @@ class CSRFToken Extends Base { } /** - * - * @param unknown $dowhat - * @return string + * Gets the HTML image (?) with short csrf description for users for the incorrect + * token error message + * @param dowhat string What will be put in the string "Simply $dowhat again to..." + * @return string HTML image with description */ public static function getDescriptionImageHTML($dowhat="try") { $string = "isAuthenticated()) { if ($config['twofactor']['enabled']) { @@ -136,14 +128,10 @@ if ($user->isAuthenticated()) { } // 2fa - one last time so we can sync with changes we made during this page if ($user->isAuthenticated() && $config['twofactor']['enabled']) { - // set the token to be the old token so we still have it if it errors out - if ($old_token_type == 5) { - $ea_token = $old_token; - } else if ($old_token_type == 7) { - $wf_token = $old_token; - } else if ($old_token_type == 6) { - $cp_token = $old_token; - } + // set the token to be the old token, just in case an error occured + $ea_token = ($oldtoken_ea !== '') ? $oldtoken_ea : $ea_token; + $wf_token = ($oldtoken_wf !== '') ? $oldtoken_wf : $wf_token; + $cp_token = ($oldtoken_cp !== '') ? $oldtoken_cp : $cp_token; if ($config['twofactor']['options']['details']) { $ea_editable = $user->token->isTokenValid($_SESSION['USERDATA']['id'], $ea_token, 5); $ea_sent = $user->token->doesTokenExist('account_edit', $_SESSION['USERDATA']['id']); From e5c97201741671a45bae2334eec49739c7495f59 Mon Sep 17 00:00:00 2001 From: xisi Date: Fri, 17 Jan 2014 03:11:14 -0500 Subject: [PATCH 09/47] Finished cleanup of account edit page added csrf protection to account edit page under sitewide config escaped all instances of CTOKEN for csrf in smarty templates --- public/include/pages/account/edit.inc.php | 122 +++++++++++------- .../templates/mpos/account/edit/default.tpl | 4 + .../mpos/contactform/contactform/default.tpl | 2 +- public/templates/mpos/contactform/default.tpl | 2 +- public/templates/mpos/login/default.tpl | 2 +- public/templates/mpos/login/small.tpl | 18 +++ public/templates/mpos/register/default.tpl | 2 +- 7 files changed, 104 insertions(+), 48 deletions(-) create mode 100644 public/templates/mpos/login/small.tpl diff --git a/public/include/pages/account/edit.inc.php b/public/include/pages/account/edit.inc.php index caa148e0..5d1d305d 100644 --- a/public/include/pages/account/edit.inc.php +++ b/public/include/pages/account/edit.inc.php @@ -6,14 +6,19 @@ if (!defined('SECURITY')) // twofactor stuff $cp_editable = $wf_editable = $ea_editable = $wf_sent = $ea_sent = $cp_sent = 0; -$ea_token = (!isset($_POST['ea_token'])) ? '' : $_POST['ea_token']; -$cp_token = (!isset($_POST['cp_token'])) ? '' : $_POST['cp_token']; -$wf_token = (!isset($_POST['wf_token'])) ? '' : $_POST['wf_token']; -// set old token so we can use it if an error happens -$oldtoken_ea = ($ea_token !== '') ? $ea_token : ''; -$oldtoken_wf = ($wf_token !== '') ? $wf_token : ''; -$oldtoken_cp = ($cp_token !== '') ? $cp_token : ''; +// 2fa - set old token so we can use it if an error happens or we need to use post +$oldtoken_ea = (isset($_POST['ea_token']) && $_POST['ea_token'] !== '') ? $_POST['ea_token'] : ''; +$oldtoken_cp = (isset($_POST['cp_token']) && $_POST['cp_token'] !== '') ? $_POST['cp_token'] : ''; +$oldtoken_wf = (isset($_POST['wf_token']) && $_POST['wf_token'] !== '') ? $_POST['wf_token'] : ''; +$updating = (@$_POST['do']) ? 1 : 0; + +// csrf stuff +$csrfenabled = ($config['csrf']['enabled'] && $config['csrf']['options']['sitewide']) ? 1 : 0; +if ($csrfenabled) { + $nocsrf = ($csrftoken->getBasic($user->getCurrentIP(), 'editaccount', 'mdyH') == @$_POST['ctoken']) ? 1 : 0; + $csrfvalid = 0; +} if ($user->isAuthenticated()) { if ($config['twofactor']['enabled']) { @@ -21,17 +26,17 @@ if ($user->isAuthenticated()) { $popuptypes = array(); if ($config['twofactor']['options']['details']) { $popuptypes[] = 'editing your details'; - $ea_editable = $user->token->isTokenValid($_SESSION['USERDATA']['id'], $ea_token, 5); + $ea_editable = $user->token->isTokenValid($_SESSION['USERDATA']['id'], $oldtoken_ea, 5); $ea_sent = $user->token->doesTokenExist('account_edit', $_SESSION['USERDATA']['id']); } if ($config['twofactor']['options']['changepw']) { $popuptypes[] = 'changing your password'; - $cp_editable = $user->token->isTokenValid($_SESSION['USERDATA']['id'], $cp_token, 6); + $cp_editable = $user->token->isTokenValid($_SESSION['USERDATA']['id'], $oldtoken_cp, 6); $cp_sent = $user->token->doesTokenExist('change_pw', $_SESSION['USERDATA']['id']); } if ($config['twofactor']['options']['withdraw']) { $popuptypes[] = 'withdrawals'; - $wf_editable = $user->token->isTokenValid($_SESSION['USERDATA']['id'], $wf_token, 7); + $wf_editable = $user->token->isTokenValid($_SESSION['USERDATA']['id'], $oldtoken_wf, 7); $wf_sent = $user->token->doesTokenExist('withdraw_funds', $_SESSION['USERDATA']['id']); } $ptc = 0; @@ -47,11 +52,22 @@ if ($user->isAuthenticated()) { } $_SESSION['POPUP'][] = array('CONTENT' => $popupmsg, 'TYPE' => 'info'); } + + // if csrf is enabled sitewide check this token + if ($csrfenabled) { + $csrfvalid = ($nocsrf && $csrfenabled) ? 1 : 0; + } + if (isset($_POST['do']) && $_POST['do'] == 'genPin') { - if ($user->generatePin($_SESSION['USERDATA']['id'], $_POST['currentPassword'])) { - $_SESSION['POPUP'][] = array('CONTENT' => 'Your PIN # has been sent to your email.', 'TYPE' => 'success'); + if (!$csrfenabled || $csrfenabled && $csrfvalid) { + if ($user->generatePin($_SESSION['USERDATA']['id'], $_POST['currentPassword'])) { + $_SESSION['POPUP'][] = array('CONTENT' => 'Your PIN # has been sent to your email.', 'TYPE' => 'success'); + } else { + $_SESSION['POPUP'][] = array('CONTENT' => $user->getError(), 'TYPE' => 'errormsg'); + } } else { - $_SESSION['POPUP'][] = array('CONTENT' => $user->getError(), 'TYPE' => 'errormsg'); + $img = $csrftoken->getDescriptionImageHTML(); + $_SESSION['POPUP'][] = array('CONTENT' => "Edit account token expired, please try again $img", 'TYPE' => 'info'); } } else { @@ -63,25 +79,23 @@ if ($user->isAuthenticated()) { $isvalid = in_array($_POST['utype'],$validtypes); if ($isvalid) { $ctype = strip_tags($_POST['utype']); - $send = $user->sendChangeConfigEmail($ctype, $_SESSION['USERDATA']['id']); - if ($send) { - $_SESSION['POPUP'][] = array('CONTENT' => 'A confirmation was sent to your e-mail, follow that link to continue', 'TYPE' => 'success'); + if (!$csrfenabled || $csrfenabled && $csrfvalid) { + $send = $user->sendChangeConfigEmail($ctype, $_SESSION['USERDATA']['id']); + if ($send) { + $_SESSION['POPUP'][] = array('CONTENT' => 'A confirmation was sent to your e-mail, follow that link to continue', 'TYPE' => 'success'); + } else { + $_SESSION['POPUP'][] = array('CONTENT' => $user->getError(), 'TYPE' => 'errormsg'); + } } else { - $_SESSION['POPUP'][] = array('CONTENT' => $user->getError(), 'TYPE' => 'errormsg'); + $img = $csrftoken->getDescriptionImageHTML(); + $_SESSION['POPUP'][] = array('CONTENT' => "Edit account token expired, please try again $img", 'TYPE' => 'info'); } } } else { - // back to get, was only post to fix for old token - $ea_token = (!isset($_GET['ea_token'])) ? '' : $_GET['ea_token']; - $cp_token = (!isset($_GET['cp_token'])) ? '' : $_GET['cp_token']; - $wf_token = (!isset($_GET['wf_token'])) ? '' : $_GET['wf_token']; - if ($ea_token == '' && isset($_POST['ea_token']) && strlen($_POST['ea_token']) > 1) { - $ea_token = $_POST['ea_token']; - } else if ($ea_token == '' && isset($_POST['cp_token']) && strlen($_POST['cp_token']) > 1) { - $cp_token = $_POST['cp_token']; - } else if ($wf_token == '' && isset($_POST['wf_token']) && strlen($_POST['wf_token']) > 1) { - $wf_token = $_POST['wf_token']; - } + // 2fa - when submitting we want the old token, otherwise we'll take what we can $_GET ... B^) + $ea_token = $updating ? $oldtoken_ea : @$_GET['ea_token']; + $wf_token = $updating ? $oldtoken_wf : @$_GET['wf_token']; + $cp_token = $updating ? $oldtoken_cp : @$_GET['cp_token']; switch (@$_POST['do']) { case 'cashOut': @@ -92,10 +106,15 @@ if ($user->isAuthenticated()) { $dBalance = $aBalance['confirmed']; if ($dBalance > $config['txfee']) { if (!$oPayout->isPayoutActive($_SESSION['USERDATA']['id'])) { - if ($iPayoutId = $oPayout->createPayout($_SESSION['USERDATA']['id'], $wf_token)) { - $_SESSION['POPUP'][] = array('CONTENT' => 'Created new manual payout request with ID #' . $iPayoutId); + if (!$csrfenabled || $csrfenabled && $csrfvalid) { + if ($iPayoutId = $oPayout->createPayout($_SESSION['USERDATA']['id'], $wf_token)) { + $_SESSION['POPUP'][] = array('CONTENT' => 'Created new manual payout request with ID #' . $iPayoutId); + } else { + $_SESSION['POPUP'][] = array('CONTENT' => $iPayoutId->getError(), 'TYPE' => 'errormsg'); + } } else { - $_SESSION['POPUP'][] = array('CONTENT' => $iPayoutId->getError(), 'TYPE' => 'errormsg'); + $img = $csrftoken->getDescriptionImageHTML(); + $_SESSION['POPUP'][] = array('CONTENT' => "Edit account token expired, please try again $img", 'TYPE' => 'info'); } } else { $_SESSION['POPUP'][] = array('CONTENT' => 'You already have one active manual payout request.', 'TYPE' => 'errormsg'); @@ -107,19 +126,29 @@ if ($user->isAuthenticated()) { break; case 'updateAccount': - if ($user->updateAccount($_SESSION['USERDATA']['id'], $_POST['paymentAddress'], $_POST['payoutThreshold'], $_POST['donatePercent'], $_POST['email'], $_POST['is_anonymous'], $ea_token)) { - $_SESSION['POPUP'][] = array('CONTENT' => 'Account details updated', 'TYPE' => 'success'); - } else { - $_SESSION['POPUP'][] = array('CONTENT' => 'Failed to update your account: ' . $user->getError(), 'TYPE' => 'errormsg'); - } + if (!$csrfenabled || $csrfenabled && $csrfvalid) { + if ($user->updateAccount($_SESSION['USERDATA']['id'], $_POST['paymentAddress'], $_POST['payoutThreshold'], $_POST['donatePercent'], $_POST['email'], $_POST['is_anonymous'], $ea_token)) { + $_SESSION['POPUP'][] = array('CONTENT' => 'Account details updated', 'TYPE' => 'success'); + } else { + $_SESSION['POPUP'][] = array('CONTENT' => 'Failed to update your account: ' . $user->getError(), 'TYPE' => 'errormsg'); + } + } else { + $img = $csrftoken->getDescriptionImageHTML(); + $_SESSION['POPUP'][] = array('CONTENT' => "Edit account token expired, please try again $img", 'TYPE' => 'info'); + } break; case 'updatePassword': - if ($user->updatePassword($_SESSION['USERDATA']['id'], $_POST['currentPassword'], $_POST['newPassword'], $_POST['newPassword2'], $cp_token)) { - $_SESSION['POPUP'][] = array('CONTENT' => 'Password updated', 'TYPE' => 'success'); - } else { - $_SESSION['POPUP'][] = array('CONTENT' => $user->getError(), 'TYPE' => 'errormsg'); - } + if (!$csrfenabled || $csrfenabled && $csrfvalid) { + if ($user->updatePassword($_SESSION['USERDATA']['id'], $_POST['currentPassword'], $_POST['newPassword'], $_POST['newPassword2'], $cp_token)) { + $_SESSION['POPUP'][] = array('CONTENT' => 'Password updated', 'TYPE' => 'success'); + } else { + $_SESSION['POPUP'][] = array('CONTENT' => $user->getError(), 'TYPE' => 'errormsg'); + } + } else { + $img = $csrftoken->getDescriptionImageHTML(); + $_SESSION['POPUP'][] = array('CONTENT' => "Edit account token expired, please try again $img", 'TYPE' => 'info'); + } break; } } @@ -129,9 +158,9 @@ if ($user->isAuthenticated()) { // 2fa - one last time so we can sync with changes we made during this page if ($user->isAuthenticated() && $config['twofactor']['enabled']) { // set the token to be the old token, just in case an error occured - $ea_token = ($oldtoken_ea !== '') ? $oldtoken_ea : $ea_token; - $wf_token = ($oldtoken_wf !== '') ? $oldtoken_wf : $wf_token; - $cp_token = ($oldtoken_cp !== '') ? $oldtoken_cp : $cp_token; + $ea_token = ($oldtoken_ea !== '') ? $oldtoken_ea : @$ea_token; + $wf_token = ($oldtoken_wf !== '') ? $oldtoken_wf : @$wf_token; + $cp_token = ($oldtoken_cp !== '') ? $oldtoken_cp : @$cp_token; if ($config['twofactor']['options']['details']) { $ea_editable = $user->token->isTokenValid($_SESSION['USERDATA']['id'], $ea_token, 5); $ea_sent = $user->token->doesTokenExist('account_edit', $_SESSION['USERDATA']['id']); @@ -153,4 +182,9 @@ $smarty->assign("DETAILSUNLOCKED", $ea_editable); $smarty->assign("CHANGEPASSSENT", $cp_sent); $smarty->assign("WITHDRAWSENT", $wf_sent); $smarty->assign("DETAILSSENT", $ea_sent); +// csrf token +if ($config['csrf']['enabled'] && $config['csrf']['options']['sitewide']) { + $token = $csrftoken->getBasic($user->getCurrentIP(), 'editaccount', 'mdyH'); + $smarty->assign('CTOKEN', $token); +} ?> diff --git a/public/templates/mpos/account/edit/default.tpl b/public/templates/mpos/account/edit/default.tpl index 4e5c779b..174b3745 100644 --- a/public/templates/mpos/account/edit/default.tpl +++ b/public/templates/mpos/account/edit/default.tpl @@ -56,6 +56,7 @@