0

首先是一些背景。
我一直在使用 nonce 令牌以wordpress允许将操作附加到 nonce 的相同方式签署我的表单数据:

// editing post id:10
$post_id = 10;
$nonce = create_nonce( 'edit-post-'.$post_id );
echo '<input type="hidden" name="post_id" value="'.$post_id.'">';
echo '<input type="hidden" name="nonce" value="'.$nonce.'">';

这允许我稍后检查用户是否正在编辑我授予他权限的帖子,因为我重建了随机数并检查我收到的随机数是否与我构建的相同:

$server_nonce = create_nonce( 'edit-post-'.$_POST['post_id'] );
if( $server_nonce != $_POST['nonce'] )
{
    echo 'bad guy...';
}

到目前为止,我将此方法误解为一种反 CSRF 令牌,它为我提供了 CSRF 保护。
当我深入研究 CSRF 问题时,我发现这个解决方案并不能 100% 保护我免受 CSRF 的影响,因为:

  1. 可以使用接收到的数据在服务器中重建随机数。CSRF 不能重建。
  2. 对于窗口时间的表单,nonce 标记将是相同的。CSRF 在每个请求中都必须是唯一的。

所以,这是我的问题:

可以在一个表单中使用两个令牌来保护 CSRF 和数据签名吗?有没有办法将这两个令牌结合起来?

4

1 回答 1

1

通常,nonce 需要保存在服务器端的某个地方。如果您在验证时重新生成随机数,这意味着随机数是基于输入的可预测值。这是非常没用的,因为这是一个静态值。这不是一个随机数

随机数应该工作的方式是:

  1. 构造表单
  2. 生成一个随机值,即 nonce
  3. 将 nonce 保存在 session 中并将其放在表单中的隐藏字段中
  4. 提交表单后,检查提交的随机数是否与会话中的随机数相对应

其他任何东西都只是action+post-id的校验和,这没什么用。

You can easily extend this proper nonce procedure with a checksum of the to-be-submitted fields, by taking the name of all expected fields and other expected static values and adding a hash of them to the session as well. E.g.:

sha1(join(',', array('first_name', 'last_name', $nonce)))

Upon form submission, get all received field names and generate the same hash again and check if it's identical to the one in the session. If not, somebody tampered with the form.

于 2012-10-24T15:25:50.537 回答