Что такое SQL инъекция и как ее предотвратить

Что такое SQL инъекция и как ее предотвратить


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

Вредоносные SQL-инъекции могут поражать любые веб-сайты или веб-приложения, использующие базы данных SQL, такие как MySQL, Oracle, SQL Server и другие. Преступники могут использовать ее для получения несанкционированного доступа к вашим конфиденциальным данным: информации о клиентах, личным данным, коммерческим тайнам, интеллектуальной собственности и т.д. Атаки с помощью SQL-инъекций являются одной из самых старых, распространенных и опасных угроз для веб-приложений. Организация OWASP (Open Web Application Security Project) в своем документе OWASP Top 10 2017 перечисляет инъекции как угрозу номер один для безопасности веб-приложений.

Как и почему происходит атака с помощью SQL-инъекций

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

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

  • Злоумышленники могут использовать SQL-инъекции для поиска в базе данных учетных данных других пользователей. Затем они могут выдать себя за этих пользователей. Выдаваемый за себя пользователь может быть администратором базы данных.
  • Уязвимость перед SQL-инъекциями может позволить злоумышленнику получить полный доступ ко всем данным на сервере базы данных.
  • Например, в финансовом приложении злоумышленник может использовать SQL-инъекцию для изменения баланса, аннулирования транзакций или перевода денег на свой счет.
  • С помощью SQL можно удалять записи и таблицы из базы данных. Даже если администратор создает резервные копии базы данных, удаление данных может повлиять на доступность приложения до тех пор, пока база не будет восстановлена. Кроме того, резервные копии могут не отражать самые последние данные.
  • В некоторых серверах баз данных вы можете получить доступ к операционной системе с помощью этого сервера. Это может быть сделано преднамеренно или случайно. В таком случае злоумышленник может использовать SQL-инъекцию в качестве начального вектора, а затем атаковать внутреннюю сеть.

Существует несколько типов атак на основе SQL-инъекций: in-band SQLi (с использованием ошибок базы данных или команд UNION), blind SQLi и out-of-band SQLi.

Простой пример SQL-инъекции

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

Следующий код представляет собой псевдокод, выполняемый на веб-сервере. Это простой пример аутентификации с помощью имени пользователя и пароля. В базе данных примера имеется таблица users со следующими столбцами: username и password.

# Заданные переменные POST
uname = request.POST['username']
passwd = request.POST['password']

# SQL запрос уязвимый перед SQLi
sql = “SELECT id FROM users WHERE username=’” + uname + “’ AND password=’” + passwd + “’”

# Выполнение SQL-запроса
database.execute(sql)

Такие поля ввода уязвимы перед SQL-инъекцией. Злоумышленник может, например, использовать трюк с одинарной кавычкой и установить в поле passwd следующее значение:

password' OR 1=1

В результате сервер базы данных выполняет следующий SQL-запрос:

SELECT id FROM users WHERE username='username' AND password='password' OR 1=1'

Из-за оператора OR 1=1 оператор WHERE возвращает первый id из таблицы users, независимо от имени пользователя и пароля. Очень часто первым id пользователя в базе данных является администратор. Таким образом, злоумышленник не только обходит аутентификацию, но и получает привилегии администратора. Он также может закомментировать остальную часть оператора SQL, чтобы контролировать дальнейшее выполнение SQL-запроса:

-- MySQL, MSSQL, Oracle, PostgreSQL, SQLite
' OR '1'='1' --
' OR '1'='1' /*
-- MySQL
' OR '1'='1' #
-- Access (using null characters)
' OR '1'='1' %00
' OR '1'='1' %16

Пример SQL-инъекции на основе UNION

Один из самых распространенных типов SQL-инъекций использует оператор UNION. Он позволяет злоумышленнику объединить результаты двух или более операторов SELECT в один результат. 

Ниже приведен пример этой типа. В нем используется веб-страница testphp.vulnweb.com, намеренно уязвимый веб-сайт.

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

GET http://testphp.vulnweb.com/artists.php?artist=1 HTTP/1.1
Host: testphp.vulnweb.com

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

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

GET http://testphp.vulnweb.com/artists.php?artist=-1 UNION SELECT 1, 2, 3 HTTP/1.1
Host: testphp.vulnweb.com

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

GET http://testphp.vulnweb.com/artists.php?artist=-1 UNION SELECT 1,pass,cc FROM users WHERE uname='test' HTTP/1.1
Host: testphp.vulnweb.com

Как предотвратить SQL-инъекцию

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

Если вы обнаружили уязвимость, вы не всегда можете устранить ее мгновенно. Например, уязвимость может находиться в открытом исходном коде. В таких случаях можно использовать брандмауэр веб-приложений для временной санации входных данных.

Общие советы

Предотвратить SQL инъекции непросто. Конкретные методы предотвращения зависят от подтипа уязвимости SQLi, от движка базы данных SQL и от языка программирования. Однако существуют определенные общие стратегические принципы, которым вы должны следовать, чтобы обезопасить свое веб-приложение.

Шаг 1: Обучение и информирование

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

Шаг 2: Не доверяйте пользовательскому вводу

Воспринимайте все вводимые пользователем данные как ненадежные. Любой пользовательский ввод, используемый в SQL-запросе, создает риск SQL-инъекции. Относитесь к вводу данных от аутентифицированных и/или внутренних пользователей так же, как и к вводу данных от публичных пользователей.

Шаг 3: Используйте whitelists, а не blacklists

Не фильтруйте пользовательский ввод на основе blacklists. Умный злоумышленник почти всегда найдет способ обойти их. По возможности проверяйте и фильтруйте вводимые пользователем данные, используя только строгие whitelists.

Шаг 4: Внедряйте новейшие технологии

Более старые технологии веб-разработки не имеют защиты SQLi. Используйте последнюю версию среды разработки и языка, а также последние технологии, связанные с этой средой/языком. Например, в PHP используйте PDO вместо MySQLi.

Шаг 5: Использование проверенных механизмов

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

Шаг 6: Регулярное сканирование

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



Оригинал статьи: https://www.acunetix.com/websitesecurity/sql-injection/

Report Page