Анализатор обнаружил использование непроверенных данных из внешнего источника для формирования запроса к NoSQL базе данных. Это может стать причиной NoSQL-инъекции в случае, если данные скомпрометированы.
Инъекции выделены в отдельную категорию рисков в OWASP Top 10 Application Security Risks 2021: A3:2021-Injection.
Рассмотрим пример:
public IFindFluent<BsonDocument, BsonDocument> Authentication() { String log = Request.Form["login"]; String pass = Request.Form["password"]; String filter = "{$where: \"function() {" + $"return this.login=='{log}' && this.password=='{pass}'"+ ";}\"}"; return collection.Find(filter); }
Метод 'Authentication' ищет запись пользователя в NoSQL базе данных MongoDB по логину и паролю. Для этого создается строка 'filter', содержащая JavaScript код. С её помощью будут фильтроваться результаты поиска. Аналогом этой операции в SQL будет следующий запрос: SELECT * FROM collection WHERE login = @log AND password = @pass.
Для формирования фильтра используются значения строк 'log' и 'pass', полученные из внешнего источника. Подобное использование непроверенных данных позволяет злоумышленнику внедрить вредоносный код внутрь запроса.
Например, здесь злоумышленник может отправить вместо ожидаемого значения 'pass' строку следующего вида:
"-1' || this.login == 'admin"
Тогда обращение к базе данных может выглядеть так:
{$where: "function() { return this.login == 'doesn't matter' && this.password == '-1' || this.login == 'admin'; }"}
В таком случае запрос вернёт данные аккаунта администратора.
Для защиты от инъекций NoSQL базы предоставляют инструменты параметризированного создания запросов.
Пример создания безопасного запроса:
public IFindFluent<BsonDocument, BsonDocument> Authentication() { String log = Request.Form["login"]; String pass = Request.Form["password"]; var filter = Builders<BsonDocument>.Filter.Eq("login", log) & Builders<BsonDocument>.Filter.Eq("password", pass); return collection.Find(filter); }
Здесь фильтр создается при помощи специального класса 'Builders'. За счёт этого запрос будет параметризованным и внешние данные не смогут повлиять на логику фильтрации.
Анализатор также считает источниками небезопасных данных параметры методов, доступных из других сборок. Более подробно эта тема раскрыта в заметке "Почему важно проверять значения параметров общедоступных методов".
Рассмотрим пример:
public class MongoDBRep { public void DeleteItemsByCounter(string count) { DeleteMany(count); } private void DeleteMany(string count) { var filter = "{$where:\"function(){return this.count == "+count+";}\"}"; collection.DeleteMany(filter); } }
Здесь потенциально заражённые данные из параметра 'count' передаются в метод 'DeleteMany', внутри которого они без проверки используются для удаления записей из базы данных.
Злоумышленник может сформировать запрос следующего вида:
{$where: "function() { return this.count == -999 || 1 == 1; }"}
Исполнение этого запроса приведёт к удалению всех документов базы данных, независимо от значения поля 'count'.
В этом случае рекомендуется защититься тем же способом, что был приведён ранее.
Данная диагностика классифицируется как:
|