Security in Node.js

The node platform is built on the Javascript V8 engine from Google, and it’s purpose is to build fast and scalable websites/network applications. It uses a non-blocking, event-driven IO.

It optimizes JavasScript for work outside of the browser by providing it with binders, allowing various C libraries, and possibilities to manipulate binary data and access system functions, which doesn’t exist in Javascript. It also supplies request handling interpreters, which allows Node.js to be used as a server – This is the most common use.

The Node Package Manager (NPM) is another feature that needs looking at, as there’s nothing to say that while a package is secure at version 1.2.5, it will still be secure at version 1.3.

Security issues

Runtime server poisoning

In most web servers, every request will create a new child process, and then when the page has been sent to the client the process will terminate. However, since our Node server is running on a single thread, then if the thread is corrupted then the behaviour of the web server will change until it is restarted, as the thread doesn’t terminate, it keeps serving until the server is stopped.

There are several things that make these sorts of attacks scary.

  1. It is stealthy. There are no log records generated except maybe of the original request, and if executed correctly then there will be no noticable changes to the server.
  2. It goes past HTTPS, since the attack is targeted at the server itself then no matter how secure the transaction to the server is, the information is still accessible.
  3. It’s hard to protect against. In PHP, the attacker would have to rewrite the server files to achieve this behaviour and usually the server process s not allowed to modify those files whereas in Nide there is no generic security restrictions that would apply.

EXAMPLE

runtimeserverpoisoning

Run-time server poisoning source code

 

 

Upon sending malicious data to this function, we can execute any statements that we want. This is one of the more benign ways of altering the server behaviour since adding another path to the list of paths is all that is done. You can see what happens when we send the data via the image below.

runtimeserverpoisoningdata

Run-time server poisoning source code

 

 

Now since the web server has been changed, any GET request to ‘/url’ will instantly send text back saying, ‘corrupted’ and terminate the connection to the server. This makes the web page completely useless until the server has been restarted.

How could it be worse?

Well all we did is save the ‘live’ copy of the function, we could edit the function in the source file and then if we were running it with Nodemon, the server would restart and the original would have to be restored via Github or whatever you’re using.

How can it be prevented?

You can validate your params.req.* on the server side before using them.

Eval() is a bad command and should not be used, since it opens up so many security flaws.

Denial of service

One of the simplest forms of network attacks. Instead of trying to delete, steal or modify data, the aim of this attack is to prevent access to the service/resource/website. This is usually achieved by flooding the server with requests which it is then unable to handle and will become unresponsive and may crash. This is particularly effective in PHP as every request creates a new process. Node’s architecture makes it require less system resources per request which makes it rather resilient.

These are some benchmarking tests against a Node.js server giving a ‘Hello World’ page.

ddosgraph

Run-time server poisoning source code

 

As you can see, Node was able to easily cope with a large number of requests on just 1 thread. There’s never a tonne you can do to stop a DDoS attack.

How can it be prevented?

Anything CPU heavy should be assigned to a worker thread. I will look into Cluster Master on Github and I’ll create an article about it before the end of the week. This will prevent the main thread from locking whilst more requests pile up.

Hash collisions (method to Denial of service)

A collision is a situation that occurs when two distinct pieces of data have the same hash valuechecksumfingerprint, or cryptographic digest. (http://en.wikipedia.org/wiki/Hash_collision)

A man by the name of Alexander ‘alech’ Klink and Julian Zeri presented a general attack against web services using hash table collision. When creating an array in JavaScript for storing, e.g., HTTP request parameters, a hash table is usually created to store the key-value pairs. Hash tables in general are very efficient for inserting (see Figure 27) and looking up values. The best case time complexity of insert and lookup operations in a hash table is constant. However, if there are a lot of hash collisions in the table then operations with that hash table degrade into linear search.

What’s the problem?

An attacker can send malicious request to your server with HTTP requests containing thousands of parameter names with colliding hash values. When a server receives this request, it takes them a long time to find the variable you were actually looking for, as most web servers will automatically populate the POST and GET arrays. A request with a 3MB payload on a 1GHz CPU would be busy for around a whole minute, This is a big issue, since those requests can be sent often.

Here is a table showing the server types and what it takes to effectively stop a server.

Server Name Result
PHP 70-100kbit/s to keep one i7 core constantly busy
Gigabit connection can keep about 10,000 i7 cores busy
ASP.NET 30kbit/s to keep one Core2 core constantly busy
Gigabit connection can keep about 30,000 Core2 cores busy
Java Tomcat6 6 kbit/s can keep one i7 core constantly busy
Gigabit connection can keep about 100,000 i7 cores busy
Python (32bit only) 20 kbit/s can keep one Core Duo core constantly busy
Gigabit connection can keep about 50,000 Core Duo cores busy.
Ruby 850 bits/s can keep one i7 core busy
Gigabit connection can keep about 1,000,000 i7 cores busy

(Data taken from - http://blog.fortify.com/blog/2012/01/04/_

How can I prevent it?

I don’t actually currently know, but if anybody know’s then please comment.

Improving Application Security

As you will know, Node is still quite young and has no default configuration for security. This means without some planning, configuring and extensive testing then you just can’t know for sure that your site is secure.  You need to run tests on every module that you install, and READ THE DOCUMENTATION.

Know what a module is used for

Just because it does what you require, doesn’t mean it’s a good choice. A module in it’s baby stages could provide huge entry points for attackers. The server was designed to be a scaling and non-blocking server, not a fortress.

Calculations

The server wasn’t designed to be used for heavy/precise calculations. Anything that requires accurate math are best implemented in languages other than Javascript, due to the floating point number problem. Alternatively use a library designed to work around these floating point limitations.

Implementing heavy calculations or long intense processing in a Node.js server should not be done in the main thread. Due to Node.js’s single event loop this will clog the server and adversely affect the availability of the service. This is why long calculations or processes in the main thread must be avoided.

Conclusion

Don’t get me wrong, Node.js can be secured rather easily, although you have to actively work on it whilst developing. There is no catch-all for node security. You want proof that it can be secured? Look at all of them here or here! They include Microsoft, Yahoo and Ebay.

6 thoughts on “Security in Node.js

  1. Is it possible to counter hash collision by finding out the params in request (req.params.length possible??) and if beyond a number reject the request?

    • You can counter it when there are a very large amount of parameters in the request, by using req.params.length.

      The chances of a collision are very very small, 1 in 2^160, so it shouldn’t really be a problem.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>