From 50061c370ca29e396d4fb8d6150e127ec6d3d3e7 Mon Sep 17 00:00:00 2001 From: Keith Irwin Date: Sun, 4 Mar 2018 20:15:43 +0000 Subject: [PATCH] #121 Added CSRF protection --- package-lock.json | 61 +++++++++++++++++++++++++++++++++++++++++++++ package.json | 1 + server.js | 14 ++++++++--- views/contact.html | 1 + views/forgot.html | 1 + views/login.html | 2 ++ views/password.html | 29 ++++++++++----------- views/pro.html | 1 + views/settings.html | 1 + 9 files changed, 93 insertions(+), 18 deletions(-) diff --git a/package-lock.json b/package-lock.json index 68f6e21..c0a6078 100755 --- a/package-lock.json +++ b/package-lock.json @@ -1228,6 +1228,16 @@ "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=", "dev": true }, + "csrf": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/csrf/-/csrf-3.0.6.tgz", + "integrity": "sha1-thEg3c7q/JHnbtUxO7XAsmZ7cQo=", + "requires": { + "rndm": "1.2.0", + "tsscmp": "1.0.5", + "uid-safe": "2.1.4" + } + }, "css-color-names": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", @@ -1327,6 +1337,34 @@ "source-map": "0.5.7" } }, + "csurf": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/csurf/-/csurf-1.9.0.tgz", + "integrity": "sha1-SdLGkl/87Ht95VlZfBU/pTM2QTM=", + "requires": { + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "csrf": "3.0.6", + "http-errors": "1.5.1" + }, + "dependencies": { + "http-errors": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.5.1.tgz", + "integrity": "sha1-eIwNLB3iyBuebowBhDtrl+uSB1A=", + "requires": { + "inherits": "2.0.3", + "setprototypeof": "1.0.2", + "statuses": "1.4.0" + } + }, + "setprototypeof": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.2.tgz", + "integrity": "sha1-gaVSFB7BBLiOic44MQOtXGZWTQg=" + } + } + }, "d": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", @@ -6046,6 +6084,11 @@ "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=" }, + "random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=" + }, "randomatic": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", @@ -6425,6 +6468,11 @@ "inherits": "2.0.3" } }, + "rndm": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/rndm/-/rndm-1.2.0.tgz", + "integrity": "sha1-8z/pz7Urv9UgqhgyO8ZdsRCht2w=" + }, "run-async": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz", @@ -7123,6 +7171,11 @@ "punycode": "1.4.1" } }, + "tsscmp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.5.tgz", + "integrity": "sha1-fcSjOvcVgatDN9qR2FylQn69mpc=" + }, "tty-browserify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", @@ -7203,6 +7256,14 @@ "resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.6.tgz", "integrity": "sha1-DqEOgDXo61uOREnwbaHHMGY7qoE=" }, + "uid-safe": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.4.tgz", + "integrity": "sha1-Otbzg2jG1MjHXsF2I/t5qh0HHYE=", + "requires": { + "random-bytes": "1.0.0" + } + }, "uid2": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.3.tgz", diff --git a/package.json b/package.json index f45ba53..3d0151c 100755 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "cookie-parser": "^1.4.3", "cookie-session": "^2.0.0-beta.2", "css-loader": "^0.28.7", + "csurf": "^1.9.0", "debug": "^2.6.9", "express": "^4.15.5", "express-request-limit": "^1.0.2", diff --git a/server.js b/server.js index f082ba3..17cb4e9 100755 --- a/server.js +++ b/server.js @@ -7,6 +7,7 @@ const rateLimit = require('express-request-limit') const bodyParser = require('body-parser') const cookieParser = require('cookie-parser') const cookieSession = require('cookie-session') +const csurf = require('csurf') const mongoose = require('mongoose') const nunjucks = require('nunjucks') const passport = require('passport') @@ -49,7 +50,7 @@ let ready_promise_list = [] /* Templates */ { nunjucks.configure(__dirname + '/views', { autoescape: true, - express: app + express: app, }) app.set('view engine', 'html') } @@ -66,11 +67,11 @@ let ready_promise_list = [] }, secret: env.session, saveUninitialized: true, - resave: true + resave: true, })) app.use(bodyParser.json()) app.use(bodyParser.urlencoded({ - extended: true + extended: true, })) app.use(flash()) } @@ -149,7 +150,7 @@ let ready_promise_list = [] res.status(err.status || 500) res.render('error', { code: err.status || 500, - message: (err.status <= 499) ? err.message : 'Server error' + message: (err.status < 500) ? err.message : 'Server error' }) }) @@ -168,6 +169,11 @@ let ready_promise_list = [] } } +// CSRF Protection +app.use(csurf({ + cookie: true, +})) + /* Sockets */ { sockets.init(io) } diff --git a/views/contact.html b/views/contact.html index 6cfd593..23df1f6 100755 --- a/views/contact.html +++ b/views/contact.html @@ -19,6 +19,7 @@

Contact

+

You need to enter a message.

diff --git a/views/forgot.html b/views/forgot.html index c1ed9a4..72de9bb 100755 --- a/views/forgot.html +++ b/views/forgot.html @@ -13,6 +13,7 @@

Enter your email below to recieve a link to reset your password.

+
diff --git a/views/login.html b/views/login.html index 7b69d1c..da52576 100755 --- a/views/login.html +++ b/views/login.html @@ -24,6 +24,7 @@

Login

+
@@ -64,6 +65,7 @@

Create account

Welcome aboard!

+

You will be sent an email confrimation with a link to create a password.

By signing up, you agree to our terms of service and privacy policy.

diff --git a/views/password.html b/views/password.html index a048248..d0b8cd2 100755 --- a/views/password.html +++ b/views/password.html @@ -18,20 +18,21 @@

Set Password

- + +

Your password must be at least 8 characters long. You can use any letter, number, symbol, emoji, or spaces. Your password will be checked using zxcvbn. All passwords are stored on the server as salted hashes.

diff --git a/views/pro.html b/views/pro.html index c8c2e6d..cd60fa8 100755 --- a/views/pro.html +++ b/views/pro.html @@ -28,6 +28,7 @@ Keith Irwin

+ {% if user.isPro %}
diff --git a/views/settings.html b/views/settings.html index a292eb1..b10c6cf 100755 --- a/views/settings.html +++ b/views/settings.html @@ -19,6 +19,7 @@

Settings

+

Account settings