先解释两个名词,CSRF 和 JWT。
CSRF (Cross Site Request Forgery),它讲的是你在一个浏览器中打开了两个标签页,其中一个页面通过窃取另一个页面的 cookie 来发送伪造的请求,因为 cookie 是随着请求自动发送到服务端的。
JWT (JSON Web Token),通过某种算法将两个 JSON 对象加密成一个字符串,该字符串能代表唯一用户。
CSRF 的产生
首先通过一个图来理解 CSRF 是什么现象。
想要攻击成功,这三步缺一不可。
第一,登录受害者网站。如果受害者网站是基于 cookie 的用户验证机制,那么当用户登录成功后,浏览器就会保存一份服务端的 SESSIONID。
第二,这时候在同一个浏览器打开攻击者网站,虽然说它无法获取 SESSIONID 是什么(因为设置了 http only 的 cookie 是无法被 JavaScript 获取的),但是从浏览器向受害者网站发出的任何请求中,都会携带它的 cookie,无论是从哪个网站发出。
第三,利用这个原理,在攻击者网站发出一个请求,命令受害者网站进行一些敏感操作。由于此时发出的请求是处于 session 中的,所以只要该用户有权限,那么任何请求都会被执行。
比如,打开优酷,并登录。再打开攻击者网站,它里面有个 标签是这样的:
这个 api 只是个例子,具体的 url 和参数都可以通过浏览器的开发者工具(Network 功能)事先确定。假如它的作用是让该登录的用户关注由 123 确定的一个节目或者用户,那么通过 CSRF 攻击,这个节目的关注量就会不断上升。
解释两点。第一,为什么举这个例子,而不是银行这种和金钱有关的操作?很简单,因为它容易猜。对于攻击者来说,没有什么是一定能成功的,比如 SQL 注入,攻击者他不知道某网站的数据库是怎么设计的,但是他一般会通过个人经验去尝试,比如很多网站把用户的主键设置为 user_id,或 sys_id 等。
银行的操作往往经过多重确认,比如图形验证码、手机验证码等,光靠 CSRF 完成一次攻击基本上是天方夜谭。但其他类型的网站往往不会刻意去防范这些问题。虽然金钱上的利益很难得到,但 CSRF 能办到的事情还是很多,比如利用别人发虚假微博、加好友等,这些都能对攻击者产生利益。
第二,如何确保用户打开优酷之后,又打开攻击者网站?做不到。否则任何人打开优酷之后,都会莫名其妙地去关注某个节目了。但是你要知道,这个攻击成 本仅仅是一条 API 调用而已,它在哪里都能出现,你从任何地方下载一张图片,让你请求这个地址,看也不看就点确定,请求不就发出去了吗?
CSRF 的防御
对于如何防范 CSRF,一般有三种手段。
判断请求头中的 Referer
这个字段记录的是请求的来源。比如 http://www.example.com 上调用了百度的接口 http://api.map.baidu.com/service 那么在百度的服务端,就可以通过 Referer 判断这个请求是来自哪里。
在实际应用中,这些跟业务逻辑无关的操作往往会放在拦截器中