试想以下场景:
那你很有可能受到了CSRF攻击。
CSRF(Cross Site Request Forgery),即跨站请求伪造,是一种常见的Web攻击,它利用用户已登录的身份,在用户毫不知情的情况下,以用户的名义完成非法操作。 CSRF是指非源站点按照源站点的数据请求格式提交非法数据给源站点服务器的一种攻击方法。非源站点在取到用户登录验证信息的情况下,可以直接对源站点的某个数据接口进行提交,如果源站点对该提交请求的数据来源未经验证,该请求可能被成功执行。 这其实并不合理。通常的解决手段是:比较安全的是通过页面Token(令牌)提交验证的方式来验证请求是否为源站点页面提交的,来阻止跨站伪请求的发生。
CSRF原理:
如图用户通过源站点页面可以正常访问源站点服务器接口,但是也有可能被钓鱼进入伪站点来访问源服务器,如果伪站点通过第三方或用户信息拼接等方式获取到了用户的信息(如cookie),直接访问源站点的服务器接口进行关键性操作(例如支付扣款或返回用户隐私信息等操作),此时如果源站点服务器未做校验防护,伪站点的请求操作就可以被成功执行。另一种情况则可能是盗刷源站点的登录等接口来暴力破解用户密码的情况,如果源站点不添加防护措施,用户信息就极可能被盗取。
以下是一个最简单的CSRF实现
// 黑客网站 localhost:4000
document.write(`
<form name="form" action="http://localhost:3000/updateText" method="post" target="csrf">
添加评论: <input type="text" name="text" value="中国澳门赌场上线啦!" />
</form>
`)
const iframe = document.createElement('iframe')
iframe.name = 'csrf'
iframe.style.display = 'none'
document.body.appendChild(iframe)
setTimeout( () => {
document.querySelector('form').submit();
}, 1000)
假如用户上到一个钓鱼网站localhost:4000/csrf.html,什么都不管。就会不断向名为scrf的页面提交数据(静默提交)。
可以通过头脑风暴的方式,思考下如何防止。
app.use(async (ctx, next) => {
await next()
const referer = ctx.request.header.referer
console.log('Referer:', referer)
})
目前解决CSRF的最佳方式就是通过加密计算的Token验证,而Token除了通过session也可以使用HTTP请求头中Authorization的特定认证字段来传递。
当然并不是说使用了Token,网站调用服务就安全了,单纯的Token验证防止CSRF的方式理论上也是可以被破解的,例如可以通过域名伪造和拉取源站实时Token信息的方式来进行提交。另外,任何所谓的安全都是相对的,只是说理论的破解时间变长了,而不容易被攻击。很多时候要使用多种方法结合的方式来一起增加网站的安全性,可以结合验证码等手段大大减少盗刷网站用户信息的频率等,进一步增强网站内容的安全性。