﻿# Почему важно проверять значения параметров общедоступных методов

В данной заметке мы обсудим, почему PVS\-Studio считает параметры общедоступных методов источниками небезопасных данных и может выдавать предупреждения, если такие параметры используются без проверок\. 

![0835_ParamsAsTaintSource_ru/image1.png](https://import.viva64.com/docx/blog/0835_ParamsAsTaintSource_ru/image1.png)

Дело в том, что излишнее доверие к внешним данным может быть причиной многих уязвимостей \- SQLI, XSS, path traversal и т\.п\. Наиболее очевидные примеры источников внешних данных \- значения параметров запросов или текст, который вводит пользователь \(например, в некоторое поле\)\. 

Однако излишнее доверие к параметрам общедоступных методов также может быть опасно\. Под общедоступными имеются в виду методы, которые могут быть вызваны из других сборок\. Например, это _public_ методы _public_ классов\. Скорее всего, подобные методы представляют собой API для взаимодействия с библиотекой\.

В чём же опасность?

Разработчики, использующие API библиотеки, могут рассчитывать, что валидация данных будет происходить внутри вызываемого метода\. Соответственно, данные из внешнего источника не будут проверены перед передачей в метод\.

Разработчики же самой библиотеки могут рассчитывать на то, что на вход приходят уже проверенные данные\. Следовательно, необходимости в их проверке нет\.

Из\-за этого может возникнуть ситуация, когда ни пользователь библиотеки, ни её разработчик не провели валидацию входных данных\. Это может стать причиной возникновения уязвимостей в случае передачи злоумышленником скомпрометированных данных\.

**Примечание**\. Ниже разбираются примеры с диагностикой [V5608](https://pvs-studio.ru/ru/docs/warnings/v5608/) \(поиск возможных SQL инъекций\)\. Тем не менее, эта информация актуальная и для других диагностик из группы OWASP, считающих параметры публично доступных методов источниками заражённых данных\.

Посмотрим, как это может выглядеть в коде:

```cpp
public class DBHelper
{
  public void ProcessUserInfo(String userName)
  {
    ....
    var command = "SELECT * FROM Users WHERE userName = '" + userName + "'";
    ExecuteCommand(command);
    ....
  }

  private void ExecuteCommand(String rawCommand)
  {
    using (SqlConnection connection = new SqlConnection(_connectionString))
    {
      ....
      using (var sqlCommand = new SqlCommand(rawCommand, connection))
      {
        using (var reader = sqlCommand.ExecuteReader())
          ....
      }
    }
  }
}
```

Класс _DBHelper_ предоставляет метод _ProcessUserInfo_ для внешнего использования, так как он доступен из других сборок\. Обратите внимание, что параметр этого метода \- _userName_ \- никак не проверяется перед использованием\. Значение, полученное извне, напрямую используется для создания команды \(переменная _command_\)\. Далее полученная команда передаётся в метод _ExecuteCommand_, где без проверки используется для создания объекта типа _SqlCommand_\.

В данном случае анализатор сможет выдать предупреждение о возможной SQLI, если принять _userName_ за источник опасных данных\.

Теперь рассмотрим возможный вариант использования метода _ProcessUserInfo_ внешним приложением:

```cpp
static void TestHelper(DBHelper helper)
{
  var userName = Request.Form["userName"];
  helper.ProcessUserInfo(userName);
}
```

Разработчик, написавший данный фрагмент кода, может не иметь доступа к коду класса _DBHelper_ и рассчитывать на то, что валидация входных данных будет происходить внутри метода _ProcessUserInfo_\. Возникает ситуация, при которой ни текущий код, ни код метода _ProcessUserInfo_ не провёл валидацию данных, а значит, приложение будет уязвимо перед SQL инъекциями\.

При анализе кода метода _TestHelper_ анализатор не сможет предупредить о возможной SQL инъекции, т\.к\. не имеет доступа к исходному коду метода _ProcessUserInfo_\. Однако, как мы видим, ситуация опасная, и сообщить о ней хочется\.

Поэтому анализатор выдаст предупреждение там, где он сможет это сделать, \- при анализе исходного кода метода _ProcessUserInfo_\. В данном случае будет выдано предупреждение V5608 на низком уровне достоверности\.

Если вы не хотите видеть подобных предупреждений, то можете отключить их с помощью комментария вида //\-V::5608:3 в \.pvsconfig файле\. Тогда предупреждения V5608 \(SQLI\) низкого уровня достоверности не попадут в отчёт\. Более подробно про \.pvsconfig\-файлы можно почитать в [документации](https://pvs-studio.ru/ru/docs/manual/0017/#ID2548D94CFD) \(раздел "Подавление ложных предупреждений с помощью файлов конфигурации диагностик \(\.pvsconfig\)"\)\. 

Если же вы, напротив, считаете такие предупреждения крайне важными, то можете повысить их уровень достоверности до высокого, используя комментарий вида //V\_LEVEL\_1::5608\. Подробности приводятся в главе "Как задать свой уровень для конкретной диагностики" в [документации](https://pvs-studio.ru/ru/docs/manual/0040/#IDC06049AE46)\.