[eluser]Jelmer[/eluser]
WARNING: I won't delete the post because that'll make the replies useless, but I didn't fully understand CSRF when I wrote this. HTTP_REFERER writing is possible through a CSRF attack when done with old Flash versions for instance, so the solution below is useless.
I wrote a very simple CSRF protection library for myself yesterday which does what every other one does: generate a key and submit it through the session and through a post or get variable and check if both match.
However it got me thinking about a different approach to this problem, by using
$_SERVER['HTTP_REFERER'] and check it against a list of permitted URI's. While I know that any
HTTP_* variable in
$_SERVER is to be considered unsafe - a CSRF attack wouldn't have access to the HTTP headers would it?
If that's true an implementation like below should be safe:
Code:
$this->load->library('csrf_protect');
$allowed_uri = array('certain_page', 'another/page');
if (! $this->csrf_protect->allowed($allowed_uris)) exit('Possible CSRF attack!');
The library would look like this
(the code is untested):
Code:
class csrf_protect
{
var $ci;
function csrf_protect()
{
$this->ci =& get_instance();
$this->ci->load->helper('url');
}
function allowed($uris)
{
if (! is_array($uris)) $uris = array($uris);
foreach($uris as $uri)
{
if (site_url($uri) == $_SERVER['HTTP_REFERER']) return true;
}
// if nothing was returned yet, it's not allowed
return false;
}
function domain_refer()
{
if (preg_match('/^'.addslashes(substr(site_url(), 0, -1)).'/', $_SERVER['HTTP_REFERER']))
return true;
else
return false;
}
}
Any thoughts on the security of this?
EDIT
To further clarify: Of course this is ONLY meant as protection against CSRF attacks using an already validated user session of my own. I know it won't protect against any other attacks.