小结:cookie并不安全,但经过仔细地配置,可以帮助保护cookie

威胁:会话劫持、账户劫持、会话固定、信息泄漏

HTTP cookie是一种用于存储用户状态,以创建和Web服务器无缝连接的效果的机制。Cookie设计用于处理用户的优先选择并跟踪会话变量,并且它们可以很好地做到这一点。但是,对于安全性,却会引发一些问题。大多数相关规范取决于服务器、客户浏览器,以及两者之间遵循相关规则的代理。遗憾的是,情况并不总是如此。此外,甚至不要求用户代理接受cookie,虽然不接受cookie将导致一些Web站点不会授权用户访问该站点。

一般情况下,为了使ASP.NET保存cookie,可以使用Response.Cookies集合。然而,ASP.NET自动编写了一些cookie,不需要程序为这些cookie编写任何代码。如果启用会话状态,ASP.NET将为连接到服务器的每个用户创建一个带有独特标记的会话cookie。如果使用带有cookie的表单验证,ASP.NET也会将一个表单验证标记添加到这个cookie。

为了访问这些cookie,可以使用Response.Cookies集合。对于表单验证cookie,FormsAuthenticationTicket对象提供对cookie属性的访问,以及对与表单验证相关的其他属性的访问。

Cookie总是更容易受到攻击,但一些设置可限制这种易受攻击性。具有重要安全意义的属性如下:

n Domain(域)

n Path(路径)

n Expires(过期时间)

n Secure(安全)

n Value(值)

Cookie域

Cookie的可选域属性确定哪一个服务器可访问cookie中的信息。如果将该属性保留为空,则假定浏览器只允许发布该cookie的主机进行访问。然而,有时仍然可能希望指定这个值。

Cookie域允许对所有匹配域名(包括所有子域)的主机进行访问。换句话说,它自右向左匹配。因此,设置为example.com的cookie域将匹配*.example.com。域名必须最少包含两个点,防止服务器将域名设置为.com样式。尽可能尝试在域上使用特定的名称。例如,如果主机名为ro.cker.org,并且将cookie域设置为.cker.org,则主机cra.cker.org,atta.cker.org和just.about.any.script.kiddie.ha.cker.org都可以访问该cookie。这一点非常重要,因为攻击者可能发现并利用这些系统上的缺陷,获得对目标系统中cookie的访问。图3-2和图3-3演示了如何在所有cookie上设置域。

