防伪令牌可重复使用
Antiforgery tokens are reusable
我们使用 ASP.NET MVC 的默认防伪技术。
最近一家安全公司对表格进行了扫描,并注意到他们可以多次使用相同的 _RequestVerificationToken
组合(cookie + 隐藏字段)。
或者他们是怎么说的:“正文中的 CSRF 令牌在服务器端进行了验证,但即使在服务器端使用后也不会被撤销
生成一个新的 CSRF 令牌。"
阅读文档和多篇关于防伪实现的文章后,我的理解是,只要会话用户与令牌中的用户匹配,这确实是可能的。
他们的部分建议:“这样的代币应该在
最少,每个用户会话都是唯一的
据我了解,情况已经如此,除了匿名用户,对吗?
我的问题:这是安全问题吗?风险有多大?是否有确保令牌不是 reusable/invalidated.
的库
如果没有,在会话中包含一个额外的随机令牌,该令牌将在每次请求时重置,听起来可以解决问题。
客户最终同意 ASP.NET 的防伪实施就足够了。
只是为了好玩,我想扩展 Antiforgery 以满足失效要求。
Antiforgery 库有一个扩展点:IAntiforgeryAdditionalDataProvider
(Core) and IAntiForgeryAdditionalDataProvider
(pre-Core)
在 ASP.NET MVC(pre-Core)中,您可以在启动时设置它。
using System.Web;
using System.Web.Helpers;
// ...
namespace AntiForgeryStrategiesPreCore
{
public class MvcApplication : HttpApplication
{
protected void Application_Start()
{
// ...
AntiForgeryConfig.AdditionalDataProvider = new MyAdditionalDataProvider();
}
}
}
对于 ASP.NET Core,您需要将 IAntiforgeryAdditionalDataProvider
注册为服务。如果你不这样做,它将使用什么都不做的 DefaultAntiforgeryAdditionalDataProvider
(source)。
using System;
using Microsoft.AspNetCore.Antiforgery;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace AntiForgeryStrategiesCore
{
// ...
public class Startup
{
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IAntiforgeryAdditionalDataProvider, SingleTokenAntiforgeryAdditionalDataProvider>();
// ...
}
}
// ...
}
现在您可以将其他数据添加到您的防伪令牌中,这些数据将被加密到您的 cookie 和表单字段中。
这是一个 MVC Core 示例,它保留会话中的单个令牌,并在使用后将其删除。
using Microsoft.AspNetCore.Antiforgery;
using Microsoft.AspNetCore.Http;
namespace AntiForgeryStrategiesCore
{
public class SingleTokenAntiforgeryAdditionalDataProvider : IAntiforgeryAdditionalDataProvider
{
private const string TokenKey = "SingleTokenKey";
public string GetAdditionalData(HttpContext context)
{
var token = TokenGenerator.GetRandomToken();
context.Session.SetString(TokenKey, token);
return token;
}
public bool ValidateAdditionalData(HttpContext context, string additionalData)
{
var token = context.Session.GetString(TokenKey);
context.Session.Remove(TokenKey);
return token == additionalData;
}
}
}
不推荐这样做,因为当您打开包含多个表单的多个选项卡时,只有一个表单在会话中具有有效令牌,而另一个表单将失败。这就是为什么我做了一个持有多个令牌的原因。
您可以在 GitHub(基于时间,基于队列)上找到 AdditionalDataProvider 和其他人。
我们使用 ASP.NET MVC 的默认防伪技术。
最近一家安全公司对表格进行了扫描,并注意到他们可以多次使用相同的 _RequestVerificationToken
组合(cookie + 隐藏字段)。
或者他们是怎么说的:“正文中的 CSRF 令牌在服务器端进行了验证,但即使在服务器端使用后也不会被撤销
生成一个新的 CSRF 令牌。"
阅读文档和多篇关于防伪实现的文章后,我的理解是,只要会话用户与令牌中的用户匹配,这确实是可能的。
他们的部分建议:“这样的代币应该在 最少,每个用户会话都是唯一的 据我了解,情况已经如此,除了匿名用户,对吗?
我的问题:这是安全问题吗?风险有多大?是否有确保令牌不是 reusable/invalidated.
的库如果没有,在会话中包含一个额外的随机令牌,该令牌将在每次请求时重置,听起来可以解决问题。
客户最终同意 ASP.NET 的防伪实施就足够了。 只是为了好玩,我想扩展 Antiforgery 以满足失效要求。
Antiforgery 库有一个扩展点:IAntiforgeryAdditionalDataProvider
(Core) and IAntiForgeryAdditionalDataProvider
(pre-Core)
在 ASP.NET MVC(pre-Core)中,您可以在启动时设置它。
using System.Web;
using System.Web.Helpers;
// ...
namespace AntiForgeryStrategiesPreCore
{
public class MvcApplication : HttpApplication
{
protected void Application_Start()
{
// ...
AntiForgeryConfig.AdditionalDataProvider = new MyAdditionalDataProvider();
}
}
}
对于 ASP.NET Core,您需要将 IAntiforgeryAdditionalDataProvider
注册为服务。如果你不这样做,它将使用什么都不做的 DefaultAntiforgeryAdditionalDataProvider
(source)。
using System;
using Microsoft.AspNetCore.Antiforgery;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace AntiForgeryStrategiesCore
{
// ...
public class Startup
{
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IAntiforgeryAdditionalDataProvider, SingleTokenAntiforgeryAdditionalDataProvider>();
// ...
}
}
// ...
}
现在您可以将其他数据添加到您的防伪令牌中,这些数据将被加密到您的 cookie 和表单字段中。 这是一个 MVC Core 示例,它保留会话中的单个令牌,并在使用后将其删除。
using Microsoft.AspNetCore.Antiforgery;
using Microsoft.AspNetCore.Http;
namespace AntiForgeryStrategiesCore
{
public class SingleTokenAntiforgeryAdditionalDataProvider : IAntiforgeryAdditionalDataProvider
{
private const string TokenKey = "SingleTokenKey";
public string GetAdditionalData(HttpContext context)
{
var token = TokenGenerator.GetRandomToken();
context.Session.SetString(TokenKey, token);
return token;
}
public bool ValidateAdditionalData(HttpContext context, string additionalData)
{
var token = context.Session.GetString(TokenKey);
context.Session.Remove(TokenKey);
return token == additionalData;
}
}
}
不推荐这样做,因为当您打开包含多个表单的多个选项卡时,只有一个表单在会话中具有有效令牌,而另一个表单将失败。这就是为什么我做了一个持有多个令牌的原因。 您可以在 GitHub(基于时间,基于队列)上找到 AdditionalDataProvider 和其他人。