头条号
  mcbWRrRPlhs5 2023年11月30日 25 0

浏览器提供了各种持久数据的解决方案。存储令牌时,您应该权衡存储选择与安全风险。

头条号_访问令牌

Web 应用程序不是静态站点,而是静态和动态内容的精心组合。更常见的是,Web 应用程序逻辑在浏览器中运行。该应用程序不是从服务器获取所有内容,而是在浏览器中运行 JavaScript,从后端 API 获取数据并相应地更新 Web 应用程序演示。

为了保护对数据的访问,组织应采用 OAuth 2.0。使用 OAuth 2.0,JavaScript 应用程序需要向 API 的每个请求添加访问令牌。出于可用性原因,JavaScript 应用程序通常不会按需请求访问令牌,而是存储它。问题是,如何在 JavaScript 中获取这样的访问令牌?当您获得令牌时,应用程序应该将令牌存储在哪里,以便在需要时将其添加到请求中?

本文讨论浏览器中可用的不同存储解决方案,并重点介绍与每个选项相关的安全风险。在审查了威胁之后,它以模式的形式描述了一种解决方案,为必须与OAuth 保护的 API集成的JavaScript 应用程序提供最佳的浏览器安全选项。

获取访问令牌AccessToken

请注意,任何人都可以检查浏览器加载的资源,包括任何JavaScript 代码。因此,任何用 JavaScript 实现的 OAuth 客户端都被视为公共客户端——无法保守秘密,因此无法在令牌请求期间进行身份验证。然而,代码交换证明密钥 ( PKCE ) 提供了一种保护公共客户端代码流安全的方法。为了降低与授权代码相关的风险,请始终在代码流中应用 PKCE。

浏览器威胁


  1. 跨站请求伪造 (CSRF)

在跨站点请求伪造 (CSRF)攻击中,恶意行为者会诱骗用户无意中通过浏览器执行恶意请求。例如,攻击者可能会在网站中嵌入精心设计的图像 src 字符串,从而触发浏览器运行 GET 请求,或者在恶意网站上添加表单来触发 POST 请求。在任何情况下,浏览器都可能会自动向此类请求添加 cookie,包括单点登录 (SSO) cookie。

CSRF 攻击也称为“会话骑乘”,因为攻击者通常利用用户经过身份验证的会话来执行恶意请求。因此,攻击者可以代表用户静默执行请求并调用用户可以调用的任何端点。不过,攻击者无法读取响应,因此他们通常会提出一次性状态更改请求,例如更新用户密码。

  1. 跨站脚本 (XSS)

跨站点脚本 (XSS)漏洞允许攻击者将恶意客户端代码注入到其他受信任的网站中。例如,漏洞可能发生在 Web 应用程序中用户输入生成未正确清理的输出的任何位置。浏览器会自动在受信任网站的上下文中运行恶意代码。

XSS 攻击可用于窃取访问和刷新令牌或执行 CSRF 攻击。不过,XSS 攻击有一个时间窗口,因为它们只能在有限的时间内运行,例如在令牌的生命周期内或只要存在漏洞的选项卡处于打开状态。

即使在无法使用 XSS 检索访问令牌的情况下,攻击者也可能利用 XSS 漏洞,使用会话骑行将经过身份验证的请求发送到安全的 Web 端点。然后,攻击者可以冒充用户,调用用户可以调用的任何后端端点,并造成严重损害。

浏览器中的存储解决方案

当应用程序收到访问令牌时,它需要存储该令牌以便在 API 请求中使用它。有多种方法可以在用户的浏览器中保存数据。应用程序可以使用专用 API(例如 Web Storage API 或 IndexedDB)来存储令牌。应用程序还可以简单地将令牌保留在内存中或将它们放入 cookie 中。有些存储机制是持久性的,而另一些存储机制在一段时间后或在页面关闭或刷新时会被擦除。

一些解决方案跨选项卡共享数据,而其他解决方案仅在选项卡本地。然而,本指南中介绍的大多数方法都存储每个源的数据。因此,了解一些概念:起源和地点,对于任何相关讨论都是有益的。

某些(Web)资源的来源是其 URL 的方案、主机名和端口。例如,两者https://example.com/number/one具有https://example.com:80/path/two相同的来源,因为它们共享方案 (https) 和主机名 (example.com) 以及端口(默认端口)。它们的起源是https://example.com,与 不同https://example.com:8443,或者https://this.example.com因为它们的端口和主机名不同。

