CSRF protection revisited
November 27, 2008 – 11:11 am Tags: PHP, Zend FrameworkYesterday, I was talking on IRC with Tom Graham. He was looking for a way to protect GET requests against CSRF. I showed him my CSRF protection plugin, as it would be suitable for protecting GETs too with minor modifications.
This got me thinking what would be the best way to allow you to easily protect certain URLs with it, and here’s the solution…
The dynamic duo
One pattern in Zend Framework apps seems to be that often there is a controller plugin, and an action helper, which exposes the controller plugin’s functionality for easy usage in action controllers.
This is the case here as well:
- An updated version of the CsrfProtect plugin, and
- A new Csrf action helper
I’ve modified the CsrfProtect plugin to accomodate the usage in the helper. The helper is completely new, and has methods that you can use in actions to get the CSRF token and check the validity of values in tokens.
Usage
The plugin’s usage is exactly the same as before, so refer to the csrf plugin post for help on that.
Using the action helper is quite simple.
First, we have the initial action and its view:
public function firstAction()
{
//Assign a token to the view
$this->view->token = $this->_helper->csrf->getToken();
}
//The view:
<a href="secondAction?token=<?= $this->token; ?>">Go to secondAction</a>And in the second action…
public function secondAction() { //This action is linked from the view in firstAction, and we want to confirm the token: $token = $this->getRequest()->getQuery('token'); if(!$this->_helper->csrf->isValidToken($token)) throw new Exception('CSRF Token validation failed'); }
Using the helper, you can easily utilize the automatic token generation and all that of the CSRF protection plugin. And it isn’t only limited to GETs either – you could pass the token from the helper to cookies or anything you’d like.

6 Responses to “CSRF protection revisited”
A while ago i implemented a similar solution to protect actions from csrf that also works for GET requests. I’m sorry it’s in german, but i guess you get the code :>
http://octavian.supersized.org/archives/17-CSRF-Protection-Updated.html
By Marc Jakubowski on Nov 27, 2008
Damn it Jani, you stole my blog post. Too quick for me
You implemented it almost exactly the same as me though, bar a few differences in class/method names.
The one thing I did do differently was to assign a token to the view from a controller plugin as I needed it for every action (when the user was signed in to append to the sign out link).
Good work!
By Tom Graham on Nov 27, 2008
Great minds think alike
By Jani Hartikainen on Nov 27, 2008
Hey I like that.
You can also use output_add_rewrite_var() to automaticaly add the token as a variable in each page
By jpauli on Dec 1, 2008
Maybe you should consider adding this method to avoid Token reinit on some action:
in plugin:
public function setPreviousToken() {
$this->_token = $this->_previousToken;
$this->_session->key = $this->_previousToken;
}
in helper:
public function setPreviousToken()
{
return $this->getPlugin()->setPreviousToken();
}
if you use an action for image displaying (for exemple), token will be reinitilized so your token will not math anymore.
use this in your action to avoid this behavior :
$this->helper->csrf->setPreviousToken();
By cursed on Feb 13, 2009