Selector Injection Attack в MongoDB
Сегодня узнал, что в мире MongoDB существует такая штука, как «Selector Injection Attack».
Если упростить, то представим, что есть приложение на Express/Koa с Mongoose и в одном из эндпоинтов надо проверить, валидны ли учётные данные пользователя. Допустим мы делаем это так:
await User.findOne({
email: req.body.email,
password: req.body.password,
});
(Да, пароль должен быть захеширован, но это пример.)
Код выглядит невинно, но это не так. Если клиент отправит такое тело запроса:
{
email: "[email protected]",
password: { "$ne": null }
}
то будут проблемы.
MongoDB интерпретирует это как запрос пользователя с указанным адресом почты и любым ненулевым паролем. Если это логика аутентификации — пользователя успешно залогинит.
То есть, даже если мы не в мире SQL, всё равно нужно санитизировать пользовательский ввод. И есть несколько способов.
Можно делать это вручную — удалять все $-подобные операторы и точки из ключей объектов. См. express-mongo-sanitize.
В Mongoose же можно включить опцию sanitizeFilter, которая оборачивает ключи фильтра в $eq, делая такие инъекции невозможными. Подробнее в блоге разработчика Mongoose.