想了解asp.net–模拟CSRF攻击的新动态吗?本文将为您提供详细的信息,我们还将为您解答关于csrf攻击实例的相关问题,此外,我们还将为您介绍关于ASP.NETCore防止跨站请求伪造(XSRF/
想了解asp.net – 模拟CSRF攻击的新动态吗?本文将为您提供详细的信息,我们还将为您解答关于csrf攻击实例的相关问题,此外,我们还将为您介绍关于ASP.NET Core 防止跨站请求伪造(XSRF/CSRF)攻击、ASP.NET Core 防止跨站请求伪造(XSRF/CSRF)攻击 (转载)、ASP.NET MVC中的AntiForgeryToken是否可以防止所有CSRF攻击?、asp.net-mvc – ASP.NET MVC中的AntiForgeryToken是否防止所有CSRF攻击?的新知识。
本文目录一览:- asp.net – 模拟CSRF攻击(csrf攻击实例)
- ASP.NET Core 防止跨站请求伪造(XSRF/CSRF)攻击
- ASP.NET Core 防止跨站请求伪造(XSRF/CSRF)攻击 (转载)
- ASP.NET MVC中的AntiForgeryToken是否可以防止所有CSRF攻击?
- asp.net-mvc – ASP.NET MVC中的AntiForgeryToken是否防止所有CSRF攻击?
asp.net – 模拟CSRF攻击(csrf攻击实例)
<form name="form1" id="form1" runat="server" method="post" action="mysite.com"> <script type="text/javascript"> document.cookie[".ASPXAUTH"] = "someaspxauth"; document.cookie["ASP.NET_SessionId"] = "somesessionid"; document.form1.submit(); </script> </form>
我还缺少什么?
提前致谢.
解决方法
所以要测试一下,假设你有一个页面Transfer.aspx接受一个POST方法和参数txtFrom,txtTo和txtAmount,并带有一个按钮btnSubmit,你想尝试从帐户1转移到帐户2.你的恶意代码可以是这样的:
<form action="http://www.mysite.com/Transfer.aspx" method="post"> <input type="hidden" name="txtFrom" value="1" /> <input type="hidden" name="txtTo" value="2" /> <input type="hidden" name="txtAmount" value="500" /> <input type="hidden" name="__VIEWSTATE" value="[PUT VIEWSTATE VALUE HERE]" /> <input type="hidden" name="__EVENTVALIDATION" value="[PUT EVENTVALIDATION VALUE HERE]" /> <input type="submit" name="btnSubmit" value="Go" /> </form>
您必须事先知道viewstate和eventvalidation值是什么,因此当您正确登录时,您需要从页面中复制该值.这假设您的viewstate是常量,无论用户或会话如何.
现在你有一个恶意页面.如果您在一个选项卡上登录,请在另一个选项卡中打开,然后提交,如果您容易受到攻击,则会进行转移.原因是发送了属于mysite.com的cookie,这意味着将使用在另一个选项卡上存活的会话.
要解决此问题,您需要在帖子中包含唯一的每会话值.通过使用ViewStateUserKey并将其设置为ASP.NET会话ID或其哈希,可以轻松完成此操作.这将使您的__VIEWSTATE值在每个会话中都是唯一的,这意味着您将不再容易受到攻击,因为没有人可以预测您的__VIEWSTATE值.
ASP.NET Core 防止跨站请求伪造(XSRF/CSRF)攻击

CSRF(Cross-site request forgery)跨站请求伪造,也被称为 “One Click Attack” 或者 Session Riding,通常缩写为 CSRF 或者 XSRF,是一种对网站的恶意利用。尽管听起来像跨站脚本(XSS),但它与 XSS 非常不同,XSS 利用站点内的信任用户,而 CSRF 则通过伪装成受信任用户的请求来利用受信任的网站。与 XSS 攻击相比,CSRF 攻击往往不大流行(因此对其进行防范的资源也相当稀少)和难以防范,所以被认为比 XSS 更具危险性。
这幅图已经能够很好地解释了跨站攻击是怎么回事,这样的网站很容易被别人钓鱼,
示例:
创建 2 个网站 officialsite 站点里有个 pay 页面
view:
<h1>支付</h1>
<form action="/pay/post" method="post">
<input name="user" placeholder="姓名" />
<input name="price" placeholder="金额" />
<button type="submit">提交</button>
</form>
paycontroller:
[HttpPost]
public IActionResult Post(string user, decimal price)
{
return Json(new { ok = true, msg = $"{user}支付成功{price}元" });
}
FakeSite 站点里有个 fakepay 页面
view:
<h1>假的支付</h1>
<form action="https://localhost:44316/pay/post" method="post">
<input name="user" placeholder="姓名" />
<input name="price" placeholder="金额" />
<button type="submit">提交</button>
</form>
提交的请求并非自己站点 而是上一个站点的接口
- 运行效果
界面 | 运行效果 |
---|---|
![]() |
![]() |
![]() |
![]() |
那么 asp.net core mvc 里怎么处理?
CSRF 能够成功是因为在同一个浏览器中 Cookies 是共享的,也就无法通过 cookies 权限认证和验证来防止。
解决的办法就是:要确保请求是自己的站点发出的就可以了,其他的站点发来的请求阻挡掉。
通过 AntiForgeryToken 在页面生成一个 Token,发请求的时候把 Token 带上。处理服务端处理请求的时候需要验证这个 Token。而其他站点没有这个 token 那么也就没法通过验证,就被阻挡了。
- 继续改造上面的 demo:
<form action="/pay/post" method="post">
@Html.AntiForgeryToken()
<input name="user" placeholder="姓名" />
<input name="price" placeholder="金额" />
<button type="submit">提交</button>
</form>
F12看生成的html
<h1>支付</h1>
<form action="/pay/post" method="post">
<input name="__RequestVerificationToken" type="hidden" value="CfDJ8Efjwr3EXZVEmlMrBkJrUWtWFC05YY78yz-ce3W4IjEE5m7SzISCXShbON9col2WEDQiqSuKJMbjnUV94a7nwO3O9YXHaFGJMl04AdDpviAGK8DidGgu9d7Gpbm8Zncd01AWL4v274emVQgJTabzPfo" />
<input name="user" placeholder="姓名" />
<input name="price" placeholder="金额" />
<button type="submit">提交</button>
</form>
controller
[ValidateAntiForgeryToken]
[HttpPost]
public IActionResult Post(string user, decimal price)
{
return Json(new { ok = true, msg = $"{user}支付成功{price}元" });
}
运行后界面一切正常
接下来我们在取运行上一个伪造的站点,什么都不改,提交后就会提示返回 400 的错误
这样就能搞定了。 以上是表单提交,项目中常用的还是 ajax 请求,那该如何处理呢
view:
@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery csrf
<form action="/pay/post" method="post">
@Html.AntiForgeryToken()
<input name="user" placeholder="姓名" />
<input name="price" placeholder="金额" />
<button type="submit">提交</button>
<button type="button" id="btnajax">ajax提交</button>
</form>
<script type="text/javascript">
$(function () {
$("#btnajax").click(function () {
$.ajax({
url: "/pay/post",
dataType: "text",
data: {
user: $("input[name=user]").val(),
price: $("input[name=price]").val()
},
headers: {
"RequestVerificationToken": ''@csrf.GetAndStoreTokens(Context).RequestToken''
},
type: "post",
success: function (res) {
alert(res);
}
});
})
})
</script>
将 ajax 请求头里加上 token,这样服务端就会校验。 运行结果
配置
这个令牌验证还是需要借助 cookie 的 配置 在 setup 里,可以根据需要去添加,比如需要验证的域名
services.AddAntiforgery(options =>
{
options.Cookie = new CookieBuilder { Domain = "company.com" };
});
demo 代码见 github|
ASP.NET Core 防止跨站请求伪造(XSRF/CSRF)攻击 (转载)
什么是反伪造攻击?
跨站点请求伪造(也称为XSRF或CSRF,发音为see-surf)是对Web托管应用程序的攻击,因为恶意网站可能会影响客户端浏览器和浏览器信任网站之间的交互。这种攻击是完全有可能的,因为Web浏览器会自动在每一个请求中发送某些身份验证令牌到请求网站。这种攻击形式也被称为 一键式攻击 或 会话控制 ,因为攻击利用了用户以前认证的会话。
CSRF攻击的示例:
(1)用户登录 www.example.com,使用表单身份验证。
(2)服务器对用户进行身份验证,并作出包含身份验证Cookie的响应。
(3)用户访问恶意网站。
恶意网站包含类似于以下内容的HTML表单:
<h1>You Are a Winner!</h1>
<form action="http://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 Me"/>
</form>
请注意,表单的Action属性将请求发送到易受攻击的网站,而不是恶意网站。这是CSRF的“跨站点”部分。
(4)用户点击提交按钮,浏览器会自动包含请求站点(在这种情况下为易受攻击的站点)的认证Cookie。
(5)请求在拥有用户身份验证上下文的服务端运行,并且可以执行允许经过身份验证用户执行的任何操作。
此示例需要用户单击表单按钮,恶意页面也可以通过以下方式:
- 自动运行提交表单的脚本。
- 通过AJAX请求发送表单提交。
- 通过CSS隐藏的表单。
使用SSL不能阻止CSRF攻击,恶意网站可以发送https://请求。
针对GET请求站点的攻击,可以使用Image元素来执行(这种形式的攻击在允许图片的论坛网站上很常见)。使用GET请求更改应用程序状态更容易受到恶意攻击。
因为浏览器将所有相关的Cookie发送到目标网站,所以可以针对使用Cookie进行身份验证的网站进行CSRF攻击。然而,CSRF攻击并不仅限于利用Cookie,例如,Basic和Digest身份验证也很脆弱。用户使用Basic或Digest身份验证登录后,浏览器将自动发送凭据,直到会话(Session)结束。
注意:在这本文中,Session是指用户进行身份验证的客户端会话。它与服务器端会话或Session中间件无关。
用户可以通过以下方式防范CSRF漏洞:
- 网站使用完毕后,注销会话。
- 定期清理浏览器的Cookie。
然而,CSRF漏洞根本上是Web应用程序的问题,而不是依靠用户来解决。
ASP.NET Core MVC是如何处理CSRF的?
警告:
ASP.NET Core使用 ASP.NET Core data protection stack 来实现防请求伪造。如果在服务器集群中必须配置 ASP.NET Core Data Protection,有关详细信息,请参阅 Configuring data protection。如果你的ASP.NET Core站点使用了负载均衡部署了多个实例,就要做ASP.NET Core Data Protection的配置,否则Html.AntiForgeryToken()用的时候会报错。
还可以参考:Host ASP.NET Core in a web farm 以及 Share authentication cookies among ASP.NET apps
如何管理ASP.NET Core Data Protection的过期key,可以查看:Data Protection - how to manage expired key?
在ASP.NET Core MVC 2.0中,FormTagHelper为HTML表单元素注入防伪造令牌。例如,Razor文件中的以下标记将自动生成防伪令牌:
<form method="post">
<!-- form markup -->
</form>
在以下情况为HTML格式元素自动生成防伪令牌:
- 该form标签包含method="post"属性
- action属性为空( action="") 或者
- 未提供action属性(<form method="post">)。
您可以通过以下方式禁用自动生成HTML表单元素的防伪令牌:
- 明确禁止asp-antiforgery,例如
<form method="post" asp-antiforgery="false">
</form>
- 通过使用标签帮助器! 禁用语法,从标签帮助器转化为表单元素。
<!form method="post">
</!form>
- 在视图中移除FormTagHelper,您可以在Razor视图中添加以下指令移除FormTagHelper:
@removeTagHelper Microsoft.AspNetCore.Mvc.TagHelpers.FormTagHelper, Microsoft.AspNetCore.Mvc.TagHelpers
提示:
Razor页面会自动受到XSRF/CSRF的保护。您不必编写任何其他代码,有关详细信息,请参阅XSRF/CSRF和Razor页面。
防御CSRF攻击的最常见方法是令牌同步模式(STP)。STP是当用户请求表单数据页面时使用的技术。服务器将与当前用户的标识相关联的令牌发送给客户端。客户端将令牌发回服务器进行验证。如果服务器接收到与验证用户身份不匹配的令牌,则该请求将被拒绝。令牌是唯一的,并且是不可预测的。令牌也可用于确保一系列请求的正确顺序(确保页面1在第2页之前,页面2在第3页之前)。ASP.NET Core MVC模板中的所有表单都会生成防伪令牌,以下两个示例演示在视图逻辑中生成防伪令牌:
<form asp-controller="Manage" asp-action="ChangePassword" method="post">
</form>
@using (Html.BeginForm("ChangePassword", "Manage"))
{
}
您可以在不使用HTML标签助手的情况下,向<form>元素显式添加防伪令牌@Html.AntiForgeryToken:
<form action="/" method="post">
@Html.AntiForgeryToken()
</form>
在前面的例子中,ASP.NET Core将添加一个隐藏的表单字段,类似于以下内容:
<input name="__RequestVerificationToken" type="hidden" value="CfDJ8NrAkSldwD9CpLRyOtm6FiJB1Jr_F3FQJQDvhlHoLNJJrLA6zaMUmhjMsisu2D2tFkAiYgyWQawJk9vNm36sYP1esHOtamBEPvSk1_x--Sg8Ey2a-d9CV2zHVWIN9MVhvKHOSyKqdZFlYDVd69XYx-rOWPw3ilHGLN6K0Km-1p83jZzF0E4WU5OGg5ns2-m9Yw" />
为项目添加防伪技术
Microsoft.AspNetCore.Antiforgery软件包已作为Microsoft.AspNetCore.Mvc的依赖项包含在内。 同样,通过在Startup.ConfigureServices(IServiceCollection services)方法中调用services.AddMvc(),所需的Antiforgery服务会自动在DI容器中注册。
仍然有些情况需要手动将Antiforgery添加到项目中:
- 需要覆盖默认Antiforgery选项,则需要手动调用services.AddAntiforgery(opts => {opts setup}),以便可以提供特定的选项设置。 这些选项包括诸如cookie标记的cookie名称以及请求标记的表单字段或标题名称等内容。
- 在不使用MVC框架的情况下从头开始编写ASP.Net Core应用程序,则需要手动包含Antiforgery包并注册服务。
请记住,这只是在项目中注册Antiforgery并设置选项。 它不会自动启用任何类型的请求验证! 需要按照以下部分手动执行操作
在ASP.NET Core 中间件(Middleware)管道中验证Antiforgery
即使Antiforgery已添加到项目中,令牌也不会自动生成,也不会根据任何请求进行验证,除非启用它们。
当你需要判断当前Http请求是否通过Antiforgery验证时,可以通过依赖注入手动添加IAntiforgery实例到中间件,然后调用ValidateRequestAsync(httpContext),捕获任何AntiforgeryValidationException并在此情况下返回400,表示Antiforgery验证失败。如下AntiforgeryValidationMiddleware中间件所示:
public class AntiforgeryValidationMiddleware
{
private readonly RequestDelegate next;
private readonly IAntiforgery antiforgery;
public AntiforgeryValidationMiddleware(RequestDelegate next, IAntiforgery antiforgery)
{
this.next = next;
this.antiforgery = antiforgery;
}
public async Task Invoke(Microsoft.AspNetCore.Http.HttpContext context)
{
try
{
await antiforgery.ValidateRequestAsync(context);
await next.Invoke(context);
}
catch (AntiforgeryValidationException exception)
{
context.Response.StatusCode = 400;
}
}
}
关键步骤,添加Cookie令牌
ASP.NET Core中Antiforgery进行跨站请求伪造验证的关键是Antiforgery的Cookie令牌,Cookie令牌是Antiforgery进行验证的依据,ASP.NET Core会验证Http请求中Cookie令牌值(是指解密后的值,默认Cookie令牌值是加密后存储在Cookie中的)是否和隐藏表单字段值、请求头值(也是指解密后的值)相等,如果相等那么Antiforgery验证通过,如果不相等那么验证就失败,所以验证的基准是到达ASP.NET Core的Http请求中要包含Cookie令牌。
在ASP.NET Core MVC视图中使用@Html.AntiForgeryToken添加防伪令牌,默认就会在Http响应中生成一个Cookie令牌,如下所示:
Antiforgery会将请求和Cookie标记作为标记集处理。 当执行IAntiforgery方法GetAndStoreTokens(httpContext)(这是在调用Html.AntiForgeryToken()生成表单隐藏字段时幕后发生的事情)时,它返回包含请求和cookie标记的标记集。 不仅如此,它还将确保:
- Cookie标记作为仅HttpOnly添加到当前的HttpContext响应中。
- 如果已经为此请求生成了令牌集(即,已经使用相同的httpContext调用了GetAndStoreTokens),它将返回相同的令牌集,而不是再次重新生成它。 这一点很重要,因为它允许页面的多个元素得到发布并通过验证,就像有多个表单一样(因为对于所有表单,cookie都是相同的,如果每个表单都有不同的标记,那么只有带有 与cookie匹配的令牌可以通过验证!)。
既然Cookie令牌这么重要,所以我们可以创建一个ASP.NET Core中间件AntiforgeryCookieMiddleware,来为所有Http请求的响应(Response)自动生成Cookie令牌:
using Microsoft.AspNetCore.Antiforgery;
using Microsoft.AspNetCore.Http;
using System.Threading.Tasks;
namespace Assembly.Middlewares
{
public class AntiforgeryCookieMiddleware
{
private readonly RequestDelegate next;
private readonly IAntiforgery antiforgery;
public AntiforgeryCookieMiddleware(RequestDelegate next, IAntiforgery antiforgery)
{
this.next = next;
this.antiforgery = antiforgery;
}
public async Task Invoke(Microsoft.AspNetCore.Http.HttpContext context)
{
var antiforgeryTokenSet = antiforgery.GetAndStoreTokens(context);//调用IAntiforgery的GetAndStoreTokens(httpContext)方法,为所有Http请求的响应添加Cookie令牌
string cookieToken = antiforgeryTokenSet.RequestToken;//IAntiforgery的GetAndStoreTokens(httpContext)方法返回的AntiforgeryTokenSet对象,通过调用其RequestToken属性可以获得Cookie令牌的值
await next.Invoke(context);
}
}
}
另外我们定义一个AntiforgeryCookieMiddleware中间件的扩展类AntiforgeryCookieMiddlewareExtension,用来在ASP.NET Core中间件管道上启用AntiforgeryCookieMiddleware中间件:
using Microsoft.AspNetCore.Builder;
namespace Assembly.Middlewares
{
public static class AntiforgeryCookieMiddlewareExtension
{
public static void UseAntiforgeryCookie(this IApplicationBuilder app)
{
app.UseMiddleware<AntiforgeryCookieMiddleware>();
}
}
}
然后我们在ASP.NET Core项目中Startup类的Configure方法中,调用app.UseAntiforgeryCookie()方法来启用AntiforgeryCookieMiddleware中间件即可,注意还要在Startup类的ConfigureServices方法中使用services.AddAntiforgery()来注册IAntiforgery的依赖注入
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddAntiforgery();//在中间件中使用IAntiforgery,记得要在ConfigureServices方法中使用services.AddAntiforgery来注册IAntiforgery的依赖注入
services.AddMvc();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseAntiforgeryCookie();//启用AntiforgeryCookieMiddleware
if (env.IsDevelopment())
{
//app.UseBrowserLink();
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
在ASP.NET Core MVC中验证Antiforgery
ASP.NET Core MVC包括三个过滤器用于防伪令牌的运行:ValidateAntiForgeryToken、AutoValidateAntiforgeryToken和 IgnoreAntiforgeryToken。
ValidateAntiForgeryToken
ValidateAntiForgeryToken是一个可应用于单个Action、控制器或全局的操作过滤器。请求必须包含一个有效的令牌,否则对具有该过滤器Action的请求将被阻止。
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> RemoveLogin(RemoveLoginViewModel account)
{
ManageMessageId? message = ManageMessageId.Error;
var user = await GetCurrentUserAsync();
if (user != null)
{
var result = await _userManager.RemoveLoginAsync(user, account.LoginProvider, account.ProviderKey);
if (result.Succeeded)
{
await _signInManager.SignInAsync(user, isPersistent: false);
message = ManageMessageId.RemoveLoginSuccess;
}
}
return RedirectToAction(nameof(ManageLogins), new { Message = message });
}
ValidateAntiForgeryToken特性标记的Action方法需要一个令牌,包括HTTP GET请求。如果您全局使用,您可以使用IgnoreAntiforgeryToken特性来覆盖它。
AutoValidateAntiforgeryToken
ASP.NET Core应用程序通常不会为HTTP安全方式(GET,HEAD,OPTIONS和TRACE)生成防伪令牌,而不是在全局范围内使用ValidateAntiForgeryToken特性,然后用IgnoreAntiforgeryToken特性覆盖它,您可以使用AutoValidateAntiforgeryToken特性。该特性与ValidateAntiForgeryToken特性相似,但对以下HTTP请求方式不需要请求令牌:
- GET
- HEAD
- OPTIONS
- TRACE
我们建议您在非API场景中广泛使用AutoValidateAntiforgeryToken。这确保您的POST Action 默认受保护。另一种方式是在默认情况下忽略反伪造令牌,除非在个别Action方法标记了ValidateAntiForgeryToken特性,不过在这种情况下,POST Action方法有可能不受保护,使您的应用程序容易受到CSRF攻击。即使匿名的POST请求也应该发送防伪令牌。
注意:API没有自动机制来发送非Cookie的令牌;您的实现可能取决于您的客户端代码的实现。
一些例子如下所示。
示例(控制器级别):
[Authorize]
[AutoValidateAntiforgeryToken]
public class ManageController : Controller
{
示例(全局)
services.AddMvc(options =>
options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute()));
IgnoreAntiforgeryToken
IgnoreAntiforgeryToken过滤器用于取消已经使用防伪标记的Action(或控制器)的需求。应用时,此过滤器将覆盖在更高级别(全局或控制器)上指定的过滤器ValidateAntiForgeryToken和/或AutoValidateAntiforgeryToken过滤器。
[Authorize]
[AutoValidateAntiforgeryToken]
public class ManageController : Controller
{
[HttpPost]
[IgnoreAntiforgeryToken]
public async Task<IActionResult> DoSomethingSafe(SomeViewModel model)
{
// no antiforgery token required
}
}
JavaScript,AJAX和SPA(单页应用程序)
在传统基于HTML的应用程序中,使用隐藏的表单字段将防伪令牌发送到服务器。在当前基于JavaScript的应用程序和单页应用程序(SPA)中,许多请求以编程方式进行。这些AJAX请求可能会使用其它技术(如请求头或Cookie)来发送令牌。如果使用Cookie来存储身份验证令牌,并在服务器上验证API请求,那么CSRF将是一个潜在的问题,但是,如果使用本地存储来存储令牌,那么CSRF漏洞可能会被减轻,因为本地存储的值不会在每个请求时自动发送到服务器。因此,使用本地存储将反伪造令牌存储在客户机上,并将令牌作为请求头发送,这是一种推荐的方式。
AngularJS
AngularJS通过约定来解决CSRF。如果服务器发送带有名称为XSRF-TOKEN的Cookie ,则Angular的$http服务将向该服务器发送的请求将该Cookie的值添加到请求头。这个过程是自动的,您不需要明确设置请求头。请求头的名称是X-XSRF-TOKEN,服务器会检测该请求头并验证其内容。
对于ASP.NET Core API,使用此约定:
- 配置您的应用程序,在一个Cookie中提供一个称为XSRF-TOKEN的令牌;
- 配置防伪服务查找名为X-XSRF-TOKEN的请求头。
services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN");
查看示例
JavaScript
在视图中使用JavaScript,您可以在视图中使用服务创建令牌,您将Microsoft.AspNetCore.Antiforgery.IAntiforgery服务注入视图并调用GetAndStoreTokens,如下所示:
@{
ViewData["Title"] = "AJAX Demo";
}
@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Xsrf
@functions{
public string GetAntiXsrfRequestToken()
{
return Xsrf.GetAndStoreTokens(Context).RequestToken;
}
}
<h2>@ViewData["Title"].</h2>
<h3>@ViewData["Message"]</h3>
<div class="row">
<input type="button" id="antiforgery" value="Antiforgery" />
<script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-2.1.4.min.js"></script>
<script>
$("#antiforgery").click(function () {
$.ajax({
type: "post",
dataType: "html",
headers:
{
"RequestVerificationToken": ''@GetAntiXsrfRequestToken()''
},
url: ''@Url.Action("Antiforgery", "Home")'',
success: function (result) {
alert(result);
},
error: function (err, scnd) {
alert(err.statusText);
}
});
});
</script>
</div>
这种方法无需在服务器设置Cookie或从客户端读取Cookie。
JavaScript还可以访问Cookie中提供的令牌,然后使用Cookie的内容创建带有令牌值的请求头,如下所示。
context.Response.Cookies.Append("CSRF-TOKEN", tokens.RequestToken,
new Microsoft.AspNetCore.Http.CookieOptions { HttpOnly = false });
然后,假设您构建的脚本发送的请求,将令牌发送为一个名为X-CSRF-TOKEN的请求头中,请配置防伪服务以查找X-CSRF-TOKEN请求头:
services.AddAntiforgery(options => options.HeaderName = "X-CSRF-TOKEN");
以下示例使用jQuery来创建一个包含相应请求头AJAX请求:
var csrfToken = $.cookie("CSRF-TOKEN");
$.ajax({
url: "/api/password/changepassword",
contentType: "application/json",
data: JSON.stringify({ "newPassword": "ReallySecurePassword999$$$" }),
type: "POST",
headers: {
"X-CSRF-TOKEN": csrfToken
}
});
配置防伪
IAntiforgery提供API来配置防伪系统。它可以在Startup类的Configure方法中使用。以下示例在应用程序的主页生成防伪令牌,并将其作为Cookie发送到响应中(使用上述默认命名约定):
public void Configure(IApplicationBuilder app, IAntiforgery antiforgery)
{
app.Use(next => context =>
{
string path = context.Request.Path.Value;
if ( string.Equals(path, "/", StringComparison.OrdinalIgnoreCase) || string.Equals(path, "/index.html", StringComparison.OrdinalIgnoreCase))
{
// We can send the request token as a JavaScript-readable cookie,
// and Angular will use it by default.
var tokens = antiforgery.GetAndStoreTokens(context);
context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken, new CookieOptions() { HttpOnly = false });
}
return next(context);
});
}
选项
您可以在ConfigureServices方法中定制防伪选项:
ASP.NET Core 1.X
services.AddAntiforgery(options =>
{
options.CookieDomain = "mydomain.com";
options.CookieName = "X-CSRF-TOKEN-COOKIENAME";
options.CookiePath = "Path";
options.RequireSsl = false;
options.FormFieldName = "AntiforgeryFieldname";
options.HeaderName = "X-CSRF-TOKEN-HEADERNAME";
options.SuppressXFrameOptionsHeader = false;
});
ASP.NET Core 2.X,与Cookie相关的配置项都移到了options.Cookie属性中,可以和上面ASP.NET Core 1.X对照理解
services.AddAntiforgery(options =>
{
options.Cookie.Domain = "mydomain.com";
options.Cookie.Name = "X-CSRF-TOKEN-COOKIENAME";
options.Cookie.Path = "Path";
options.Cookie.SecurePolicy = CookieSecurePolicy.None;
options.FormFieldName = "AntiforgeryFieldname";
options.HeaderName = "X-CSRF-TOKEN-HEADERNAME";
options.SuppressXFrameOptionsHeader = false;
});
选项 | 描述 |
---|---|
CookieDomain | Cookie的域名。默认为null 。 |
CookieName | Cookie的名称。如果未设置,系统将生成一个以DefaultCookiePrefix (".AspNetCore.Antiforgery")开头的唯一名称。 |
CookiePath | Cookie设置的路径。 |
FormFieldName | 在视图中隐藏表单字段的名称。 |
HeaderName | 防伪系统使用的请求头的名称。如果null ,系统将仅使用表单数据。 |
RequireSsl | 指定防伪系统是否需要SSL。默认为false 。如果为true ,非SSL请求会失败。 |
SuppressXFrameOptionsHeader | 指定是否禁止X-Frame-Options 响应头的生成。默认情况下,响应头生成的值为“SAMEORIGIN”。默认为false 。 |
有关详细信息,请参阅 https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.antiforgery.antiforgeryoptions
扩展防伪
IAntiForgeryAdditionalDataProvider类型允许开发者扩展anti-XSRF系统的行为,在每个令牌中的增加额外数据。每次创建令牌时会调用GetAdditionalData方法,并且返回的值被嵌入生成的令牌内。实现者可以返回时间戳、随机数或任何其它值,然后在验证令牌时调用ValidateAdditionalData来验证此数据。客户的用户名已经嵌入到生成的令牌中,因此不需要包含此信息。如果令牌包含补充数据但没有配置IAntiForgeryAdditionalDataProvider,则补充数据不被验证。
常用场景
CSRF攻击依赖于浏览器默认行为,向站点发出请求同时,会发送与站点相关联的Cookie。这些Cookies存储在浏览器中,它们经常用于经过身份验证的用户提供会话Cookie。基于Cookie的身份验证是一种非常流行的身份验证模式。基于令牌的认证系统越来越受欢迎,特别是对于SPA和其它“智能客户端”场景。
基于Cookie的身份验证
一旦用户使用他们的用户名和密码进行身份验证,就会发出一个令牌,用于标识它们并验证它们是否经过身份验证。令牌存储为Cookie,客户端所做的每个请求都会附带令牌。生成和验证此Cookie是由Cookie身份验证中间件完成的。ASP.NET Core提供了将用户主体序列化为加密Cookie的Cookie 中间件,然后在随后的请求中验证Cookie,重新创建主体并将其分配给HttpContext的User属性。
当使用Cookie时,身份验证Cookie只是表单身份验证凭证的一个容器。在每个请求中,票据作为的表单认证Cookie的值传递并通过表单身份验证,在服务端,以标识经过身份验证的用户。
当用户登录到系统时,会在服务器端创建用户会话,并将其存储在数据库或其他持久存储中,系统生成指向数据存储中的会话密钥,并将其作为客户端Cookie发送。每当用户请求需要授权的资源时,Web服务器将检查此会话密钥,系统检查关联的用户会话是否具有访问请求的资源的权限。如果是,请求继续;否则,请求返回为未授权。在这种方法下,Cookie的使用,使应用程序看起来是有状态的,因为它能够“记住”用户以前已经在服务端完成了身份验证。
用户令牌
基于令牌的身份验证不会在服务器上存储会话。相反,当用户登录时,将颁发令牌(不是防伪令牌)。该令牌保存验证令牌所需的所有数据,它还包含用户信息,以claims的形式。当用户想要访问需要身份验证的服务器资源时,会使用 Bearer {token} 形式的附加授权头发送令牌给服务器。这使得应用程序无状态,因为在每个后续请求中,令牌在请求中传递给服务器端验证。该令牌未 加密 , 而是 编码 。在服务器端,令牌可以被解码以访问令牌内的原始信息。要在随后的请求中发送令牌,您可以将其存储在浏览器的本地存储或Cookie中。如果您的令牌存储在本地存储中,则不必担心XSRF漏洞,但如果令牌存储在Cookie中,则会出现问题。
多个应用程序托管在一个域中
即使example1.cloudapp.net和example2.cloudapp.net是不同的主机,在.cloudapp.net域内的所有主机之间存在一种隐式信任关系。这种隐式信任关系允许潜在的不受信任的主机影响彼此的Cookie(管理AJAX请求的同源策略不一定适用于HTTP Cookie)。ASP.NET Core运行时提供了一些缓解,用户名被嵌入到字段令牌中,因此即使恶意子域能够覆盖会话令牌,它将无法为用户生成有效的字段令牌。然而,当托管在这样的环境中,内置的反XSRF例程仍然无法防止会话劫持或登录CSRF攻击。共享主机环境对会话劫持、登录CSRF和其它攻击都是不可控制的。
其他资源
XSRF on Open Web Application Security Project (OWASP)。
原文:《Preventing Cross-Site Request Forgery (XSRF/CSRF) Attacks in ASP.NET Core》https://docs.microsoft.com/en-us/aspnet/core/security/anti-request-forgery
在ASP.NET Core Web程序中使用Antiforgery防御CSRF
原文链接
ASP.NET MVC中的AntiForgeryToken是否可以防止所有CSRF攻击?
使用AntiForgeryToken要求每个请求都传递一个有效的令牌,因此带有简单脚本将数据发布到我的Web应用程序的恶意网页将不会成功。
但是,如果恶意脚本首先发出一个简单的GET请求(由Ajax发出),以便在隐藏的输入字段中下载包含防伪令牌的页面,然后将其提取出来并用于进行有效的POST,该怎么办?
是否有可能,或者我缺少什么?
asp.net-mvc – ASP.NET MVC中的AntiForgeryToken是否防止所有CSRF攻击?
但是如果一个恶意脚本首先会做一些简单的GET请求(由Ajax),以便在隐藏的输入域中下载包含防伪令牌的页面,将其提取并使用它来生成一个有效的POST?
有可能吗,还是我错过了什么?
解决方法
只要在每个受保护的页面上生成一个新的标记,<%= Html.AntiForgeryToken()%>
并始终确保在任何受保护的操作中检查,使用[ValidateAntiForgeryToken]
这将实现Owasp CSRF Prevention Cheat Sheet处讨论的同步器令牌模式。
为了使脚本成功地提出可接受的请求,它必须先获取表单并读取令牌,然后发布令牌。 Same Origin Policy将阻止它在浏览器中被允许。网站可以向另一个网站制作AJAX样式http请求;只对自己如果由于某种原因可以违反相同的起源政策,那么您将变得脆弱。
请注意,如果您有跨站点脚本漏洞,则攻击者可能会滥用xss漏洞来规避同一原始策略提供的保护(因为脚本现在正在从您自己的站点运行,因此SOP成功)。然后,注入的脚本可以愉快地读取并重新提交令牌。通过XSS实现CSRF保护的这种技术最近在一些蠕虫中很常见。基本上,如果您有XSS,您的CSRF保护是浪费时间,所以确保您不会受到任何影响。
另外值得注意的是Flash和Silverlight。这两种技术都不订阅相同的原始策略,而是使用跨域策略文件来限制对远程资源的访问。如果您在自己的网站上发布跨域策略xml文件,Flash / Silverlight脚本只能访问您网站上的资源。如果您发布此文件,只允许允许信任的第三方服务器的白名单,并且不允许*。
阅读更多关于CSRF at OWASP
参见:XSS Prevention Cheat Sheet
我们今天的关于asp.net – 模拟CSRF攻击和csrf攻击实例的分享已经告一段落,感谢您的关注,如果您想了解更多关于ASP.NET Core 防止跨站请求伪造(XSRF/CSRF)攻击、ASP.NET Core 防止跨站请求伪造(XSRF/CSRF)攻击 (转载)、ASP.NET MVC中的AntiForgeryToken是否可以防止所有CSRF攻击?、asp.net-mvc – ASP.NET MVC中的AntiForgeryToken是否防止所有CSRF攻击?的相关信息,请在本站查询。
本文标签: