Securing Your Node.js App

By default, Node.js is fairly secure by itself. Although, there are definitely things you have to watch out for. If your Node web-app starts to get more and more popular, for example, you'll need to be thinking more and more about security to ensure that you're keeping your users' data safe.

After seeing some questions about Node.js security around the web in the last few weeks, I figured it would be helpful to write up a short guide on what you can do to secure your apps.

Many, if not all, of the suggestions here are really easy to follow and implement, and are mostly specific to Node itself or its modules. So I won't be covering things like a encryption or user authentication, which is a bit out of scope of this article. Many of the tips here will be focused on Node web frameworks, since those are typically the most vulnerable to attack.

Don't Run Code with Sudo

This happens way more than you think, and it's dangerous. Since it gives root permissions, running code with sudo can make annoying problems go away, like writing to a directory that the user doesn't own. But that's just the easy way out, and these shortcuts bring up a mess of other problems you shouldn't ignore.

Instead, find the root cause of the problem and figure out a way to get around it without compromising the whole system.

So, for example, if you need to open port 80 for a web service but can't since you're not running under root, you should instead use a proxy like Nginx to forward the requests from port 80 to whatever other port your service is actually running on.

If you run under root and your application is taken over by attackers, they can then do whatever they want with your system and your data. This is the worst-case scenario that you're trying to protect yourself from.

Avoid eval at all Costs

Okay, I'll admit it, at times it can be tempting to make your code more dynamic by letting it execute arbitrary JavaScript using eval, but believe me, this is a bad idea.

Some people even try to use it when they get lazy with parsing user input. After all, the V8 JavaScript engine is really good at parsing things like simple math operations, so it would be tempting to use that to your advantage:

var result = eval('(13 + (2 * 23.249) / 0.981)');
// result = 60.398572884811415

There are just too many ways this can come back to bite you. Unless you're an expert and know how to protect yourself from all of the different kinds of malicious JavaScript code, just steer clear of this.

Here is a simple example of the exploit:

var userInput = req.body.userInput;    // User entered 'process.exit()'
var answer = eval(userInput);          // App quits here

Running this code will shut down your app, causing a denial of service (DOS) to your users.

Add/Remove HTTP Headers

There are quite a few HTTP headers out there that can both help you and hurt you. Using the right ones in the right way is the tricky part.

Express, by default, adds the X-Powered-By: Express header, which really does nothing but tell potential attackers what web framework you're using, and therefore how to exploit it based on publicly-known vulnerabilities. The more information they have about your technology stack, the more ways they'll be able to attack it.

That's where helmet comes in to play. Helmet is a small module for Node that helps secure Express/Connect apps by adding/removing various HTTP headers.

You can do anything from enabling HSTS to preventing click-jacking attacks. These are things that take little to no work on your part, but they can make a world of difference. So if you're building an Express app, this should be a no-brainer (and really, for any web service you should do this).

Use Scanning Utilities like Retire.js

Not all programmers are security experts, and while you should do your best to stay up-to-date on common exploits like XSS or SQL injection, it's tough to know them all.

To make up for this, you should try using tools like Retire.js, which scans your Node app for dependencies that contain vulnerabilities.

For example, Ember.js has a specific XSS vulnerability in a few different versions (CVE-2014-0046), all of which are checked by Retire.js. When you execute retire in your project's directory, it'll compare packages in node_modules to a public repository of vulnerabilities and report to you which of your dependencies are insecure.

There are just far too many vulnerabilities in a lot of these packages to check yourself, so you're better off letting a tool like this do it for you.

You can easily make this a part of your workflow by integrating it with Grunt or Gulp, thanks to the plugins provided. The details are in the README.

Another option is to just run it in a prepublish command, which would run before npm sends your package to the repository. Just add something like this to your package.json:

{
  "name": "myProject",
  "version": "0.0.1",
  "scripts": {
    "prepublish": "retire",
  }
}

Be Careful with the child_process Module

Like eval, using spawn and exec from the child_process module can be really useful, but also really dangerous. Any user input that sneaks in to these commands could mean your system gets compromised pretty quickly (especially if you're running your app with sudo!).

For example, Image Magick is a very popular command line tool for displaying, converting, and editing images. With so many web-apps using images these days, Image Magick is often being used in the background for things like cropping and resizing. To use this tool with Node, you might see code like this:

child = child_process.exec('convert ' + imageFilename + ' ' + imageFilename + '.bmp', ['-depth', '24'], function(err, stdout, stderr) {
    console.log('Done');
});

This may look harmless, but with a carefully crafted imageFilename, you can execute any code you want in the shell.

exec should only be used if it doesn't depend on user input or if the arguments are heavily sanitized. Even better, check npm for a library that wraps the command line tool. These are usually built with this kind of security in mind, or at least have more eyes on the code to check for problems. For Image Magick, there are a few modules available, like gm.

Understand the Vulnerabilities

Many vulnerabilities in web applications apply to all services, regardless of programming language and framework used. Although, how you attack those services may differ based on the technology stack you're using. To better defend yourself, you really need to learn how these exploits work.

Free eBook: Git Essentials

Check out our hands-on, practical guide to learning Git, with best-practices, industry-accepted standards, and included cheat sheet. Stop Googling Git commands and actually learn it!

Lucky for you, OWASP puts out a list of the top 10 risks to web applications. Review these and then do a thorough analysis of your website to see if any of these apply to you.

Even better, check out NodeGoat, which is a deployable website created by OWASP meant to teach you how to identify these risks in Node applications specifically. There is no better way to learn these concepts than actually doing it yourself.

The tutorial provided will walk you through all of the risks, showing specific examples of how to both exploit and defend against the vulnerabilities. For example, here is a video provided by OWASP showing how to inject JavaScript using a web form:

More Info

Node security is a big topic, so it wouldn't be reasonable to try and cover it all here. If you're interested in getting more details, I'd suggest reading some more resources, like these:

Conclusion

All too often the security of an application is an after-thought to development and design. It's difficult enough just to get your code to work correctly, let alone making it safe to use for your users.

Luckily you're not the only one going through these problems, so that means there are plenty of tools and resources out there created by others to help you secure your apps quickly and easily. Just take the time to search NPM, ask questions on forums, or even hire an expert. It's definitely worth the time and money!

What other ways do you secure your Node applications? Let us know in the comments!

Last Updated: November 24th, 2015
Was this article helpful?

Improve your dev skills!

Get tutorials, guides, and dev jobs in your inbox.

No spam ever. Unsubscribe at any time. Read our Privacy Policy.

© 2013-2024 Stack Abuse. All rights reserved.

AboutDisclosurePrivacyTerms