图3-2  在所有cookie上设置域(C#)

图3-3  在所有cookie上设置域(VB.NET)

除了提供特定的主机名外,可能也希望检查接收的cookie域。例如,假设主机ro.cker.org将域属性设置为ro.cker.org。然而,主机ha.cker.org将域属性设置为.cker.org。现在,假如用户浏览到ha.cker.org,并且服务器使用如下的头发送一个会话cookie:

现在,用户浏览到ro.cker.org,并且浏览器看到主机ro.cker.org也匹配域.cker.org。因此,它回送从ha.cker.org接收到的cookie:

ro.cker.org服务器并没有检查域,只是简单地接受cookie。这种类型的缺陷可能会将服务器暴露给许多攻击,包括会话固定、账户跳跃和标记操纵。为了防止这种类型的攻击,总是检查cookie的域,如图3-2(C#)和图3-3(VB.NET)所示。注意,在所有cookie上设置域之前(如图3-2和图3-3所示),应该总是运行图3-4(C#)和图3-5(VB.NET)中的验证代码。

Cookie路径

类似于域,Cookie也有一个路径属性来限制它们的作用域。通过域检查后,服务器将检查cookie路径。路径自左向右匹配,并且匹配任意路径和该路径下的路径。因此,如果将路径设置为“/”(斜杠),则cookie将应用于服务器上的所有路径。路径“/shopping”将cookie限制为shopping目录及其所有子目录中的所有项。

图3-4  验证cookie域(C#)

图3-5  验证cookie域(VB.NET)

尽可能设置特定的路径将很有帮助,因为浏览器将cookie发送到所有匹配该路径的URL。通过保持较小的作用域,可以防止浏览器在不适当的时候发送cookie,例如浏览非SSL的页面时。如果攻击者发现应用程序某一部分中的缺陷,它也可以限制将这些缺陷暴露给跨站点脚本的攻击。例如,假设有一个只有www.example.com/ protected/中成员才可使用的Web应用程序。但是,也提供了一个演示应用程序,任何人在www.example.com/demo/都可以登录。现在,假设一些人仔细研究了这个演示应用程序,并且发现一些跨站点脚本的缺陷。通过这个缺陷,他们可以使用演示应用程序来窃取所有成员的验证cookie。在这种情况中,为受保护的目录和演示目录设置特定的cookie路径可以限制暴露给相关攻击的风险。使得攻击者需要访问受保护的目录,以利用缺陷攻击实际的成员,而每个人都可以访问演示目录。虽然这绝对不是用于跨站点脚本的解决方案,但它确实限制了暴露给攻击者的风险。

安全策略通常具有不同级别的有效性。一些技术绝对有效;而其他技术则通过限制作用域减缓攻击。然而,有些技术只用于使事情模糊,以此来减缓攻击,使一些容易半途而废的电脑黑客知难而退。用于缓和攻击和模糊事情的技术并没有提供稳固的保护方法,但对于减少暴露给攻击的风险,的确具有一定的效果,特别是在结合使用多种技术时。

总是设置特定的cookie路径,并且总是检查客户发送给应用程序的cookie上的路径。对于表单验证,为web.config文件中的表单元素设置路径属性。

Cookie过期

在ASP.NET中,Cookie的过期有时容易产生混淆。但是,保持尽可能短的cookie生命周期非常重要,这样可以限制暴露给cookie劫持攻击的风险。Cookie有一个Expires属性,通过该属性可设置浏览器保持cookie多长时间的限制。如果过期时间保留为空,则假定客户浏览器在关闭时删除cookie,不将cookie保存到磁盘。虽然过期日期可以告诉浏览器什么时候应该停止使用cookie,但却无法保证浏览器移除过期的cookie。因此,即使这不是一个可靠的安全措施,还是应该利用该特性。

当ASP.NET发布一个会话ID cookie时,它并没有设置一个过期日期,因此浏览器应该在其关闭时删除cookie。根据web.config文件中SessionState元素的会话超时设置,ASP.NET自己处理会话标记的过期和重新发布。设置如下所示:

ASP.NET也处理表单验证票。表单验证标记的cookie不会有过期日期,除非Web应用程序将cookie设置为永久性。FormsAuthentication.RedirectFormLoginPage方法有一个参数来表明是否希望使用永久性cookie,如下所示:

注意,FormsAuthenticationTicket类也有一个可以设置的IsPersistent属性。一些Web应用程序给用户提供 “Remember Me”特性,让他们不需要在每次访问时都输入证书。这是不安全的安全性做法,在存储个人用户信息或允许用户执行重要财务、个人或通信动作的Web站点上,绝对不应该提供该功能。

FormsAuthenticationTicket有一个Expiration属性,该属性表明验证标记何时过期,但并没有设置cookie的过期日期。发送给浏览器的cookie并没有过期日期,除非将其标记为持久性的。一旦ASP.NET检测到旧验证标记,它将取消该标记并发布一个新标记。

表单验证提供了两种控制它如何处理标记过期的设置:timeout和sliding Expiration。timeout指定cookie过期之前的分钟数。slidingExpiration设置为true时在每次浏览器请求时都更新cookie的过期日期,只要指定的时间已经过去了至少一半。换句话说,如果将超时设置为20分钟,并且将slidingExpiration设置为true,则用户可从上一次页面请求开始,经过20分钟后再验证。如果将slidingExpiration设置为false,则需要用户在第一次请求后20分钟内重新验证。

超时设置对于持久性的cookie没有效果。如果将验证票设置为持久性,ASP.NET将给cookie设置一个过期时间,这个时间是从服务器发布该cookie开始向后50年。不在表单验证中使用持久性cookie还有更多的原因。

虽然能够选择相对或绝对超时时间这一点非常好,但同时拥有两者将会更理想。通过这种方法,可以在一定量的空闲时间后超时,也可以在固定的分钟数后超时。在没有绝对超时时间的情况下,如果用户保持浏览器打开一个自动刷新的页面,则该会话永远不会结束。通过将标记保持为激活状态,攻击者可利用这种缺陷进行会话固定攻击。

安全的cookie

服务器可将cookie标记为安全的,以向客户表明应该采取措施保护该cookie。虽然RFC并没有指定浏览器应该采取何种措施,但一般意味着只在加密的SSL会话上发送cookie。不过,将cookie标记为安全的,这只是从服务器角度考虑的建议,客户浏览器并不一定要严格遵守该设置。理论上,客户端应该提供和发布cookie时所假设的相同的安全性级别。大多数常见Web浏览器并没有严格采用这种设置。

如果使用SSL保护Web站点,也应该将cookie标记为安全的,从而客户不会将它们发送到Web站点上的非SSL页面。

应该将表单验证配置为总是使用带有web.config文件requireSSL设置的安全cookie,具体如下:

注意,如果将表单验证cookie标记为true,则必须为Web应用程序的整个受保护区域提供一个SSL连接。如果用户访问非SSL页面,浏览器不会发送cookie,并且用户必须再次验证以创建一个新的FormsAuthenticationTicket,从而创建一个新cookie。如果需要表单验证cookie的安全性,则必须确保整个受保护的区域都支持SSL。同样,也可能不希望将会话cookie标记为安全,除非整个Web应用程序都支持SSL。

Cookie值

Cookie最常见的用法是存储用户变量,例如购物车中的数据项或用户的优先选择。然而,一些开发者使用cookie来存储敏感信息,例如用户名、密码、甚至是信用卡的细节信息。绝对不应该在cookie中存储敏感信息,并且总是加密适合于存储的其他信息。

安全策略

n 总是设置一个特定的域属性,并且在读取cookie时检查这个域属性。

n 总是设置一个特定的cookie路径,并且检查cookie上客户发送应用程序的路径。

n 在会话cookie上使用较短的超时时间,以限制暴露给会话劫持攻击的风险。

n 如果使用SSL,则将cookie标记为安全。

n 绝对不要存储验证证书或信用卡号等敏感信息,并且总是加密所有存储的信息。

posted on 2009-03-09 09:56  钱途无梁  阅读(3766)  评论(0编辑  收藏  举报