防止具有相同站点 cookie 属性的 CSRF
Posted
技术标签:
【中文标题】防止具有相同站点 cookie 属性的 CSRF【英文标题】:Preventing CSRF with the same-site cookie attribute 【发布时间】:2016-12-21 15:26:35 【问题描述】:我在网上冲浪,发现文章Preventing CSRF with the same-site cookie attribute。
在链接维护时,我们需要添加 Set-Cookie 标头。
设置-Cookie:键=值;仅http; SameSite=严格
现在我的问题是,我想在我的 ASP.NET 站点中设置所有 Cookie 和身份验证 Cookie。 我尝试使用 IIS 的标头来设置它,但有人说这是错误的实现方式。
下面我也试过了。
HttpCookie newAuthenticationCookie = new HttpCookie(FormsAuthentication.FormsCookieName
, FormsAuthentication.Encrypt(newAuthenticationTicket))
HttpOnly = true
;
newAuthenticationCookie.Values.Add("SameSite", "strict");
但这似乎对我没有帮助。
请建议我一个更好的方法来做到这一点。
谢谢。
【问题讨论】:
【参考方案1】:在对HttpCookie Source 进行深入审查后,确认我们无法对代码执行此操作,因为无法在 Cookie 上添加额外属性,并且类被标记为密封。
但无论如何我还是通过如下修改 web.config 来管理解决方案。
<rewrite>
<outboundRules>
<rule name="Add SameSite" preCondition="No SameSite">
<match serverVariable="RESPONSE_Set_Cookie" pattern=".*" negate="false" />
<action type="Rewrite" value="R:0; SameSite=strict" />
<conditions>
</conditions>
</rule>
<preConditions>
<preCondition name="No SameSite">
<add input="RESPONSE_Set_Cookie" pattern="." />
<add input="RESPONSE_Set_Cookie" pattern="; SameSite=strict" negate="true" />
</preCondition>
</preConditions>
</outboundRules>
</rewrite>
这会在每个 Set-Cookie 上添加 SameSite=strict。
【讨论】:
.NET 现已支持此功能,请在下方查看我的答案 从 Asp.NET 4.7.2 开始,您可以通过将以下行添加到 Web.config 中的<system.web>
节点来执行相同的操作。 <httpcookies samesite="Strict"/>
我尝试在 .Net 4.7.2 中使用 Unrecognized attribute 'samesite'
在 MS 文档中也没有提到【参考方案2】:
因为在这个时代,我们使用 owin 来修复同样愚蠢的 webapi cookie 错误...
public class CookieSameSiteMiddleware : OwinMiddleware
public CookieSameSiteMiddleware(OwinMiddleware next) : base(next)
public override async Task Invoke(IOwinContext context)
var url = context.Request.Path.Value.ToLowerInvariant();
if (url.Contains("/api/mylogin"))
context.Response.OnSendingHeaders(x =>
var scv = context.Response.Headers.FirstOrDefault(h => h.Key == "Set-Cookie");
if (!scv.Equals(default(KeyValuePair<string, string[]>)))
//context.Response.Headers.Remove("Set-Cookie");
context.Response.Headers.Set("Set-Cookie", scv.Value[0] + "; SameSite=strict");
, null);
await this.Next.Invoke(context);
确保中间件在 .UseWebApi() 之前注册
【讨论】:
+1 这种方法效果很好。代码中有一个小错误——当您的登录页面设置多个 cookie 时,它会过滤掉 cookie。我修复了错误并完善了代码here。【参考方案3】:您也可以在创建 cookie 时在代码中设置:
var httpCookie = new HttpCookie("mycookie", "myvalue");
httpCookie.Path += ";SameSite=Strict";
Response.SetCookie(httpCookie);
这将为您提供以下标题:
Set-Cookie:mycookie=myvalue; path=/;SameSite=Strict
在将其推入框架之前有点破解。
【讨论】:
更好的解决方案!但是,在响应时,您只能读取 cookie,但不能对其进行修改...您必须创建一个新的。【参考方案4】:.NET 4.7.2 现在内置支持SameSite
属性。HttpCookie
现在有一个名为SameSite
的属性。 查看来自 Microsoft 的更多信息 here。
不再需要通过配置文件破解它。
【讨论】:
以防万一它通过此线程帮助其他旅行者:将 .NET 4.7.2 添加到 Visual Studio 2017 from dotnet.microsoft.com/download/dotnet-framework 我不知道为什么,但我仍然看到警告说“不允许使用 'sameSite' 属性。” 我使用的是 4.7.2【参考方案5】:在 4.7.2 之前,您只需将字符串附加到 cookie 路径即可。
FormsAuthentication.SetAuthCookie(username, false, FormsAuthentication.FormsCookiePath + "; SameSite=Lax");
【讨论】:
这是一个重复的答案 @Julian 不是真的。另一个答案提到了自定义 cookie,而不是内置的 Forms Auth 一个 在哪里添加这一行? 验证用户名/密码后在您的登录页面中。您有 2 个选项用于从此类设置身份验证 cookie - 另一个是 FormsAuthentication.RedirectFromLogin()。【参考方案6】:只需添加我的答案即可系统化在此处和其他地方找到的所有信息。
1。在 4.7.2 及更高版本下保护自定义 cookie
var c = new HttpCookie("test");
c.SameSite = SameSiteMode.Lax;
2。保护表单身份验证 cookie
在 web.config 中
<authentication mode="Forms">
<forms ..... cookieSameSite="Lax" />
</authentication>
3。保护 ASP.NET 会话 cookie
在 Global.asax 中
void Session_Start(Object sender, EventArgs e)
Response.Cookies["ASP.NET_SessionId"].SameSite = SameSiteMode.Lax;
//while we're at it lets also make it secure
if (Request.IsSecureConnection)
Response.Cookies["ASP.NET_SessionId"].Secure = true;
有趣的事实:即使您设置了<httpCookies requireSSL="true" />
,ASP.NET 会话 cookie由于某种原因仍然是不安全的。
3(a)。更新 01.2020:.NET 4.8 会话 cookie 现在默认为“SameSite”
安装最新的 Windows 更新将使您的会话 cookie 默认为 Lax
。你可以在这里控制它:
<sessionState cookieSameSite="Lax" /> <!-- in system.web -->
4。 <httpCookies samesite=xxx>
不存在?
添加<httpCookies sameSite="Strict" />
就像在 web.config 上面的评论中建议的那样不起作用,我收到了错误。
无法识别的属性'samesite'
即使我的目标是 4.7.2。在多个项目和多台机器上测试,VS2019 也没有在智能感知中显示这一点,MS 文档也没有在任何地方提及。
【讨论】:
我正在使用旧版 .NET 4.5 应用程序并且遇到了困难。正如你所说,the Nov. 2019 security update 似乎强制所有内容为SameSite=Lax
,虽然它说这种行为可以在web.config
中更改,但实际上它只在 4.7.2 及更高版本中受支持。接下来我要从接受的答案中尝试rewrite
。
我正在使用 4.7.2 并在错误列表“不允许使用 'sameSite' 属性”下收到警告。它允许我构建解决方案,但不确定此警告。
目前,如果未指定 Same-Site,大多数浏览器会自动将 cookie 增加到 Lax,因此如果有人想要相反的情况(将安全性降低回无),我已经制定了类似的解决方案 @987654322 @(根据上面的答案)
如何在.NET 4.6.2中实现解决方案?
感谢“为了将 SameSite 定义为 ASP.NET_SessionId cookie,我必须在 system.web 部分下设置 web.config:
<sessionState cookieSameSite="Lax" />
【讨论】:
非常感谢。这对我有用。就像指出<httpCookies sameSite="Lax" />
,但这似乎没有任何作用。【参考方案8】:
https://www.nuget.org/packages/Microsoft.Owin.Security.Cookies/4.1.0 现在支持 SameSite。
这是一个非常好的消息,因为这里的其他解决方案没有那么出色:
实现OwinMiddleware
:效果很好,除了性能。这可能是特定于我们环境的东西,但该解决方案大约占我们 CPU 的 10%。
<outboundRules>
: 应该可以开始工作了。但是到目前为止,我看到的所有解决方案以及我们测试过的解决方案,包括这个线程中的解决方案,当在同一个响应中设置多个 cookie 时都会出现一些问题。
【讨论】:
以上是关于防止具有相同站点 cookie 属性的 CSRF的主要内容,如果未能解决你的问题,请参考以下文章
是否可以将相同站点属性添加到 Spring Security CSRF 的 .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFal