旁拮猾 发表于 2025-8-14 08:32:31

防范跨网站请求伪造 (XSRF/CSRF) 攻击

Web 浏览器会随着对网站的每个请求自动发送cookie。例如在A网页中对B网页发送请求,浏览器就会自动带上B网页的cookie,如果B网页采用基于cookie的身份验证,A网页就能冒充用户给B网页发送请求。这种形式的攻击就是跨网站请求伪造(Cross-site request forgery, CSRF),也称为XSRF。
CSRF 攻击并不局限于利用 Cookie,基本身份验证和摘要式身份验证也容易受到攻击。 用户使用基本或摘要式身份验证登录后,浏览器会自动发送凭据,直到会话结束。
CSRF 攻击示例:

[*]用户使用表单身份验证登录到 www.good-banking-site.example.com。 服务器对用户进行身份验证,并发出包含身份验证 cookie 的响应。如果此网站信任收到的任何带有有效身份验证cookie的请求,那么就会容易受到CSRF攻击。
[*]用户访问恶意网站 www.bad-crook-site.example.com。
恶意网站 www.bad-crook-site.example.com 包含类似于以下示例的 HTML 表单:
<h1>Congratulations! You're a Winner!</h1>
<form action="https://www.good-banking-site.example.com/api/account" method="post">
    <input type="hidden" name="Transaction" value="withdraw" />
    <input type="hidden" name="Amount" value="1000000" />
    <input type="submit" value="Click to collect your prize!" />
</form>表单的 action 将发送到www.good-banking-site.example.com网站。
[*]用户点击提交按钮,浏览器发出请求,并自动包括所请求域www.good-banking-site.example.com 的身份验证cookie 。因此请求可以执行经过身份验证的用户可执行的任何操作。
除了用户点击按钮来提交表单外,恶意网站还可以通过以下方式执行攻击:

[*]运行自动提交表单的脚本。
[*]以 AJAX 请求形式发送表单提交。
[*]使用 CSS 隐藏表单。

防范跨网站请求伪造攻击

防范CSRF攻击最常用的方法是采用同步令牌模式(STP):

[*]服务器为每个用户会话生成一个随机且唯一的令牌发送到客户端。因为同源策略,其他网页不能读取到此令牌。
[*]发送请求时,客户端将令牌包含在请求头中发送回服务器进行验证。而恶意网站伪造此请求时,浏览器不会自动附加请求头。
[*]如果服务器收到的令牌与已认证用户的身份不符,那么该请求将被拒绝。
例如,ASP.NET Core MVC或Razor Pages会在页面中添加隐藏的表单域,其包含了防伪令牌:
发送表单请求时,将防伪令牌添加到表单字段或添加到RequestVerificationToken请求头发送给服务器。当请求标头和表单有效负载中都提供了防伪造令牌时,仅验证标头中的令牌。
另一种方式是服务器将防伪令牌添加到cookie中,客户端从cookie中读取防伪令牌添加到请求头发送请求。

ASP.NET Core 中的防伪造

在Program.cs中调用以下 API 之一时,防伪造中间件将自动添加到容器:

[*]AddMvc
[*]MapRazorPages
[*]MapControllerRoute
[*]AddRazorComponents

最小API添加防伪造中间件

var builder = WebApplication.CreateBuilder();

builder.Services.AddAntiforgery();

var app = builder.Build();

app.UseAntiforgery();

app.MapGet("/", () => "Hello World!");

app.Run();调用 AddAntiforgery 和 UseAntiforgery(IApplicationBuilder) 在 DI 中注册防伪造服务。
手动启用时,防伪造中间件必须在身份验证和授权中间件之后运行,以防止在用户未经身份验证时读取表单数据。

配置防伪造

在Program.cs中配置AntiforgeryOptions:
builder.Services.AddAntiforgery(options =>
{
    options.FormFieldName = "__RequestVerificationToken";
    options.HeaderName = "RequestVerificationToken";
    options.Cookie.Name = "XSRF-TOKEN";
});选项说明Cookie确定用于创建防伪造 Cookie 的设置。FormFieldName防伪造系统用于在视图中呈现防伪造令牌的隐藏表单域的名称。HeaderName防伪造系统使用的标头的名称。 如果为 null,则系统仅考虑表单数据。SuppressXFrameOptionsHeader指定是否禁止生成 X-Frame-Options 标头。 默认情况下,标头是使用值“SAMEORIGIN”生成的。 默认为 false。‍
生成防伪造令牌

​IAntiforgery 提供用于配置防伪功能的 API,可通过依赖注入获取IAntiforgery。
示例:生成防伪令牌,并作为cookie在响应中发送:
app.UseRouting();

app.UseAuthorization();

var antiforgery = app.Services.GetRequiredService<IAntiforgery>();

app.Use((context, next) =>
{
    var requestPath = context.Request.Path.Value;

    if (string.Equals(requestPath, "/", StringComparison.OrdinalIgnoreCase)
      || string.Equals(requestPath, "/index.html", StringComparison.OrdinalIgnoreCase))
    {
      var tokenSet = antiforgery.GetAndStoreTokens(context);
      context.Response.Cookies.Append("XSRF-TOKEN", tokenSet.RequestToken!,
            new CookieOptions { HttpOnly = false });
    }

    return next(context);
});前面的示例设置了一个名为 XSRF-TOKEN 的 Cookie。客户端可以读取此 Cookie,并将其值作为附加到 AJAX 请求的标头提供。
例如,Angular 包含内置的 XSRF 保护 ,默认情况下会读取名为 XSRF-TOKEN 的 Cookie。

要求防伪验证

ASP.NET Core 包含三个用于处理防伪造令牌的筛选器:

[*]ValidateAntiForgeryToken
[*]AutoValidateAntiforgeryToken
[*]IgnoreAntiforgeryToken
ValidateAntiForgeryToken

​ValidateAntiForgeryToken筛选器要求请求包含有效的防伪令牌,此筛选器可应用于Action、Controller或全局。


public IActionResult Index()
{
    // ...

    return RedirectToAction();
}AutoValidateAntiForgeryToken

​AutoValidateAntiforgeryToken筛选器仅要求不安全的HTTP方法请求包含有效的防伪令牌,以下HTTP方法发出的请求不需要令牌:

[*]GET
[*]HEAD
[*]OPTIONS
[*]TRACE
示例:

public class HomeController : Controller全局设置此筛选器:
builder.Services.AddControllersWithViews(options =>
{
    options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
});IgnoreAntiforgeryToken

如果 ValidateAntiForgeryToken 特性应用于控制器,则可以在Action用 IgnoreAntiforgeryToken 特性覆盖它。
​IgnoreAntiforgeryToken筛选器用于消除指定Action或Controller对防伪令牌的要求。此筛选器将覆盖在更高级别指定的 ValidateAntiForgeryToken 和 AutoValidateAntiforgeryToken筛选器。
示例:

public IActionResult IndexOverride()
{
    // ...

    return RedirectToAction();
}
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: 防范跨网站请求伪造 (XSRF/CSRF) 攻击