• 关于Forms Authentication安全性方面的一些讨论


      最近突发奇想,想对微软的.net验证进行测试,是否是如我之前预想的安全。

      我最初的想法是,生成的Cookie也应该与这台电脑的独特的参数相关,拿到另一台电脑上就应该无效了。那么是不是一个用户名对应一个Cookie值呢?是否能够通过伪造Cookie值来骗过表单验证呢?做一番试验。

      测试如下:  

      1.我在一台电脑上登陆成功后,找到该生成的cookie:

      cookie名:Auth

      值:3FF83247C29EB5D14D61F389D453EEE0586B94E27609C321B017BE7B88D1A94D249996428A7A18F5C2D69F3C4DD2B88C00172CAFB0B4B4ED8784DB62D1D61BCC0C786B4EA7868FC6。

      2.换另一台电脑,未登陆状态,手动新建一个之前名为Auth的cookies,值相同,域等其他也都相同。刷新页面,结果发现竟然已经登陆成功了,并且在顶部直接显示,欢迎您,zhanghai,而zhanghai就是我从User.Identity.Name取到的,也正是我的登录名。

      这说明,Cookie的加密不依赖于登录的电脑。也就是说,一旦你的Cookie被别人获得,他就有可能获得你在这台服务器上的权限。

      这和我们的预想完全不同,这是不是一个漏洞,黑客是否能通过某种手段获取得到这个值呢?

      解决这个问题,必须先看cookies的加密过程。由于某种原因,此处只贴出网上的一段代码。

     1 public static void SetAuthCookie(string userName, bool createPersistentCookie, string strCookiePath)
     2 {
     3       FormsAuthentication.Initialize();
     4       HttpContext.Current.Response.Cookies.Add(FormsAuthentication.GetAuthCookie(userName, createPersistentCookie, strCookiePath));
     5 }
     6 
     7 public static HttpCookie GetAuthCookie(string userName, bool createPersistentCookie, string strCookiePath)
     8 {
     9       FormsAuthentication.Initialize();
    10       if (userName == null)
    11       {
    12             userName = "";
    13       }
    14       if ((strCookiePath == null) || (strCookiePath.Length < 1))
    15       {
    16             strCookiePath = FormsAuthentication.FormsCookiePath;
    17       }
    18       FormsAuthenticationTicket ticket1 = new FormsAuthenticationTicket(1, userName, DateTime.Now, createPersistentCookie ? DateTime.Now.AddYears(50) : DateTime.Now.AddMinutes((double) FormsAuthentication._Timeout), createPersistentCookie, "", strCookiePath);
    19       string text1 = FormsAuthentication.Encrypt(ticket1);
    20       FormsAuthentication.Trace("ticket is " + text1);
    21       if ((text1 == null) || (text1.Length < 1))
    22       {
    23             throw new HttpException(HttpRuntime.FormatResourceString("Unable_to_encrypt_cookie_ticket"));
    24       }
    25       HttpCookie cookie1 = new HttpCookie(FormsAuthentication.FormsCookieName, text1);
    26       cookie1.Path = strCookiePath;
    27       cookie1.Secure = FormsAuthentication._RequireSSL;
    28       if (ticket1.IsPersistent)
    29       {
    30             cookie1.Expires = ticket1.Expiration;
    31       }
    32       return cookie1;
    33 }

    由此可见,cookie的值是ticket1加密后得出,ticket1是由public FormsAuthenticationTicket(int version, string name, DateTime issueDate, DateTime expiration, bool isPersistent, string userData, string cookiePath)得到。里面有用户名、生成ticket1的时间和过期时间。注意上面这个方法,有我的用户名,用户数据,路径等等,但是连密码都没有。这样的话,岂不是黑客通过类似加密后,生成cookie,就有所有账号的权限了。这是非常恐怖的一件事。

    现在只能寄希望于Encrypt这个函数了。看看它的实现:

     1 public static string Encrypt(FormsAuthenticationTicket ticket)
     2 {
     3       if (ticket == null)
     4       {
     5             throw new ArgumentNullException("ticket");
     6       }
     7       FormsAuthentication.Initialize();
     8       byte[] buffer1 = FormsAuthentication.MakeTicketIntoBinaryBlob(ticket);
     9       if (buffer1 == null)
    10       {
    11             return null;
    12       }
    13       if (FormsAuthentication._Protection == FormsProtectionEnum.None)
    14       {
    15             return MachineKey.ByteArrayToHexString(buffer1, 0);
    16       }
    17       if ((FormsAuthentication._Protection == FormsProtectionEnum.All) || (FormsAuthentication._Protection == FormsProtectionEnum.Validation))
    18       {
    19             byte[] buffer2 = MachineKey.HashData(buffer1, null, 0, buffer1.Length);
    20             if (buffer2 == null)
    21             {
    22                   return null;
    23             }
    24             FormsAuthentication.Trace("Encrypt: MAC length is: " + buffer2.Length);
    25             byte[] buffer3 = new byte[buffer2.Length + buffer1.Length];
    26             Buffer.BlockCopy(buffer1, 0, buffer3, 0, buffer1.Length);
    27             Buffer.BlockCopy(buffer2, 0, buffer3, buffer1.Length, buffer2.Length);
    28             if (FormsAuthentication._Protection == FormsProtectionEnum.Validation)
    29             {
    30                   return MachineKey.ByteArrayToHexString(buffer3, 0);
    31             }
    32             buffer1 = buffer3;
    33       }
    34       buffer1 = MachineKey.EncryptOrDecryptData(true, buffer1, null, 0, buffer1.Length);
    35       return MachineKey.ByteArrayToHexString(buffer1, buffer1.Length);
    36 }

      看到了MachineKey这个词,终于松了一口气。看来加解密过程是与服务器的参数有关系。也就是说,服务器上有自己的密钥,只有用这个密钥才能进行Cookie的加解密。如果不知道这个密钥,别人是无法伪造Cookie的。

          看来Cookie还是安全的,在你的电脑没有被入侵的前提下。与其他任何信息一样,所需注意的仅仅是网络传输中的安全性了。

      还有一个问题不容忽视。虽然Cookie的值的生成与具体的时间有关,也就是我注销后再次登陆所生成的Cookie是不一样的,但是一个合法的 Cookie值是永久有效的,不受是否改变密码及时间的影响。也就是说,我上一次生成的Cookie在我注销以后拿到另一台电脑上仍然可以用,只要服务器 的MachineKey不变。的确是个安全隐患。我们也只能说:“Cookie的值很长,要穷举到一个有效的Cookie在有生之年是办不到的”来找一些 安慰。密码可以通过频繁的更改来进一步减小穷举到的可能性,但合法的Cookie却无法更改。密码是唯一的,但合法的Cookie值却不是唯一的。这一切 总让人觉得不太放心。
         也许担心是多余的,因为电子签名、证书都是建立在“穷举要付出很大代价”的基础上的,要是考虑“碰巧被穷举到”的话,安全就不复存在了。相信在一般的安全领域,Forms生成的Cookie的安全级别还是足够的。

  • 相关阅读:
    docker 数据卷 ---- 进阶篇
    docker 数据卷 ---- 基础篇
    python做基本的图像处理
    conv1d UpSampling1D aotoencoder 自编码代码摘录
    python daal test
    python dict 构造函数性能比较
    CNN autoencoder 进行异常检测——TODO,使用keras进行测试
    利用CNN进行流量识别 本质上就是将流量视作一个图像
    Deep Belief Network简介——本质上是在做逐层无监督学习,每次学习一层网络结构再逐步加深网络
    python pipe stdout 实现cat|grep 功能
  • 原文地址:https://www.cnblogs.com/zhanghai/p/4533648.html
Copyright © 2020-2023  润新知