如果我们的网站看到用户签名的Facebook具有用户ID 678678678在cookie中,我们怎么知道这个cookie不是伪造的?

StackOverflow https://stackoverflow.com/questions/4002616

  •  25-09-2019
  •  | 
  •  

我认为,如果我们使用REST或GRAPH API拨打Facebook的电话,我们会知道它是否是假的,因为它会回来说fake session / auth_token / access_token。但是,如果我们显示自己的DB信息,例如用户的“最喜欢的产品列表”,那么我们不会打电话给Facebook,而是显示DB的数据。我们怎么知道它确实是用户,而不是有人伪造饼干?

有帮助吗?

解决方案

当您使用Facebook阅读cookie时,它包含一个名为“ SIG”的值。有了这个值,其他cookie值以及您的应用程序秘密将cookie的内容放在cookie中,并将其验证为SIG。如果它们匹配,则cookie是有效的。您可以信任此结果,因为只有您和Facebook可以访问该应用程序的秘密。这是Facebook的PHP SDK如何完成的示例。任何受人尊敬的Facebook SDK都会为您内部做这一切。

/**
   * Validates a session_version=3 style session object.
   *
   * @param Array $session the session object
   * @return Array the session object if it validates, null otherwise
   */
  protected function validateSessionObject($session) {
    // make sure some essential fields exist
    if (is_array($session) &&
        isset($session['uid']) &&
        isset($session['access_token']) &&
        isset($session['sig'])) {
      // validate the signature
      $session_without_sig = $session;
      unset($session_without_sig['sig']);
      $expected_sig = self::generateSignature(
        $session_without_sig,
        $this->getApiSecret()
      );
      if ($session['sig'] != $expected_sig) {
        self::errorLog('Got invalid session signature in cookie.');
        $session = null;
      }
      // check expiry time
    } else {
      $session = null;
    }
    return $session;
  }

这是C#中的同一件事(Facebook C#SDK):

 /// <summary>
    /// Validates a session_version=3 style session object.
    /// </summary>
    /// <param name="session">The session to validate.</param>
    protected override void ValidateSessionObject(FacebookSession session)
    {
        if (session == null)
        {
            return;
        }

        var signature = this.GenerateSignature(session);
        if (session.Signature == signature.ToString())
        {
            return;
        }

        session = null;
    }

    /// <summary>
    /// Generates a MD5 signature for the facebook session.
    /// </summary>
    /// <param name="session">The session to generate a signature.</param>
    /// <returns>An MD5 signature.</returns>
    /// <exception cref="System.ArgumentNullException">If the session is null.</exception>
    /// <exception cref="System.InvalidOperationException">If there is a problem generating the hash.</exception>
    protected override string GenerateSignature(FacebookSession session)
    {
        var args = session.Dictionary;
        StringBuilder payload = new StringBuilder();
        var parts = (from a in args
                     orderby a.Key
                     where a.Key != "sig"
                     select string.Format(CultureInfo.InvariantCulture, "{0}={1}", a.Key, a.Value)).ToList();
        parts.ForEach((s) => { payload.Append(s); });
        payload.Append(this.ApiSecret);
        byte[] hash = null;
        using (var md5 = System.Security.Cryptography.MD5CryptoServiceProvider.Create())
        {
            if (md5 != null)
            {
                hash = md5.ComputeHash(Encoding.UTF8.GetBytes(payload.ToString()));
            }
        }

        if (hash == null)
        {
            throw new InvalidOperationException("Hash is not valid.");
        }

        StringBuilder signature = new StringBuilder();
        for (int i = 0; i < hash.Length; i++)
        {
            signature.Append(hash[i].ToString("x2", CultureInfo.InvariantCulture));
        }

        return signature.ToString();
    }

其他提示

您唯一可以信任的是 session_key 对于旧的休息API和 access_token 对于图形API。获得它后,将其传递给服务器端,并带有您的Data Reetirval请求。在服务器端致电Facebook API并获取当前的用户ID。获得用户ID后,您可以将其存储在会话中并以后使用。

不要将其存放在饼干中。将其放在会话变量中,这样您就可以控制

不要将用户ID放入cookie中。会话cookie应该只是一个随机数,该数字映射到服务器端会话数据库中的记录。与该会话关联的任何数据仅存储服务器端。

这样,为了伪造会话,攻击者将不得不猜测当时实际使用的随机数。鉴于有很多随机数和会话过期,这几乎是不可能的。

这里有几种方法。

效率低下:每当您执行身份验证的操作时,请抓住FB cookie并使用其中的数据来进行虚拟API调用,以查看访问令牌有效并与用户匹配(即grab /me?fields = id)。

更有效的效率:您第一次看到用户的FB cookie时,将cookie存储在服务器端会话中的用户(带有足够硬的猜测会话ID传递给cookie中的客户端)。

另一种方法,并且不需要服务器端会话状态:您第一次看到用户的FB cookie时,只有服务器才有秘密的cookie hmac the cookie,并将结果存储在cookie中。然后,您可以检查是否有有效的FB cookie哈希,如果是,您信任它。否则,您可以回到验证。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top