﻿# Taint\-анализ \(анализ помеченных данных, taint checking\)

Taint\-анализ \(или анализ помеченных данных, taint checking\) — это технология, позволяющая отслеживать распространение непроверенных внешних данных по программе во время её работы\. Попадание таких данных в некоторые ключевые точки может приводить к возникновению различных уязвимостей, среди которых SQL injection, cross\-site scripting \(XSS\), path traversal и другие\. Эти уязвимости могут быть использованы злоумышленником для нарушения корректной работы системы, получения конфиденциальных данных или проведения прочих несанкционированных операций\.

## Источники заражения

Первичным понятием в данной теме являются заражённые данные\. Под этим термином подразумеваются некоторые значения, которые могут позволить злоумышленнику выполнить несанкционированные и, как правило, вредоносные операции при взаимодействии с системой\. В зависимости от способа использования внешних данных приложение может быть уязвимо к тем или иным атакам\.  Например, если приложение использует непроверенные внешние данные при формировании запросов к БД, то оно может быть уязвимо к SQL injection\.

Таким образом, внешние данные являются потенциально заражёнными\. Точки, в которых приложение получает к ним доступ, называют источниками заражения \(taint source\)\. Например, источником заражения может быть операция получения значения параметра HTTP\-запроса:

```cpp
void ProcessRequest(HttpRequest request)
{
  ....
  string name = request.Form["name"]; // taint source
  // now "name" contains potentially tainted data
  ....
}
```

## Передача заражения

Важным аспектом при проведении taint\-анализа является определение "трасс распространения" заражённых данных по приложению\. В приведённом примере заражённые данные из источника передаются в переменную _name_\. Впоследствии они могут также переходить в другие переменные или выступать в качестве аргументов функций:

```cpp
void ProcessRequest(HttpRequest request)
{
  string name = request.Form["name"]; // taint source
  // now "name" contains potentially tainted data

  string sql = $"SELECT * FROM Users WHERE name='{name}'";
  ExecuteReaderCommand(sql); // tainted data passed as an argument
  ....
}

void ExecuteReaderCommand(string sql)
{
  // sql contains potentially tainted data here 
  ....
}
```

Стоит отметить, что заражение может передаваться далеко не только при присваивании и передаче аргументов\. В примере выше переменная _name_, хранящая потенциально заражённые данные, используется для формирования строки, которая будет записана в переменную _sql_\. В результате значение _sql _также будет потенциально заражённым\.

## Приёмники заражения

