Рубрики

Смягчение атаки SQL-инъекций с использованием подготовленных операторов (параметризованных запросов)

Как объясняется в этой статье , атака SQL Injection или SQLi — это способ использовать основную уязвимость оператора SQL, вставляя в его поле ввода для выполнения гнусные операторы SQL. Впервые он появился в 1998 году, и с тех пор он в основном ориентирован на ритейлеров и банковские счета. В сочетании с другими формами атак, такими как DDOS-атаки, межсайтовый скриптинг (XSS) или перехват DNS, это может привести к крупным результатам.

Терминология:

  • Валидация. Валидация — это процесс проверки того, соответствует ли входные данные ряду критериев (например, строка не содержит отдельных одинарных кавычек).
  • Дезинфекция. Дезинфекция — это процесс изменения входных данных, чтобы обеспечить их действительность (например, двойные одинарные кавычки).

Чтобы избежать внедрения SQL, все входные данные, которые должны быть объединены в динамический SQL, должны быть правильно отфильтрованы и очищены.

Анатомия SQL-атаки:
Атака SQL состоит из двух частей:

  • Исследование: просмотр уязвимых частей пользовательского приложения, которые соединяются с базой данных.
  • Атака: введите вредоносные поля, которые могут изменить запрос в ваших интересах.

Example1:
Рассмотрим следующий фрагмент кода для формы аутентификации, написанной на Java:

String query = "SELECT userName, balance FROM accounts" 

    + "WHERE userID=" + request.getParameter("userID") + 

  "and password='" + request.getParameter("Password") + "'";

  
try
{

    Statement statement = connection.createStatement();

    ResultSet rs = statement.executeQuery(query);

    while (rs.next()) 

    {

        page.addTableRow(rs.getString("userName"), 

                        rs.getFloat("balance"));

    }

catch (SQLException e) 

    {}

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

SELECT userName, balance 
FROM accounts 
WHERE userID=512 and password='thisisyoda'

Возможная атака с использованием SQL-инъекции может использовать поле пароля для создания логического выражения, которое сделает выражение истинным для всех случаев. Представьте себе, что вы устанавливаете поля userID и password как

userID = 1' or '1' = '1
password = 1' or '1' = '1

Затем оператор SQL становится

SELECT userName, balance 
FROM accounts 
WHERE userID='1' OR '1'='1' and 
      password='1' OR '1'='1'

Запрос вернет значение, потому что условие (OR 1 = 1) всегда выполняется. Таким образом, система аутентифицировала пользователя, не зная имени пользователя и пароля.

Уязвимость можно устранить с помощью подготовленного оператора для создания параметризованного запроса следующим образом:

String query = "SELECT userName, balance "+

               "FROM accounts WHERE userID = ? 

                and password = ?";

  

try {

  PreparedStatement statement = connection.prepareStatement(query);

  statement.setInt(1, request.getParameter("userID")); 

  ResultSet rs = statement.executeQuery();

  while (rs.next()) 

  {

    page.addTableRow(rs.getString("userName"), 

                     rs.getFloat("balance"));

  }

} catch (SQLException e)

       { ... }

Если злоумышленник попытается указать значение в поле userID, которое не является простым целым числом, то оператор Statement.setInt () выдаст ошибку SQLException, а не разрешит выполнение запроса.

Пример 2 :
Рассмотрим другой тип атаки во время аутентификации:

String query = "SELECT userID, userName, passwordHash"+

               " FROM users WHERE userName = '" 

               + request.getParameter("user") + "'";

int userID = -1;

HashMap userGroups = new HashMap();

try 
{

  Satement statement = connection.createStatement();

  ResultSet rs = statement.executeQuery(query);

  rs.first();

  userID = rs.getInt("userID");

      

  if (!hashOf(request.getParameter("password")).equals(rs.getString("passwordHash"))) 

  {

    throw BadLoginException();

  }

  

  String userGroupQuery = "SELECT group FROM groupMembership"+

                         " WHERE userID = " + userID;

      

  rs = statement.executeQuery(userGroupQuery);

      

  while (rs.next()) 

  {

    userGroup.put(rs.getString("group"), true);

  }

catch (SQLException e){}

catch (BadLoginException e){}

Обычный запрос будет выглядеть следующим образом.

SELECT userID, userName, passwordHash 
FROM users 
WHERE userName = 'Anannya'

Злоумышленник может ввести следующее в поле userName.

Anannya';
INSERT INTO groupMmbership (userID, group) 
VALUES (SELECT userID FROM users
WHERE userName='Anannya', 'Administrator'); --

В связи с этим фактический запрос изменится на:

SELECT userID, userName, passwordHash FROM 
       users WHERE userName = 'Anannya';
INSERT INTO groupMmbership (userID, group) 
VALUES (SELECT userID FROM users 
WHERE userName='Anannya', 'Administrator'); --'

Это приведет к тому, что другой оператор SQL будет добавлен к фактическому оператору, в результате чего пользователь будет добавлен в базу данных администратора. Атака может быть смягчена путем использования подготовленного оператора с параметризованным запросом следующим образом.

String query = "SELECT userID, userName, passwordHash"+

               " FROM users WHERE userName = ?";

  

try 
{

  PreparedSatement statement = 

         connection.prepareStatement(userLoginQuery);

  statement.setString(1, request.getParameter("user"));

  ResultSet rs = statement.executeQuery();

Пример 3 :
Рассмотрим еще один пример уязвимости запроса, рассмотренной ниже:

String query = "INSERT INTO users VALUES("

        request.getParameter("userName") + ");";

Общий запрос будет:

INSERT INTO users VALUES("Anannya")

Подумайте, вводит ли злоумышленник следующий запрос в поле userName:

"Anannya); DROP TABLE users;"

Запрос будет изменен на:

INSERT INTO users VALUES("Anannya"); DROP TABLE users;

Этот запрос полностью удаляет таблицу пользователей при ее выполнении. Обходной путь здесь, опять же, является подготовленным заявлением.

Как помогает использование подготовленного оператора в Java?

Подготовленное заявление «санирует» входные данные. Это означает, что все, что вводит пользователь, обрабатывается как строковый литерал в SQL, а НЕ как часть запроса SQL. Он также может экранировать определенные символы и обнаруживать / удалять вредоносный код. В других языках, таких как PHP, filter_input или filter_input_array могут использоваться для очистки строки.

Эта статья предоставлена Ананней Уберой . Если вы как GeeksforGeeks и хотели бы внести свой вклад, вы также можете написать статью с помощью contribute.geeksforgeeks.org или по почте статьи contribute@geeksforgeeks.org. Смотрите свою статью, появляющуюся на главной странице GeeksforGeeks, и помогите другим вундеркиндам.

Пожалуйста, пишите комментарии, если вы обнаружите что-то неправильное или вы хотите поделиться дополнительной информацией по обсуждаемой выше теме.

Рекомендуемые посты:

Смягчение атаки SQL-инъекций с использованием подготовленных операторов (параметризованных запросов)

0.00 (0%) 0 votes