Sample code repository address
Github.com/ishanyang/b…
The sample code is done using the NodeJS Express framework
CSRF (csrf-example)
Create an app to provide form submission services
mkdir app
cd app
npm init -y
npm install express pug --save
mkdir views
touch app.js views/layout.pug views/list.pug views/post.pug
Copy the code
app.js
const path = require('path');
const express = require('express');
const pug = require('pug');
const app = express();
let list = [
{title: 'Article 1'},
{title: 'Article 2'},]; app.set('view engine'.'pug');
app.set('views', path.join(__dirname, 'views'));
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.get('/'.function(req, res, next) {
res.render('list', {
title: 'Article List',
list
})
});
app.get('/post'.function(req, res, next) {
res.render('post', {
title: 'New article'
});
});
app.post('/post'.function(req, res, next) {
const title = req.body.title
if(title) {
list.push({title})
}
return res.redirect('/');
});
app.get(The '*'.function (req, res) {
res.send('hello world! ')
})
app.listen(4001, () => {
console.log('http://localhost:4001/')})Copy the code
views/layout.pug
doctype html
html
head
title= title
body
block content
Copy the code
views/list.pug
Extends Layout Block Content (href="/post") extends Layout Block Content (href="/post")Copy the code
views/post.pug
extends layout block content form(action="/post" method="POST") input(type="text" name="title" required Placeholder =" please input the title of the article ") button(type="submit"Copy the code
Run node app.js to access http://localhost:4001/
Create services that simulate attacks
touch mockCsrf.js views/mockCsrf.pug
Copy the code
mockCsrf.js
const path = require('path');
const express = require('express');
const pug = require('pug');
const app = express();
app.set('view engine'.'pug');
app.set('views', path.join(__dirname, 'views'));
app.get(The '*'.function (req, res) {
res.render('mockCsrf', {title: 'mock csrf'});
})
app.listen(4002, () => {
console.log('mock csrf http://localhost:4002/')})Copy the code
views/mockCsrf.pug
extends layout block content h1 mock csrf form#mock-form(action="http://localhost:4001/post" method="POST") Input (type="text" name="title" required placeholder=" please input ") button(type="submit") submit script. document.getElementById("mock-form").submit();Copy the code
Execute Node mockcsrf.js to access http://localhost:4002/
CSRF (@authentication/ csrF-protection)
Install @authentication/csrf-protection on csrf-example
npm install @authentication/csrf-protection --save
Copy the code
app.js
const path = require('path');
const express = require('express');
const pug = require('pug');
const csrfProtection = require('@authentication/csrf-protection')
const app = express();
let list = [
{title: 'Article 1'},
{title: 'Article 2'},]; app.set('view engine'.'pug');
app.set('views', path.join(__dirname, 'views'));
app.use(csrfProtection());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.get('/'.function(req, res, next) {
res.render('list', {
title: 'Article List',
list
})
});
app.get('/post'.function(req, res, next) {
res.render('post', {
title: 'New article'
});
});
app.post('/post'.function(req, res, next) {
const title = req.body.title
if(title) {
list.push({title})
}
return res.redirect('/');
});
app.get(The '*'.function (req, res) {
res.send('hello world! ')
})
app.listen(4001, () => {
console.log('http://localhost:4001/')})Copy the code
Restart the service
npm start
npm run start-mock-csrf
Copy the code
The CSRF attack service http://localhost:4002/ has the following effect:
This is accomplished by checking the prevention CSRF of the Referer field.
Protect against CSRF through token mode
Install dependencies based on csrf-example
npm i csurf csrf cookie-parser --save
Copy the code
Before implementing the token synchronization pattern, take a look at package CSRF, because the Express middleware CSURF uses this library. The application should at least ensure that each user’s csrfSecret is different.
const Tokens = require('csrf');
const tokens = new Tokens();
// Create keys asynchronously: tokens. Secret (callback)
const csrfSecret = tokens.secretSync();
// Create a token
const some_user_token = tokens.create(csrfSecret);
// Validate the token
if(! tokens.verify(csrfSecret, some_user_token)) {throw new Error('invalid token! ')}else {
console.log('Verified');
}
Copy the code
Modify views/post.pug as follows
extends layout block content form(action="/post" method="POST") input(type="hidden" name="_csrf" value= csrfToken) Input (type="text" name="title" required placeholder=") button(type="submit") submitCopy the code
Modify app.js as follows
const path = require('path');
const express = require('express');
const pug = require('pug');
const cookieParser = require('cookie-parser');
const csrf = require('csurf');
const csrfProtection = csrf({ cookie: true })
const app = express();
let list = [
{title: 'Article 1'},
{title: 'Article 2'},]; app.set('view engine'.'pug');
app.set('views', path.join(__dirname, 'views'));
app.use(cookieParser())
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.get('/'.function(req, res, next) {
res.render('list', {
title: 'Article List',
list
})
});
app.get('/post', csrfProtection, function(req, res, next) {
res.render('post', {
title: 'New article'.csrfToken: req.csrfToken()
});
});
app.post('/post', csrfProtection, function(req, res, next) {
const title = req.body.title
if(title) {
list.push({title})
}
return res.redirect('/');
});
app.get(The '*'.function (req, res) {
res.send('hello world! ')
})
app.listen(4001, () => {
console.log('http://localhost:4001/')})Copy the code
Run Node app.js and Node Mockcsrf.js again
Visit http://localhost:4001 to add articles as normal
But here’s what happens when you visit http://localhost:4002 and try a cross-site forgery attack
ForbiddenError: invalid csrf token
Copy the code
For more information, such as Ajax, or the use of single-page APP to transfer tokens, please refer to github.com/expressjs/c…
The original link
www.hijs.ren/article/blo…