分享
 
 
 

ASP.NET Forms Authentication所生成Cookie的安全性

王朝asp·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

原创 By Fancyf(Fancyray)

我做这个实验是因为http://community.csdn.net/Expert/topic/3927/3927012.xml?temp=.3752405

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

Web.config修改如下:

<authentication mode="Forms">

<forms name="MyLab" loginUrl="/Login.aspx">

<credentials passwordFormat="Clear">

<user name="Fancyray" password="Fancyray"/>

</credentials>

</forms>

</authentication>

<authorization>

<deny users="?" />

</authorization>

Login.aspx只有一个用户名输入框txtUsername、一个密码输入框txtPassword和一个提交按钮,Click事件如下:

if (FormsAuthentication.Authenticate(this.txtUsername.Text, this.txtPassword.Text))

{

FormsAuthentication.RedirectFromLoginPage(this.txtUsername.Text, true);

}

else

{

Response.Write("Login denied");

}

借助ieHttpHeaders(http://www.blunck.info/)可以看到,通过验证后增加了一个类似这样的Cookie:

MyLab=3FF83247C29EB5D14D61F389D453EEE0586B94E27609C321B017BE7B88D1A94D249996428A7A18F5C2D69F3C4DD2B88C00172CAFB0B4B4ED8784DB62D1D61BCC0C786B4EA7868FC6

看来这就是加密以后的Cookie了。下面要换一台电脑,直接将这个值设置为Cookie,看看是否需要Forms验证。

在Login.aspx页面中加上这样一句话:

<script language=javascript>

document.cookie="MyLab=3FF83247C29EB5D14D61F389D453EEE0586B94E27609C321B017BE7B88D1A94D249996428A7A18F5C2D69F3C4DD2B88C00172CAFB0B4B4ED8784DB62D1D61BCC0C786B4EA7868FC6";

</script>

这样只要一打开Login.aspx页面就会自动加入这个Cookie。

另一台电脑:输入同一个WebApplication下的另外一个页面(应该会自动跳转到Login.aspx页面)http://10.0.0.7/upload.aspx,这时成功跳转到了http://10.0.0.7/Login.aspx?ReturnUrl=%2fupload.aspx,正常。这时Cookie的值应该已经生效了。那么我们再输入刚才那个页面的网址http://10.0.0.7/upload.aspx

按照我的猜想,肯定还会跳到login.aspx页面的,因为那个cookie是在另一台电脑上生成的。实际呢,没有跳转!完整地显示出了upload.aspx的内容!而我们根本没有在这台电脑上登录,甚至我们连用户名都不知道!

我回到10.0.0.7这台电脑在upload.aspx页面的Page_Load()第一行添了一句:Response.Write(User.Identity.Name);,在另一台电脑上刷新显示出来了的upload.aspx,结果也出现了Fancyray,正是我的用户名。

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

那么Cookie的这个值是怎么来的呢?黑客是否可能不通过穷举就得到这个值呢?

我们先来看看Cookie中到底存储了一些什么,以及怎样进行的加密。Reflactor(http://www.aisto.com/roeder/dotnet)上场!

public static void SetAuthCookie(string userName, bool createPersistentCookie, string strCookiePath)

{

FormsAuthentication.Initialize();

HttpContext.Current.Response.Cookies.Add(FormsAuthentication.GetAuthCookie(userName, createPersistentCookie, strCookiePath));

}

public static HttpCookie GetAuthCookie(string userName, bool createPersistentCookie, string strCookiePath)

{

FormsAuthentication.Initialize();

if (userName == null)

{

userName = "";

}

if ((strCookiePath == null) || (strCookiePath.Length < 1))

{

strCookiePath = FormsAuthentication.FormsCookiePath;

}

FormsAuthenticationTicket ticket1 = new FormsAuthenticationTicket(1, userName, DateTime.Now, createPersistentCookie ? DateTime.Now.AddYears(50) : DateTime.Now.AddMinutes((double) FormsAuthentication._Timeout), createPersistentCookie, "", strCookiePath);

string text1 = FormsAuthentication.Encrypt(ticket1);

FormsAuthentication.Trace("ticket is " + text1);

if ((text1 == null) || (text1.Length < 1))

{

throw new HttpException(HttpRuntime.FormatResourceString("Unable_to_encrypt_cookie_ticket"));

}

HttpCookie cookie1 = new HttpCookie(FormsAuthentication.FormsCookieName, text1);

cookie1.Path = strCookiePath;

cookie1.Secure = FormsAuthentication._RequireSSL;

if (ticket1.IsPersistent)

{

cookie1.Expires = ticket1.Expiration;

}

return cookie1;

}

Cookie中存储的值就是里面的text1,text1是由string text1 = FormsAuthentication.Encrypt(ticket1);生成的,所以text1里面的信息就是ticket1了。FormsAuthenticationTicket的构造函数原形为:

public FormsAuthenticationTicket(int version, string name, DateTime issueDate, DateTime expiration, bool isPersistent, string userData, string cookiePath)

里面有用户名、生成ticket1的时间和过期时间。

看到这里我不禁打了一个冷颤。ticket1实际上只用到了用户名一个关键信息,连密码都没有用!这样岂不是任何一个用户的ticket1都可以轻易的制造出来吗?只要通过FormsAuthentication.Encrypt(ticket1)就得到了Cookie的值,来伪装成任何一个用户?太可怕了。现在只能寄希望于Encrypt这个函数了。看看它的实现:

public static string Encrypt(FormsAuthenticationTicket ticket)

{

if (ticket == null)

{

throw new ArgumentNullException("ticket");

}

FormsAuthentication.Initialize();

byte[] buffer1 = FormsAuthentication.MakeTicketIntoBinaryBlob(ticket);

if (buffer1 == null)

{

return null;

}

if (FormsAuthentication._Protection == FormsProtectionEnum.None)

{

return MachineKey.ByteArrayToHexString(buffer1, 0);

}

if ((FormsAuthentication._Protection == FormsProtectionEnum.All) || (FormsAuthentication._Protection == FormsProtectionEnum.Validation))

{

byte[] buffer2 = MachineKey.HashData(buffer1, null, 0, buffer1.Length);

if (buffer2 == null)

{

return null;

}

FormsAuthentication.Trace("Encrypt: MAC length is: " + buffer2.Length);

byte[] buffer3 = new byte[buffer2.Length + buffer1.Length];

Buffer.BlockCopy(buffer1, 0, buffer3, 0, buffer1.Length);

Buffer.BlockCopy(buffer2, 0, buffer3, buffer1.Length, buffer2.Length);

if (FormsAuthentication._Protection == FormsProtectionEnum.Validation)

{

return MachineKey.ByteArrayToHexString(buffer3, 0);

}

buffer1 = buffer3;

}

buffer1 = MachineKey.EncryptOrDecryptData(true, buffer1, null, 0, buffer1.Length);

return MachineKey.ByteArrayToHexString(buffer1, buffer1.Length);

}

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

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

Cookie的这个值和SessionID一样,都是一旦被猜中就可能引发安全问题。但又与SessionID有区别,因为SessionID总是短暂的,而Cookie的值却有可能是永远有效的。Cookie值的长度也让我们稍稍放了一点心。

还有一个问题不容忽视。虽然Cookie的值的生成与具体的时间有关,也就是我注销后再次登陆所生成的Cookie是不一样的,但是一个合法的Cookie值是永久有效的,不受是否改变密码及时间的影响。也就是说,我上一次生成的Cookie在我注销以后拿到另一台电脑上仍然可以用,只要服务器的MachineKey不变。的确是个安全隐患。我们也只能说:“Cookie的值很长,要穷举到一个有效的Cookie在有生之年是办不到的”来找一些安慰。密码可以通过频繁的更改来进一步减小穷举到的可能性,但合法的Cookie却无法更改。密码是唯一的,但合法的Cookie值却不是唯一的。这一切总让人觉得不太放心。

也许担心是多余的,因为电子签名、证书都是建立在“穷举要付出很大代价”的基础上的,要是考虑“碰巧被穷举到”的话,安全就不复存在了。相信在一般的安全领域,Forms生成的Cookie的安全级别还是足够的。

放心地去用吧!(又一篇毫无价值的文章,当你没看过好了)

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有