0

我的网站上有一个用户可以选择的子域列表。我想为他们选择的子域创建一个身份验证 cookie,而不是所有子域 假设我的站点是 mysite.com,那么用户可以看到

  • domainOne.mysite.com
  • domainTwo.mysite.com

当他们选择了他们的子域时,我在控制器操作中执行以下操作

var faCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket)
faCookie.HttpOnly = true
faCookie.Domain = (subdomain + ".mysite.com")
faCookie.Secure = FormsAuthentication.RequireSSL
response.Cookies.Add(faCookie)
return this.Redirect("http://" + subdomain + ".mysite.com")

其中 encTicket 只是一些加密的用户信息

在提琴手我认为这是响应

HTTP/1.1 302 Found
Cache-Control: private, s-maxage=0
Content-Type: text/html; charset=utf-8
Location: http://domainOne.mysite.com
Server: Microsoft-IIS/8.0
X-AspNetMvc-Version: 4.0
X-AspNet-Version: 4.0.30319
Set-Cookie: .ASPXAUTH=9ECF5B2533<snip>; domain=domainOne.mysite.net; path=/; HttpOnly
X-Powered-By: ASP.NET
Date: Fri, 19 Jul 2013 04:19:02 GMT
Content-Length: 142

<html><head><title>Object moved</title></head><body>
<h2>Object moved to <a href="http://domainOne.mysite.net">here</a>.</h2>
</body></html>

好的,所以对我来说一切都很好。repsonse 告诉浏览器为子域添加 cookie。然而,基于重定向的后续 GET 在其请求中根本没有 cookie。

有什么我想念的诡计吗?为了清楚起见,我不想为根 (.mydomain.com) 创建一个 cookie,因为这将提供跨所有子域的身份验证。

谢谢你的帮助

4

1 回答 1

1

我有好消息和坏消息。

坏消息是——你做不到。请参阅此处以获取解释。本质上,您的服务器正在为它不包含的域设置 cookie,因此 cookie 被拒绝。

好消息是——无论如何你都不想这样做。您的设计违反了 OWASP 2013 A4(不安全且未经验证的直接对象引用)。在这种情况下,您将用户的访问权限存储为 cookie 的域,黑客可以轻松修改该域。

找到一种不同的方式来指定子域访问。有各种各样的方法可以做到这一点。

这是一种非常接近您的计划的方法:

将子域存储在 cookie 值本身中。创建一个安全的文档容器,列出授予用户访问权限的子域。例如,您可以将子域存储为逗号分隔的字符串,后跟 HMAC,以防止恶意用户篡改列表。

    var contents = "subdomain1.domain.com,subdomain2.domain.com";
    var bytes = System.Text.Encoding.UTF8.GetBytes(contents);
    var hash = System.Web.Security.MachineKey.Encode(bytes,
                     Web.Security.MachineKeyProtection.Validation);
    var cookie = new HttpCookie("MYCOOKIE", contents + "|" + hash);
    cookie.domain = "domain.com";

当子域站点收到请求时,它必须查找 cookie,检查哈希以验证 cookie,然后检查有效负载以查看是否应授予访问权限。

    var cookie = Request.Cookies["MYCOOKIE'];
    var chunks = cookie.Value.Split("|");
    var list = chunks[0];
    var hash = chunks[1];
    var bytes = System.Text.Encoding.UTF8.GetBytes(contents);
    var checkHash = System.Web.Security.MachineKey.Encode(bytes,
                     Web.Security.MachineKeyProtection.Validation);
    if (checkHash != hash) throw new System.SecurityException("Someone tampered with the cookie!");
    var subdomains = list.split(",");
    if (!subdomains.Contains(MY_SUBDOMAIN))  throw new System.SecurityException("Someone is using their cookie to access the wrong domain!");

另一种方法是将授予的子域列表存储在服务器端的数据库中,将列表与令牌相关联,并在 cookie 中传递令牌。这种方法会更安全一些,因为访问列表永远不会通过网络传递。

第三种方法是构建一个真正的基于 SAML 的 SSO 基础设施,但这有点涉及。

于 2013-10-15T02:10:11.830 回答