登录态 Cookie 的 Key 是浏览器默认自动携带的,Key 通常是会话 Cookie,只要浏览器不关闭,Key 一直存在。所以只要用户 A 曾经登录过相册网站(这里用 http://www.photo.com
举例),浏览器没有关闭,用户在没有关闭的浏览器打开一个黑客网页(这里用 http://www.hacker.com
),黑客页面发送 HTTP 请求到 http://www.photo.com
的后台会默认带上 http://www.photo.com
的登录态 Cookie,也就能模拟用户 A 做一些增删改等敏感操作。Get 和 Post 都一样,这就是 CSRF 攻击原理。这种攻击过程也是最常见的攻击过程。
上面说的增删改都是写操作,会对后台数据产生负面影响,所以是能被攻击的。另外一种读操作,是具有幂等性,不会对后台数据残生负面影响,能否被攻击到?读操作也可能是敏感数据,举个例子,比如 www.photo.com
上的私密相册数据能否被 www.hacker.com
页面拿到?这就涉及到前端跨域知识点了,默认大部分情况是拿不到,这里列举两种特殊情是可以拿到的:
如果后台返回的数据是 JSONP 格式的,这种只能是 Get 操作,是能被黑客页面拿到的。
如果后台是通过 CORS 处理跨域,没有对请求头的 Origin 做白名单限制,ACAO 响应头是 *
或者包括黑客页面,包括 Get/Post/Del 等操作,也是能被黑客页面拿到的。
除了这两种特殊情况,读操作都是不能被攻击到的,因为浏览器跨域限制是天然的安全的。关于跨域知识细节,我写过另外一篇文章。
知道攻击原理,防护方法也很简单,找到能够区分请求发送的页面是自己的页面还是黑客的页面的方法就可以了。
HTTP 请求头 Referrer 字段是浏览器默认带上,含义是发送请求的页面地址,比如同样是删除相册的操作 http://www.photo.com/del?id=xxx
; 如果是从相册自己页面发送出来,Referrre的值是 http://www.photo.com/index.html
(以首页举例),如果是从黑客页面发送出来的Referrer的值是 http://www.hacker.com/index.html
(以首页举例),所以后端只要通过Referrrer做白名单判断就能防这种常见的CSRF攻击。
Referrer 会不会被伪造或者篡改?在浏览器环境下,Referrer 是浏览器自己带上的,js 是改不了 Rerferrer,所以是不能被伪造和篡改的。浏览器插件能改 Referre,通过网关或者抓包也能修改 Referrer。除了这几种特殊情况,用 Referrer 防 CSRF 是安全的。
读写 Cookie 有跨域限制(作用域,Domain,Path),所以我们可以用这个特性来区分是自己页面还是黑客页面。只要页面能读(或者写)www.photo.com
域名 Cookie,就证明是自己的页面。懂了原理,方案就很简单,比如服务器通过 cookie 下发一个 token,token 值是随机数,页面发请求的时候从 cookie 取出 token 通过 HTTP 请求参数传给后台,后台比对参数里的 token 和 cookie 里的 token 是否一致,如果一致就证明是自己页面发的请求,如果不一致就返回失败。防 CSRF 的方案就是这么简单,这种方法能够 100%防 CSRF。