相比之下,站点比资源的来源更大。站点是提供资源集合的 Web 应用程序的通用名称。简单来说,站点就是方案和域名,例如https://example.com. 虽然https://example.com和https://this.example.com:8443具有不同的来源(不同的主机名和端口),但它们是同一站点,因为它们托管在同一域(example.com)上并使用相同的方案(https)。(从技术上讲,这个定义存在细微差别,但这个简化的陈述有助于解释这个概念)。

本地存储

每当应用程序调用 API 时,它都会从存储中获取令牌并将其手动添加到请求中。然而,由于本地存储可通过 JavaScript 获得,这意味着该解决方案也容易受到跨站点脚本攻击 (XSS)。

如果您使用 localStorage 来持久保存访问令牌,并且攻击者设法在您的应用程序中运行外部 JavaScript 代码,则攻击者可以窃取任何令牌并直接调用 API。此外,XSS还允许攻击者操纵应用程序本地存储中的数据,这意味着攻击者可以更改令牌。

请注意,本地存储中的数据是永久存储的,这意味着存储在其中的任何令牌都驻留在用户设备(笔记本电脑、计算机、移动设备或其他设备)的文件系统上,即使在浏览器关闭后也可以被其他应用程序访问。因此,在使用 localStorage 时,请考虑端点安全性。考虑并防范浏览器外部的攻击媒介,例如恶意软件、被盗设备或磁盘。

根据上述讨论,请遵循以下建议:

  • 不要在本地存储中存储令牌等敏感数据。
  • 不要信任本地存储中的数据(尤其是用于身份验证和授权的数据)。

会话存储

会话存储是Web Storage API 提供的另一种存储机制。与本地存储不同,sessionStorage当选项卡或浏览器关闭时,使用该对象存储的任何数据都会被擦除。此外,存储在会话存储中的数据无法在其他选项卡中访问。只有当前选项卡和源中的 JavaScript 代码可以使用相同的会话存储进行读写。

会话存储可以被认为比本地存储更安全,因为浏览器会在窗口关闭时自动删除任何令牌,因此不会留下任何令牌。此外,由于会话存储不在选项卡之间共享,攻击者无法从另一个选项卡(或窗口)读取令牌,这减少了 XSS 攻击的影响。

实际上,使用 sessionStorage 存储令牌时的主要安全问题是 XSS。如果您的应用程序容易受到 XSS 攻击,攻击者可以从存储中窃取令牌并在 API 调用中重放它。因此,会话存储不适合存储令牌等敏感数据。

索引数据库

IndexedDB 是索引数据库 API 的缩写。它是一个用于在浏览器中异步存储大量数据的 API。但是,在存储令牌时,通常不需要此浏览器 API 提供的功能和功能。由于应用程序会在每次 API 调用时发送令牌,因此最好将其大小保持在最低限度。

与迄今为止讨论的其他客户端存储机制一样,对使用索引数据库 API 存储的数据的访问受到同源策略的限制。只有同源的资源和服务工作者才能访问数据。从安全角度来看,IndexedDB 与本地存储相当:

  • 令牌可能会通过文件系统泄漏。
  • 令牌可能会通过 XSS 攻击泄漏。

因此,请勿在 IndexedDB 中存储访问令牌或其他敏感数据。IndexedDB更适合应用程序离线工作所需的数据,例如图像。

在记忆中

存储令牌的一种非常安全的方法是将其保存在内存中。与其他方法相比,令牌不存储在文件系统中,从而降低了设备文件系统的风险。

请注意,攻击者在获取令牌后可能无法直接访问令牌,因此可能无法直接使用令牌调用 API。即便如此,他们也可以随时通过apiClient保存令牌引用的 API 调用 API。然而,任何此类攻击都仅限于选项卡打开的时间段以及界面提供的功能。

除了与潜在 XSS 漏洞相关的安全问题之外,将令牌保留在内存中对于用户体验也有很大的缺点,因为令牌会在页面重新加载时丢失。然后,应用程序必须获取新的令牌,这可能会触发新的用户身份验证。安全的设计应该考虑用户体验。

使用服务工作人员的架构通过在与主网页分离的单独线程中运行令牌处理程序功能来减轻可用性问题。服务工作者有效地充当应用程序、浏览器和网络之间的代理。因此,它们可以拦截请求和响应,例如缓存数据并启用离线访问,或者获取和添加令牌。

