Node JS Security


Use Helmet
- Helmet can help protect your app from some well-known web vulnerabilities by setting HTTP headers appropriately.
- Helmet is actually just a collection of nine smaller middleware functions that set security-related HTTP headers:
- csp sets the Content-Security-Policy header to help prevent cross-site scripting attacks and other cross-site injections.
- hidePoweredBy removes the X-Powered-By header.
- noCache sets Cache-Control and Pragma headers to disable client-side caching.
- noSniff sets X-Content-Type-Options to prevent browsers from MIME-sniffing a response away from the declared content-type.
- frameguard sets the X-Frame-Options header to provide clickjacking protection.
- xssFilter sets X-XSS-Protection to enable the Cross-site scripting (XSS) filter in most recent web browsers.
var csrf = require('csurf');
/*some code here*/
var app = express();
/*some code here*/
app.use(csrf());
app.get('/', function(req, res, next){
res.render('index', {
_csrfToken = req.csrfToken();
});
});
Prevent XSS ! Context Based Encoding
var csrf = require('csurf');
/*some code here*/
var app = express();
/*some code here*/
app.use(csrf());
app.get('/', function(req, res, next){
res.render('index', {
_csrfToken = req.csrfToken();
});
});
Prevent CSRF (Cross Site Request Forgery) with Anti-Forgery Tokens
/*some code here*/
app.use(csrf());
app.use(function (req, res, next) {
res.cookie('XSRF-TOKEN', req.csrfToken());
next();
});
Send CSRF Token
/*some code here*/
var express = require('express');
var session = require('express-session');
var app = express();
app.use(session({
name: 'SESS_ID',
secret: '^#$5sX(Hf6KUo!#65^',
resave: false,
saveUninitialized: true,
cookie: {
secure: true,
httpOnly: true
}
}));
Secure Express.js Sessions and Cookies
Make cookies more secure


Make cookies more secure
/* some code */
app.get('/', function(req, res, next){
/*some logic here before setting cookie*/
res.cookie('User', 'John Doe',
{ httpOnly: true, secure: true });
res.status(200)
.json('this is a repsonse with a safe cookie');
});
Signing Cookies
var cookieParser = require('cookie-parser');
var express = require('express');
var app = express();
app.use(cookieParser('6xH$*CYY*u44gcUN57%H'));
app.get('/', function(req, res, next){
res.cookie('User', 'John Doe', { signed: true });
res.render('index');
});
app.get('/somepath', function(req, res, next)){
var currentUser = req.signedCookies['User'];
// "John Doe" will be returned to
// currentUser only if the signation is verified
}
Query param population
http://example.com/?firstname='Jack'&lastname='Sparrow'
An attacker would try to attack the application by modifying the
http://example.com/?firstname='Jack'&lastname='Sparrow'&firstname='Jill'
Preventing HTTP Parameter Pollution (HPP)
var hpp = require('hpp');
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.urlencoded({extended: false}));
//body parser should be placed before using hpp
app.use(hpp());
app.get('/', function(req, res, next){
console.log('Query Parameters : ' + JSON.stringify(req.query));
console.log('Polluted Query Parameters : '+ JSON.stringify(req.queryPolluted));
res.render('index');
});
Setting Security Response Headers
var express = require('express');
var app = express();
app.disable('x-powered-by'); // disable X-Powered-By header
app.use(function(req, res, next){
res.header('X-XSS-Protection', '1; mode=block');
res.header('X-Frame-Options', 'deny');
res.header('X-Content-Type-Options', 'nosniff');
next();
});
Setting Security Response Headers
- X-Frame-Options — Prevents your application being displayed in iframes
- X-XSS-Protection — Invokes browser XSS protection mechanisms
- X-Content-Type-Options — Prevents mime sniffing
Setting Security Response Headers
var helmet = require('helmet');
app.use(helmet.hidePoweredBy({setTo: 'DummyServer 1.0'}));
//change value of X-Powered-By header to given value
app.use(helmet.noCache({noEtag: true}));
//set Cache-Control header
app.use(helmet.noSniff());
// set X-Content-Type-Options header
app.use(helmet.frameguard());
// set X-Frame-Options header
app.use(helmet.xssFilter());
// set X-XSS-Protection header
NPM Modules
- csurf — Implement Anti-CSRF tokens to prevent cross site request forgery
- cors — Enable Cross origin resource sharing
- hpp — Protection from HTTP Parameter Pollution
- express-content-length-validator — Prevent DOS attacks
- rate-limiter — Prevent DOS attacks
- helmet — Set custom security headers
- nsp — Scan for deprecated/vulnerable npm modules used in your app
- retire — Scan for deprecated/vulnerable npm modules used in your app
- mocha, should, supertest — Writing node.js tests
-
bunyan — Logging
Use explicit package versions
{
"name": "My App",
"version": "0.0.0",
"scripts": {
"start": "node ./bin/www"
},
"dependencies": {
"body-parser": "~1.13.2",
"cookie-parser": "~1.3.5",
"debug": "~2.2.0",
"express": "~4.13.1",
"http-auth": "~2.2.8",
"jade": "~1.11.0",
"jsonfile": "~2.2.1",
"morgan": "~1.6.1",
"nodemon": "~1.4.1",
"serve-favicon": "~2.3.0"
}
}
No sensitive data inside your repo !!!
app.use(session({
name: 'SESS_ID',
secret: process.env.EXPRESS_SESSION_SECRET,
resave: false,
saveUninitialized: true,
cookie: {
secure: true,
httpOnly: true
}
}));
always keep your application components up-to-date. Following are few tools that you can use to identify potential outdated components in your application.
And also keep your Node.js version and NPM up to date. Node.js version can be updated with “n”
sudo npm install n sudo n stable
You can update
sudo npm install -g npm
Can we, effectively, build a program using this notion?
Meet your new friend:
The Observable
Your friendly neighbor: RxJS
Reactive Extensions
Are a set of libraries for composing asynchronous and event-based programs using observable sequences and fluent query operators
Rx is everywhere

