node-secure
Description
node-secure is a tiny module for Node.JS which protects some globals (undefined
, NaN
,
Infinity
, eval
, isNaN
) from being overridden and adds functionality to protect your
modules from hacking and code injection
Author: David de Rosier
License: public domain
Server-side must be secured!
Hope we all agree that server-side programming requires special attention. An error on this level can crash not only a single client (browser), but entire server. Moreover we need to take an extra care of the security. JavaScript is a super dynamic language that allows us to rapidly implement server functionality, but it also leaves open doors for hackers (through code injections from client). We can also often struggle from some strange/stupid/typo mistakes which are difficult to find.
Example? Lets start from something simple. JavaScript does not protect
global variables like undefined
. Overriding such value can be dangerous -
in example the http module of Node.JS uses insecure comparisons with undefined
value,
so following example:
undefined = 666;var http = ;http;
will kill the entire server after first HTTP request with "Cannot call method 'slice' of null" error. Not easy to find a real source of problem with such message, isn't it?
V8 means ECMAScript 5
Fortunately ECMAScript 5 brings some features, which can limit
an access to object properties. They can be even used on standard global properties,
like undefined
. And we don't have to bother about backward-compatibility on Node.JS.
The basic code snippet presented below can protect the standard global variables for
entire application:
ObjectdefineProperty && { // take global object var global = {return this;}; // when "strict mode' is on we can leave - globals are protected by default if!global return; // redefine proper values in case they got overridden undefined = void 0; NaN = 0/0; Infinity = 1/0; // make globals read only and non-configurable "undefined" "NaN" "Infinity";};
The code above is quite universal and will work on all environments (browsers, SSJS, Rhino, etc) which provide property descriptor functionality. I would recommend to copy-paste such code to the main modules of all your applications (if you are not planning to use node-secure module - which gives much more control).
spoon="strict mode"; there is no spoon!
Some developers might say that we shouldn't bother about global variables in Node.JS because there is a strict mode. Theoretically true, but... currently V8 supports all features of ECMAScript 5 excluding... the strict mode! Doors for insecurity remains open!
What is node-secure?
node-secure is a tiny module for Node.JS which gives some protection mechanisms to your code. In particular:
- It protects the standard global variables (
undefined
,NaN
,Infinity
,isNaN
) from being overridden. - It gives an extra control on most insecure element of the language -
eval
function. With node-secure you will be able to track each execution ofeval
with typical for Node.JS behavior - events. Every time someone executeseval
, the module will emit an event with a reference to executor function. Why to bother about events? Wouldn't be better to just override the evileval
with empty function? Well.. some of the modules you use may operate oneval
. Better not to break the existing functionality. - The module provides two utility functions -
secureMethods
andsecurePrivates
. First one protects all methods of given object from being overridden. Why? In most of the cases you wouldn't like to let your own methods being overridden by external code, so is better to keep them read-only - especially in your custom modules.
Second method makes all private-like elements of an object (named with underscore prefix) non-enumerable.
If you don't want to hide elements fully (using closures) and just use naming convention for it,
you can add an extra protection by hiding the private elements from being enumerable.
4. There is a risky situation when someone override and protect eval
or standard globals before
you even load the node-secure module. In such case the module won't be able to secure
the application. However you can control this situation by calling isSecure
method or by checking
status
object. The status can tell you exactly which element couldn't be secured. Moreover
every time when protection of global elements fails, the module will produce an insecure event.
Examples
Just load the module to protect standard globals variables and the eval
function
;undefined = 666; // nothing happen (in non strict mode there is no error, however the value won't be overridden)
To control execution of eval
, add the listener:
var secure = ;secure;
To check whether the module managed to protect all elements you can define another listener:
var secure = ;secure;
eventually you can directly check the statuses:
if !secure console; ifsecurestatusUNDEFINED_VALUE && securestatusUNDEFINED_PROTECTION console;
Finally you can protect your own objects. Consider it especially for your custom modules.
var secure = ;exports{...};// at the end of the module codesecure;
Code above just sets the writable flag to false for all methods in given object. So you can always redefine the access with property descriptor, unless you make the methods non-configurable:
secure;
Remember to hide the private-like elements of your object for for..in
or Object.keys
operations:
var secure = ;obj = __salary: 1024 {} { return this__salary }; secure;
In practice securePrivates
and secureMethods
can fail for already non-configurable members.
Fortunately node-secure allows you to track such situation. Lets take example code:
var secure = ; var obj = {} __prv1: 0; Object;Object;
and consider some cases:
secure;
everything is fine here. According to ECMAScript 5 specification you can change the value of writable property from true to false (but not opposite) even if the property is marked as non-configurable. However:
secure;
will not work, because there is not possible to change enumerable
and configurable
attributes
of non-configurable property. You can track such situation with node-secure:
secure;
Listener function takes as an attribute an array of objects. Each object contains
property and error attributes. secureMethods
and securePrivates
never fail when
they can't protect some of the object elements. They continue and produce a report
which you can check with callback function.
New to property descriptors?
If your are new to the concept of ECMAScript 5 property descriptors and the things here seem to be bit strange for you - just see the great ECMAScript 5 Object methods cheatsheet written by Kasia Drzyzga.