從而在並未受權的狀況下執行在權限保護之下的操做,有很大的危害性。php
php CSRF Guard
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);
if ($token===false)
{
return false;
}
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']) or !isset($_POST['CSRFToken']) )
{
trigger_error("No CSRFName found, probable invalid request.",E_USER_ERROR);
}
$name =$_POST['CSRFName'];
$token=$_POST['CSRFToken'];
if (!csrfguard_validate_token($name, $token))
{
trigger_error("Invalid CSRF token.",E_USER_ERROR);
}
}
ob_start();
/* adding double quotes for "csrfguard_inject" to prevent:
Notice: Use of undefined constant csrfguard_inject - assumed 'csrfguard_inject' */
register_shutdown_function("csrfguard_inject");
}
csrfguard_start(2881064151);html
前三個功能,是一個抽象的概念如何會話變量存儲。若是你不使用PHP會話更換。生成功能,建立一個隨機的安全一次性CSRF令牌。若是SHA512是可用的,它被使用,不然產生一個512位的隨機字符串在同一格式。這個功能也將生成一個惟一的名稱下的令牌在會話變量。驗證功能,檢查惟一名下的令牌。有三步:
會話不主動:驗證成功(沒有CSRF風險)
會話發現但不相同,或令牌不發現:驗證失敗
會話發現相同:驗證成功
任何狀況下,該函數刪除會話令牌,確保一例
替換功能,接收HTML數據的一部分,發現全部<form>事件並添加了兩個隱藏域他們:csrfname和csrftoken。若是任何這些形式有一個屬性或值nocsrf」,除了不會被執行(注意,使用默認的注入,這個檢測時間)。
其餘兩個函數,將開始是一個演示如何使用其餘功能。使用輸出緩衝對你的整個輸出不推薦(有些圖書館可能轉儲輸出緩衝)。這種默認行爲,執行CSRF令牌全部形式使用POST方法。它是假定沒有任何敏感的操做方法是在應用程序獲得執行,由RFC 2616要求
爲了測試這些代碼,添加如下HTML吧:
<form method='post'>
<input type='text' name='test' value='<?php echo "testing"?>' />
<input type='submit' />
</form>
<form class='nocsrf'>
</form>安全