

Oh my Node or Security in NodeJS
by Roman Sachenko


Oh my Node or Security in NodeJS
by Roman Sachenko
About Me
back-end developer, team lead in DA-14
~ 2.5 years in software development area


Topics: sources of security problems


Topics: what do they lead up to


Topics: painkiller


Topics: best practices


Contents:

- Weak authentication process
- Poor error handling
- Poor request validation
- Insecure dependencies
- Opensource Itself
- Useful Toos
- Best Practice
Weak Authentication process


Sources: Weak Authentication process

- infinite session expiration date
- infinite token expiration date
- weak secret key
Sources: Weak Authentication process

app.use(session({
secret: 'secret.secret.secret',
name: <name>
}))
Session Options
Sources: Weak Authentication process

jwt.sign({
data: 'foobar'
}, 'secret', { expiresIn: '999999999999999h' });
Auth Token Options
Painkiller for: Weak Authentication process

- Access/JWT token (https://github.com/auth0/node-jsonwebtoken)
- PassportJS (http://passportjs.org/)
- Auth Services (stormpath)
Poor error handling


Sources: Poor error handling

try {
let data = doSomething();
res.send({ success: true, data: data });
} catch(err) {
res.send({ success: false: error: err });
}
Sources: Poor error handling

ReferenceError: foo is not defined\n at /home/roman_sachenko/Projects/API/app/controllers/main.js:28:9\n at wrapped (/home/roman_sachenko/Projects/API/node_modules/newrelic/lib/transaction/tracer/index.js:183:28)\n at wrappedPromise.linkTransaction (/home/roman_sachenko/Projects/API/node_modules/newrelic/lib/instrumentation/promise.js:273:65)\n at wrappedPromise.wrapped [as __NR_wrapper] (/home/roman_sachenko/Projects/API/node_modules/newrelic/lib/transaction/tracer/index.js:183:28)\n at __NR_wrappedThenHandler (/home/roman_sachenko/Projects/API/node_modules/newrelic/lib/instrumentation/promise.js:445:26)
Sources: Poor error handling

Cast to ObjectId failed for value \"\" at path \"_id\"","name":"CastError","kind":"ObjectId","value":"","path":"_id"},"details":"CastError: Cast to ObjectId failed for value \"\" at path \"_id\"\n at MongooseError.CastError (/home/roman_sachenko/Projects/API/node_modules/mongoose/lib/error/cast.js:18:16)
Sources: Poor error handling

Sensitive information in headers or error messages like:
X-Powered-By: Express
Painkiller for: Poor error handling

- log sensitive error, not send in response
- use environment-based error handler
let error = 'some weird error message';
log.err(error);
if(process.env.NODE_ENV === ENV_PRODUCTION) {
return res.send({ success: false, error: 'Oops, something went wrong' });
}
return res.send({ success: false, error: error });
Module:
- error handler (https://github.com/expressjs/errorhandler)
Manual Way:
Poor request validation


ONE DOES NOT SIMPLY
VALIDATE REQUESTS
Sources: Poor request validation
example #1:

DELETE /users/?id=<userId>
- delete user by id
Sources: Poor request validation
example #1:

DELETE /users/?id={'$exists': true}
UserModel.remove({ _id: req.query.id });
=> UserModel.remove({ _id: { '$exists': true } });
Sources: Poor request validation
example #2:

User Model
{
id : <object id>,
first_name : <string>,
last_name : <string>,
deleted : <boolean>
}
Sources: Poor request validation
example #2:

User Model
{
id : <object id>,
first_name : <string>,
last_name : <string>,
deleted : <boolean>
}
PUT /users/<userId>
//update writable fields
DELETE /users/<userId>
//set 'deleted' as true
Sources: Poor request validation
example #2:

User Model
{
id : <object id>,
first_name : <string>,
last_name : <string>,
deleted : <boolean>
}
PUT /users/<userId>
//update writable fields
DELETE /users/<userId>
//set 'deleted' as true
What if we send 'deleted: true' in the body of our PUT request?
Sources: Poor request validation
example #3:

db.myCollection.find( { $where: "this.first_name == <value>" } );
Sources: Poor request validation
example #3:

db.myCollection.find( { $where: "this.first_name == 'a; sleep(1000000)'" } );
Painkiller for: Poor request validation

- validate incoming query params, body data etc.
- node validator (https://github.com/chriso/validator.js/)
- express validator (https://github.com/ctavan/express-validator)
- joi (https://github.com/hapijs/joi)
Insecure Dependencies


Sources: Insecure Dependencies

your code
3rd party dependencies
Application
Painkiller for: Insecure Dependencies

- snyk (https://snyk.io/)
Painkiller for: Insecure Dependencies

`snyk wizard`
2 vulnerabilities introduced via apn@2.1.4
- info: https://snyk.io/package/npm/apn/2.1.4
Remediation options (Use arrow keys)
> Re-install apn@2.1.4 (triggers upgrade to ms@2.0.0)
Review issues separately
Set to ignore for 30 days (updates policy)
Skip
Painkiller for: Insecure Dependencies

`nsp check`
Regular Expression Denial of Service
Name: uglify-js
CVSS: 5.3 (Medium)
Installed: 2.2.5
Vulnerable: <2.6.0
Patched: >=2.6.0
Path: api@0.5.0 > jade@1.11.0 > transformers@2.1.0 > uglify-js@2.2.5
More Info: https://nodesecurity.io/advisories/48
Opensource Itself


Sources: Opensource

Conditions:
- everyone is allowed to commit
- internal module dependencies
Result:
- easy to download and install insecure or malicious code
- hijacking the require chain
Sources: Opensource


Useful Tools


Best Practice: Useful Modules

- helmet (https://github.com/helmetjs/helmet)
- csurf (https://github.com/expressjs/csurf)
- node-rate-limiter (https://github.com/jhurliman/node-rate-limiter)
- cors (https://github.com/expressjs/cors)
Best Practice


Best Practice: "dont's"

- do not use 'eval'
- use carefully friends of 'eval' (setInterval, setTimeout)
- don't create buffer with int number in params ( new Buffer(100) )
- don't install suspicious modules
- don't install or use carefully issued modules
Best Practice: "do's"

- OWASP top 10 (http://nodegoat.herokuapp.com/tutorial)
- Limit requests frequency
- Use database ORM (mongoose, sequelize)
- Don't accept or use carefully query params as database query items
- Validate incoming body, query params
- Validate incoming body schema
- Set strong access control system
- Use SSL
- Use Security check tools (nodesecurity)

Questions?
*tried to find funny meme, but couldn't :(

Oh my Node or Security in NodeJS
By Roman Sachenko
Oh my Node or Security in NodeJS
- 2,123