好的,我有一个函数:newCSRF($ formID);生成一个我在表单中调用的CSRF令牌。像这样
if(){
echo "<some html form>". newCSRF("login-form")."<rest of html>";
}
在同一个index.php页面上还有另一种形式
if(){
echo "<some html form>". newCSRF("register-form")."<rest of html>";
}
那些csrf令牌应该是不同的(我已经检查过newCSRF()没有错。但它们不是...... 为了证明它应该工作,如果我把它们写成:
echo "<some html form>"; echo newCSRF("register-form"); echo "<rest of html>";
它的工作非常出色。我的第一次拼写有什么问题?我不喜欢第二个,这对我来说似乎很奇怪。
编辑添加了newCSRF():
function newCSRF($formId)
{
$c_ip = $_SERVER['REMOTE_ADDR']; //gets the client IPv4 address
//generates a unique security token, randString has been added beacuse of dupes when refresh spamming.
//$csrf = dechex(crc32($c_ip."".$formId."".time()."".randString(16)));
$csrf = hash("crc32", $c_ip + $formId + time() + randString(16));
try
{
$pdo_options[PDO::ATTR_ERRMODE] = PDO::ERRMODE_EXCEPTION;
//connecting to the sql server
$bdd = new PDO('mysql:host='.DB_HOST.';dbname='.DB_NAME, DB_USER, DB_PASSWORD, $pdo_options);
$a = $bdd->prepare('INSERT INTO csrf (form_id, client_ip, token, expire) VALUES(:form, :ip, :csrf, :expi)');
$a->execute(array(
'form' => ichar($formId),
'ip' => $c_ip,
'csrf' => $csrf,
'expi' => time() + 1800)); //CSRF token remains valid for 15 min.
$bdd = null;
log_write("New CSRF token successfuly created", 0, false);
}
catch (PDOException $e)
{
log_write("Error occured when creating new CSRF token", 3, false);
log_write("in File: " . __FILE__ . " on line: " . __LINE__ . " : " . $e->getMessage(), 3, false);
$bdd = null;
exit(1);
}
return $csrf;
}
答案 0 :(得分:1)
这里有几个因素在于你获得相同价值的原因。首先,您对newCSRF()
的所有通话都可能足够接近,当您在每个通话中调用time()
时,您获得的值相同。其次,虽然你没有在这里显示它的内容,但我的猜测是randString()
返回(顾名思义)一个文本字符串。由于您正在进行数学加法而不是连接,因此来自$formId
和randString(16)
的文本字符串在从每个调用获取不同值方面确实无效。由于time()
在两次调用中都是相同的,因此整个计算在每个调用中在数学上是等效的。
通过切换到连接,$formId
和randString(16)
实际上都会发挥作用,time()
相同的事实不会成为问题。每次调用newCSRF()
时,您都会得到不同的结果(假设$formId
不同)。
简而言之,解决方案是将$c_ip + $formId + time() + randString(16)
更改为$c_ip . $formId . time() . randString(16)