如何保护 ASP.NET Core Web API 免受被盗的 JWT 令牌的冒充
How to secure ASP.NET Core Web API from stolen JWT token for Impersonation
我有一个 ASP.NET 核心 REST API 部署在 IIS 后面的服务器中。 REST API 由 Angular JS Web 应用程序和移动(Android/IOS)应用程序使用。对于授权,我使用的是 JWT token()。最近通过安全审计,他们发现存储在本地存储中的 JWT 可以被来自同一组织的其他攻击者窃取并用于冒充(例如,员工利用经理的功能)。
我想将这个人或那台机器标记到那个 JWT,这样当 JWT 被盗时,攻击者就不能滥用它,也不会使用被盗的令牌。我尝试使用 JWT 令牌标记 IP,并将这些查找存储在服务器(内存缓存中)中。以下是我试过的代码,但没有用。
private readonly IHttpContextAccessor _httpContextAccessor;
public TestController(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
var ipAddress = _httpContextAccessor.HttpContext.Connection.RemoteIpAddress.ToString();
我希望每次从不同机器发出请求时输出都不同。但实际输出每次都是相同的 IP,就像这个 15.11.101.25 (虽然我在不同的机器上试过)。如果有任何更好的解决方案,请与我分享。请原谅我的英语。
如果你真的需要那种安全性,你可以将 JWT 令牌与一个安全的(=cookies 只允许通过 https 发送)http-only cookie 结合起来,并在其中存储一种请求令牌根据每个请求发送。
您可以阅读 Where to Store your JWTs – Cookies vs HTML5 Web Storage 涵盖主题的内容,并解释本地存储与 JWT cookie 的优势 down-sides。
Http-only cookie 无法通过 JavaScript 读取(因此不会被盗),因此可以安全抵御 XSS 攻击。并且基于 CSRF 的攻击无法获取 JWT 令牌(因为它是通过 headers 发送的)。
因此,基于 XSS 的攻击将没有基于 cookie 的令牌,而基于 CSRF 的请求将没有对用户进行身份验证所需的 JWT 令牌。 cookie 令牌可以在登录时生成,因此它与登录该计算机的用户相关联。
你当然也可以反过来,将 JWT 放在安全的 cooke 中,并将反请求令牌作为 header。
当然,您仍然可以通过对机器的物理访问来窃取 anti-forgery cookie,但这既不是 XSS 也不是 CSRF,并且不能仅由应用程序保护,机器本身需要受到保护物理攻击类型。
或者,不要将 JWT 令牌存储在本地存储中。当您使用 OpenID 流程时,您的应用程序将在第一次加载时看到它未被授权,将您重定向到 OpenID 提供商,让用户输入他的凭据并使用令牌(或授权代码的代码)将他们重定向回流量)。
当用户关闭浏览器并再次打开网站时,没有令牌了,用户将被重定向到 OpenID 提供商。由于用户仍处于登录状态,因此不会询问任何凭据,他将被重定向回他来自的页面,包括一组新的令牌。您只需要将当前应用程序的令牌存储在内存中(并在到期时刷新)session。
我有一个 ASP.NET 核心 REST API 部署在 IIS 后面的服务器中。 REST API 由 Angular JS Web 应用程序和移动(Android/IOS)应用程序使用。对于授权,我使用的是 JWT token()。最近通过安全审计,他们发现存储在本地存储中的 JWT 可以被来自同一组织的其他攻击者窃取并用于冒充(例如,员工利用经理的功能)。
我想将这个人或那台机器标记到那个 JWT,这样当 JWT 被盗时,攻击者就不能滥用它,也不会使用被盗的令牌。我尝试使用 JWT 令牌标记 IP,并将这些查找存储在服务器(内存缓存中)中。以下是我试过的代码,但没有用。
private readonly IHttpContextAccessor _httpContextAccessor;
public TestController(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
var ipAddress = _httpContextAccessor.HttpContext.Connection.RemoteIpAddress.ToString();
我希望每次从不同机器发出请求时输出都不同。但实际输出每次都是相同的 IP,就像这个 15.11.101.25 (虽然我在不同的机器上试过)。如果有任何更好的解决方案,请与我分享。请原谅我的英语。
如果你真的需要那种安全性,你可以将 JWT 令牌与一个安全的(=cookies 只允许通过 https 发送)http-only cookie 结合起来,并在其中存储一种请求令牌根据每个请求发送。
您可以阅读 Where to Store your JWTs – Cookies vs HTML5 Web Storage 涵盖主题的内容,并解释本地存储与 JWT cookie 的优势 down-sides。
Http-only cookie 无法通过 JavaScript 读取(因此不会被盗),因此可以安全抵御 XSS 攻击。并且基于 CSRF 的攻击无法获取 JWT 令牌(因为它是通过 headers 发送的)。
因此,基于 XSS 的攻击将没有基于 cookie 的令牌,而基于 CSRF 的请求将没有对用户进行身份验证所需的 JWT 令牌。 cookie 令牌可以在登录时生成,因此它与登录该计算机的用户相关联。
你当然也可以反过来,将 JWT 放在安全的 cooke 中,并将反请求令牌作为 header。
当然,您仍然可以通过对机器的物理访问来窃取 anti-forgery cookie,但这既不是 XSS 也不是 CSRF,并且不能仅由应用程序保护,机器本身需要受到保护物理攻击类型。
或者,不要将 JWT 令牌存储在本地存储中。当您使用 OpenID 流程时,您的应用程序将在第一次加载时看到它未被授权,将您重定向到 OpenID 提供商,让用户输入他的凭据并使用令牌(或授权代码的代码)将他们重定向回流量)。
当用户关闭浏览器并再次打开网站时,没有令牌了,用户将被重定向到 OpenID 提供商。由于用户仍处于登录状态,因此不会询问任何凭据,他将被重定向回他来自的页面,包括一组新的令牌。您只需要将当前应用程序的令牌存储在内存中(并在到期时刷新)session。