CSRF Protection

Hi all! Who knows how can I protect all forms (~10 forms) on page of CSRF? I already tried to set hidden input:

{{ form.render('csrf', ['value': security.getToken()]) }}

in form builder class:

// CSRF
$csrf = new Hidden('csrf');
$csrf->addValidator(
    new Identical(array(
        'value' => $this->security->getSessionToken(),
        'message' => $t->form->post->csrf
    ))
);

But it's always validating as false. I have 3 suggestions: 1. I should start session in some BaseController, but I don't know how to do it.. Help plz! 2. Every form have an unique value="...", but server side stores only last token... So on one page all forms protected from CSRF will fails except of last form. (I hope that's not true.)

Any suggestions?

Hi! Thanks for your answer, have one more question can I use all of this but without form builder??

Huh! That's not so obivous, that what I need this line: ```php if ($this->request->isPost()) { ``` to validate the token, even route to action is already declared as addPost(...) ;)

edited Oct '14

PFFFFFFFFFFFFF I need your help again! I did exaclty the same like in that chapter. I developing app like a forum, on one page I have a 10 themes on page and under each theme I have a form called "Quick post" each of this form protected from CSRF. And when I testing it, answering in many themes on one page, my token is invalidates very often.

Action that handles adding post request

public function addAction($boardAbbr)
    {
        if ($this->request->isPost()) {
            if ($this->security->checkToken()) {

              ..................

               if (!$post->save()) {
                    foreach ($post->getMessages() as $message)
                    $this->flash->error((string) $message);

                } else {
                    if ($this->request->isAjax()) {
                        echo json_encode(array(
                            'status' => true,
                            'message' => 'post added.',
                            'data' => array(
                                'post_id' => $post->id,
                                'pictures' => explode('|', $names)
                            )
                        ));
                    }
                    else {
                        $this->flashSession->success('post added.');
                        $this->response->redirect('#post-'.$post->id);
                    }
                }
            } else { echo 'token is bad.'; }

In form:

<input type="hidden" name="{{ security.getTokenKey() }}" value="{{ security.getToken() }}">

Token invalidates from time to time ..... What can I do??

Get the CSRF tokens in the controller through the Security and assign it to the view.

<?php
class AccountController extends BaseController
{
    public function indexAction()
    {
        $this->view->setVars([
            'tokenKey' => $this->security->getTokenKey(),
            'token' => $this->security->getToken()
        ]);
    }
}

Then My view I re-used the variable:

<form method="post" action="{{ url('account/doEmailUpdate') }}">
    <input type="text" name="email" class="form-control" placeholder="Email address" autofocus>
    <input type="text" name="confirm_email" class="form-control" placeholder="Confirm">
    <input type="hidden" name="{{ tokenKey }}" value="{{ token }}" />
    <input class="btn btn-lg btn-primary btn-block" type="submit" value="Submit">
</form>
<form method="post" action="{{ url('account/doPasswordUpdate') }}">
    <input type="text" name="password" class="form-control" placeholder="New Password">
    <input type="text" name="confirm_password" class="form-control" placeholder="Confirm">
    <input type="hidden" name="{{ tokenKey }}" value="{{ token }}" />
    <input class="btn btn-lg btn-primary btn-block" type="submit" value="Submit">
</form>


1.7k

Thank you for this advice. Actually, to manage token for form security, I found 2 things important:

  • First One: if you want to add a form using getToken() from IndexController, you will have a problem as getToken() will be called each time, so that the csrf checking will fail. My solution; create a HomeController and setup default controller at home

  • Second One: if you have more than one form for same action/controller, if each form call getToken(), you will have 2 different tokens. So the last form will work but not the first one Jesse solution solve this problem.

I learn Phalcon/csrf with Vokuro sample and I'm not sure this the best way as it's not dealing with form in index page or multi-form on same page

Sorry for my english, I hope that'll help

I know the problem is solved but there is an easier way too,

if you see checkToken method defenition:

public boolean checkToken ([string $tokenKey], [string $tokenValue])

it gets input parameters so you just need to define unique key for each form and when you want to check token, pass both key and the value to checkToken method.

For pages that have more than one form you can use the same token for all forms. You are protecting the page and all form(s) from cross site attacks. Protecting multiple forms individually has no advantage.

Thank you for this advice. Actually, to manage token for form security, I found 2 things important:

  • First One: if you want to add a form using getToken() from IndexController, you will have a problem as getToken() will be called each time, so that the csrf checking will fail. My solution; create a HomeController and setup default controller at home

  • Second One: if you have more than one form for same action/controller, if each form call getToken(), you will have 2 different tokens. So the last form will work but not the first one Jesse solution solve this problem.

I learn Phalcon/csrf with Vokuro sample and I'm not sure this the best way as it's not dealing with form in index page or multi-form on same page

Sorry for my english, I hope that'll help



4.5k

I had a problem getting the check for the token to work on a login form and i could solve it using your method.

$token    = $this->request->getPost('csrf');

if($this->security->checkToken( $token, $this->security->getSessionToken()) ) {

}