当使用 JavaScript 闭包或服务工作人员处理令牌和 API 请求时,XSS 攻击可能会针对 OAuth 流(例如回调或静默流)来获取令牌。他们可能会取消注册并绕过任何服务工作者,或者使用原型污染通过覆盖诸如window.fetch. 因此,考虑 JavaScript 闭包和服务工作者是为了方便,而不是安全。

Cookie

Cookie 是存储在浏览器中的数据片段。根据设计,浏览器会向服务器的每个请求添加 cookie。因此,应用程序必须谨慎使用 cookie。如果配置不仔细,浏览器可能会在跨站点请求中附加 cookie,并允许跨站点请求伪造 (CSRF) 攻击。

Cookie 具有控制其安全属性的属性。例如,SameSite 属性可以帮助降低 CSRF 攻击的风险。当 Cookie 的 SameSite 属性设置为 时Strict,浏览器会将其添加到源自 Cookie 来源站点且目标站点相同的请求中。当请求嵌入任何第三方网站(例如通过链接)时,浏览器不会添加 cookie。

您可以通过 JavaScript 设置和检索 cookie。然而,当使用 JavaScript 读取 cookie 时,应用程序容易受到 XSS(除了 CSRF 之外)的攻击。因此,首选方案是使用一个后端组件来设置 cookie 并将其标记为HttpOnly. 该标志可以减少 XSS 攻击造成的数据泄露,因为它向浏览器表明 cookie 不能通过 JavaScript 获得。

为了防止 cookie 通过中间人攻击泄漏(这可能会导致会话劫持),cookie 只能通过加密连接 (HTTPS) 发送。要指示浏览器仅在 HTTPS 请求中发送 cookie,cookie 必须设置安全属性。

Set-Cookie:token=myvalue;SameSite=Strict;Secure;HttpOnly

与浏览器中的任何其他永久存储解决方案一样,即使浏览器关闭后,cookie 也可能驻留在文件系统上(例如,cookie 不必过期,或者浏览器可以保留会话 cookie 作为恢复会话功能的一部分)。为了降低从文件系统中窃取令牌的风险,请仅将加密令牌存储在 cookie 中。因此,后端组件必须仅在 Set-Cookie 标头中返回加密令牌。

威胁矩阵

下表总结了浏览器中存储解决方案的威胁评估,其中主要威胁向量标记为红色。橙色威胁需要的缓解措施超出了网络技术所能提供的范围。使用正确的设置可以成功消除绿色威胁。

头条号_API_02

每当攻击者设法窃取令牌时,只要访问令牌独立于用户和应用程序有效,他们就可以使用访问令牌。如果攻击者设法窃取刷新令牌,他们可以显着延长攻击时间并增加损害,因为他们可以更新访问令牌。黑客甚至可能将攻击扩展到 JavaScript 应用程序使用的 API 之外的 API。例如,攻击者可以尝试重放访问令牌并利用不同 API 中的漏洞。

被盗的访问令牌可能会导致重大损害,而 XSS 仍然是 Web 应用程序的主要问题。因此,请避免将访问令牌存储在客户端代码可以访问的位置。相反,将访问令牌存储在 cookie 中。配置适当的属性后,浏览器不存在通过 cookie 泄露访问令牌的风险。XSS 漏洞可与同一站点上的会话攻击漏洞相媲美。

带有 Cookie 的 OAuth 语义

Cookie 仍然是传输令牌和充当 API 凭证的最佳选择,因为即使攻击者成功利用 XSS 漏洞,也无法从 Cookie 中检索访问令牌。然而,要实现这一点,必须正确配置 cookie。

首先,将 cookie 标记为HttpOnly无法通过 JavaScript 访问,以解决 XSS 攻击的风险。另一个重要属性是安全标志,可确保 cookie 仅通过 HTTPS 发送,以减轻中间人攻击。

其次,颁发仅在几分钟内有效的短期访问令牌。在最坏的情况下,具有最短生命周期的访问令牌只能在可接受的短时间内被滥用。通常认为 15 分钟的有效时间是合适的。让 cookie 和 token 大约在同一时间过期。

第三,将令牌视为敏感数据。仅在 cookie 中存储加密令牌。如果攻击者设法获得加密令牌,他们将无法从中解析任何数据。攻击者也无法将加密的令牌重放给任何其他 API,因为其他 API 无法解密该令牌。加密令牌只是限制了被盗令牌的影响。

