HttpOnly cookie 如何处理 AJAX 请求?
Posted
技术标签:
【中文标题】HttpOnly cookie 如何处理 AJAX 请求?【英文标题】:How do HttpOnly cookies work with AJAX requests? 【发布时间】:2010-09-06 21:04:25 【问题描述】:如果在基于 cookie 的访问限制的站点上使用 AJAX,则 javascript 需要访问 cookie。 HttpOnly cookie 可以在 AJAX 网站上工作吗?
编辑: 如果指定了 HttpOnly,Microsoft 通过禁止 JavaScript 访问 cookie 创建了一种防止 XSS 攻击的方法。 FireFox 后来采用了这个。所以我的问题是:如果您在 *** 之类的网站上使用 AJAX,是否可以选择 Http-Only cookie?
编辑 2: 问题 2。如果 HttpOnly 的目的是阻止 JavaScript 访问 cookie,并且您仍然可以通过 XmlHttpRequest 对象通过 JavaScript 检索 cookie,有什么意义的HttpOnly?
编辑 3:这是来自***的引述:
当浏览器收到这样的 cookie 时,它应该像往常一样在以下 HTTP 交换中使用它,但不让它对客户端脚本可见。[32]
HttpOnly
标志不是任何标准的一部分,也不是在所有浏览器中都实现。请注意,目前无法阻止通过 XMLHTTPRequest 读取或写入会话 cookie。 [33]。
我了解document.cookie
在您使用 HttpOnly 时被阻止。但似乎您仍然可以读取 XMLHttpRequest 对象中的 cookie 值,从而允许 XSS。 HttpOnly 是如何让你变得更安全的呢?通过使cookie基本上只读?
在您的示例中,我无法写信给您的document.cookie
,但我仍然可以窃取您的 cookie 并使用 XMLHttpRequest 对象将其发布到我的域。
<script type="text/javascript">
var req = null;
try req = new XMLHttpRequest(); catch(e)
if (!req) try req = new ActiveXObject("Msxml2.XMLHTTP"); catch(e)
if (!req) try req = new ActiveXObject("Microsoft.XMLHTTP"); catch(e)
req.open('GET', 'http://***.com/', false);
req.send(null);
alert(req.getAllResponseHeaders());
</script>
编辑 4: 抱歉,我的意思是您可以将 XMLHttpRequest 发送到 *** 域,然后将 getAllResponseHeaders() 的结果保存到字符串,正则表达式输出 cookie,然后发布到外部域。***和黑客似乎在这一点上同意我的观点,但我很想接受再教育......
最终编辑: 啊,显然两个网站都错了,这实际上是bug in FireFox。 IE6 & 7 实际上是目前唯一完全支持 HttpOnly 的浏览器。
重申我所学到的一切:
HttpOnly 限制对 IE7 & 和 FireFox 中的 document.cookie 的所有访问(不确定其他浏览器) HttpOnly 从 IE7 中 XMLHttpObject.getAllResponseHeaders() 的响应头中删除 cookie 信息。 XMLHttpObjects 只能提交到它们起源的域,因此不会跨域发布 cookie。编辑:此信息可能不再是最新的。
【问题讨论】:
我将您的示例放入了一个greasemonkey 脚本中,看起来FF 不再显示cookie。出色的研究和示例。 也许使用同源策略,您无法向与脚本运行所在的域不同的域发出 http 请求;但是,我相信您可以通过使用 window.location 将用户重定向到页面并通过查询字符串参数传递所有信息来轻松传递 cookie。 @LucaMarzi "你不能向与运行脚本的域不同的域发出 http 请求" 你是说站点 X 不能包含图像来自主机 Y? (自 Mosaic 以来所有浏览器都支持的功能?) 【参考方案1】:是的,HTTP-Only cookie 可以满足此功能。仍然会向服务器提供 XmlHttpRequest 的请求。
在 Stack Overflow 的情况下,cookie 会自动作为 XmlHttpRequest 请求的一部分提供。我不知道 Stack Overflow 身份验证提供程序的实现细节,但该 cookie 数据可能会自动用于在比“投票”控制器方法更低的级别验证您的身份。
更一般地说,AJAX不需要 cookie。技术上只需要 XmlHttpRequest 支持(甚至是 iframe 远程处理,在旧版浏览器上)。
但是,如果您想为启用 AJAX 的功能提供安全性,则适用与传统网站相同的规则。您需要一些方法来识别每个请求背后的用户,而 cookie 几乎总是达到此目的的手段。
在您的示例中,我无法写入您的 document.cookie,但我仍然可以窃取您的 cookie 并使用 XMLHttpRequest 对象将其发布到我的域。
XmlHttpRequest 不会发出跨域请求(正是出于您所提到的各种原因)。
您通常可以使用 iframe 远程处理或 JSONP 注入脚本以将 cookie 发送到您的域,但随后 HTTP-Only 会再次保护 cookie,因为它无法访问。
除非您在服务器端入侵了 ***.com,否则您将无法窃取我的 cookie。
编辑 2:问题 2. 如果 Http-Only 的目的是阻止 JavaScript 访问 cookie,并且您仍然可以通过 XmlHttpRequest 对象通过 JavaScript 检索 cookie,那么 Http-Only 的意义何在?
考虑这种情况:
我找到了一种将 JavaScript 代码注入页面的途径。 Jeff 加载页面,我的恶意 JavaScript 修改了他的 cookie 以匹配我的。 Jeff 为您的问题提供了出色的答案。 因为他提交的是我的 cookie 数据而不是他的,所以答案将成为我的。 您投票支持“我的”出色答案。 我的真实账户明白了。使用仅 HTTP cookie,第二步将是不可能的,从而挫败了我的 XSS 尝试。
编辑 4:抱歉,我的意思是您可以将 XMLHttpRequest 发送到 *** 域,然后将 getAllResponseHeaders() 的结果保存到字符串,正则表达式输出 cookie,然后将其发布到外部域。***和黑客似乎在这一点上同意我的观点,但我希望接受再教育......
没错。您仍然可以通过这种方式进行会话劫持。不过,它确实大大减少了能够成功执行针对您的 XSS 攻击的人。
但是,如果您回到我的示例场景,您可以看到仅 HTTP确实 成功切断了依赖于修改客户端 cookie 的 XSS 攻击(并不少见)。
归结为以下事实:a)没有任何一项改进可以解决所有漏洞,b)没有系统永远是完全安全的。 HTTP-Only 是支持 XSS 的有用工具。
同样,即使 XmlHttpRequest 的跨域限制不能 100% 成功阻止所有 XSS 攻击,您仍然做梦也想不到取消限制。
【讨论】:
很多框架都放了csrf
token in cookies。我想需要 csrf
检查的 AJAX 调用将不起作用,除非您将 csrf 令牌放在隐藏的 html 元素中以便 JS 检索它。【参考方案2】:
是的,它们对于基于 Ajax 的站点来说是一个可行的选择。身份验证 cookie 不用于脚本操作,而只是由浏览器包含在向服务器发出的所有 HTTP 请求中。
脚本不需要担心会话 cookie 的内容 - 只要您通过了身份验证,那么用户或脚本向服务器发起的任何请求都将包含适当的 cookie。脚本本身无法知道 cookie 的内容这一事实并不重要。
对于任何用于身份验证以外的 cookie,如果您希望脚本能够修改或读取它们,则可以在没有 HTTP only 标志的情况下设置它们。您可以选择哪些 cookie 仅应为 HTTP,因此,例如 UI 首选项(排序顺序、折叠左侧窗格或不折叠)等任何非敏感信息都可以在 cookie 中与脚本共享。
我真的很喜欢仅 HTTP 的 cookie - 它是一种专有的浏览器扩展,是一个非常好的想法。
【讨论】:
【参考方案3】:不一定,这取决于你想做什么。你能详细说明一下吗? AJAX 不需要访问 cookie 即可工作,它可以自己发出请求以提取信息,AJAX 调用发出的页面请求可以访问 cookie 数据并将其传递回调用脚本,而无需 Javascript 直接访问饼干
【讨论】:
【参考方案4】:作为澄清 - 从服务器的角度来看,AJAX 请求所请求的页面与用户单击链接完成的标准 HTTP 获取请求本质上没有什么不同。所有正常的请求属性:user-agent、ip、session、cookies等都传递给服务器。
【讨论】:
“会话”不是 HTTP 概念。这是一个由框架构建在 HTTP 概念之上的高级概念。【参考方案5】:还有更多内容。
Ajax 并不严格要求使用 cookie,但正如其他海报所提到的那样,它们可能很有用。将 cookie 标记为 HTTPOnly 以将其从脚本中隐藏只能部分起作用,因为并非所有浏览器都支持它,而且还有一些常见的解决方法。
奇怪的是 XMLHTTPresponse 标头提供了 cookie,从技术上讲,服务器不必在响应中返回 cookie。在客户端上设置后,它会一直保持设置,直到过期。尽管有些方案会随着每个请求更改 cookie 以防止重复使用。因此,您可以通过将服务器更改为不在 XMLHTTP 响应中提供 cookie 来避免这种解决方法。
不过,总的来说,我认为应该谨慎使用 HTTPOnly。存在跨站点脚本攻击,攻击者安排用户使用简单的 post 表单提交来自另一个站点的类似 ajax 的请求,而不使用 XMLHTTP,并且您的浏览器仍处于活动状态的 cookie 将对请求进行身份验证。
如果您想确保 AJAX 请求经过身份验证,则请求本身和 HTTP 标头需要包含 cookie。例如,通过使用脚本或独特的隐藏输入。 HTTPOnly 会阻碍这一点。
通常需要 HTTPOnly 的有趣原因是防止您网页中包含的第三方内容窃取 cookie。但是有很多有趣的理由让我们对包含第三方内容非常谨慎,并积极过滤它。
【讨论】:
我应该提到,当前的最佳实践是验证有效负载和请求,正如我上面提到的,但使用 HTTPOnly secure cookie 来验证请求,以及不同的带有有效负载的令牌,因此 HTTPOnly 不是障碍。【参考方案6】:当您进行 AJAX 调用时,浏览器会自动处理 Cookie,因此您的 Javascript 无需处理 Cookie。
【讨论】:
【参考方案7】:因此,我假设 JavaScript 需要访问您的 cookie。
来自您浏览器的所有 HTTP 请求都会传输您针对相关网站的 cookie 信息。 JavaScript 既可以设置也可以读取 cookie。根据定义,Ajax 应用程序不需要 Cookie,但大多数 Web 应用程序都需要它们来维护用户状态。
您的问题的正式答案是“如果使用 AJAX,JavaScript 是否需要访问 cookie?” - 因此是“不”。例如,考虑使用 Ajax 请求提供自动建议选项的增强搜索字段。在这种情况下不需要 cookie 信息。
【讨论】:
XmlHttpRequest 需要 cookie。您提到的增强搜索可能位于登录页面后面。但是 Javascript 是否需要能够将 cookie 值暴露给 VM 是一个不同的问题。【参考方案8】:不,AJAX 调用请求的页面也可以访问 cookie,这就是检查您是否登录的原因。
您可以使用 Javascript 进行其他身份验证,但我不相信它,我总是更喜欢将任何类型的身份验证检查放在后端。
【讨论】:
【参考方案9】:是的,cookie 对 Ajax 非常有用。
将身份验证放在请求 URL 中是不好的做法。上周有一条关于从 google 缓存中获取 URL 中的身份验证令牌的新闻。
不,没有办法防止攻击。较旧的浏览器仍然允许通过 javascript 访问 cookie。您只能绕过http等。只要付出足够的努力,您想出的任何东西都可以解决。诀窍是付出太多努力而不值得。
如果您想让您的网站更安全(没有完美的安全性),您可以使用过期的身份验证 cookie。然后,如果 cookie 被盗,攻击者必须在它过期之前使用它。如果他们不这样做,那么您有一个很好的迹象表明该帐户存在可疑活动。时间窗口越短,安全性越好,但它对您的服务器生成和维护密钥的负载就越大。
【讨论】:
以上是关于HttpOnly cookie 如何处理 AJAX 请求?的主要内容,如果未能解决你的问题,请参考以下文章