Reputation: 4388
I'm using the Mongoose ODM wrapper for NodeJS and I'm concerned about injection attacks. Let's assume I have the following schema:
const UserSchema = new mongoose.Schema({ userName: String, password: String });
If I were to perform a login request that looks like the following:
router.post('/login', (request, response) => {
const userName = request.body.userName;
const password = request.body.password;
User.findOne({ userName: userName }, function (error, user) {
// ... check password, other logic
});
});
I would be open to an injection attack with the following JSON payload which will always find a user:
{
"email": { "$gte": "" },
"password": { "$gte": "" }
}
I'm not concerned about the password as it is hashed if a user is found which prevents any actual log in but I want to make sure my input is sanitized so that an attacker wouldn't even make it to that point.
I'm aware of the mongo-sanitize NPM package referenced in a similar StackOverflow post which appears to remove all JSON keys that begin with '$'. I plan on using this anyway but I will never allow the user to submit raw, unparsed JSON. Is it good practice in that case to just call toString() on the userName assuming I do the correct null
checks?
const userName = request.body.userName.toString();
That would eliminate the query from being executed but it doesn't feel very secure. I assume the following is a better approach as it tries to convert userName
to a String
:
User.findOne({ userName: { "$eq": userName } }, function (error, user) {
// ... other logic
});
I can't find anything concerning this in the in the Model.findOne() documentation which leads me to believe I'm overlooking something.
Any insight would be appreciated.
Other References:
Upvotes: 10
Views: 10745
Reputation: 3185
Additionally, you can use npm package "mongo-sanitize" as given as per their documentation as below:
var sanitize = require('mongo-sanitize');
// The sanitize function will strip out any keys that start with '$' in the input,
// so you can pass it to MongoDB without worrying about malicious users overwriting
// query selectors.
var clean = sanitize(req.params.username);
Users.findOne({ name: clean }, function(err, doc) {
// ...
});
If sanitize() is passed an object, it will mutate the original object.
Upvotes: 1
Reputation: 311865
While you could use $eq
to ensure an equality comparison is used in the query, your express route handler is a better place to perform request format validation.
A valid POST /login
should have userName
and password
string fields in the body of the request. If not, it should be rejected before it even gets to Mongoose.
Upvotes: 9