第四,限制发送 API 凭证的时间。仅将 cookie 发送到需要 API 凭据的资源。这意味着确保浏览器仅将 cookie 添加到实际需要访问令牌的 API 调用中。为此,cookie 需要具有适当的设置,例如SameSite=Strict指向 API 端点的域和路径的域属性。

最后,当使用刷新令牌时,请确保将它们存储在自己的 cookie 中。无需在每个 API 请求中都发送它们,因此请确保情况并非如此。仅当刷新过期的访问令牌时才必须添加刷新令牌。这意味着持有刷新令牌的 cookie 与具有访问令牌的 cookie 的设置略有不同。

令牌处理程序模式

令牌处理程序模式是一种设计模式,它结合了 JavaScript 客户端中 OAuth 的最佳实践原则。它遵循前端后端 (BFF) 的方法,如基于浏览器的应用程序的 OAuth 2.0中所述。该模式引入了一个后端组件,该组件能够发出具有加密令牌和必要属性的 cookie,如上所述。

后端组件的职责是:

  • 作为OAuth客户端与授权服务器交互,发起用户认证并获取token。
  • 管理 JavaScript 应用程序的令牌,使其不可访问。
  • 代理和拦截所有 API 请求以附加正确的访问令牌。

令牌处理程序模式定义了一个 BFF,它为浏览器中运行的应用程序抽象 OAuth。换句话说,令牌处理程序模式建议 JavaScript 应用程序可以使用一个 API 来对用户进行身份验证并安全地对 API 进行经过身份验证的调用。为此,该模式使用 cookie 来存储和发送访问令牌。

令牌处理程序是一个后端组件,例如可以驻留在 API 网关中。它由两部分组成:

  • OAuth 代理,处理 OAuth 流程以从授权服务器获取令牌。
  • OAuth 代理,拦截对 API 的所有请求并将 cookie 转换为令牌。

头条号_应用程序_03

OAuth代理获取令牌后,会发出具有以下属性的cookie:

  • SameSite=严格
  • 仅HTTP
  • 安全的
  • API 的路径

由于令牌处理程序是后端组件,因此 OAuth 代理是一个机密客户端,可以向授权服务器进行身份验证(与作为公共客户端的 JavaScript 客户端相比)。这意味着要获取令牌,OAuth 代理需要进行身份验证。因此,攻击者需要掌握客户端凭据才能成功获取新令牌。在没有客户端凭据的情况下在 JavaScript 中运行静默流程将会失败。

为了使令牌处理程序模式发挥作用,JavaScript 应用程序和令牌处理程序组件必须部署在同一站点上(换句话说,它们必须在同一域中运行)。否则,由于 cookie 的同站限制,浏览器不会将 token cookie 添加到 API 请求中。

要获取数据,JavaScript 应用程序只需通过 OAuth 代理调用 API:

浏览器会自动将 cookie 添加到请求中。在上面的示例中,浏览器在跨域请求中包含 cookie。但是,由于 cookie 属性SameSite=Strict,浏览器只会在同一站点(同一域)的跨域请求中添加 cookie。

OAuth 代理解密 cookie 并将令牌添加到上游 API。cookie 属性确保浏览器仅向 HTTPS 请求添加 cookie,从而确保它们在传输过程中的安全。由于令牌是加密的,因此它们在静态时也是安全的。然后使用令牌来安全访问 API。

结论

使用 OAuth 和访问令牌可以最好地保护 API 访问。然而,JavaScript 应用程序落后于八号球。没有安全的解决方案可以在浏览器中存储令牌。所有可用的解决方案在某种程度上都容易受到 XSS 的攻击。因此,保护任何应用程序的首要任务应该是防止 XSS 漏洞。

令牌处理程序模式通过将加密令牌存储在任何 JavaScript 都无法使用的 cookie 中来降低 XSS 风险。它将 Web 问题与 API 问题分开,并为使用成熟的 Web 技术强化 JavaScript 应用程序提供了指导,而不会影响 Web 架构。查看令牌处理程序模式的详细描述并探索各种示例。


【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月30日 0

暂无评论

推荐阅读
  mcbWRrRPlhs5   2023年11月30日   26   0   0 访问令牌API应用程序
mcbWRrRPlhs5
作者其他文章 更多