Внедрение SQL-кода (
Внедрение SQL, в зависимости от типа используемой
Атака типа внедрения SQL может быть возможна из-за некорректной обработки входных данных, используемых в SQL-запросах.
Разработчик прикладных программ, работающих с базами данных, должен знать о таких уязвимостях и принимать меры противодействия внедрению SQL.
Принцип атаки внедрения SQL
Допустим, серверное
Если на сервер передан параметр id, равный 5 (например так:
Но если злоумышленник передаст в качестве параметра id строку -1 OR 1=1 (например, так:
Таким образом, изменение входных параметров путём добавления в них конструкций языка SQL вызывает изменение в логике выполнения SQL-запроса (в данном примере вместо новости с заданным идентификатором будут выбраны все имеющиеся в базе новости, поскольку выражение 1=1 всегда истинно —
Внедрение в строковые параметры
Предположим, серверное ПО, получив запрос на поиск данных в новостях параметром search_text, использует его в следующем SQL-запросе (здесь параметры экранируются кавычками):
Сделав запрос вида
Но, внедрив в параметр search_text символ кавычки (который используется в запросе), мы можем кардинально изменить поведение SQL-запроса. Например, передав в качестве параметра search_text значение ')+and+(news_id_author='1, мы вызовем к выполнению запрос:
Использование UNION
Язык SQL позволяет объединять результаты нескольких запросов при помощи оператора
Рассмотрим скрипт отображения новости (идентификатор новости, которую необходимо отобразить, передается в параметре id):
Если злоумышленник передаст в качестве параметра id конструкцию -1 UNION SELECT 1,username, password,1 FROM admin, это вызовет выполнение SQL-запроса
Так как новости с идентификатором −1 заведомо не существует, из таблицы news не будет выбрано ни одной записи, однако в результат попадут записи, несанкционированно отобранные из таблицы admin в результате инъекции SQL.
Использование UNION + group_concat()
В некоторых случаях хакер может провести атаку, но не может видеть более одной колонки. В случае
которая объединяет несколько колонок в одну. Например, для примера данного выше вызов функции будет таким:
Экранирование хвоста запроса
Зачастую SQL-запрос, подверженный данной уязвимости, имеет структуру, усложняющую или препятствующую использованию union. Например скрипт
отображает имя автора новости по передаваемому идентификатору id только при условии, что имя начинается с буквы а, и внедрение кода с использованием оператора UNION затруднительно.
В таких случаях злоумышленниками используется метод экранирования части запроса при помощи символов комментария(/* или -- в зависимости от типа СУБД).
В данном примере злоумышленник может передать в скрипт параметр id со значением -1 UNION SELECT password FROM admin/*, выполнив таким образом запрос
в котором часть запроса ( AND author LIKE ('a%')) помечена как комментарий и не влияет на выполнение.
Расщепление SQL-запроса
Для разделения команд в языке SQL используется символ ; (точка с запятой), внедряя этот символ в запрос, злоумышленник получает возможность выполнить несколько команд в одном запросе, однако не все диалекты SQL поддерживают такую возможность.
Например, если в параметры скрипта
злоумышленником передается конструкция, содержащая точку с запятой, например 12;INSERT INTO admin (username, password) VALUES ('Dark-Time', 'Life'); то в одном запросе будут выполнены 2 команды
и в таблицу admin будет несанкционированно добавлена запись Dark-Time.
Методика атак типа внедрение SQL-кода
Поиск скриптов, уязвимых для атаки
На данном этапе злоумышленник изучает поведение скриптов сервера при манипуляции входными параметрами с целью обнаружения их аномального поведения. Манипуляция происходит всеми возможными параметрами:
Аномальным поведением считается любое поведение, при котором страницы, получаемые до и после подстановки кавычек, различаются (и при этом не выведена страница о неверном формате параметров).
Наиболее частые примеры аномального поведения:
Защита от атак типа внедрение SQL-кода
Для защиты от данного типа атак необходимо тщательно фильтровать входные параметры, значения которых будут использованы для построения SQL-запроса.
Фильтрация строковых параметров
Предположим, что код, генерирующий запрос (на языке программирования
Чтобы внедрение кода (закрытие строки, начинающейся с кавычки, другой кавычкой до её завершения текущей закрывающей кавычкой для разделения запроса на две части) было невозможно, для некоторых
Для PHP фильтрация может быть такой:
Фильтрация целочисленных параметров
Возьмём другой запрос:
В данном случае поле id имеет числовой тип, и его чаще всего не берут в кавычки. Поэтому «закавычивание» и замена спецсимволов на escape-последовательности не проходит. В таком случае помогает проверка типа; если переменная id не является числом, запрос вообще не должен выполняться.
Например, на
Для PHP этот метод будет выглядеть так:
Усечение входных параметров
Для внесения изменений в логику выполнения SQL-запроса требуется внедрение достаточно длинных строк. Так, минимальная длина внедряемой строки в вышеприведённых примерах составляет 8 символов («1 OR 1=1»). Если максимальная длина корректного значения параметра невелика, то одним из методов защиты может быть максимальное усечение значений входных параметров.
Например, если известно, что поле id в вышеприведённых примерах может принимать значения не более 9999, можно «отрезать лишние» символы, оставив не более четырёх:
Использование параметризованных запросов
Многие серверы баз данных поддерживают возможность отправки параметризованных запросов (подготовленные выражения). При этом параметры внешнего происхождения отправляются на сервер отдельно от самого запроса либо автоматически экранируются клиентской библиотекой. Для этого используются
Пожалуйста,
Вход
или
Регистрация
для просмотра содержимого URL-адресов!
SQL injection) — один из распространённых способов взлома Пожалуйста,
Вход
или
Регистрация
для просмотра содержимого URL-адресов!
и Пожалуйста,
Вход
или
Регистрация
для просмотра содержимого URL-адресов!
, работающих с Пожалуйста,
Вход
или
Регистрация
для просмотра содержимого URL-адресов!
, основанный на внедрении в запрос произвольного Пожалуйста,
Вход
или
Регистрация
для просмотра содержимого URL-адресов!
-кода.Внедрение SQL, в зависимости от типа используемой
Пожалуйста,
Вход
или
Регистрация
для просмотра содержимого URL-адресов!
и условий внедрения, может дать возможность атакующему выполнить произвольный запрос к базе данных (например, прочитать содержимое любых Пожалуйста,
Вход
или
Регистрация
для просмотра содержимого URL-адресов!
, удалить, изменить или добавить Пожалуйста,
Вход
или
Регистрация
для просмотра содержимого URL-адресов!
), получить возможность чтения и/или записи локальных файлов и выполнения произвольных команд на атакуемом сервере.Атака типа внедрения SQL может быть возможна из-за некорректной обработки входных данных, используемых в SQL-запросах.
Разработчик прикладных программ, работающих с базами данных, должен знать о таких уязвимостях и принимать меры противодействия внедрению SQL.
Принцип атаки внедрения SQL
Допустим, серверное
Пожалуйста,
Вход
или
Регистрация
для просмотра содержимого URL-адресов!
, получив входной параметр id, использует его для создания SQL-запроса. Рассмотрим следующий Пожалуйста,
Вход
или
Регистрация
для просмотра содержимого URL-адресов!
-скрипт:
PHP:
$id = $_REQUEST['id'];
$res = mysqli_query("SELECT * FROM news WHERE id_news = " . $id);
Пожалуйста,
Вход
или
Регистрация
для просмотра содержимого URL-адресов!
(недоступная ссылка)), то выполнится следующий Пожалуйста,
Вход
или
Регистрация
для просмотра содержимого URL-адресов!
-запрос:
SQL:
SELECT * FROM news WHERE id_news = 5
Пожалуйста,
Вход
или
Регистрация
для просмотра содержимого URL-адресов!
(недоступная ссылка)), то выполнится запрос:
SQL:
SELECT * FROM news WHERE id_news = -1 OR 1=1
Пожалуйста,
Вход
или
Регистрация
для просмотра содержимого URL-адресов!
). Внедрение в строковые параметры
Предположим, серверное ПО, получив запрос на поиск данных в новостях параметром search_text, использует его в следующем SQL-запросе (здесь параметры экранируются кавычками):
SQL:
$search_text = $_REQUEST['search_text'];
$res = mysqli_query("SELECT id_news, news_date, news_caption, news_text, news_id_author
FROM news WHERE news_caption LIKE('%$search_text%')");
Пожалуйста,
Вход
или
Регистрация
для просмотра содержимого URL-адресов!
(недоступная ссылка) мы получим выполнение следующего SQL-запроса:
SQL:
SELECT id_news, news_date, news_caption, news_text, news_id_author FROM news
WHERE news_caption LIKE('%Test%')
SQL:
SELECT id_news, news_date, news_caption, news_text, news_id_author FROM news
WHERE news_caption LIKE('%') and (news_id_author='1%')
Язык SQL позволяет объединять результаты нескольких запросов при помощи оператора
Пожалуйста,
Вход
или
Регистрация
для просмотра содержимого URL-адресов!
. Это предоставляет злоумышленнику возможность получить несанкционированный доступ к данным.Рассмотрим скрипт отображения новости (идентификатор новости, которую необходимо отобразить, передается в параметре id):
PHP:
$res = mysqli_query("SELECT id_news, header, body, author FROM news WHERE id_news = " . $_REQUEST['id']);
SQL:
SELECT id_news, header, body, author FROM news WHERE id_news = -1 UNION SELECT 1,username,password,1 FROM admin
Использование UNION + group_concat()
В некоторых случаях хакер может провести атаку, но не может видеть более одной колонки. В случае
Пожалуйста,
Вход
или
Регистрация
для просмотра содержимого URL-адресов!
взломщик может воспользоваться функцией:
SQL:
group_concat(col, symbol, col)
SQL:
-1 UNION SELECT group_concat(username, 0x3a, password) FROM admin
Зачастую SQL-запрос, подверженный данной уязвимости, имеет структуру, усложняющую или препятствующую использованию union. Например скрипт
PHP:
$res = mysqli_query("SELECT author FROM news WHERE id=" . $_REQUEST['id'] . " AND author LIKE ('a%')");
В таких случаях злоумышленниками используется метод экранирования части запроса при помощи символов комментария(/* или -- в зависимости от типа СУБД).
В данном примере злоумышленник может передать в скрипт параметр id со значением -1 UNION SELECT password FROM admin/*, выполнив таким образом запрос
SQL:
SELECT author FROM news WHERE id=-1 UNION SELECT password FROM admin/* AND author LIKE ('a%')
Расщепление SQL-запроса
Для разделения команд в языке SQL используется символ ; (точка с запятой), внедряя этот символ в запрос, злоумышленник получает возможность выполнить несколько команд в одном запросе, однако не все диалекты SQL поддерживают такую возможность.
Например, если в параметры скрипта
PHP:
$id = $_REQUEST['id'];
$res = mysqli_query("SELECT * FROM news WHERE id_news = $id");
SQL:
SELECT * FROM news WHERE id_news = 12;
INSERT INTO admin (username, password) VALUES ('Dark-Time', 'Life');
Методика атак типа внедрение SQL-кода
Поиск скриптов, уязвимых для атаки
На данном этапе злоумышленник изучает поведение скриптов сервера при манипуляции входными параметрами с целью обнаружения их аномального поведения. Манипуляция происходит всеми возможными параметрами:
- Данными, передаваемыми через методы POST и GET
- Значениями [HTTP-Cookie]
- HTTP_REFERER (для скриптов)
- AUTH_USER и AUTH_PASSWORD (при использовании аутентификации)
Аномальным поведением считается любое поведение, при котором страницы, получаемые до и после подстановки кавычек, различаются (и при этом не выведена страница о неверном формате параметров).
Наиболее частые примеры аномального поведения:
- выводится сообщение о различных ошибках;
- при запросе данных (например, новости или списка продукции) запрашиваемые данные не выводятся вообще, хотя страница отображается
Защита от атак типа внедрение SQL-кода
Для защиты от данного типа атак необходимо тщательно фильтровать входные параметры, значения которых будут использованы для построения SQL-запроса.
Фильтрация строковых параметров
Предположим, что код, генерирующий запрос (на языке программирования
Пожалуйста,
Вход
или
Регистрация
для просмотра содержимого URL-адресов!
), выглядит так:
Код:
statement := 'SELECT * FROM users WHERE name = "' + userName + '";';
Пожалуйста,
Вход
или
Регистрация
для просмотра содержимого URL-адресов!
, в том числе, для Пожалуйста,
Вход
или
Регистрация
для просмотра содержимого URL-адресов!
, требуется брать в Пожалуйста,
Вход
или
Регистрация
для просмотра содержимого URL-адресов!
все строковые параметры. В само́м параметре заменяют кавычки на \", апостроф на \', обратную косую черту на \\ (это называется «Пожалуйста,
Вход
или
Регистрация
для просмотра содержимого URL-адресов!
»). Это можно делать таким кодом:
Код:
statement := 'SELECT * FROM users WHERE name = ' + QuoteParam(userName) + ';';
Код:
function QuoteParam(s : string) : string;
{ на входе — строка; на выходе — строка в кавычках и с заменёнными спецсимволами }
var
i : integer;
Dest : string;
begin
Dest := '"';
for i:=1 to length(s) do
case s[i] of
'''' : Dest := Dest + '\''';
'"' : Dest := Dest + '\"';
'\' : Dest := Dest + '\\';
else Dest := Dest + s[i];
end;
QuoteParam := Dest + '"';
end;
PHP:
$query = "SELECT * FROM users WHERE user='" . mysqli_real_escape_string($user) . "';";
Возьмём другой запрос:
Код:
statement := 'SELECT * FROM users WHERE id = ' + id + ';';
Например, на
Пожалуйста,
Вход
или
Регистрация
для просмотра содержимого URL-адресов!
для противодействия таким инъекциям помогает код:
Код:
if TryStrToInt(id, id_int) then
statement := Format('SELECT * FROM users WHERE id =%0:d;', [id_int]);
PHP:
$query = 'SELECT * FROM users WHERE id = ' . (int)$id;
Для внесения изменений в логику выполнения SQL-запроса требуется внедрение достаточно длинных строк. Так, минимальная длина внедряемой строки в вышеприведённых примерах составляет 8 символов («1 OR 1=1»). Если максимальная длина корректного значения параметра невелика, то одним из методов защиты может быть максимальное усечение значений входных параметров.
Например, если известно, что поле id в вышеприведённых примерах может принимать значения не более 9999, можно «отрезать лишние» символы, оставив не более четырёх:
Код:
statement := 'SELECT * FROM users WHERE id = ' + LeftStr(id, 4) + ';';
Многие серверы баз данных поддерживают возможность отправки параметризованных запросов (подготовленные выражения). При этом параметры внешнего происхождения отправляются на сервер отдельно от самого запроса либо автоматически экранируются клиентской библиотекой. Для этого используются
- на Пожалуйста, Вход или Регистрация для просмотра содержимого URL-адресов!— свойство
[B]TQuery.Params[/B]
;
Код:
var
sql, param : string
begin
sql := 'select :text as value from dual';
param := 'alpha';
Query1.Sql.Text := sql;
Query1.ParamByName('text').AsString := param;
Query1.Open;
ShowMessage(Query1['value']);
end;
- на Пожалуйста, Вход или Регистрация для просмотра содержимого URL-адресов!— через
DBI::quote
илиDBI::prepare
; - на Пожалуйста, Вход или Регистрация для просмотра содержимого URL-адресов!— через класс
PreparedStatement
; - на Пожалуйста, Вход или Регистрация для просмотра содержимого URL-адресов!— свойство
SqlCommand.Parameters
; - на Пожалуйста, Вход или Регистрация для просмотра содержимого URL-адресов!—Пожалуйста, Вход или Регистрация для просмотра содержимого URL-адресов!(при работе сПожалуйста, Вход или Регистрация для просмотра содержимого URL-адресов!),
PDO
.