谨为今后学习参考的笔记。内容来自互联网。
Cookie的基本概念:
Cookie是由服务器端生成,发送给User-Agent(一般是浏览器),浏览器会将Cookie的key/value保存到某个目录下的文本文件内,下次请求同一网站时就发送该Cookie给服务器(前提是浏览器设置为启用cookie)。Cookie名称和值可以由服务器端开发自己定义,对于JSP而言也可以直接写入jsessionid,这样服务器可以知道该用户是否合法用户以及是否需要重新登录等,服务器可以设置或读取Cookies中包含信息,借此维护用户跟服务器会话中的状态。
Cookie 和身份验证
Cookie 之所以存在,是因为它们可以帮助开发人员达到一定目的。Cookie 充当了浏览器与服务器之间的一种持续性链接。特别是对于使用单次登录的应用程序来说,失窃的 cookie 正是使得攻击成为可能的罪魁祸首。这对于一次单击攻击来说一点没错。
要使用 Cookie,无需以编程方式显式创建和读取它们。如果您使用会话状态且实现表单身份验证,您会隐式地使用 Cookie。当然,ASP.NET 支持无 cookie 的会话状态,而且,ASP.NET 2.0 还引入了无 cookie 的表单身份验证。因此,理论上您可以在没有 Cookie 的情况下使用这些功能。我并不是说您不再必须这么做了,但事实上这正是疗法比疾病更糟的情形之一。无 Cookie 的会话,实际上将会话 ID 嵌入了 URL 中,这样谁都可以看到。
与使用 Cookie 有关的潜在问题有哪些?Cookie 可能被盗(即被复制到黑客的计算机)和投毒(即被填充以恶意数据)。这些操作通常是即将发起的攻击的前奏。如果被盗,Cookie 会“授权”外部用户以您的名义连接到应用程序(并使用受保护的页),这可能使黑客轻松地规避授权,并能够执行角色和安全设置所允许受害者执行的任何操作。因此,身份验证 Cookie 通常被赋予相对较短的生存期,即 30 分钟。(请注意,即使浏览器的会话完成所需的时间更长,cookie 仍会过期。)发生失窃时,黑客有 30 分钟的时限来尝试攻击。
可以将这个时限加长,以免用户不得不过于频繁地登录;但请注意,这么做会将您自己置于危险境地。任何情况下,都应避免使用 ASP.NET 持续性 Cookie。它将导致 cookie 具有几乎永久的生存期,最长可达 50 年!下面的代码片段演示了如何轻松修改 cookie 的过期日期。
void OnLogin(object sender, EventArgs e) { // Check credentials if (ValidateUser(user, pswd)) { // Set the cookie's expiration date HttpCookie cookie; cookie = FormsAuthentication.GetAuthCookie(user, isPersistent); if (isPersistent) cookie.Expires = DateTime.Now.AddDays(10); // Add the cookie to the response Response.Cookies.Add(cookie); // Redirect string targetUrl; targetUrl = FormsAuthentication.GetRedirectUrl(user, isPersistent); Response.Redirect(targetUrl); } }
您可以在自己的登录表单中使用这些代码来微调身份验证 Cookie 的生存期。
会话劫持
Cookie 还被用于检索特定用户的会话状态。会话的 ID 被存储到 cookie 中,该 cookie 与请求一起来回传送,存储在浏览器的计算机上。同样,如果失窃,会话 cookie 将可被用来使黑客进入系统并访问别人的会话状态。不用说,只要指定的会话处于活动状态(通常不超 20 分钟),这就有可能发生。通过冒充的会话状态发起的攻击称为会话劫持。有关会话劫持的详细信息,请阅读 Theft On The Web: Prevent Session Hijacking。
这种攻击有多危险?很难讲。这要取决于 Web 站点的功能,更为重要的是,该站点的页是如何设计的。例如,假定您能够获得别人的会话 cookie,并将它附加到对站点上某个页的请求中。您加载该页并逐步研究它的普通用户界面。除了该页使用另一个用户的会话状态工作外,您无法将任何代码注入该页,也无法修改该页中的任何内容。这本身并不太坏,但是如果该会话中的信息是敏感和关键性的,就有可能直接导致黑客成功实现利用。黑客无法渗透到会话存储的内容中,但他可以使用其中存储的信息,就像自己是合法进入的一样。例如,假定有这样一个电子商务应用程序,它的用户在浏览站点时将物品添加到购物车中。
-
方案 1。 购物车的内容存储在会话状态中。但是,在结帐时,用户被要求通过安全的 SSL 连接确认和输入付款详细信息。这种情况下,通过接入其他用户的会话状态,黑客仅可以了解到一些有关受害者的购物喜好的细节。在这种环境下劫持实际上并不会导致任何损害。受威胁的只是保密性。
-
方案 2。应用程序为每位注册用户处理一份档案,并将档案保存在会话状态中。糟糕的是,档案中(可能)包括信用卡信息。为什么要将用户档案详细信息存储到会话中?可能应用程序的其中一个目标是,从根本上避免使用户不得不重复键入自己的信用卡和银行信息。因此,在结算时,应用程序会将用户定位到一个具有预先填充的域的页。而有失谨慎的是,这些域的其中一个是从会话状态中获取的信用卡号。现在您可以猜到故事的结局了吗?
应用程序的页的设计,是防止会话劫持攻击的关键所在。当然,还有两点没有理清。第一点是,如何防止 cookie 盗窃?第二点是,ASP.NET 可以如何检测和阻止劫持?
ASP.NET 会话 cookie 极其简单,仅限于包含会话 ID 字符串本身。ASP.NET 运行库从 cookie 中提取会话 ID,并将其与活动的会话进行比较。如果 ID 有效,ASP.NET 将连接到对应的会话并继续。这种行为极大地方便了已经偷到或者可以猜出有效的会话 ID 的黑客。
XSS 和中间人 (man-in-the-middle) 攻击以及对客户端 PC 的强力访问,都是获取有效 cookie 的方法。为了防止盗窃,您应当实现安全最佳实践来防止 XSS 及其各变种得手。
而为了防止会话 ID 猜测,您应当干脆避免太高估计自己的技能。猜测会话 ID 意味着您知道如何预测有效的会话 ID 字符串。对于 ASP.NET 所使用的算法(15 个随机数字,映射为启用 URL 的字符),随机猜测到有效 ID 的概率接近于零。我想不到任何理由来用自己的会话 ID 生成器替换默认的会话 ID 生成器。许多情况下,这么做只会为攻击者提供方便。
会话劫持更为糟糕的后果是一旦 cookie 被盗或者被猜出,ASP.NET 并没有什么办法来检测欺诈性的 cookie 使用。同样,原因是 ASP.NET 将自己限制为检查 ID 的有效性,以及 cookie 的来源地。
我在 Wintellect 的朋友 Jeff Prosise 为 MSDN Magazine 写了一篇很好的关于会话劫持的文章。他的结论并不令人安慰:几乎不可能建立能够完全抵御依靠偷来的会话 ID Cookie 所发起的攻击的防御工事。但是他开发的代码为进一步提升安全标准提供了非常明智的建议。Jeff 创建了一个 HTTP 模块,该模块为会话 ID Cookie 监视传入的请求和传出的响应。该模块将一条哈希代码附加到会话 ID 之后,使攻击者重用 cookie 更为困难。