CSRF是什么
CSRF(Cross-site request forgery)跨站请求伪造。攻击者诱导用户点击进入第三方网站,在第三方网站中,对攻击网站发送跨域请求。其中携带了用户的登录成功的信息,达到冒充用户的目的。
比如:
1)用户访问a.com网站,并且获取了登录凭证(Cookie)。
2)攻击者在a.com网站留下了b.com的地址,诱导用户点击。
3)当用户点击进入b.com的时候,b.com向a.com同域的接口发送了一个请求,这个请求将会携带a.com域的Cookie。
4)服务端验证Cookie成功,并认为是用户执行操作。
实战
1)当访问http://www.qinhanwen.xyz:3000/index
的时候,页面如下:
1 |
|
koa部分:
1 | const koa = require('koa'); |
保证了页面与接口处于相同域。同时请求http://www.qinhanwen.xyz:3000/setCookie
接口,会获得Cookie。请求http://www.qinhanwen.xyz:3000/getCookie
接口,则会将传递的Cookie放在响应体内返回。
访问页面的时候,当前域下的Cookie如下图:
2)点击登录按钮
http://www.qinhanwen.xyz:3000
域下多了个Cookie,这就是它的登录凭证。
3)点击第二个按钮,会发送另外一个请求到http://www.qinhanwen.xyz:3000
域下,同时会自动带上这个域下的Cookie,接着请求返回,Cookie的值被放在响应体内。如图:
4)这时候新增一个不同域的链接,模仿第三方网站。
修改一下初始的页面,新增一个链接,跳转到新增的页面
1 |
|
新增的页面:
1 |
|
其实就是一个表单,向http://www.qinhanwen.xyz:3000/csrf
接口地址,发送了一个post提交请求。
修改一下koa部分,新增http://www.qinhanwen.xyz:3000/csrf
,响应体为key为name的Cookie
1 | const koa = require('koa'); |
再次访问http://www.qinhanwen.xyz:3000/index
,Cookie中存在值,这时候点击外链,表单自动提交,并且返回响应体
响应体如图:
服务端处理了来自第三方站点发送的请求,同时携带了Cookie(用户凭证),并且做出响应。
以上便完成了一次CSRF攻击。
CSRF中的攻击类型
1)post请求
上面的表单提交就是一个例子
2)get请求
在第三方站点内,添加一个img标签,src指向http://www.qinhanwen.xyz:3000/getCookie
稍微修改一下之前的代码
1 |
|
Koa:
1 | const koa = require('koa'); |
第三方页面:
1 |
|
当点击第三方页面的时候,如图:
可以看到跨域阻止了响应,但是服务端仍然收到了这个请求,并且打印出了key为name的Cookie,如图:
也就是说服务端收到了携带用户凭证的请求(Cookie),并且会做出响应。
3)还有一个就是在第三方页面再添加一个a标签,点击的时候会发送请求,这个就不多说了。
如何防御
1)检测来源(origin,referer)
修改一下上面的koa代码,分别打印它们的origin和referer看一下
1 | const koa = require('koa'); |
当同域下的页面访问接口http://www.qinhanwen.xyz:3000/getCookie
的时候,打印如图:
分别是 key为name的Cookie,origin以及referer
当访问第三方站点,自动提交表单访问http://www.qinhanwen.xyz:3000/csrf
接口的时候,打印如图:
分别是 key为name的Cookie,origin以及referer
补充个知识点:
跨域的时候:get,post都会显示origin。
同域的时候:get不显示origin,post显示origin。
不过origin以及referer主要依赖浏览器,不是最好的选择。
referer这个以后再深入了解吧,先放着
2)token
比如用户登陆之后,为用户添加一个标识(随机生成的唯一标识),标识不再放在Cookie里。在请求中传递。
总结
CSRF攻击主要是在第三方站点发生的,它只是使用了用户的登录凭证,没能够获得用户的登录凭证。