服务器端验证发出的 cookie 的域是否与主机匹配 header
Server side verification that the domain of an issued cookie matches the host header
如果应用程序向经过身份验证的用户发出 session 并为他们提供一个只对特定子域有效的 cookie(例如,因为其他客户位于其他子域上,但所有子域都解析为相同的 运行 应用程序)那么服务器是否应该在请求开始时设置 session 之前针对主机 header 验证此 cookie 的预期子域?
例如
- 用户成功通过
client.example.com
的身份验证
服务器为他们创建一个新的 session 并在 session 中添加一个 属性 关于原始域
{user: "fred@gmail.com", domain: "client.example.com"}
服务器在响应中发送 Set-Cookie header,ID session
Set-Cookie: secure-session-id=1234-5678; Secure
- 如果用户导航到
otherclient.example.com
,由于 Set-Cookie
的隐式 same-domain 行为,浏览器不会发送该 cookie
- 没有什么可以阻止用户使用该 cookie 构建 curl 命令但指向
otherclient.example.com
。
- 如果服务器未验证传入请求的主机 header 与 cookie 中提供的 session id 的 session 的原始域相匹配,则它是拥有有效帐户的用户可能会伪装成另一个客户(如果应用程序基于子域的任何逻辑,而不是纯粹基于从身份验证收集的信息)。在设置用户的 session 并继续请求之前,我希望服务器接受提交的 session id,查找 session,查看请求主机是否 header匹配存储的 session 上的 "originating domain",如果不匹配,则 return 401 或将用户重定向到适当的子域。
这似乎是一个足够通用的场景,我希望大多数服务器身份验证框架都能开箱即用,除非您将其关闭(最终归结为在服务器端强制执行浏览器所依赖的相同行为默认情况下要执行的操作(不将一个子域的 session cookie 发送到另一个子域)。你知道这样做的吗?有没有更好的方法来防止这种情况发生?我是不是误解了什么?
Are you aware of any that do this?
ASP.NET 每个 IIS 应用程序有不同的 Application Domain。因此,来自一个应用程序的会话 cookie 在另一个应用程序上将无效。唯一的例外是,如果您编写了驻留在同一应用程序域中的多租户应用程序,并且您没有对接收到的会话 cookie 进行任何验证以确保主机与设置的主机匹配。
另一方面,PHP 会将所有会话存储在 session.save_path
中(例如 /var/lib/php/session
),因此来自一个应用程序的会话 cookie 如果用于另一个应用程序将设置会话变量,正如您正确指出的那样,这是一个安全问题。
这可以通过为每个应用程序或应用程序的访问主机覆盖 session.save_path
local value 来补救。
Is there a better way of preventing this scenario?
作为额外的安全措施,您可以在开始会话时设置主机。
Session["host"] = HttpContext.Current.Request.ServerVariables["HTTP_HOST"];
然后在请求中使用任何会话值之前对此进行验证。即你在问题中所说的:
I would expect the server to take the session id submitted, look up
the session, see if the request host header matches the "originating
domain" that was put on the stored session and if not then either
return a 401 or redirect the user to the appropriate subdomain.
如果不采取这些措施,那么将一组会话变量从一个应用程序替换为驻留在同一服务器上的另一个应用程序将成为一个有趣的攻击媒介。当然,如果应用程序是相同的(例如多租户场景),那么就会存在漏洞利用,例如利用一台主机上的管理员访问权限来获得另一台主机上的管理员访问权限。如果不是,那么仍然可能存在攻击路径,具体取决于设置了哪些变量以及如何使用它们。
如果应用程序向经过身份验证的用户发出 session 并为他们提供一个只对特定子域有效的 cookie(例如,因为其他客户位于其他子域上,但所有子域都解析为相同的 运行 应用程序)那么服务器是否应该在请求开始时设置 session 之前针对主机 header 验证此 cookie 的预期子域?
例如
- 用户成功通过
client.example.com
的身份验证
服务器为他们创建一个新的 session 并在 session 中添加一个 属性 关于原始域
{user: "fred@gmail.com", domain: "client.example.com"}
服务器在响应中发送 Set-Cookie header,ID session
Set-Cookie: secure-session-id=1234-5678; Secure
- 如果用户导航到
otherclient.example.com
,由于Set-Cookie
的隐式 same-domain 行为,浏览器不会发送该 cookie
- 没有什么可以阻止用户使用该 cookie 构建 curl 命令但指向
otherclient.example.com
。 - 如果服务器未验证传入请求的主机 header 与 cookie 中提供的 session id 的 session 的原始域相匹配,则它是拥有有效帐户的用户可能会伪装成另一个客户(如果应用程序基于子域的任何逻辑,而不是纯粹基于从身份验证收集的信息)。在设置用户的 session 并继续请求之前,我希望服务器接受提交的 session id,查找 session,查看请求主机是否 header匹配存储的 session 上的 "originating domain",如果不匹配,则 return 401 或将用户重定向到适当的子域。
这似乎是一个足够通用的场景,我希望大多数服务器身份验证框架都能开箱即用,除非您将其关闭(最终归结为在服务器端强制执行浏览器所依赖的相同行为默认情况下要执行的操作(不将一个子域的 session cookie 发送到另一个子域)。你知道这样做的吗?有没有更好的方法来防止这种情况发生?我是不是误解了什么?
Are you aware of any that do this?
ASP.NET 每个 IIS 应用程序有不同的 Application Domain。因此,来自一个应用程序的会话 cookie 在另一个应用程序上将无效。唯一的例外是,如果您编写了驻留在同一应用程序域中的多租户应用程序,并且您没有对接收到的会话 cookie 进行任何验证以确保主机与设置的主机匹配。
另一方面,PHP 会将所有会话存储在 session.save_path
中(例如 /var/lib/php/session
),因此来自一个应用程序的会话 cookie 如果用于另一个应用程序将设置会话变量,正如您正确指出的那样,这是一个安全问题。
这可以通过为每个应用程序或应用程序的访问主机覆盖 session.save_path
local value 来补救。
Is there a better way of preventing this scenario?
作为额外的安全措施,您可以在开始会话时设置主机。
Session["host"] = HttpContext.Current.Request.ServerVariables["HTTP_HOST"];
然后在请求中使用任何会话值之前对此进行验证。即你在问题中所说的:
I would expect the server to take the session id submitted, look up the session, see if the request host header matches the "originating domain" that was put on the stored session and if not then either return a 401 or redirect the user to the appropriate subdomain.
如果不采取这些措施,那么将一组会话变量从一个应用程序替换为驻留在同一服务器上的另一个应用程序将成为一个有趣的攻击媒介。当然,如果应用程序是相同的(例如多租户场景),那么就会存在漏洞利用,例如利用一台主机上的管理员访问权限来获得另一台主机上的管理员访问权限。如果不是,那么仍然可能存在攻击路径,具体取决于设置了哪些变量以及如何使用它们。