# V5627. OWASP. Possible NoSQL injection. Potentially tainted data is used to create query.

Анализатор обнаружил использование непроверенных данных из внешнего источника для формирования запроса к 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'.

В этом случае рекомендуется защититься тем же способом, что был приведён ранее.

Выявляемые диагностикой ошибки классифицируются согласно ГОСТ Р 71207–2024 как критические и относятся к типу: Ошибки непроверенного использования чувствительных данных (ввода пользователя, файлов, сети и пр.).

Данная диагностика классифицируется как:

CWE-943 OWASP-5.3.4