什么是 CSRF?
CSRF(Cross-site request forgery)跨站请求伪造攻击,是一种 Web 应用程序中常见的攻击方式。攻击者在受害用户的计算机中使用已登录的 Web 浏览器,来伪造用户的身份,然后向 Web 应用程序发送请求,从而执行未经授权的操作。
CSRF 攻击原理
随着 Web 应用程序的流行,许多用户的个人信息都会在 Web 网站上保存,包括银行账户信息、电子邮件、社交网络、商业信息等。如果攻击者冒充用户并执行操作,这将对用户和企业带来严重的后果。例如:攻击者可以篡改用户的个人信息,发送电子邮件,从银行账户转款,或将用户定位到恶意网站上。
CSRF 攻击的原理是攻击者利用用户已经登录的 Web 网站,来发送恶意请求。例如:用户在 A 网站登录,攻击者在邮件或论坛网站上插入恶意代码,当用户访问邮件或论坛网站时,代码就会向 A 网站发送攻击请求。由于用户已经登录 A 网站,攻击请求将被当做合法请求执行,这就完成了 CSRF 攻击。
如何防止 CSRF 攻击
为了避免 CSRF 攻击,在 Web 应用程序开发中,我们需要采取一些特殊的预防措施。
1.检查 Referer 和 Origin
要检查 Referer 或 Origin 头是否合法。例如,我们可以检查它们的值来确保请求的来源是允许的。
2.使用Token
我们可以使用 Token,将其添加到每个表单提交或重要请求中,并且确保它是唯一的和不可预测的。这样做的目的是,我们可以比较表单提交或请求中的 Token 与服务器上存储的当前 Token 值。如果不相等,则拒绝请求,以此避免 CSRF 攻击。
3. 利用浏览器 CSRF 保护机制
大部分浏览器都有 CSRF 保护机制:当浏览器在处理一个会发生状态变更的请求时,会主动向服务器询问是否同意执行该请求。如果服务器返回允许请求的信号,那么浏览器才会允许发送该请求。这种机制可以有效避免 CSRF 攻击。
Express.js 中使用 CSRF
在 Express.js 中确保 CSRF 攻击不成功非常简单。我们可以使用第三方中间件,例如 csurf 或者 Helmet 来实现。
使用 csurf 中间件
安装 csurf 中间件:
npm install --save csurf
引入 csurf 和 cookie-parser,并全局引用:
// www.javascriptcn.com code example
var csrf = require('csurf');
var cookieParser = require('cookie-parser');
app.use(cookieParser());
app.use(csrf());
app.use(function (req, res, next) {
res.cookie('XSRF-TOKEN', req.csrfToken());
res.locals._csrfToken = req.csrfToken();
next();
});注意:在服务器向客户端发送 HTML 页面时,在页面 head 中必须添加以下内容:
<meta name="csrf-token" content="{{_csrfToken}}">在需要保护的表单中添加以下内容:
<input type="hidden" name="_csrf" value="{{_csrfToken}}">完成以上步骤后,CSRF 保护已经启用。
使用 Helmet 中间件
Helmet 中间件提供了一系列安全功能,其中包括 CSRF 防御机制。
var express = require('express')
var helmet = require('helmet')
var app = express()
// 将 Helmet 中间件添加到 Express:
app.use(helmet())
app.listen(3000)示例代码
使用 csurf 中间件
// www.javascriptcn.com code example
const express = require('express');
const csurf = require('csurf');
const cookieParser = require('cookie-parser');
const app = express();
app.use(cookieParser());
app.use(csurf());
app.use(function (req, res, next) {
res.cookie('XSRF-TOKEN', req.csrfToken());
res.locals._csrfToken = req.csrfToken();
next();
});
app.post('/form', function (req, res) {
res.send('form submitted!');
console.log(req.body);
});
app.listen(3000);在表单中添加 _csrf 隐藏值:
<form method="POST" action="/form">
<input type="hidden" name="_csrf" value="{{_csrfToken}}">
<input type="text" name="message">
<button type="submit">Submit</button>
</form>使用 Helmet 中间件
// www.javascriptcn.com code example
const express = require('express');
const helmet = require('helmet');
const app = express();
app.use(helmet());
app.post('/form', function (req, res) {
res.send('form submitted!');
console.log(req.body);
});
app.listen(3000);在表单中添加 _csrf 隐藏值:
<form method="POST" action="/form"> <input type="text" name="message"> <button type="submit">Submit</button> </form>
结语
恶意攻击者利用 CSRF 攻击来窃取用户账户信息、发送电子邮件,从银行账户转款等,这对用户和企业会带来严重后果。在开发 Web 应用程序时,我们应该采取相应的预防措施,保证 Web 应用程序不会被 CSRF 攻击骚扰。
在 Express.js 中实现 CSRF 防御可以使用第三方中间件 csurf 或者 Helmet,具体使用方式详见本文。在实际项目中,可以根据情况选择合适的防御措施。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67d6b8d3a941bf7134c93976