Php – Form keys (CSRF) in CakePHP

cakephpcsrfPHP

I have seen in some MVC applications the use of Token keys to prevent CSRF. A typical example of where it may be used is on the delete method for a post.

And I've seen implementations using both GET and POST methods.

An example GET request link with a token:

https://domain.com/posts/G7j/delete/EOwFwC4TIIydMVUHMXZZdkbUR0cluRSkFzecQy3m5pMTYVXRkcFIBWUZYLNUNSNgQKdnpTWu

And an example of a POST request with a token:

<form action="/posts/G7j/delete" method="post">
    <input type="hidden" name="token" value="EOwFwC4TIIydMVUHMXZZdkbUR0cluRSkFzecQy3m5pMTYVXRkcFIBWUZYLNUNSNgQKdnpTWu" />
    <button type="submit">Delete</button>
</form>

I've been looking into implementing this into my CakePHP applications based on the documents: http://book.cakephp.org/2.0/en/core-libraries/components/security-component.html

And according to the documents, adding the Security component auto adds the form key to all forms that use the Form Helper.

e.g.

public $components = array(
    'Security' => array(
        'csrfExpires' => '+1 hour'
    )
);

However I have some questions:

1.) Why use POST over GET for some actions such as delete? As the request in the controller will check if the user is authenticated, has permission, and that it has the correct form key.

2.) How can I use the security component with a GET request in CakePHP? Presume I would also need to handle the routing as well.

Best Answer

Firstly CakePHP uses post links to delete as an added level of security because lets say for example your authentication system is not 100% secure and users can access a delete method by manually typing in a URL - if I go in and type /users/delete/10 , I can actually delete users on your server which is risky as you can imagine.

Secondarily GET requests can be cached or bookmarked so users who bookmark these links could end up navigating to broken links which is never a good thing ,also sensitive data will be visible in the URL so for example if someone bookmarks a login page with the GET variables intact - this could compromise there security.

Finally you can easily generate your own tokens using the following code :

$string = Security::hash('string', 'sha1 or md5', true);
print $this->Html->link("Link to somewhere",array("controller"=>"users","action"=>"delete",$string));

The above will use the salt key setup in your core config file but you can also replace true with a custom salt.