【问题标题】:PHP CSRF Token code. Sufficient security?PHP CSRF 令牌代码。足够的安全性?
【发布时间】:2011-10-24 21:25:27
【问题描述】:

最近尽我所能保护我的网站免受 XSS 攻击,我现在正在保护我的网站免受 CSRF 攻击,观看并阅读了一些关于此事的文章,我创建了以下代码。

我想知道我的实现是否正确,在数据库中使用字符串来帮助安全。我应该做不同的事情吗?我应该检查两边的数据库吗???

代码:

if(!isset($_SESSION['register_token'])){

  $keytype = 'register';

  $getregisterkey = mysql_query("SELECT key FROM tokenkeys WHERE type='".$keytype."' ") or die(mysql_error()); 
  while ($row = mysql_fetch_array($getregisterkey))
  {
$registerkey = mysql_real_escape_string($row['key']);
  }; 


  $_SESSION['register_token']=sha1(uniqid(rand(), TRUE).$registerkey);
  $_SESSION['register_token_time']=time();
}

<input type="hidden" name="token" value="<?php echo $_SESSION['register_token'];?>" />



if($_POST['register_token']==$_SESSION['register_token']){
  $register_token_age=time()-$_SESSION['register_token_time'];
  if($register_token_age=>300){

    //process form
  } else{
    //valid token but expired
  }
} else{
  die('Access Forbidden')

}

【问题讨论】:

  • 为什么要转义 sql 查询的输出?你知道 mysql_real_escape_string 甚至是做什么的吗?

标签: php sql security csrf


【解决方案1】:

XSRF 令牌仅与发送页面的通道一样安全。在此表单上使用 https 并且仅使用 https,并且仅将其提交到 https 端点。否则,MITM 可以在提供或提交表单时从表单中获取您的 XSRF 令牌。

while ($row = mysql_fetch_array($getregisterkey))
{
    $registerkey = mysql_real_escape_string($row['key']);
}; 

当行数为零时永远不会执行,这样你以后不会从$getregisterkey 获得太多熵

$_SESSION['register_token']=sha1(uniqid(rand(), TRUE).$registerkey);

所以如果返回零行,我会确保您的实现快速失败。也许更改为if ($row = mysql_fetch_array(...)) { ... } else { /* abort */ },因为您不会从额外的行中受益。

rand() 必须是真正随机的或 cryptographically strong PRNG。

我不熟悉 PHP 的标准库,但 [wikipedia] 建议 rand() 在密码学上不强。 wikipedia

有建议为 PHP 添加强随机数生成。

Strong cryptography in PHP 建议使用openssl_random_pseudo_bytes()

不要使用 rand() 或 mt_rand()

要在 PHP 中生成强加密随机数,您必须使用 OpenSSL 库的函数 openssl_random_pseudo_bytes()

如果您使用弱随机性,那么攻击者可以观察您生成的数字(通过请求表单的多个版本并解析隐藏的输入)并使用它来确定下一个数字可能是什么并伪造 CSRF 令牌。

如果攻击者修改了'register_token_time' 会话属性,那么他们可以避免您的 XSRF 检查。

例如,如果您有一个页面,

$_SESSION[$_POST['x']] = $_POST['y'];

然后攻击者可以 POST

x=register_token&y=pwnd

替换存储在会话中的register_token,然后用

发送帖子
token=pwnd

并绕过您的 XSRF 保护。

【讨论】:

  • 考虑到您的回答,我应该删除数据库连接还是以其他方式实现它? $_SESSION[$attackerControlledInput] = ... 我应该添加其他内容吗?
  • @user1002916,请查看我的编辑。我试图澄清这两个部分。
  • 我不明白你的意思。如果会话 id 因 owasp a9 违规而泄露,那么您不需要使用 CSRF,您已经拥有整个会话,没有必要继续使用它。它是鸡还是鸡蛋。
  • 另外,不是会话固定,而是会话变量名称空间的平衡。会话固定是指攻击者创建一个新的会话 ID 并欺骗用户使用该 ID 进行身份验证。这应该通过您的 php.ini 配置来防止。
  • @Rook,我认为您对“会话固定”的看法是正确的。我认为我从来没有谈论过会话泄漏,只是攻击者预测 CSRF 令牌的能力。当您谈论“如果会话 id 被泄露...”时,您能否引用您所指的文字?
猜你喜欢
  • 2015-08-17
  • 2023-03-23
  • 1970-01-01
  • 2016-08-12
  • 1970-01-01
  • 2021-04-14
  • 1970-01-01
  • 1970-01-01
  • 2017-10-27
相关资源
最近更新 更多