﻿# 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](https://owasp.org/Top10/A03_2021-Injection/)\.

Рассмотрим пример:

```cpp
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' строку следующего вида:

```cpp
"-1' || this.login == 'admin"
```

Тогда обращение к базе данных может выглядеть так:

```cpp
{$where: "function() 
{ 
  return    this.login == 'doesn't matter'
         && this.password == '-1'
         || this.login == 'admin';
}"}
```

В таком случае запрос вернёт данные аккаунта администратора\.

Для защиты от инъекций NoSQL базы предоставляют инструменты параметризированного создания запросов\.

Пример создания безопасного запроса:

```cpp
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'\. За счёт этого запрос будет параметризованным и внешние данные не смогут повлиять на логику фильтрации\.

Анализатор также считает источниками небезопасных данных параметры методов, доступных из других сборок\. Более подробно эта тема раскрыта в заметке "[Почему важно проверять значения параметров общедоступных методов](https://pvs-studio.ru/ru/blog/posts/csharp/0835/)"\.

Рассмотрим пример:

```cpp
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', внутри которого они без проверки используются для удаления записей из базы данных\.

Злоумышленник может сформировать запрос следующего вида:

```cpp
{$where: "function() 
{ 
  return    this.count == -999
         || 1 == 1;
}"}
```

Исполнение этого запроса приведёт к удалению всех документов базы данных, независимо от значения поля 'count'\.

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