Loading
Roman Sachenko
This is a live streamed presentation. You will automatically follow the presenter and see the slide they're currently on.
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 :(