有没有想过,如果网站的 Cookie 特别多特别大,会发生什么情况?
不多说,马上来试验一下:
for (i = 0; i < 20; i++) document.cookie = i + '=' + 'X'.repeat(2000)
什么,网站居然报错了?
众所周知,Cookie 是塞在请求头里的。如果 Cookie 太多,显然整个 HTTP 头也会被撑大。
然而现实中,几乎所有的服务器都会对请求头长度做限制,避免畸形封包消耗服务器资源。
那么有趣的事就来了 —— Cookie 是可以长期储存的,所以只要不过期,对应的站点就一直无法访问!
不信?点击这里试试 (警告:不会清 Cookie 的用户慎点)
为什么会这样!因为博客园是支持自定义装扮的,用户可以嵌入自己的脚本。于是,一旦执行了恶作剧脚本,站点 Cookie 被污染,导致整个网站都无法访问了!
进阶
根据这个原理,我们继续挖掘 Cookie 的相关属性,让攻击效果变得更好。
expires
Cookie 之所以能被持久储存,完全得益于 expires 这个过期值。
理论上,Cookie 的过期时间可以足够长。不过鉴于实际情况,最多也就几个月的时间。
但对于互联网来说,这也非常长了,谁能容忍一个网站几个月没法用?
所以,我们可以设置足够久的过期时间 —— 只要用户不主动清空 Cookie,相应的站点就一直没法访问!
domain
例如博客园,所有用户都在 www.cnblogs.com 下。除了这个主站,能否将其他的子站服务也一起破坏呢?
答案是可以!因为 Cookie 具有一个特殊的属性 domain,它允许子站设置上级站点的 Cookie。甚至可以是根域!
于是 www.cnblogs.com 的页面,就能写入超大 Cookie 到 cnblogs.com 域下了。
未来,只要用户访问 *.cnblogs.com 的资源,统统变成 400 了。
这个特征可被利用到 XSS 攻击上。只要某网站任何一个子站能够运行跨站脚本,攻击者就可以对该网站进行全站屏蔽了!(GFW:比我还狠~)
path
不过太霸道也是不好的。尤其是这年头大家都懂些网络知识,清缓存这样简单的事,不少小白用户都会尝试下。
所以,为了低调起见,我们不对页面进行屏蔽,以免被过早被用户发现。
我们只屏蔽特殊的 URL,例如 AJAX 请求接口。这样,页面仍能正常打开,只是后期的一些操作总是提示失败 —— 于是,用户大多会认为是网站出问题了,而不会怀疑是自己的原因。
为了能更精确的控制 Cookie 粒度,path 属性得利用起来。例如,我们只污染博客园的 /mvc/vote/VoteComment.aspx 页面:
for (i = 0; i < 20; i++) { document.cookie = i + '=' + 'X'.repeat(2000) + ';domain=cnblogs.com; path=/mvc/vote/VoteComment.aspx'
这样,页面仍能正常浏览,只是把『点赞』功能给屏蔽了:
是不是很有趣:)
这种局部屏蔽的效果,显然有更好的迷惑性。
协议
仔细回顾一遍 Cookie 属性,除了 secure,再没和 URL Scheme 相关的属性了。
这意味着,HTTP 和 HTTPS 的 Cookie 默认都是共享的。因此,我们可以在 HTTP 下屏蔽 HTTPS 站点了!
不过 XSS 也不是也想有就能有的,但在特殊的条件下,任何站点都可以有 XSS —— 那就是流量被劫持的时候。
当用户流量被劫持时,中间人可以模拟出任何 HTTP 站点,因此就能对任意站点设置 Cookie:
当用户打开任意 HTTP 页面时,往其中注入脚本。接着悄悄创建目标站点的隐藏框架页,中间人返回特定的页面内容,其中的脚本即可修改目标站点 Cookie 了。
下面就来尝试一下吧。
通过代理,我们模拟流量被劫持的场景。当打开任意页面时,开始对目标站点释放 DeBuff:
主页面的实现:
目标框架页实现:
通过一堆框架页,即可批量对目标站点的 Cookie 进行修改。
最后,切换回正常网络 —— 发现邪恶光环仍在生效:
更杯具的是,连加密传输的 HTTPS 站点也未能幸免:
中间人缓存攻击,又多了一种新玩法!
用途
或许你要说了,这除了恶作剧恶搞之外,有实际意义吗。
不过,只要充分发挥想象,还是能玩出一些有趣的效果。例如配合 XSS:
- 屏蔽资料修改页面,阻止用户改密码
- 屏蔽注销接口,保持用户会话不过期
- 屏蔽管理后台,让管理员暂时无法操作(XSS 盲打时,对管理员造成眩晕效果,持续时间视管理员 IQ 而定)
或者流量劫持的场合:
- 屏蔽前端检测脚本,降低用户安全性
- 屏蔽程序、补丁的更新站点,等等
小结
当然,这种所谓的『拒绝服务』,只是本地自欺欺人而已,对真实服务器并没什么影响。
虽然效果不及传统攻击,但这种方式显得更文明一些。只对部分人、甚至部分功能实施攻击,而完全不妨碍其他用户。