macoutinho
Posts: 1
|
Posted: 11/02/2012, 7:07 AM |
|
I needed to put in some CSRF protection code on my CCS project. I found OWASP's PHP CSRF Guard https://www.owasp.org/index.php/PHP_CSRF_Guard and wanted to use it but their directions weren't terribly straightforward. I would appreciate anyone's comments on how I implemented it and if I could do it better. I tried to find a section of the common.php that would hit every page rather than coding it in each of the 200+ pages I have in the site.
The code adds two tokens to every form on my project that looks like this:
<input type="hidden" value="CSRFGuard_780758828" name="CSRFName"> <input type="hidden" value="93eeca9e815ff6841659de701871c44c3e199fd48c168c8806d30a8a39043cda471add53b3259ec3df5f2c80c5cbe39ffb6d5a1c863f1238da1e218241d4f32f" name="CSRFToken">
The token is stored as a php session variable and displayed on the page.When the form is processed, if the token has changed, it fails and generally blows up.
Here is how I did it:
On Common.php where it is initializing common variables I added this line right after session_start(); line 48.
session_start();
On Common.php I added these lines at the end:
function store_in_session($key,$value)
{
if (isset($_SESSION))
{
$_SESSION[$key]=$value;
}
}
function unset_session($key)
{
$_SESSION[$key]=hash("sha512",mt_rand(0,mt_getrandmax()));
unset($_SESSION[$key]);
}
function get_from_session($key)
{
if (isset($_SESSION))
{
return $_SESSION[$key];
}
else { return false; } //no session data, no CSRF risk
}
function csrfguard_generate_token($unique_form_name)
{
//if (function_exists("hash_algos") and in_array("sha512",hash_algos()))
//{
$token=hash("sha512",mt_rand(0,mt_getrandmax()));
//}
//else
//{
// $token=for ($i=0;$i<128;++$i)
// {
// $r=mt_rand(0,35);
// if ($r<26)
// {
// $c=chr(ord('a')+$r);
// }
// else
// {
// $c=chr(ord('0')+$r-26);
// }
// $token.=$c;
// }
//}
store_in_session($unique_form_name,$token);
return $token;
}
function csrfguard_validate_token($unique_form_name,$token_value)
{
$token=get_from_session($unique_form_name);
echo $token;
if ($token===false)
{
return true;
}
elseif ($token==$token_value)
{
$result=true;
}
else
{
$result=false;
}
unset_session($unique_form_name);
return $result;
}
function csrfguard_replace_forms($form_data_html)
{
$count=preg_match_all("/<form(.*?)>(.*?)<\\/form>/is",$form_data_html,$matches,PREG_SET_ORDER);
if (is_array($matches))
{
foreach ($matches as $m)
{
if (strpos($m[1],"nocsrf")!==false) { continue; }
$name="CSRFGuard_".mt_rand(0,mt_getrandmax());
$token=csrfguard_generate_token($name);
$form_data_html=str_replace($m[0],
"<form{$m[1]}>
<input type='hidden' name='CSRFName' value='{$name}' />
<input type='hidden' name='CSRFToken' value='{$token}' />{$m[2]}</form>",$form_data_html);
}
}
return $form_data_html;
}
function csrfguard_inject()
{
$data=ob_get_clean();
$data=csrfguard_replace_forms($data);
echo $data;
}
function csrfguard_start()
{
if (count($_POST))
{
if (!isset($_POST['CSRFName']))
{
trigger_error("No CSRFName found, probable invalid request.",E_USER_ERROR);
exit();
}
$name =$_POST['CSRFName'];
$token=$_POST['CSRFToken'];
if (!csrfguard_validate_token($name, $token))
{
trigger_error("Invalid token.",E_USER_ERROR);
exit();
}
}
ob_start();
register_shutdown_function('csrfguard_inject');
}
|