Атаки с помощью SQL-инъекции: теория, примеры, способы защиты
Атака SQL-инъекции состоит из вставки или “инъекции” SQL-запроса через входные данные от клиента в приложение. Успешный эксплойт SQL - инъекции может считывать конфиденциальные данные из базы данных, изменять данные базы данных (Вставлять/Обновлять/Удалять), выполнять операции администрирования базы данных (такие как завершение работы СУБД), восстанавливать содержимое данного файла, присутствующего в файловой системе СУБД, и в некоторых случаях выдавать команды операционной системе. Атаки с использованием SQL–инъекций - это тип атаки с использованием инъекций, при которой команды SQL вводятся во входные данные на уровне данных, чтобы повлиять на выполнение предопределенных команд SQL.
Моделирование угроз
- Атаки с использованием SQL-инъекций позволяют злоумышленникам подделывать личность, изменять существующие данные, вызывать проблемы с отказом, такие как аннулирование транзакций или изменение баланса, разрешать полное раскрытие всех данных в системе, уничтожать данные или делать их недоступными иным образом, а также становиться администраторами сервера базы данных.
- Инъекция SQL очень распространена в приложениях PHP и ASP из-за преобладания старых функциональных интерфейсов. В связи с характером доступных программных интерфейсов, J2EE и ASP.NET приложения с меньшей вероятностью будут легко использовать SQL-инъекции.
- Серьезность атак с использованием SQL-инъекций ограничивается навыками и воображением злоумышленника и, в меньшей степени, глубокими контрмерами защиты, такими как подключения с низкими привилегиями к серверу базы данных и так далее. В общем, считайте, что внедрение SQL имеет высокую степень воздействия.
Атака SQL-инъекции происходит, когда:
- Непредвиденные данные поступают в программу из ненадежного источника.
- Данные используются для динамического построения SQL-запроса.
- Конфиденциальность: Поскольку базы данных SQL обычно содержат конфиденциальные данные, потеря конфиденциальности является частой проблемой, связанной с уязвимостями SQL-инъекций.
- Аутентификация: Если для проверки имен пользователей и паролей используются плохие команды SQL, возможно, удастся подключиться к системе от имени другого пользователя, ранее не знавшего пароль.
- Авторизация: Если информация об авторизации хранится в базе данных SQL, возможно, удастся изменить эту информацию путем успешного использования уязвимости SQL-инъекции.
- Целостность: Точно так же, как может быть возможно прочитать конфиденциальную информацию, также возможно внести изменения или даже удалить эту информацию с помощью атаки SQL-инъекции.
- Язык: SQL
- Платформа: Любая (требуется взаимодействие с базой данных SQL)
Примеры
Пример 1
В SQL:
select id, firstname, lastname from authorsЕсли будет имя: evil'ex и фамилия: newman, то строка запроса становится:
select id, firstname, lastname from authors where firstname = 'evil'ex' and lastname ='newman'который база данных пытается запустить как:
Incorrect syntax near il' as the database tried to execute evil.Безопасная версия приведенного выше оператора SQL может быть закодирована на Java следующим образом:
String firstname = req.getParameter("firstname"); String lastname = req.getParameter("lastname"); // сделайте свою собственную проверку для обнаружения атак String query = "SELECT id, firstname, lastname FROM authors WHERE firstname = ? and lastname = ?"; PreparedStatement pstmt = connection.prepareStatement( query ); pstmt.setString( 1, firstname ); pstmt.setString( 2, lastname ); try { ResultSet results = pstmt.execute( ); }Пример 2
Следующий код C# динамически создает и выполняет SQL-запрос, который выполняет поиск элементов, соответствующих указанному имени. Запрос ограничивает отображаемые элементы теми, владелец которых совпадает с именем пользователя, прошедшего проверку подлинности в данный момент.
... string userName = ctx.getAuthenticatedUserName(); string query = "SELECT * FROM items WHERE owner = "'" + userName + "' AND itemname = '" + ItemName.Text + "'"; sda = new SqlDataAdapter(query, conn); DataTable dt = new DataTable(); sda.Fill(dt); ...Запрос, который этот код намеревается выполнить, следует:
SELECT * FROM items WHERE owner = AND itemname = ;Однако, поскольку запрос строится динамически путем объединения строки запроса с постоянной базой и строки пользовательского ввода, запрос работает правильно только в том случае, если имя элемента не содержит символа в одной кавычке. Если злоумышленник с именем пользователя wiley вводит строку "name' OR 'a'='a" для имени элемента, то запрос становится следующим:
SELECT * FROM items WHERE owner = 'wiley' AND itemname = 'name' OR 'a'='a';Добавление условия OR 'a'='a' приводит к тому, что предложение where всегда принимает значение true, поэтому запрос становится логически эквивалентным гораздо более простому запросу:
SELECT * FROM items;Это упрощение запроса позволяет злоумышленнику обойти требование о том, чтобы запрос возвращал только элементы, принадлежащие аутентифицированному пользователю; теперь запрос возвращает все записи, хранящиеся в таблице элементов, независимо от их указанного владельца.
Пример 3
В этом примере рассматривается влияние другого вредоносного значения, переданного в запрос, созданный и выполненный в примере 1. Если злоумышленник с именем пользователя хакер вводит строку "name'); DELETE FROM items; --" для имени элемента, то запрос становится следующими двумя запросами:
SELECT * FROM items WHERE owner = 'hacker' AND itemname = 'name'; DELETE FROM items; --'Многие серверы баз данных, включая Microsoft ® SQL Server 2000, позволяют выполнять несколько операторов SQL, разделенных точками с запятой, одновременно. Хотя эта строка атаки приводит к ошибке на серверах Oracle и других баз данных, которые не разрешают пакетное выполнение инструкций, разделенных точками с запятой, в базах данных, которые разрешают пакетное выполнение, этот тип атаки позволяет злоумышленнику выполнять произвольные команды против базы данных.
Обратите внимание на конечную пару дефисов (--), которая указывает большинству серверов баз данных, что остальная часть инструкции должна рассматриваться как комментарий и не выполняться. В этом случае символ комментария служит для удаления последней одинарной кавычки, оставшейся в измененном запросе. В базе данных, где комментарии не разрешены для использования таким образом, общая атака все еще может быть эффективной с помощью трюка, аналогичного показанному в примере 1. Если злоумышленник введет строку "name'); DELETE FROM items; SELECT \* FROM items WHERE 'a'='a" будут созданы следующие три допустимых оператора:
SELECT * FROM items WHERE owner = 'hacker' AND itemname = 'name'; DELETE FROM items; SELECT * FROM items WHERE 'a'='a';Один из традиционных подходов к предотвращению атак с использованием SQL-инъекций заключается в том, чтобы обрабатывать их как проблему проверки входных данных и либо принимать только символы из списка разрешенных безопасных значений, либо идентифицировать список запрещенных потенциально вредоносных значений и избегать его. Список разрешений может быть очень эффективным средством обеспечения строгих правил проверки входных данных, но параметризованные операторы SQL требуют меньшего обслуживания и могут предоставить больше гарантий в отношении безопасности. Как это почти всегда бывает, список отказов изобилует лазейками, которые делают его неэффективным для предотвращения атак с использованием SQL - инъекций.
Например, злоумышленники могут:
- найти целевые поля, которые не заключены в кавычки
- найти способы обойти необходимость в определенных экранированных мета-символах
- использовать хранимые процедуры, чтобы скрыть введенные мета-символы
Другим решением, обычно предлагаемым для борьбы с атаками с использованием SQL-инъекций, является использование хранимых процедур. Хотя хранимые процедуры предотвращают некоторые типы атак с использованием SQL-инъекций, они не защищают от многих других. Например, следующая процедура PL/SQL уязвима для той же атаки SQL-инъекции, показанной в первом примере.
procedure get_item ( itm_cv IN OUT ItmCurTyp, usr in varchar2, itm in varchar2) is open itm_cv for ' SELECT * FROM items WHERE ' || 'owner = '''|| usr || ' AND itemname = ''' || itm || ''''; end get_item;Хранимые процедуры обычно помогают предотвратить атаки с использованием SQL-инъекций, ограничивая типы инструкций, которые могут передаваться их параметрам. Однако существует множество способов обойти ограничения и множество интересных инструкций, которые все еще могут быть переданы хранимым процедурам. Опять же, хранимые процедуры могут предотвратить некоторые эксплойты, но они не защитят полностью ваше приложение от всех атак с использованием SQL-инъекций.
Автор этого материала - я - Пахолков Юрий. Я оказываю услуги по написанию программ на языках Java, C++, C# (а также консультирую по ним) и созданию сайтов. Работаю с сайтами на CMS OpenCart, WordPress, ModX и самописными. Кроме этого, работаю напрямую с JavaScript, PHP, CSS, HTML - то есть могу доработать ваш сайт или помочь с веб-программированием. Пишите сюда.
Читайте также:
Отправляя сообщение я подтверждаю, что ознакомлен и согласен с политикой конфиденциальности данного сайта.