At Software Secured, we have been building our internal tools around Node.js and Express. Node.js is becoming more and more popular nowadays and several frameworks have popped up to wrap Node.js functionality and APIs. One of these frameworks is Express. Express is very popular today as it was one of the first frameworks for Node.js that handled server side web tasks. It takes care of mundane tasks, like routing, parameter parsing, templates, and sending responses to the clients browser.Express and Node.js make it easier to develop secure applications; there are a bunch of security features that can be enabled easily by making simple modifications. The following contains a quick run down of these features.

Enable CSRF protection

This is super easy to setup. We use the lusca module. The code looks something like this:

[code]var express = require(‘express’);
var session = require(‘express-session’);
var app = express();
var csrf = require(‘lusca’).csrf();

app.use(lusca.csrf());[/code]

This is then used in the forms that post to the server:

[code]form(role=”form” action=”…” method=”post”)
input(type=’hidden’ name=’_csrf’ value=_csrf)
…[/code]

Dont run as root

It’s been long foretold by the ancient bearded ops that one shall run a service with the least amount of privilege necessary and no more.

One way to approach this is to drop process privileges after you bind to the port using something like this:

[code]var express = require(‘express’);
var app = express();

app.listen(app.get(‘port’), function() {
process.setgid(‘www-data’);
process.setuid(‘www-data’);
});[/code]

Another way is putting something like nginx or another proxy in front of your application. Whatever you do, just don’t freak’n run as root.

Turn off X-Powered-By

Why? Because you don’t want to make it easy for an attacker to figure what you are running The X-Powered-By header can be extremely useful to an attacker for building a site’s risk profile

X-Powered-By: Express

Can be removed using:

[code]var express = require(‘express’);
var app = express();

app.disable(‘x-powered-by’);[/code]

Use generic cookie name

One way to fingerprint your application is using the cookie name.
jsessionid -> Java application
phpsessid -> PHP application
ASP.NET_SessionId -> .net application

This is again a technique to hide information about what technology is being used.

[code]app.use(express.session({
secret: ‘some secret that now one knows’,
key: ‘sessionId’
}));[/code]

Add HTTPOnly and Secure flags to session cookies

Session cookies should have the SECURE and HTTPOnly flags set. This ensures they can only be sent over HTTPS (you are using HTTPS, right?) and there is no script access to the cookie client side.

[code]app.use(express.session({
secret: “s3Cur3”,
key: “sessionId”,
cookie: {
httpOnly: true,
secure: true
}}));[/code]

Use the Content Security Policy (CSP) header

This header is implemented in a select set of browsers at the moment, but still helps towards fending off attacks.

[code]var express = require(‘express’);
var helmet = require(‘helmet’);

var app = express();

app.use(helmet.contentSecurityPolicy({
defaultSrc: [“‘self'”, ‘default.com’],
scriptSrc: [‘scripts.com’],

}));[/code]

Use security headers

These can all be enabled in an express app using some combination of helmet and lusca modules

  • X-Content-Type-Options – stops browser mime type sniffing
  • X-XSS-Protection – Setting to ‘1; mode=block’ tells IE to turn on anti cross site scripting engine
  • X-Frame-Options – Setting this disallows the site to be included in a frame or iframe
  • Cache-Control – This enhances privacy. We can set to nocache for sensitive information.
  • X-Content-Security-Policy – This is CSP and was described
  • Strict-Transport-Security – checks for use of https
  • Access-Control-Allow-Origin – Controls which site can bypass same origin policy

Each header is further described here: Seven Web Server HTTP Headers that Improve Web Application Security for Free

Check for HTTP Parameter Pollution (HPP)

Give the following GET request:

[code]// GET /search?firstname=John&firstname=John[/code]

What will this return?

[code]req.query.firstname[/code]

It will return the following:

[code][“John”, “John”][/code]

Express populates HTTP request parameters with same name in an array

An attacker can:

  • Trigger Type Errors in application
  • Any uncaught errors in async code could crash the HTTP server causing DoS
  • Modify application behavior
  • Bypass input validations applied on strings in our code, WAF, browser filters.

Solution:

  • Check expected type as part of the input validation
  • Implement robust error handling mechanism using try/catch, domain, and cluster.

Regular Expression Denial of Service (ReDoS) Attack

Evil regex can take exponential execution time when applied to certain non-matching inputs.
By default, regex gets executed in event loop thread, so could be exploited for DoS attack.
In order for a regex to be evil regex, several requirements should happen
( )+
( a+ )+
( a|aa )+

1. Grouping with repetition, and
2. Inside repeated group, repetition or alternation with operlapping

Solution:

  • Review regex in our or external code for evil pattern
  • Do not use user supplied inputs as regex

 

Final Notes:

This a very cool project that has sprung up semi recently that is working towards making the nodejs ecosystem more secure

__https://nodesecurity.io/__

That’s all for now folks.

Sources:

  • https://gist.github.com/cerebrl/6487587
  • https://blog.liftsecurity.io/2012/12/07/writing-secure-express-js-apps
  • http://blog.risingstack.com/node-js-security-tips/
  • http://webapplog.com/express-js-security-tips/
White Paper - Proving Adherence to Software Security Best Practices

White Paper - Proving Adherence to Software Security Best Practices

Industry standards and the best practices for developing secure software. Please provide your email and name to receive your copy.

Success! Your copy is on the way.