En

JazzTeam Software Development Company

Agile Java Development

SQL Injection

Введение

SQL Injection - один из возможных путей взлома веб приложений, работающих с SQL базами данных (БД). Данный путь основан на внедрении вредоносного кода в исходный SQL-скрипт. Например, на взламываемом сервере баз данных злоумышленник может:

Разработчик таких программ, работающих с БД, должен брать во внимание потенциальную уязвимость своих приложений и принимать меры для противодействия SQL Injections.

Суть SQL Injection

Представим, что имеется веб приложение на языке Java, работающее с пользовательскими запросами по HTTP. Реализация на самом деле не важна, внедрить SQL код можно используя неверно спроектированный интерфейс пользователя даже в консольное приложение. Часть логики данного уязвимого приложения описана в следующем примере:

String login = ...;
String password = ...;
String generatedSql = “SELECT * FROM users WHERE 
     (login = ‘“ + login +”’ and 
     password = ‘“ + password+ ”’)”;

При штатном использовании сервера на него приходят валидные и логичные данные. Например, могут прийти значения:

В этом случае произойдёт конкатенация строк Java и финальный SQL запрос к БД будет выглядеть так:

String generatedSql = “SELECT * FROM users WHERE 
     (login = ‘my_login@mail.com’ and 
     password = ‘my_password_123’)”;

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

Следовательно, будет выполнен SQL запрос с внедрением кода злоумышленника:

String generatedSql = “SELECT * FROM users WHERE 
     (login = ‘my_login@mail.com’ and 
     password = ‘’ or 1=1#’)”;

Выполнив этот скрипт, сервер БД вернет корректный ответ, несмотря на отсутствие пароля в нужном параметре. Стоит отметить, что символ решетки на конце SQL Injection нужен для экранирования (комментирования) последующих ограничений исходного SQL запроса в RDBMS MySQL.

Как уже упоминалось ранее, злоумышленник может провести не только вход в систему, но и, например, удаление данных и даже таблиц. Если уязвимость имеет место, ничего не мешает вместо параметра внедрить примерно следующую SQL программу:

Bob ‘); DROP TABLE contracts;#

Что также нанесет огромный вред атакуемой программе.

Использование Union в SQL Injection

SQL обладает возможностью использовать слово UNION и тем самым объединять несколько результатов запросов в одну таблицу. Этот способ также даёт возможность получить несанкционированный доступ к данным. Представим, что имеется HTTP сервис, отдающий пользователю новости и принимающий лишь ID новости. Внутри этого сервиса имеется следующий SQL скрипт, который отвечает за отображение новостей:

String newsId = ...;
SELECT id_news, header, body, author 
     FROM news 
     WHERE id_news = " + newsId;

В этом кейсе злоумышленник может внедрить в качестве параметра newsId следующую SQL программу:

-1 UNION SELECT 1,username, password,1 FROM admin

В результате финальный SQL запрос будет выглядеть так:

SELECT id_news, header, body, author 
     FROM news WHERE id_news = -1 
UNION SELECT 1, username, password, 1 
     FROM admin

Данный поддельный запрос вернет записи, относящиеся к безопасности сервиса - список имен и паролей пользователей из таблицы admin и, в то же время, не будет выведено никаких записей из таблицы news.

SQL Injection в ORM Hibernate

Потенциальном риску SQL-атаки также подвержены ORM системы, в частности, Hibernate. Это происходит по той причине, что Hibernate имеет возможность оперировать языком HQL (Hibernate Query Language). Во время создания HQL запроса у разработчика есть возможность допустить ошибку - использовать конкатенацию строк, как показано в примере:

SessionFactory sessionFactory = ...;
String user = ...;
String password = ...;
String generatedHql = “FROM LoginInfo 
        WHERE userName = ”+ user +” AND password = “+ password +”;”;
List<LoginInfo> logins = sessionFactory.
	getCurrentSession().
	createQuery(generatedHql).list();

В этом кейсе HQL код находится под уязвимостью т.к. данный пример Java кода сконструирован опасно и предоставляет возможность внедрить пользовательский HQL код.

Способы защиты от SQL Injection

Защита с помощью интерфейсов PreparedStatement и Statement

В стандартной библиотеке Java имеются интерфейсы PreparedStatement и Statement, которые можно использовать для защиты от SQL Injection.

Основное отличие PreparedStatement от Statement в том, что интерфейс Statement не принимает никаких параметров и применяется в случае статических SQL. Statement обладает низкой производительностью в связи с тем, что кэширование реализаций таких запросов не производится.

PreparedStatement используется в случае, когда планируется использовать SQL – выражения множество раз с различными параметрами. Например, исправленный вариант приведенного выше SQL запроса будет выглядеть так:

String login = ...;
String password = ...;
String sqlTemplate= “SELECT * FROM users WHERE 
     (login = ? and password = ?)”;
Connection connection = ...;
PreparedStatement statement = connection.prepareStatement(sql);
statement.setString(1, login);
statement.setString(2, password);

Нужно отметить, что использование PreparedStatement здесь оправдано как с точки зрения безопасности, так и с точки зрения производительности:

Защита Hibernate с помощью параметризации

Для предотвращения уязвимостей в HQL нужно использовать именованные параметры вместо конкатенации Java String. Такая возможность встроена в ORM Hibernate:

SessionFactory sessionFactory = ...;
String user = ...;
String password = ...;
// Измененный HQL запрос:
String generatedHql = “FROM LoginInfo 
        WHERE userName = :name AND password = :password”;
// Задание HQL параметров:
query.setParameter("name", user);
query.setParameter("password", password);
List<LoginInfo> logins = sessionFactory.
	getCurrentSession().
	createQuery(generatedHql).list();

Использование анализатора sqlmap

Для автоматизированного подхода в поиске SQL Injection в программном обеспечении можно использовать программу sqlmap. Этот инструмент входит в дистрибутив Kali Linux и может быть установлен на Windows (дополнительно нужен Python).
Он обладает следующими возможностями:

Для запуска проверки на наличие уязвимостей необходимо запустить sqlmap из консоли для сканирования:

>python sqlmap.py -u localhost/test/

В процессе работы sqlmap будет задавать различные вопросы, например, нужно ли пытаться определить наименование Web Application Firewall или даже попытаться проверить сервис на наличие XSS (Cross-Site Scripting - когда вредоносный код загружается вместе с Web-страницей). Результаты работы программы, например, найденные SQL Injections, отобразятся в консоли приложения.

Заключение

В данной статье мы раскрыли суть SQL Injection, рассмотрели некоторые общие способы защиты от SQL Injection, которые вы можете применять:

Используемые ссылки:

  1. https://habr.com/post/148151/
  2. https://en.wikipedia.org/wiki/SQL_injection
  3. https://xakep.ru/2011/12/06/57950/
  4. http://sqlmap.org/
  5. https://kali.tools/?p=816

, , , , , ,

Leave a Reply

Your email address will not be published. Required fields are marked *