С точки зрения taint\-анализа, приложение уязвимо в случае, если заражённые данные могут попасть в некоторые ключевые точки приложения\. Их называют приёмниками заражения \(taint sink\)\. Каждой [потенциальной уязвимости](https://pvs-studio.ru/ru/blog/terms/6441/) соответствуют свои приёмники\. Для SQL injection, к примеру, приёмником может являться точка передачи строки запроса в объект SQL команды:

```cpp
void ProcessRequest(HttpRequest request)
{
  string name = request.Form["name"]; // <= taint source
  // now "name" contains potentially tainted data

  string sql = $"SELECT * FROM Users WHERE name='{name}'";
  ExecuteReaderCommand(sql); // tainted data passed as an argument
  ....
}

void ExecuteReaderCommand(string sql)
{
  using (var command = new SqlCommand(sql, _connection)) // <= sink
  {
    using (var reader = command.ExecuteReader()) { /*....*/ }
  }
  ....
}
```

Здесь внешние данные из источника \(_request\.Form\["name"\]_\) непосредственно используются при формировании sql\-запроса, который далее передаётся в приёмник — конструктор _SqlCommand_\. Задача taint\-анализа состоит в проверке наличия пути передачи заражённых данных от источника к приёмнику\.

По сути, taint\-анализ является одной из форм статического анализа\. Таким образом, он вполне может быть реализован в соответствующих инструментах в качестве отдельного механизма или набора диагностических правил\. К примеру, если проверить вышеприведённый код с помощью PVS\-Studio, то результатом станет следующее предупреждение: "[V5608](https://pvs-studio.ru/ru/docs/warnings/v5608/) Possible SQL injection inside method\. Potentially tainted data in the first argument 'sql' is used to create SQL command"\.

Для полноты картины приведём другой пример атаки – [XSS \(межсайтовый скриптинг\)](https://pvs-studio.ru/ru/blog/terms/6462/)\. Она позволяет злоумышленнику внедрять вредоносный код на открываемые пользователями веб\-страницы\. Приёмником в данном случае может являться вызов метода _Response\.Write_:

```cpp
protected void Page_Load(object sender, EventArgs e)
{
  ....

  var userName = Request.Params["userName"];  // taint source
  
  string message;
  if (string.IsNullOrWhiteSpace(userName))
  {
    message = "Empty 'userName' parameter";
  }
  else
  {
    message = $"'{userName}' data has been processed.";
  }
  
  Response.Write(message);          // taint sink
}
```

Производя taint\-анализ, PVS\-Studio обнаружил здесь возможность попадания данных из _Request\.Params\["userName"\]_ в _Response\.Write_ и сформировал соответствующее предупреждение:

[V5610](https://pvs-studio.ru/ru/docs/warnings/v5610/) Possible XSS vulnerability\. Potentially tainted data in the 'message' variable might be used to execute a malicious script\.

В данном случае уязвимость состоит в следующем: если в параметр запроса _userName_ будет записан вредоносный скрипт, то из\-за вызова _Response\.Write_ он попадёт на загружаемую пользователем страницу и впоследствии выполнится\.

Подробнее о различных типах уязвимостей можно прочитать в документации к соответствующим диагностическим правилам:

* [V1010 \- Unchecked tainted data is used in expression](https://pvs-studio.ru/ru/docs/warnings/v1010/)
* [V5608 – SQL Injection](https://pvs-studio.ru/ru/docs/warnings/v5608/)
* [V5609 – Path Traversal](https://pvs-studio.ru/ru/docs/warnings/v5609/)
* [V5610 – XSS](https://pvs-studio.ru/ru/docs/warnings/v5610/)
* [V5611 – Insecure Deserialization](https://pvs-studio.ru/ru/docs/warnings/v5611/)

## Устранение потенциальных уязвимостей

Для устранения потенциальной уязвимости внешние данные необходимо проверять или преобразовывать в некоторый безопасный вид\. Конкретный способ защиты зависит от типа атаки\. Например, в случае с SQL injection могут быть использованы параметризованные запросы:

```cpp
String userName = Request.Form["userName"];
String query = "SELECT * FROM Users WHERE UserName = @userName";

using (var command = new SqlCommand(query, _connection))
{
  var userNameParam = new SqlParameter("@userName", userName);
  command.Parameters.Add(userNameParam);
            
  using (var reader = command.ExecuteReader())
  ....
}
```

Соответственно, при проведении taint\-анализа предупреждение на данный код выдано не будет\.

Для других атак также предусмотрены свои способы защиты\. Например, в случае с XSS можно использовать специальные методы преобразования внешних данных\. Одним из них является _HtmlEncode_:

```cpp
protected void Page_Load(object sender, EventArgs e)
{
  String userName = Request.Form["userName"];
  ....
  var encodedUserName = System.Net.WebUtility.HtmlEncode(userName);
  var message = $"'{encodedUserName}' data has been processed.";
  
  Response.Write(message);
}
```

Благодаря такой обработке вредоносный скрипт попадёт на страницу в виде обычного текста\. Следовательно, никакие опасные действия выполняться не будут\.

<details>
   <summary>Определение анализа помеченных данных по ГОСТ Р 71207\\\-2024\\\.</summary>

[ГОСТ Р 71207\-2024](https://pvs-studio.ru/ru/pvs-studio/gost-71207/) — Статический анализ программного обеспечения\. В разделе терминов дано следующее определение анализа помеченных данных:

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

Примечания:

* Под источниками понимаются точки программы, в которых данные начинают иметь пометку — некоторое заданное свойство\. Под стоками понимаются точки программы, в которых данные перестают иметь пометку\.
* Распространённая цель анализа помеченных данных — показать, что помеченные данные не могут попасть из источников — точек ввода пользователя в стоки — процедуры записи на диск или в сеть\. Факт такого попадания означает утечку конфиденциальных данных\.

Также в стандарте указывается, что если статический анализатор реализует анализ помеченных данных для выявления [критических ошибок](https://pvs-studio.ru/ru/blog/terms/6441/), то должна быть предоставлена возможность конфигурации анализа: должны задаваться процедуры\-источники и процедуры\-стоки чувствительных данных\.


</details>


## Дополнительные ссылки

1. [OWASP, уязвимости и taint анализ в PVS\-Studio C\#\. Смешать, но не взбалтывать](https://pvs-studio.ru/ru/blog/posts/csharp/0831/)
1. [Описание уязвимости Path Traversal](https://pvs-studio.ru/ru/blog/terms/6470/)
1. [Описание уязвимости XSS \(межсайтовый скриптинг\)](https://pvs-studio.ru/ru/blog/terms/6462/) 
1. [OWASP, OWASP Топ\-10](https://pvs-studio.ru/ru/blog/terms/6458/) 
1. [Классификация предупреждений PVS\-Studio согласно OWASP Application Security Verification Standard \(ASVS\)](https://pvs-studio.ru/ru/pvs-studio/sast/owasp/) 
1. [Классификация предупреждений PVS\-Studio согласно OWASP Top 10](https://pvs-studio.ru/ru/pvs-studio/sast/owasptopten/)