亲手实验一下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:3060
向http://127.0.0.1:3050
发送请求,不是跨域了吗?为什么还能携带cookie?没错,传统的表单就是存在这样的问题,这是历史遗留问题,表单提提交是允许跨域的
现在说下什么是csrf跨站请求伪造,它其实就是利用技术手段欺骗用户的浏览器,去访问一个已经认证过的网站,并执行一些恶意操作,由于用户已经认证过,所以服务器端会认为这是用户发送的合法请求。如何解决这个问题呢,首先就是不要用GET请求,尽管POST请求也无法避免这个问题,但是起码要安全点。然后就是对于传统的表单提交,后端可以在请求表单时向表单中添加一个随机token,表单提交后后端验证token有效性,这样就可以知道是不是用户提交的了。对于前后端分离的项目,这个问题就更好解决了,可以把后端返回的token存到localStorage中,这样在跨域的情况下攻击者是无法获取token的,自然也就无法钓鱼了
胖胖熊笔记,笔记已迁移