概念
CSRF(Cross-Site Request Forgery) 跨站请求伪造
CSRF:是一种网站攻击方法, 它强制用户在当前对其进行身份验证的Web应用程序上, 执行其他的操作(这里指的是非用户要求的操作).
CSRF攻击专门针对状态更改请求,而不是数据被盗,因为攻击者无法查看伪造请求的响应。借助社交工程(例如通过电子邮件或聊天发送链接),攻击者可以欺骗Web应用程序的用户执行攻击者选择的操作。
造成问题
如果受害者是普通用户,则成功的CSRF攻击可以强制用户执行状态更改请求,例如转移资金,更改其电子邮件地址等。
如果受害者是管理帐户,CSRF可能会危及整个Web应用程序。
实现过程
- 1 用户使用浏览器登录信任的网站A
- 2 验证通过, 此时会在用户的浏览器上产生A的cookie
- 3 用户在没有退出当前页面, 且用当前浏览器访问攻击网站
- 4 攻击网站访问第三站点(就是之前用户登录的网站A), 发出请求
- 5 根据(-4)的请求,浏览器带着(-2)中产生的cookie访问A
-6 A网站并无法识别请求的否是由用户发出的,由于浏览器会自动带上用户C的cookie, 所以网站A会根据用户处理(-5)的请求,这样攻击网站就达到了模拟用户操作的目的.
实现前提
-1 用户没有关闭网站A的页面
-2 并且使用的是同一个浏览器访问了攻击网站
说到这里,我们就大概清楚了CSRF的攻击原理及过程了.
那为什么要在没有关闭网站A的前提下呢?其实就是session的存活时间,我们在之前的文章中有介绍,想详细了解,可以去看看.这里写链接内容
那我们作为一个网站的开发者,我们应该怎么去处理这么一个问题,让我们的网站更安全呢?其实,如果你逻辑性强一点的话,你应该会发现,其实攻击网站就是利用了用户在其他网站产生的cookie,去达成他的目的.那我们可以在cookie上做点事情.
防止CSRF的方法
方法一 防伪令牌
为了帮助防止CSRF攻击,ASP.NET MVC使用反伪令牌
-1 客户端请求包含表单的HTML页面。
-2 服务器在响应中包含两个令牌。一个令牌作为cookie发送。另一个放在隐藏的表单字段中。令牌是随机生成的,因此攻击者无法猜测值。
-3 当客户端提交表单时,它必须将两个令牌发送回服务器。客户端将cookie令牌作为cookie发送,并将表单令牌发送到表单数据中。(当用户提交表单时,浏览器客户端会自动执行此操作。)
-4 如果请求不包含两个令牌,则服务器不允许该请求。
防伪令牌起作用是因为恶意页面由于同源策略而无法读取用户的令牌。(同源策略阻止托管在两个不同站点上的文档访问彼此的内容。因此在前面的示例中,恶意页面可以向example.com发送请求,但它无法读取响应。)
对于任何非安全方法(POST,PUT,DELETE),您都应该要求防伪标记。另外,确保安全方法标记(GET,HEAD)并没有任何副作用。但是如果您启用跨域支持,例如CORS或JSONP,那么即使是安全的方法(如GET)也可能容易受到CSRF攻击,从而允许攻击者读取可能敏感的数据。
方法二 token验证
-1 在客户端向后端请求界面数据的时候,后端会往响应中的 cookie 中设置 csrf_token 的值
-2 在 Form 表单中添加一个隐藏的的字段,值也是 csrf_token
-3 在用户点击提交的时候,会带上这两个值向后台发起请求
-4 后端接受到请求,以会以下几件事件:
从 cookie中取出 csrf_token
从 表单数据中取出来隐藏的 csrf_token 的值
进行对比
-5 如果比较之后两值一样,那么代表是正常的请求,如果没取到或者比较不一样,代表不是正常的请求,不执行下一步操作
代码实现
@app.route("/verify", methods=["POST", "GET"])
def verify():
...
if request.method == "POST":
...(相应的逻辑操作)
else:
# 生成csrf_token的值
csrf_token = generate_csrf()
# 渲染转换页面, 传入crsf_token到模板中
response = make_response(render_template('temp_transfer.html', csrf_token=csrf_token))
# 设置scrf_token到cookie中,用于提交校验
response.set_cookie('csrf_token', crsf_token)
return response
# 在模板表单中添加csrf_token隐藏字段
<form method="post">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
...
</form>
若有错漏, 欢迎各路好友批评指正!