Атаки с помощью SQL-инъекции: теория, примеры, способы защиты


Атака SQL-инъекции состоит из вставки или “инъекции” SQL-запроса через входные данные от клиента в приложение. Успешный эксплойт SQL - инъекции может считывать конфиденциальные данные из базы данных, изменять данные базы данных (Вставлять/Обновлять/Удалять), выполнять операции администрирования базы данных (такие как завершение работы СУБД), восстанавливать содержимое данного файла, присутствующего в файловой системе СУБД, и в некоторых случаях выдавать команды операционной системе. Атаки с использованием SQL–инъекций - это тип атаки с использованием инъекций, при которой команды SQL вводятся во входные данные на уровне данных, чтобы повлиять на выполнение предопределенных команд SQL.



Моделирование угроз

  • Атаки с использованием SQL-инъекций позволяют злоумышленникам подделывать личность, изменять существующие данные, вызывать проблемы с отказом, такие как аннулирование транзакций или изменение баланса, разрешать полное раскрытие всех данных в системе, уничтожать данные или делать их недоступными иным образом, а также становиться администраторами сервера базы данных.
  • Инъекция SQL очень распространена в приложениях PHP и ASP из-за преобладания старых функциональных интерфейсов. В связи с характером доступных программных интерфейсов, J2EE и ASP.NET приложения с меньшей вероятностью будут легко использовать SQL-инъекции.
  • Серьезность атак с использованием SQL-инъекций ограничивается навыками и воображением злоумышленника и, в меньшей степени, глубокими контрмерами защиты, такими как подключения с низкими привилегиями к серверу базы данных и так далее. В общем, считайте, что внедрение SQL имеет высокую степень воздействия.
Описание

Атака SQL-инъекции происходит, когда:

  1. Непредвиденные данные поступают в программу из ненадежного источника.
  2. Данные используются для динамического построения 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-инъекций полностью.

Другим решением, обычно предлагаемым для борьбы с атаками с использованием 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 - то есть могу доработать ваш сайт или помочь с веб-программированием. Пишите сюда.



тегизаметки, информационная безопасность, sql, java, си шарп




Отправляя сообщение я подтверждаю, что ознакомлен и согласен с политикой конфиденциальности данного сайта.




Реестр почти без программирования, или KISS
Матрица Тёплица на Java
Урок 10. Инлайн стили, классы и условия в Vue.js