flawopen.com/Справочник/NoSQL-инъекция MongoDB: когда входные данные меняют запрос
NoSQL-инъекция MongoDB: когда входные данные меняют запрос
MongoDB не выполняет SQL, поэтому склейка SQL-строк здесь ни при чём. NoSQL-инъекция возможна, если приложение принимает недоверенный вложенный объект вместо скалярного значения и передаёт его в фильтр MongoDB. Это ошибка проверки входных данных приложения, а не CVE сервера MongoDB.
Простыми словами: значение становится правилом
Представьте форму, где просят имя, но сотрудник принимает в поле целый набор инструкций. База выполняет инструкции вместо сравнения одного имени. Проверяйте ожидаемый тип значения и создавайте правило поиска самостоятельно.
Граница доверия: от JSON-запроса до фильтра MongoDB
- Фильтр запроса
- Документ BSON, который MongoDB трактует как сравнения полей и, если они явно заданы, как операторы запроса.
- Внедрение оператора
- Приложение передаёт контролируемую пользователем структуру туда, где ожидалось одно литеральное значение.
- Проверка скаляра
- Проверка типа, длины и допустимого формата до того, как входные данные повлияют на операцию с базой.
- Проекция
- Выбранный сервером список полей, ограничивающий случайное раскрытие данных.
Как возникает ошибка
Конечная точка ожидает скаляр
Контракт API определяет username как строку, но JSON-парсер также может вернуть массив, объект, boolean или null.
Приложение пропускает проверку типа
Обработчик напрямую вставляет разобранное значение в созданный сервером фильтр; объект остаётся структурой запроса, а не простой строкой.
MongoDB интерпретирует переданную структуру
Если вложенный документ содержит операторы запроса, условие может отличаться от задуманного точного сравнения. Затронутые записи зависят от запроса и проверок авторизации приложения.
Ответ определяет масштаб раскрытия
Возвращаемые поля и число записей зависят от проекции, конечной точки и привилегий учётной записи БД. Само по себе это не доказывает обход аутентификации или доступ ко всей базе.
Официальные рекомендации MongoDB для драйверов описывают эту границу, когда конечная точка преобразует непроверенный JSON в BSON и использует его как фильтр. Здесь показана ошибка уровня приложения. Руководство не утверждает, что уязвимы все установки MongoDB, не указывает CVE сервера и не содержит инструкции по обходу аутентификации.
Уязвимый и защищённый шаблоны Node.js
app.post("/users/lookup", async (req, res, next) => {
try {
// The route expects a string, but req.body.username is untrusted JSON.
const user = await users.findOne({ username: req.body.username });
res.json(user ? { username: user.username } : null);
} catch (error) {
next(error);
}
});
const loginSchema = z.object({
username: z.string().trim().min(1).max(128),
password: z.string().min(1).max(1024)
}).strict();
app.post("/login", async (req, res, next) => {
try {
const parsed = loginSchema.safeParse(req.body);
if (!parsed.success) return res.sendStatus(400);
const { username, password } = parsed.data;
// The application owns the filter key; input supplies only a string value.
const user = await users.findOne(
{ username },
{ projection: { _id: 1, username: 1, passwordHash: 1 } }
);
const passwordMatches = user &&
await argon2.verify(user.passwordHash, password);
if (!passwordMatches) return res.sendStatus(401);
return res.sendStatus(204); // Session creation is application-specific.
} catch (error) {
next(error);
}
});
Защищённый путь отклоняет поля нестрокового типа до обращения к базе данных, не принимает фильтр от клиента, задаёт фиксированный ключ фильтра в коде приложения, возвращает только выбранные поля и проверяет хеш пароля после поиска пользователя. В примере z — это Zod, users — коллекция MongoDB, а argon2 — настроенная библиотека хеширования паролей; создание сессии намеренно оставлено за рамками примера.
Проверки исправления
- ✓Отправьте обычную строку и убедитесь, что обработчик запрашивает только точное поле, заданное приложением.
- ✓Отправьте объект, массив, число, boolean, null, отсутствующее поле, слишком длинную строку и неизвестное свойство; схема должна отклонить неверные формы до вызова MongoDB.
- ✓Убедитесь, что вызов БД получает фильтр, созданный сервером, а не фильтр клиента или необработанный фрагмент JSON.
- ✓Проверьте, что проекция исключает хеши паролей и посторонние поля, а роль БД имеет только необходимые разрешения.
- ✓Хешируйте пароли с Argon2id или bcrypt и проверяйте хеши в приложении; не используйте присланный пароль как фильтр MongoDB.
Первичные источники
- MongoDB — рекомендации для клиентских библиотек: проверка входных данных до преобразования JSON в BSON
- OWASP — памятка по безопасности NoSQL
- MongoDB — создание фильтра запроса (драйвер C#): проверка — ответственность приложения