﻿# SQL\-инъекция

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

Уязвимости данного типа представляют серьёзную угрозу\. В [OWASP ASVS](https://owasp.org/www-project-application-security-verification-standard/) они принадлежат категориям 5\.3\.4 и 5\.3\.5, а в списке [OWASP Top Ten 2017](https://owasp.org/www-project-top-ten/2017/) их можно отнести к категории [A1 \(Injection\)](https://owasp.org/www-project-top-ten/2017/A1_2017-Injection)\. Также в [Common Weakness Enumeration](https://cwe.mitre.org/) SQL\-инъекциям соответствует позиция [CWE\-89](https://cwe.mitre.org/data/definitions/89.html)\.

## Пример уязвимости

Для наглядной демонстрации возможностей SQLI рассмотрим следующий пример:

```cpp
void ProcessRequest(HttpRequest request) 
{ 
  string name = request.Form["name"];

  string sql = $"SELECT * FROM Users WHERE name='{name}'";
  ExecuteReaderCommand(sql);

  .... 
}

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

Предполагается, что в параметре 'name' будет записано имя пользователя, данные которого будут получены из базы и в последствии обработаны\. При этом модификация значений в базе не производится – приведённый фрагмент должен лишь считывать их\.

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

К примеру, в параметре 'name' может быть записано следующее значение:

```cpp
'; DELETE FROM Users WHERE name != '
```

При подстановке этой строки в шаблон запроса получится следующая SQL\-команда:

```cpp
SELECT * FROM Users WHERE name='';
DELETE FROM Users WHERE name != ''
```

Выполнение такого запроса приведёт к удалению всех записей из таблицы 'Users' \(при условии, что для каждого пользователя задано значение столбца 'name'\)\.

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

Одной из важнейших задач при обеспечении устойчивости приложения к SQL\-инъекциям является поиск фрагментов кода, которые могут быть уязвимы к данному виду атак\. Для этого необходимо найти и изучить все места, в которых производится формирование и выполнение запросов к базе данных\. Многие разработчики используют для этих целей различные инструменты, производящие [taint\-анализ](https://pvs-studio.ru/ru/blog/terms/6496/)\. Одним из таких инструментов является статический анализатор PVS\-Studio\.

Вернёмся к ранее приведённому примеру:

```cpp
void ProcessRequest(HttpRequest request) 
{ 
  string name = request.Form["name"];

  string sql = $"SELECT * FROM Users WHERE name='{name}'";
  ExecuteReaderCommand(sql);

  .... 
}

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

Производя 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\.

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

## Борьба с SQL\-инъекциями

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

Способы работы с параметризованными запросами в различных языках программирования могут отличаться, однако основная идея остаётся неизменной\. К примеру, в C\# формирование запроса с параметрами может производиться следующим образом:

```cpp
String userName = Request.Form["name"];

using (var command = new SqlCommand()
{
  Connection = _connection,
  CommandText = "SELECT * FROM Users WHERE UserName = @userName",
  CommandType = System.Data.CommandType.Text
})
{
  var userNameParam = new SqlParameter("@userName", userName);
  command.Parameters.Add(userNameParam);
            
  using (var reader = command.ExecuteReader()) { .... }
}
```

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

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

1. [OWASP, OWASP Топ\-10](https://pvs-studio.ru/ru/blog/terms/6458/)
1. [Описание SQL Injection на сайте Microsoft](https://docs.microsoft.com/en-us/sql/relational-databases/security/sql-injection?view=sql-server-ver15)
1. [Классификация предупреждений PVS\-Studio согласно OWASP Top 10 Web Application Security Risks](https://pvs-studio.ru/ru/pvs-studio/sast/owasptopten/)
1. [Классификация предупреждений PVS\-Studio согласно OWASP Application Security Verification Standard \(ASVS\)](https://pvs-studio.ru/ru/pvs-studio/sast/owasp/)
1. [OWASP, уязвимости и taint анализ в PVS\-Studio C\#\. Смешать, но не взбалтывать](https://pvs-studio.ru/ru/blog/posts/csharp/0831/)
1. [Диагностическое правило V5608 \(SQL Injection\)](https://pvs-studio.ru/ru/docs/warnings/v5608/)
1. [Статья о SQL Injection на официальном сайте OWASP](https://owasp.org/www-community/attacks/SQL_Injection)