使用 same-site cookie 属性防止 CSRF
Preventing CSRF with the same-site cookie attribute
我在网上冲浪时发现了文章 Preventing CSRF with the same-site cookie attribute。
如link维护我们需要添加Set-Cookieheader.
Set-Cookie: key=value; HttpOnly; SameSite=strict
现在我的问题是,我想在我的 ASP.NET 站点的所有 Cookie 和身份验证 Cookie 中设置它。
我尝试使用 IIS 中的 header 进行设置,但有人说这是错误的实现方式。
下面我也试过了
HttpCookie newAuthenticationCookie = new HttpCookie(FormsAuthentication.FormsCookieName
, FormsAuthentication.Encrypt(newAuthenticationTicket))
{
HttpOnly = true
};
newAuthenticationCookie.Values.Add("SameSite", "strict");
但好像对我没有帮助。
请建议我更好的方法。
谢谢。
在对 HttpCookie Source 进行深入审查后确认我们无法使用代码执行此操作,因为无法在 Cookie 上添加额外的属性并且 class 被标记为密封。
But still anyhow I manage solution by modifying web.config as below.
<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
因为在这个时代我们使用 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()之前注册了中间件
您也可以在创建cookie时在代码中设置:
var httpCookie = new HttpCookie("mycookie", "myvalue");
httpCookie.Path += ";SameSite=Strict";
Response.SetCookie(httpCookie);
这将为您提供以下内容 header:
Set-Cookie:mycookie=myvalue; path=/;SameSite=Strict
在将其推入框架之前,有点 hack。
.NET 4.7.2 现在内置支持 SameSite
属性.
HttpCookie
现在有一个 属性 叫做 SameSite
。
从 Microsoft 查看更多信息 here。
无需再通过配置文件进行破解。
在 4.7.2 之前,您可以将字符串附加到 cookie 路径。
FormsAuthentication.SetAuthCookie(username, false, FormsAuthentication.FormsCookiePath + "; SameSite=Lax");
只需添加我的答案即可系统化在这里和其他地方找到的所有信息。
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)。 2020 年 1 月更新:.NET 4.8 会话 cookie 现在默认为“SameSite”
安装最新的 Windows 更新将使您的会话 cookie 默认为 Lax
。你可以在这里控制它:
<sessionState cookieSameSite="Lax" /> <!-- in system.web -->
4。 <httpCookies samesite=xxx>
不存在?
按照 web.config 上面评论中的建议添加 <httpCookies sameSite="Strict" />
没有用,我遇到了错误。
Unrecognized attribute 'samesite'
尽管我的目标是 4.7.2。在多个项目和多台机器上测试过,VS2019 也没有在智能感知中显示这一点,MS 文档也没有在任何地方提及它。
为了将 SameSite 定义为 ASP.NET_SessionId cookie,我必须在 system.web 部分下设置 web.config:
<sessionState cookieSameSite="Lax" />
https://www.nuget.org/packages/Microsoft.Owin.Security.Cookies/4.1.0 现在支持 SameSite。
这是个好消息,因为这里的其他解决方案效果不佳:
实施 OwinMiddleware
:效果很好,除了性能。这可能是我们环境的特定问题,但该解决方案约占我们 CPU 的 10%。
<outboundRules>
:可能可以开始工作。但是到目前为止,我所见过和测试过的所有解决方案,包括本线程中的解决方案,在同一响应中设置多个 cookie 时都会出现一些问题。
我在网上冲浪时发现了文章 Preventing CSRF with the same-site cookie attribute。
如link维护我们需要添加Set-Cookieheader.
Set-Cookie: key=value; HttpOnly; SameSite=strict
现在我的问题是,我想在我的 ASP.NET 站点的所有 Cookie 和身份验证 Cookie 中设置它。 我尝试使用 IIS 中的 header 进行设置,但有人说这是错误的实现方式。
下面我也试过了
HttpCookie newAuthenticationCookie = new HttpCookie(FormsAuthentication.FormsCookieName
, FormsAuthentication.Encrypt(newAuthenticationTicket))
{
HttpOnly = true
};
newAuthenticationCookie.Values.Add("SameSite", "strict");
但好像对我没有帮助。
请建议我更好的方法。
谢谢。
在对 HttpCookie Source 进行深入审查后确认我们无法使用代码执行此操作,因为无法在 Cookie 上添加额外的属性并且 class 被标记为密封。
But still anyhow I manage solution by modifying web.config as below.
<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因为在这个时代我们使用 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()之前注册了中间件
您也可以在创建cookie时在代码中设置:
var httpCookie = new HttpCookie("mycookie", "myvalue");
httpCookie.Path += ";SameSite=Strict";
Response.SetCookie(httpCookie);
这将为您提供以下内容 header:
Set-Cookie:mycookie=myvalue; path=/;SameSite=Strict
在将其推入框架之前,有点 hack。
.NET 4.7.2 现在内置支持 SameSite
属性.
HttpCookie
现在有一个 属性 叫做 SameSite
。
从 Microsoft 查看更多信息 here。
无需再通过配置文件进行破解。
在 4.7.2 之前,您可以将字符串附加到 cookie 路径。
FormsAuthentication.SetAuthCookie(username, false, FormsAuthentication.FormsCookiePath + "; SameSite=Lax");
只需添加我的答案即可系统化在这里和其他地方找到的所有信息。
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)。 2020 年 1 月更新:.NET 4.8 会话 cookie 现在默认为“SameSite”
安装最新的 Windows 更新将使您的会话 cookie 默认为 Lax
。你可以在这里控制它:
<sessionState cookieSameSite="Lax" /> <!-- in system.web -->
4。 <httpCookies samesite=xxx>
不存在?
按照 web.config 上面评论中的建议添加 <httpCookies sameSite="Strict" />
没有用,我遇到了错误。
Unrecognized attribute 'samesite'
尽管我的目标是 4.7.2。在多个项目和多台机器上测试过,VS2019 也没有在智能感知中显示这一点,MS 文档也没有在任何地方提及它。
为了将 SameSite 定义为 ASP.NET_SessionId cookie,我必须在 system.web 部分下设置 web.config:
<sessionState cookieSameSite="Lax" />
https://www.nuget.org/packages/Microsoft.Owin.Security.Cookies/4.1.0 现在支持 SameSite。
这是个好消息,因为这里的其他解决方案效果不佳:
实施 OwinMiddleware
:效果很好,除了性能。这可能是我们环境的特定问题,但该解决方案约占我们 CPU 的 10%。
<outboundRules>
:可能可以开始工作。但是到目前为止,我所见过和测试过的所有解决方案,包括本线程中的解决方案,在同一响应中设置多个 cookie 时都会出现一些问题。