Skip to content
Permalink
Browse files Browse the repository at this point in the history
Added CSRF prevention
  • Loading branch information
sah-comp committed Sep 28, 2020
1 parent b9bf163 commit d7836a4
Show file tree
Hide file tree
Showing 12 changed files with 281 additions and 198 deletions.
5 changes: 4 additions & 1 deletion app/res/tpl/account/changepassword.php
Expand Up @@ -21,7 +21,10 @@
class="panel panel-<?php echo $record->getMeta('type') ?> action-changepassword"
method="POST"
accept-charset="utf-8"
enctype="multipart/form-data">
enctype="multipart/form-data">

<input type="hidden" name="token" value="<?php echo Model::getCSRFToken() ?>" />

<!-- changepassword form -->
<fieldset>
<legend><?php echo I18n::__('account_legend_changepassword') ?></legend>
Expand Down
5 changes: 4 additions & 1 deletion app/res/tpl/account/index.php
Expand Up @@ -22,14 +22,17 @@ class="panel panel-<?php echo $record->getMeta('type') ?> action-profile"
method="POST"
accept-charset="utf-8"
enctype="multipart/form-data">

<input type="hidden" name="token" value="<?php echo Model::getCSRFToken() ?>" />

<div>
<img
src="<?php echo Gravatar::src($record->email, 72) ?>"
class="gravatar-account circular no-shadow"
width="72"
height="72"
alt="<?php echo htmlspecialchars($record->getName()) ?>" />
</div>
</div>
<!-- account form -->
<fieldset>
<legend><?php echo I18n::__('account_legend') ?></legend>
Expand Down
3 changes: 3 additions & 0 deletions app/res/tpl/account/login.php
Expand Up @@ -29,6 +29,9 @@ class="notification">
class="panel login"
method="POST"
accept-charset="utf-8">

<input type="hidden" name="token" value="<?php echo Model::getCSRFToken() ?>" />

<div>
<input type="hidden" name="dialog[type]" value="<?php echo $record->getMeta('type') ?>" />
<input type="hidden" name="dialog[id]" value="<?php echo $record->getId() ?>" />
Expand Down
3 changes: 3 additions & 0 deletions app/res/tpl/account/lostpassword.php
Expand Up @@ -29,6 +29,9 @@ class="notification">
class="panel lostpassword"
method="POST"
accept-charset="utf-8">

<input type="hidden" name="token" value="<?php echo Model::getCSRFToken() ?>" />

<fieldset>
<legend><?php echo I18n::__('lostpassword_legend') ?></legend>
<div
Expand Down
3 changes: 3 additions & 0 deletions app/res/tpl/admin/index.php
Expand Up @@ -19,6 +19,9 @@ class="panel panel-<?php echo $record->getMeta('type') ?> action-edit"
method="POST"
accept-charset="utf-8"
enctype="multipart/form-data">

<input type="hidden" name="token" value="<?php echo Model::getCSRFToken() ?>" />

<?php echo $form_details ?>
<div class="buttons">
<input
Expand Down
6 changes: 4 additions & 2 deletions app/res/tpl/scaffold/form.php
Expand Up @@ -22,11 +22,13 @@ class="panel panel-<?php echo $record->getMeta('type') ?> action-<?php echo $cur
method="POST"
accept-charset="utf-8"
enctype="multipart/form-data">


<input type="hidden" name="token" value="<?php echo Model::getCSRFToken() ?>" />

<!-- form details -->
<?php echo $form_details ?>
<!-- end of form details -->

<!-- Scaffold buttons -->
<div class="buttons">
<select name="next_action">
Expand Down
47 changes: 25 additions & 22 deletions src/Controller/Account.php
Expand Up @@ -35,22 +35,24 @@ public function index()
session_start();
Auth::check();
$this->template = 'account/index';

if (Flight::request()->method == 'POST') {
if (! Model::validateCSRFToken(Flight::request()->data->token)) {
$this->redirect("/logout");
}
Flight::get('user')->import(Flight::request()->data->dialog);
try {
R::store(Flight::get('user'));
Flight::get('user')->notify(I18n::__('account_edit_success'), 'success');
$this->redirect('/account/');
}
catch (Exception $e) {
} catch (Exception $e) {
Flight::get('user')->notify(I18n::__('account_edit_failure'), 'error');
}
}
}

$this->render();
}

/**
* Displays a page to change the password.
*
Expand All @@ -62,8 +64,11 @@ public function changepassword()
session_start();
Auth::check();
$this->template = 'account/changepassword';

if (Flight::request()->method == 'POST') {
if (! Model::validateCSRFToken(Flight::request()->data->token)) {
$this->redirect("/logout");
}
if (Flight::get('user')->changePassword(
Flight::request()->data->pw,
Flight::request()->data->pw_new,
Expand All @@ -73,35 +78,33 @@ public function changepassword()
R::store(Flight::get('user'));
Flight::get('user')->notify(I18n::__('account_changepassword_success'), 'success');
$this->redirect('/account/');
}
catch (Exception $e) {
} catch (Exception $e) {
//Whoops, what nu?
}
}
else {
} else {
Flight::get('user')->notify(I18n::__('account_changepassword_failure'), 'error');
}
}
}

$this->render();
}

/**
* Renders the account page.
*/
protected function render()
{
Flight::render('shared/notification', array(), 'notification');
//
Flight::render('shared/notification', array(), 'notification');
//
Flight::render('shared/navigation/account', array(), 'navigation_account');
Flight::render('shared/navigation/main', array(), 'navigation_main');
Flight::render('shared/navigation/main', array(), 'navigation_main');
Flight::render('shared/navigation', array(), 'navigation');
Flight::render('account/toolbar', array(), 'toolbar');
Flight::render('shared/header', array(), 'header');
Flight::render('shared/footer', array(), 'footer');
Flight::render($this->template, array(
'record' => Flight::get('user')
), 'content');
Flight::render('shared/header', array(), 'header');
Flight::render('shared/footer', array(), 'footer');
Flight::render($this->template, array(
'record' => Flight::get('user')
), 'content');
Flight::render('html5', array(
'title' => I18n::__("account_head_title"),
'language' => Flight::get('language')
Expand Down
9 changes: 6 additions & 3 deletions src/Controller/Login.php
Expand Up @@ -33,13 +33,16 @@ class Controller_Login extends Controller
public function index()
{
session_start();
if ( ! isset($_SESSION['login_id'])) {
if (! isset($_SESSION['login_id'])) {
$_SESSION['login_id'] = 0;
}
$login = R::load('login', $_SESSION['login_id']);
if (Flight::request()->method == 'POST') {
if (! Model::validateCSRFToken(Flight::request()->data->token)) {
$this->redirect("/logout");
}
try {
$login = R::graph( Flight::request()->data->dialog, TRUE );
$login = R::graph(Flight::request()->data->dialog, true);
if ($login->trial()) {
//you must trial before store because of pw reset in update
$_SESSION['user']['id'] = $login->user->getId();
Expand All @@ -56,7 +59,7 @@ public function index()
}
}
// either no yet submitted or the credentials given failed
if ( Flight::request()->query->goto == '' || Flight::request()->query->goto == '/login' ) {
if (Flight::request()->query->goto == '' || Flight::request()->query->goto == '/login') {
$goto = '/cms';
} else {
$goto = Flight::request()->query->goto;
Expand Down
23 changes: 13 additions & 10 deletions src/Controller/Lostpassword.php
Expand Up @@ -23,12 +23,12 @@ class Controller_Lostpassword extends Controller
* @var string
*/
public $template = 'account/lostpassword';

/**
* Holds the username entered by the password seeking party.
*/
public $uname = '';

/**
* May hold a message (textile) to the user that want to re-enter a password.
*/
Expand All @@ -43,28 +43,31 @@ class Controller_Lostpassword extends Controller
public function index()
{
if (Flight::request()->method == 'POST') {
if (! Model::validateCSRFToken(Flight::request()->data->token)) {
$this->redirect("/logout");
}
$this->uname = Flight::request()->data->dialog['uname'];
if ( ! $user = R::findOne('user', ' email = ? LIMIT 1 ', array($this->uname))) {
if (! $user = R::findOne('user', ' email = ? LIMIT 1 ', array($this->uname))) {
$this->message = I18n::__('lostpassword_user_unknown');
} elseif ( ! $user->requestPassword()) {
} elseif (! $user->requestPassword()) {
$this->message = I18n::__('lostpassword_email_failed');
} else {
$this->redirect('login');
}
}

$this->render();
}

/**
* Renders the lostpassword page.
*/
protected function render()
{
Flight::render($this->template, array(
'uname' => $this->uname,
'message' => $this->message
), 'content');
Flight::render($this->template, array(
'uname' => $this->uname,
'message' => $this->message
), 'content');
Flight::render('html5', array(
'title' => I18n::__("lostpassword_head_title"),
'language' => Flight::get('language'),
Expand Down
9 changes: 9 additions & 0 deletions src/Controller/Scaffold.php
Expand Up @@ -488,6 +488,9 @@ public function index($layout, $page, $order, $dir)
//$this->template = "model/{$this->type}/{$this->layout}";
$this->template = "scaffold/{$this->layout}";
if (Flight::request()->method == 'POST') {
if (! Model::validateCSRFToken(Flight::request()->data->token)) {
$this->redirect("/logout");
}
//clear filter?
if (Flight::request()->data->submit == I18n::__('filter_submit_clear')) {
R::trash($this->filter);
Expand Down Expand Up @@ -559,6 +562,9 @@ public function add($layout)
}
}
if (Flight::request()->method == 'POST') {
if (! Model::validateCSRFToken(Flight::request()->data->token)) {
$this->redirect("/logout");
}
$this->record = R::graph(Flight::request()->data->dialog, true);
$this->setNextAction(Flight::request()->data->next_action);
if ($this->doRedbeanAction()) {
Expand Down Expand Up @@ -605,6 +611,9 @@ public function edit($page, $order, $dir, $layout)
$this->template = "scaffold/edit";
}
if (Flight::request()->method == 'POST') {
if (! Model::validateCSRFToken(Flight::request()->data->token)) {
$this->redirect("/logout");
}
Permission::check(Flight::get('user'), $this->type, 'edit');//check for edit perm now
$this->record = R::graph(Flight::request()->data->dialog, true);
$this->setNextAction(Flight::request()->data->next_action);
Expand Down
33 changes: 33 additions & 0 deletions src/Model.php
Expand Up @@ -87,6 +87,39 @@ public function __construct()
{
}

/**
* Returns a "random" string to prevent CSRF.
*
* @return string
*/
public static function getCSRFToken()
{
@session_start();
if (empty($_SESSION['csrf_tokens'])) {
$_SESSION['csrf_tokens'] = [];
}
$nonce = md5(uniqid(rand(), true));
$_SESSION['csrf_tokens'][$nonce] = true;
return $nonce;
}

/**
* Returns wether the CSRF token validates or not.
*
* @param string $token
* @return bool
*/
public static function validateCSRFToken($token)
{
@session_start();
if (isset($_SESSION['csrf_tokens'][$token])) {
unset($_SESSION['csrf_tokens'][$token]);
error_log('Good user');
return true;
}
return false;
}

/**
* Returns an array with attributes for lists.
*
Expand Down

0 comments on commit d7836a4

Please sign in to comment.