web之攻与受(CSRF篇)

试想以下场景:

  • 一个软件以国庆抢票为名,诱导你输入12306个人账号。
  • 百度搜索"xx银行",在排名第一的网站下输入你的账号密码。
  • 比如我在个人博客上发了一篇学习文章,下面放了一堆"学习资料链接"。你点击之后,就发了一个好评。通过好评内容扩散fake页面。

那你很有可能受到了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的页面提交数据(静默提交)。

危害

  • 利用用户登录态
  • 用户不知情时完成业务请求(如转账,消费,个人信息盗取)
  • 损害网站声誉

怎么办?

头脑风暴

可以通过头脑风暴的方式,思考下如何防止。

  • 禁止第三方携带cookie(兼容性不好)
  • Referer Check - Https不发送referer 没错,这又是一个koa插件。
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信息的方式来进行提交。另外,任何所谓的安全都是相对的,只是说理论的破解时间变长了,而不容易被攻击。很多时候要使用多种方法结合的方式来一起增加网站的安全性,可以结合验证码等手段大大减少盗刷网站用户信息的频率等,进一步增强网站内容的安全性。

原文发布于微信公众号 - 一Li小麦(gh_c88159ec1309)

原文发表时间:2019-09-04

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券