有没有想过,如果网站的 Cookie 特别多特别大,会发生什么情况?
不多说,马上来试验一下:
for (i = 0; i < 20; i++)
document.cookie = i + '=' + 'X'.repeat(2000)
什么,网站居然报错了?
众所周知,Cookie 是塞在请求头里的。如果 Cookie 太多,显然整个 HTTP 头也会被撑大。
然而现实中,几乎所有的服务器都会对请求头长度做限制,避免畸形封包消耗服务器资源。
那么有趣的事就来了 —— 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'
这样,页面仍能正常浏览,只是把『点赞』功能给屏蔽了:
是不是很有趣:)
这种局部屏蔽的效果,显然有更好的迷惑性。