亲手实验一下csrf跨站请求伪造

这里我先不解释什么是csrf以及如何预防,先看实验

我现在有一个很简单的站点,它有两个API接口,如下所示:

// 模拟登录
app.get('/api/login', function(req, res) {
 res.cookie('token', 'asdf')
  res.json({
    msg: '登录成功'
  })
})

// 模拟删除
app.post('/api/delete', function(req, res) {
  res.json({
    msg: '文章已删除'
  })
})
app.listen(3050);

现在我访问/api/login表示登录成功,然后后端会设置cookie

现在有个恶意攻击者,它知道通过向http://127.0.0.1:3050/api/delete发送post请求可以删除用户文章,只要用户已经登录了,它就可以这么做

第一步:它向用户发送了一封邮件(邮件可以是HTML格式的哦),告诉他中奖了

<!DOCTYPE html>
<html lang="en">
<head>
  
  <title>Document</title>
</head>
<body>
  <form action="http://127.0.0.1:3050/api/delete" method="POST">
    <input value="1" name="id" hidden> <!--删除id为1的文章-->
    <button type="submit">恭喜你中奖啦,去看看</button>
  </form>
</body>
</html>

用户点开邮件,看到了下面的页面

看到自己中奖了很高兴,迫不及待的点了按钮去领奖,于是出现了下面的效果

哈哈,它成功删除了自己的文章。

你可能会奇怪,从http://127.0.0.1:3060http://127.0.0.1:3050发送请求,不是跨域了吗?为什么还能携带cookie?没错,传统的表单就是存在这样的问题,这是历史遗留问题,表单提提交是允许跨域的

现在说下什么是csrf跨站请求伪造,它其实就是利用技术手段欺骗用户的浏览器,去访问一个已经认证过的网站,并执行一些恶意操作,由于用户已经认证过,所以服务器端会认为这是用户发送的合法请求。如何解决这个问题呢,首先就是不要用GET请求,尽管POST请求也无法避免这个问题,但是起码要安全点。然后就是对于传统的表单提交,后端可以在请求表单时向表单中添加一个随机token,表单提交后后端验证token有效性,这样就可以知道是不是用户提交的了。对于前后端分离的项目,这个问题就更好解决了,可以把后端返回的token存到localStorage中,这样在跨域的情况下攻击者是无法获取token的,自然也就无法钓鱼了

posted @ 2021-10-07 14:29  wmui  阅读(71)  评论(0编辑  收藏  举报