如何在ASP.NET中将SameSite Cookie属性减少回None?

时间:2020-02-07 16:46:10

标签: asp.net csrf samesite

为了避免CSRF(跨站点请求伪造),大多数浏览器(自2019年末开始)会自动考虑将未明确定义SameSite属性的任何cookie均视为Lax,而不是以前的默认设置为None。

最近(从Chrome 80开始,2020年2月)浏览器也忽略了定义SameSite = None并且不安全的cookie。

如何在Web.config中将会话cookie更改为自动更改为“无”(以保持SSO集成正常工作)?

1 个答案:

答案 0 :(得分:8)

编辑2020-08-03 Chrome 85 doesn't allow insecure SameSite=None cookies
我相应地更新了代码:1)仅在连接为https时应用SameSite=None; 2)仅在连接为https时应用Secure;; 3)如果SameSite=None是http且属性已添加相同站点(重写规则),则将其删除

原始回复

这是一个纯web.config解决方案,

  • 定义应使用SameSite=None呈现会话cookie
  • SameSite=None附加到任何未明确定义SameSite属性的cookie(使用在所有版本的框架中均可使用的方法,在最坏的情况下,如果某些属性不被接受,则可以将其删除)
  • Secure属性附加到任何尚不安全的cookie(只要是https请求)
  • 如果先前的规则已将SameSite=None删除,并且由于缺少https而无效,则
<!-- This sets ASP.NET_SessionId cookie to SameSite=None, 
avoiding the default of current frameworks which is LAX -->
<system.web>

<!-- in newer framework versions you have to change the samesite 
level like by changing this default level -->
<!-- in old versions these attributes might not be allowed
and in case (if they don't work) just ignore/skip them -->

<sessionState cookieSameSite="None" />
<httpCookies sameSite="None"/>
<authentication mode="Forms">
    <forms ..... cookieSameSite="None" />
</authentication>

...
</system.web>
...
<system.webServer>
<rewrite>
   <outboundRules>
    <!-- for old versions the only solution is to intercept/modify cookies -->

    <!-- Add "SameSite=None" to any cookie which does NOT have it yet -->
    <!-- currently this only works for secure https cookies -->
    <rule name="Add SameSite">
     <conditions>
      <add input="{RESPONSE_Set_Cookie}" pattern="." />
      <add input="{RESPONSE_Set_Cookie}" pattern="; SameSite=None" negate="true" />
      <add input="{HTTPS}" pattern="on" ignoreCase="true" />
     </conditions>
     <match serverVariable="RESPONSE_Set_Cookie" pattern=".*" negate="false" />
     <action type="Rewrite" value="{R:0}; SameSite=None" />
    </rule>

    <!-- Add "Secure" to any cookie which does NOT have it yet, as long as it's HTTPS request or else a secure cookie would just be ignored -->
    <rule name="Add Secure">
     <conditions>
        <add input="{RESPONSE_Set_Cookie}" pattern="." />
        <add input="{RESPONSE_Set_Cookie}" pattern="; Secure" negate="true" />
        <add input="{HTTPS}" pattern="on" ignoreCase="true" />
     </conditions>
     <match serverVariable="RESPONSE_Set_Cookie" pattern=".*" negate="false" />
     <action type="Rewrite" value="{R:0}; Secure" />
    </rule>

    <!-- If samesite was set to none by cookieSameSite="None", -->
    <!-- remove it for non-https requests (currently only works for https) -->
    <rule name="No SameSite For HTTP">
     <conditions>
      <add input="{HTTPS}" pattern="off" ignoreCase="true" />
     </conditions>
     <match serverVariable="RESPONSE_Set_Cookie" pattern="(.*);(\s*)SameSite=None" />
     <action type="Rewrite" value="{R:1}" />
    </rule>


   </outboundRules>
</rewrite>
</system.webServer>

如果您不使用<sessionState cookieSameSite="None" />,则默认情况下,某些较新的ASP.NET Framework版本将呈现SameSite=Lax。而且,如果您只是将重写规则添加到所有cookie中,而将SameSite=None添加到所有cookie中,那么您将获得两次SameSite属性,根据我的测试,该属性在诸如Chrome和Firefox(将使用 last >出现SameSite属性),但在Edge之类的功能(使用属性的 first 出现)中无法使用。

由于第一个标记<sessionState cookieSameSite="None" />将自动设置SameSite=None,但不会自动添加Secure属性,因此我将SameSite=NoneSecure配置为独立规则。如果将所有内容放在一个规则中,我将得到重复的属性SameSite=None,它可能会破坏浏览器(如上所述,它是无效的,浏览器可能会不一致地处理此问题)。

仅在HTTPS请求中添加Secure,因此,如果您仍在接受HTTP连接,则会话cookie不会添加Secure,这会使浏览器忽略您的cookie(并且会话完全无效)。如果您在负载平衡器或反向代理后面,则应使用HTTP_X_FORWARDED_PROTO attribute

最后,some versions of Safari中存在一个错误,浏览器无法理解SameSite=None并将其视为SameSite=Strict。因此,对于那些特定的版本,您可能决定不渲染SameSite=None,尽管如果未指定,默认值仍为SameSite=Lax级别,这可能不是您所需要的(尚未找到解决方案)。