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…