如何保护 Web 应用程序免受 cookie 窃取攻击?

Posted

技术标签:

【中文标题】如何保护 Web 应用程序免受 cookie 窃取攻击?【英文标题】:How to protect web application from cookie stealing attack? 【发布时间】:2018-09-08 19:27:11 【问题描述】:

我的 Web 应用程序的身份验证机制目前非常简单。

当用户登录时,网站会发回一个会话 cookie,该 cookie 存储在用户的浏览器中(使用localStorage)。

但是,此 cookie 很容易被窃取并用于从另一台机器重播会话。我注意到其他网站(例如 Gmail)有更强大的机制来确保仅复制 cookie 不会允许您访问该会话。

这些机制是什么?小公司或单个开发人员是否也可以使用它们?

【问题讨论】:

this cookie can too easily be stolen,这个假设的基础是什么? 查看 OWASP 上的双重提交 Cookie:owasp.org/index.php/… cookies != 本地存储 【参考方案1】:

我们遇到了类似的问题。您如何安全地存储客户端数据?

我们最终使用了包含 UUID 和该 UUID 的附加副本(存储在 localStorage 中)的 HttpOnly cookie。每个请求,用户都必须将 UUID 和 cookie 都发送回服务器,服务器将验证 UUID 是否匹配。我认为这就是OWASP's double submit cookie 的工作原理。

本质上,攻击者需要访问cookie和localStorage。

【讨论】:

【参考方案2】:

这里有一些想法:

始终使用 https - 并且仅使用 https cookie。

将 cookie 保存在存储系统 (nosql/cache system/db) 中,并将其设置为 TTL(expiry)。

永远不要将收到的 cookie 保存到存储中,而是在保存或检查之前添加盐和哈希,就像使用密码一样。

始终从商店中清除过期的会话。

保存发行IP和IP2Location区域。这样你就可以检查IP是否改变了。

专属会话,一个用户一个会话。

检测到会话冲突(另一个 ip)踢用户并为下一次登录请求 2 路身份验证,例如向注册的电话号码发送短信,以便他可以在登录中输入。

在任何情况下都不要加载不受信任的库。最好将您使用的所有库托管在您自己的服务器/cdn 上。

检查没有注入漏洞。诸如个人资料之类的东西或通常以一种或另一种方式将用户输入的内容发回给用户的东西必须经过严格清理,因为它们是妥协的主要载体。通过任何方式发送到服务器的数据也是如此:cookie、get、post、headers 您可能从客户端使用或不使用的所有内容都必须经过清理。

我应该提到 SQLInjections 吗?

使用 url 会话或在本地存储中存储加密会话 id 的双会话都很好,但它们最终都是无用的,因为它们都可以被已经包含在您网站中的恶意代码访问,比如从加载的库以某种方式被劫持的域(dns 毒药、被破坏的服务器、代理、拦截器等)。努力是勇敢的,但最终是徒劳的。

还有一些其他选项会进一步增加获取和有效使用会话的难度。例如,即使您让用户保持登录状态,您也可以非常频繁地重新发布会话 id,如果它超过 1 分钟,他会得到一个新的会话 id,因此可能的攻击者只有 1 分钟的时间来处理劫持的会话身份证。

即使您应用了所有这些,也不能保证您的会话不会以某种方式被劫持,您只会让这样做变得难以置信地困难到不切实际的地步,但不要犯错100% 安全是不可能的。

您需要在服务器级别考虑许多其他安全功能,例如执行隔离、数据隔离等。这是一个非常大的讨论。安全性不是您对系统应用的东西,它必须是系统从头开始构建的方式!

【讨论】:

【参考方案3】:

确保你绝对不会受到XSS attacks. 的攻击如果你是,下面的一切都是无用的!

显然,你混合了两个东西:LocalStorage 和 Cookies。

它们绝对是两种不同的存储机制:

Cookies 是一串数据,随每个请求发送到您的服务器。 Cookie 以 HTTP 标头的形式发送,并且可以使用 javascript 如果 HttpOnly 未设置。 另一方面,LocalStorage 是浏览器提供的键/值存储机制。数据存储在浏览器本地,不会发送到任何地方。访问它的唯一方法是使用 JavaScript。

现在我假设您使用令牌(可能是 JWT?)对用户进行身份验证。

如果您将令牌存储在 LocalStorage 中,那么只需确保在将其发送到服务器时,将其作为 HTTP 标头发送,这样就完成了,您不会受到任何虚拟攻击。 这种存储/认证技术非常适合单页应用(VueJS、ReactJS等)

但是,如果你使用cookies来存储token,那么问题来了:虽然token不会被其他网站盗用,但是被他们使用。这叫Cross-Site Request Forgery. (CSRF)

这种攻击基本上是通过添加以下内容来实现的:

<img src="https://yourdomain.com/account/delete">

当您的浏览器加载他们的页面时,它会尝试加载图像,并且还会发送身份验证 cookie,最终会删除用户的帐户。

现在有一个很棒的CSRF prevention cheat sheet 列出了绕过此类攻击的可能方法。

一个非常好的方法是使用Synchronizer token method. 它基本上是通过生成令牌服务器端,然后将其作为隐藏字段添加到您要保护的表单中。然后在提交表单时,您只需在应用更改之前验证该令牌。 此技术适用于使用简单表单的模板引擎的网站。 (不是 AJAX)

HttpOnly 标志也增加了 cookie 的安全性。

【讨论】:

【参考方案4】:

您可以通过电话号码或电子邮件使用两步验证。 Steam 也是一个很好的例子。每次从新计算机登录时,您必须将其标记为“安全计算机”或使用电话号码/电子邮件进行验证。

【讨论】:

以上是关于如何保护 Web 应用程序免受 cookie 窃取攻击?的主要内容,如果未能解决你的问题,请参考以下文章

如何保护刷新令牌免受黑客攻击

如何保护 ASP.NET Core Web API 免受被盗 JWT 令牌以进行模拟

如何保护 Webservice 免受拒绝服务攻击?

如何获取用户当前的国家并保护它免受操纵?

如何使用公钥保护 Web API 免受未经授权的访问?

使用 Spring Security 保护 Web 应用程序免受 CSRF 攻击