Loading deck

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

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

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 :(