Facebook JS SDK:纯文本和安全性的access_token

时间:2010-11-30 23:15:49

标签: javascript facebook

当用户使用FB.login()调用显示的弹出窗口登录Facebook时,JS SDK会在我的域中植入一个包含纯文本oauth access_token的cookie。然后,每个后续请求都会将此cookie发送到我的服务器 - 很明显,并非每个请求都使用https

这不是安全问题吗?如果是这样,那怎么解决呢?

2 个答案:

答案 0 :(得分:3)

这不是问题,因为您可以验证cookie的真实性。 Facebook在每个cookie中都包含一个名为sig的值。我不会详细介绍,但基本上,您将API秘密附加到cookie,删除sig值,散列cookie值并验证散列是否与sig匹配。因为您和Facebook是唯一知道API秘密价值的人,所以可以确保cookie没有被篡改。

事情的另一方面,查看cookie内容的用户也无关紧要。 cookie仅包含与该用户关联的访问令牌。如果用户试图篡改cookie,那么唯一会发生的事情就是使cookie无效。而且他们的访问令牌只能让他们访问自己的帐户。

最重要的是验证cookie是真实的。许多人不这样做,确实造成了巨大的安全问题。例如,cookie包含facebook用户ID。假设我得到该用户ID然后询问我的用户他们的信用卡。如果我使用该用户ID存储该信用卡,但不验证cookie,则任何人都可以进入并更改cookie中的用户ID值并访问私有数据。但是,如果我使用API​​密钥验证cookie,我会知道cookie是否被篡改。

以下是我们在Facebook C#SDK(http://facebooksdk.codeplex.com)中验证cookie的方法:

        /// <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();
        }

答案 1 :(得分:2)

能够嗅探网络流量(例如无线局域网)的攻击者可以读取cookie。并假装是为其创建的人。

这不是一个真正的问题,因为同样的攻击可以在facebook页面上运行:只有用户名/密码 - 身份验证是通过https完成的。以下所有页面都使用未加密的http,其中包含cookie。

如果您能够嗅探网络流量,那么有一个易于使用的Firefox扩展程序,允许使用Cookie:http://codebutler.com/firesheep

PS:stackoverflow.com也很脆弱。