Java
JavaScript
.Net
Ruby
Swift
C++
Clojure
Scala
What is the most asynchronous?
User





More async data streams
-
XHR requests
-
WebSocket
-
Promises
-
Events
-
Dom Inputs
-
Web Worker
-
Web RTC
RxJS operators
RxJS operators
RxJS operators: map

resStream
RxJS operators: delay

resStream
RxJS operators: debounce

resStream
RxJS operators: merge

resStream
RxJS operators: combineLatest

resStream
RxJS operators: zip

resStream
Let's create a morse-code decoder!
Morse-code decoder

click...
click...
click.............
click...
Morse-code decoder
click...
click...
click.............
click...
Morse-code decoder
-
Dom events (keydown, keyup)
-
Start signal/End signal
-
Dot/Dash/Whitespace
-
Letter
-
Word/Sentence
Morse-code decoder

Morse-code decoder
-
"." = ~400ms
-
"_" = 3 * "."
-
between codes = "."
-
between letters = 3 * "."
-
between words = 7 * "."

Morse-code decoder
const keyUps = Rx.Observable
.fromEvent(document, 'keyup');
const keyDowns = Rx.Observable
.fromEvent(document, 'keydown');
Morse-code decoder
const spaceKeyUps = keyUps.filter((data) => data.keyCode === 32);
const spaceKeyDowns = keyDowns.filter((data) => data.keyCode === 32);

Morse-code decoder
const signalStartsRaw = spaceKeyDowns.map(() => "start");
const signalEndsRaw = spaceKeyUps.map(() => "end");
const signalStartsEnds = Rx.Observable
.merge(signalStartsRaw, signalEndsRaw)
.distinctUntilChanged();

Morse-code decoder
const signalStarts = signalStartsEnds
.filter((ev) => ev === "start")
.timestamp();
const signalEnds = signalStartsEnds
.filter((ev) => ev === "end")
.timestamp();
const spanStream = signalStarts.flatMap((start) => {
return signalEnds.map((end) => end.timestamp - start.timestamp)
.first();
});
Morse-code decoder

Morse-code decoder
const SPAN = 400;
const dotsStream = spanStream
.filter((v) => v <= SPAN)
.map(() => ".");
const lineStream = spanStream
.filter((v) => v > SPAN)
.map(() => "-");
Morse-code decoder
const dotsAndLines = Rx.Observable.merge(dotsStream, lineStream);
// [['.', '.', '-'], ['-', '.', '-'] ... ]
const letterCodes = dotsAndLines.buffer(letterWhitespaces);
// ['A', 'B' ...]
const lettersStream = letterCodes
.map((codes) => morse.decode(codes.join("")));
Morse-code decoder

demo — http://alexmost.github.io/morse/
source — https://github.com/AlexMost/morse
Morse-code decoder

What else?
Component bindings

Component bindings
click...
click...
click.............
click...
click
category.
comp.
bundle.
package.
Component bindings

Component bindings

Problems RxJS solves
-
Data Manipulation
-
Events handling
-
Callback Hell
-
Promise Hell
-
Comet/Async Manipulation
-
Race Conditions
-
Complex State
-
Tests

RxJS problems
Complexity

Integration with imperative part of code

Documentation
Projects each element of an observable sequence to an observable sequence and merges the resulting observable sequences or Promises or array/iterable into one observable sequence.
Cascade Updating
Cascade Updating
Cascade Updating/Exceptions
RxJS with other frameworks
RxJS with Angular - rx.angular.js
angular.module('example', ['rx'])
.controller('AppCtrl', function($scope, $http, rx) {
function searchWikipedia (term) {
return rx.Observable
.fromPromise($http({}))
.map(function(response){ return response.data[1]; });
}
$scope.search = '';
$scope.results = [];
$scope.$createObservableFunction('click')
.map(function () { return $scope.search; })
.flatMapLatest(searchWikipedia)
.subscribe(function(results) {
$scope.results = results;
});
});
RxJS with Angular2 - inside

RxJS with React - rx-react

RxJS with others







Alternative?
Bacon

Kefir

Highland
I want more hardcore!
Javelin and ClosureScript
(defc test-results
{:scores [74 51 97 88 89 91 72 77 69 72 45 63]
:proctor "Mr. Smith"
:subject "Organic Chemistry"
:sequence "CHM2049"})
(defc= test-results-with-mean
(let [scores (:scores test-results)
mean (/ (reduce + scores) (count scores))
grade (cond (<= 90 mean) :A
(<= 80 mean) :B
(<= 70 mean) :C
(<= 60 mean) :D
:else :F)]
(assoc test-results :mean mean :grade grade)))
Cycle.js
-
RxJS
-
Side effects/Logic
-
Composition
-
Streams, streams, streams, streams

Questions?
Async in JS webinar 01
By Tarun Sharma
Async in JS webinar 01
- 748