NoSQL INJECTIONS IN NODE.JS
The case of MongoDB
Vladimir de Turckheim
5 DEC 2016
</> IN PRACTICEapp.post(‘/documents/find’, (req, res) => {
const query = { };
if (req.body.desiredType) query.type = req.body.desiredType;
if (!query.type) return res.json([ ]);
Document.find(query).exec()
.then((r) => res.json(r));
1
2
3
4
5
6
</> IN PRACTICEapp.post(‘/documents/find’, (req, res) => {
const query = { };
if (req.body.desiredType) query.type = req.body.desiredType;
if (!query.type) return res.json([ ]);
Document.find(query).exec()
.then((r) => res.json(r));
1
2
3
4
5
6
</> IN PRACTICEapp.post(‘/documents/find’, (req, res) => {
const query = { };
if (req.body.desiredType) query.type = req.body.desiredType;
if (!query.type) return res.json([ ]);
Document.find(query).exec()
.then((r) => res.json(r));
1
2
3
4
5
6
req.body
query
outcome
{ desiredType: ‘blog’ }
{ type: ‘blog’ }
All documents which field ‘type’ equals ‘blog’
</> IN PRACTICEapp.post(‘/documents/find’, (req, res) => {
const query = { };
if (req.body.desiredType) query.type = req.body.desiredType;
if (!query.type) return res.json([ ]);
Document.find(query).exec()
.then((r) => res.json(r));
1
2
3
4
5
6
req.body
query
outcome
{ desiredType: }
{ type: }
</> IN PRACTICEapp.post(‘/documents/find’, (req, res) => {
const query = { };
if (req.body.desiredType) query.type = req.body.desiredType;
if (!query.type) return res.json([ ]);
Document.find(query).exec()
.then((r) => res.json(r));
1
2
3
4
5
6
req.body
query
outcome
{ desiredType: { $ne: 0 } }
{ type: }
</> IN PRACTICEapp.post(‘/documents/find’, (req, res) => {
const query = { };
if (req.body.desiredType) query.type = req.body.desiredType;
if (!query.type) return res.json([ ]);
Document.find(query).exec()
.then((r) => res.json(r));
1
2
3
4
5
6
req.body
query
outcome
{ desiredType: { $ne: 0 } }
{ type: { $ne: 0 } }
</> IN PRACTICEapp.post(‘/documents/find’, (req, res) => {
const query = { };
if (req.body.desiredType) query.type = req.body.desiredType;
if (!query.type) return res.json([ ]);
Document.find(query).exec()
.then((r) => res.json(r));
1
2
3
4
5
6
req.body
query
outcome
{ desiredType: { $ne: 0 } }
{ type: { $ne: 0 } }
All documents which field ‘type’ does not equal 0
WAIT, THERE IS WORST
{ $where:’this.amount > 0’ }
In MongoDB < 2.4, it is possible to perform all operations
on a database from an injection (including dropDatabase).
VALIDATE WHAT GETS INSIDE
YOUR APPLICATION
hapi
on a route, use config.validate
express
add a data validation middleware
It can be a custom one
It can use a third party library
See tutorial online
</> EXPRESS: CUSTOM DATA VALIDATION MIDDLEWARE
app.post('/documents/find', validate, (req, res) => ...);
const validate = function (req, res, next) {
const body = req.body;
if (body.desiredType && !(typeof body.desiredType==='string')){
return next(new Error('title must be a string'));
}
next();
};
1
2
3
4
5
6
7
</> EXPRESS: USING JOI AND CELEBRATE TO VALIDATE DATA
app.post('/documents/find', validate, (req, res) => ...);
const validate = Celebrate({
body: Joi.object.keys({
desiredType: Joi.string().optional()
})
});
1
2
3
4
5
THANKS FOR YOUR ATTENTION !
Contact me at
vladimir@sqreen.io

NoSQL Injections in Node.js - The case of MongoDB

  • 1.
    NoSQL INJECTIONS INNODE.JS The case of MongoDB Vladimir de Turckheim 5 DEC 2016
  • 2.
    </> IN PRACTICEapp.post(‘/documents/find’,(req, res) => { const query = { }; if (req.body.desiredType) query.type = req.body.desiredType; if (!query.type) return res.json([ ]); Document.find(query).exec() .then((r) => res.json(r)); 1 2 3 4 5 6
  • 3.
    </> IN PRACTICEapp.post(‘/documents/find’,(req, res) => { const query = { }; if (req.body.desiredType) query.type = req.body.desiredType; if (!query.type) return res.json([ ]); Document.find(query).exec() .then((r) => res.json(r)); 1 2 3 4 5 6
  • 4.
    </> IN PRACTICEapp.post(‘/documents/find’,(req, res) => { const query = { }; if (req.body.desiredType) query.type = req.body.desiredType; if (!query.type) return res.json([ ]); Document.find(query).exec() .then((r) => res.json(r)); 1 2 3 4 5 6 req.body query outcome { desiredType: ‘blog’ } { type: ‘blog’ } All documents which field ‘type’ equals ‘blog’
  • 5.
    </> IN PRACTICEapp.post(‘/documents/find’,(req, res) => { const query = { }; if (req.body.desiredType) query.type = req.body.desiredType; if (!query.type) return res.json([ ]); Document.find(query).exec() .then((r) => res.json(r)); 1 2 3 4 5 6 req.body query outcome { desiredType: } { type: }
  • 6.
    </> IN PRACTICEapp.post(‘/documents/find’,(req, res) => { const query = { }; if (req.body.desiredType) query.type = req.body.desiredType; if (!query.type) return res.json([ ]); Document.find(query).exec() .then((r) => res.json(r)); 1 2 3 4 5 6 req.body query outcome { desiredType: { $ne: 0 } } { type: }
  • 7.
    </> IN PRACTICEapp.post(‘/documents/find’,(req, res) => { const query = { }; if (req.body.desiredType) query.type = req.body.desiredType; if (!query.type) return res.json([ ]); Document.find(query).exec() .then((r) => res.json(r)); 1 2 3 4 5 6 req.body query outcome { desiredType: { $ne: 0 } } { type: { $ne: 0 } }
  • 8.
    </> IN PRACTICEapp.post(‘/documents/find’,(req, res) => { const query = { }; if (req.body.desiredType) query.type = req.body.desiredType; if (!query.type) return res.json([ ]); Document.find(query).exec() .then((r) => res.json(r)); 1 2 3 4 5 6 req.body query outcome { desiredType: { $ne: 0 } } { type: { $ne: 0 } } All documents which field ‘type’ does not equal 0
  • 9.
    WAIT, THERE ISWORST { $where:’this.amount > 0’ }
  • 10.
    In MongoDB <2.4, it is possible to perform all operations on a database from an injection (including dropDatabase).
  • 11.
    VALIDATE WHAT GETSINSIDE YOUR APPLICATION hapi on a route, use config.validate express add a data validation middleware It can be a custom one It can use a third party library See tutorial online
  • 12.
    </> EXPRESS: CUSTOMDATA VALIDATION MIDDLEWARE app.post('/documents/find', validate, (req, res) => ...); const validate = function (req, res, next) { const body = req.body; if (body.desiredType && !(typeof body.desiredType==='string')){ return next(new Error('title must be a string')); } next(); }; 1 2 3 4 5 6 7
  • 13.
    </> EXPRESS: USINGJOI AND CELEBRATE TO VALIDATE DATA app.post('/documents/find', validate, (req, res) => ...); const validate = Celebrate({ body: Joi.object.keys({ desiredType: Joi.string().optional() }) }); 1 2 3 4 5
  • 14.
    THANKS FOR YOURATTENTION ! Contact me at vladimir@sqreen.io