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

本文深入探讨了ASP.NET Forms认证机制下Cookie的安全性问题,包括Cookie的生成原理、加密方式及其潜在的安全隐患。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

asp.net forms authentication所生成cookie的安全性
我做这个实验是因为http://community.youkuaiyun.com/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; 
} 
formsauthenticati ticket1 = new formsauthenticati 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.expirati 
} 
return cookie1; 
} 


cookie中存储的值就是里面的text1,text1是由string text1 = formsauthentication.encrypt(ticket1);生成的,所以text1里面的信息就是ticket1了。 formsauthenticati 
public formsauthenticati versi string name, datetime issuedate, datetime expirati bool ispersistent, string userdata, string cookiepath) 
里面有用户名、生成ticket1的时间和过期时间。 
看到这里我不禁打了一个冷颤。ticket1实际上只用到了用户名一个关键信息,连密码都没有用!这样岂不是任何一个用户的ticket1都可以轻易的制造出来吗?只要通过formsauthentication.encrypt(ticket1)就得到了cookie的值,来伪装成任何一个用户?太可怕了。现在只能寄希望于encrypt这个函数了。看看它的实现: 
public static string encrypt(formsauthenticati ticket) 
{ 
if (ticket == null) 
{ 
throw new argumentnullexcepti 
} 
formsauthentication.initialize(); 
byte[] buffer1 = formsauthentication.maketicketintobinaryblob(ticket); 
if (buffer1 == null) 
{ 
return null; 
} 
if (formsauthentication._protection == formsprotectionenum.n 
{ 
return machinekey.bytearraytohexstring(buffer1, 0); 
} 
if ((formsauthentication._protection == formsprotectionenum.all) || (formsauthentication._protection == formsprotectionenum.validati 
{ 
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.validati 
{ 
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的这个值和sessi 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值