Автор: Питер Яворски.
Переводчик: Летающий дракон.
Лицензия: CC BY-NC-SA 4.0.
SQL-инъекции (SQLi) позволяют злоумышленникам внедрять SQL-запросы в целевую систему и получать доступ к её базам данных. Они обладают огромным потенциалом и часто становятся уязвимостями с высокой степенью риска, позволяя злоумышленникам выполнять все или некоторые операции CURD (создание, чтение, обновление, удаление) для получения информации из базы данных. Злоумышленники могут даже осуществлять удалённое выполнение команд.
Обычно SQLi-атаки возникают из-за неэкранированных входных данных, которые передаются на сайт и используются в качестве части запроса к базе данных. Пример такой атаки:
$name = $_GET['name'];
$query = "SELECT * FROM users WHERE name = $name";
Здесь значение, полученное от пользователя, напрямую вставляется в запрос к базе данных. Если пользователь введёт test' or 1=1
, запрос вернёт первую запись, где name = test or 1=1
, то есть первую строку. В других случаях вы можете получить:
$query = "SELECT * FROM users WHERE (name = $name AND password = 12345)";
Если вы используете тот же ввод, ваш запрос будет выглядеть следующим образом:
$query = "SELECT * FROM users WHERE (name = 'test' OR 1=1 AND password = 12345)";
В этом случае запрос будет вести себя немного иначе (по крайней мере, в MySQL). Мы получим все записи, где имя — test
или пароль — 12345
. Очевидно, что мы не достигли цели поиска первой записи в базе данных. Поэтому нам нужно игнорировать параметр пароля и использовать комментарии для этого, например, test' or 1=1;--
. Здесь мы добавляем точку с запятой для корректного завершения SQL-запроса и сразу после этого ставим два дефиса (и пробел), чтобы пометить всё остальное как комментарий. Это не будет выполнено. Результат будет таким же, как и в нашем первоначальном примере.
Описание:
Drupal — популярная система управления контентом, используемая для создания веб-сайтов, похожая на WordPress и Joomla. Она написана на PHP и основана на модулях, что позволяет добавлять новые функции через установку модулей на сайт Drupal. Сообщество Drupal создало более тысячи бесплатных модулей, включая электронную коммерцию, трёхстороннее наследование, контентные продукты и другие. Однако каждая установка Drupal включает в себя набор основных модулей, необходимых для работы платформы и требующих подключения к базе данных. Эти модули обычно называются ядром Drupal.
В 2014 году группа безопасности Drupal выпустила срочное обновление безопасности для ядра Drupal, обнаружив, что все сайты Drupal подвержены риску SQL-инъекций, которыми могут воспользоваться анонимные пользователи. Эта уязвимость позволяет злоумышленникам контролировать любой неообновлённый сайт Drupal.
Проблема заключается в том, что разработчик Drupal неправильно реализовал функцию обёртки для запросов к базе данных, которую злоумышленники могут использовать в своих целях. Более конкретно, Drupal использует PHP Data Objects (PDO) в качестве структуры для доступа к базе данных. Разработчик ядра Drupal написал код для вызова этих функций PDO, и любой другой разработчик, пишущий код для взаимодействия с базой данных Drupal, может использовать этот код. Это является наилучшей практикой в разработке программного обеспечения, поскольку она позволяет Drupal работать с различными типами баз данных (MySQL, Postgres и другими), устраняя сложность и обеспечивая стандартизацию.
Теперь проблема заключается в том, что Stefan Horst обнаружил ошибку в коде обёртки Drupal для передачи данных массива в SQL-запрос, который может быть использован злоумышленниками. Вот исходный код:
foreach ($data as $i => $value) {
[...]
$new_keys[$key . '_' . $i] = $value;
}
Можете ли вы найти ошибку (я тоже не могу)? Предпосылка разработчика заключается в том, что данные массива всегда содержат числовые ключи, такие как 0, 1, 2
и так далее ($i
— это значение). Поэтому они объединяют переменную $key
с $i
и присваивают ей значение $value
. Вот пример обычного запроса из функции db_query
в Drupal:
db_query("SELECT * FROM {users} WHERE name IN (:name)", array(':name'=>array('user1','user2')));
Здесь функция db_query
принимает запрос к базе данных SELECT * FROM {users} WHERE name IN (:name)
и заменяет заполнитель :name
значениями из предоставленного массива. В PHP, когда вы объявляете массив как array('value','value2',value3')
, он фактически создаёт [0 =>'value',1=>'value2',2=>'value3']
, где каждое значение можно получить по числовому ключу. Таким образом, :name
заменяется значениями массива. Вы получаете следующее:
SELECT * FROM users WHERE name IN (:name_0, :name_1)
Пока всё хорошо. Но когда вы получаете массив без числовых ключей, возникает проблема, например:
db_query("SELECT * FROM {users} where name IN (:name)",
array(':name'=>array('test) -- ' => 'user1','test' => 'user2')));
Здесь :name
— массив с ключами 'test) –', 'test'
Можете ли вы понять, почему это может потребовать некоторой хитрости? Когда Drupal получает его и обрабатывает массив для создания запроса, мы получаем:
SELECT * FROM users WHERE name IN (:name_test) -- , :name_test)
Видите, почему здесь может потребоваться некоторая хитрость? Давайте пройдёмся по нему ещё раз. На основе описанного выше цикла foreach
Drupal перебирает каждый элемент массива. Итак, для первого цикла $i = test) –
и $value = user1
. Теперь $key
— это заполнитель (:name)
, и после объединения с $i
мы получаем name_test) –
. Для второго цикла $i = test
и $value = user2
, поэтому после объединения $key
и $i
получаем name_test
, что приводит к заполнителю :name_test
, равному user2
.
Теперь, зная это, факт использования Drupal оболочки для PHP PDO Object становится актуальным, поскольку PDO допускает множественные запросы. Таким образом, злоумышленник может передать злонамеренный ввод, такой как фактический SQL-запрос, для создания учётных записей администратора для любого ключа массива, который интерпретируется и выполняется как множественный запрос.
Важный вывод
SQLi кажется сложнее обнаружить, по крайней мере, на основе отчётов, найденных для этой книги. Этот пример интересен тем, что он не связан с отправкой одинарных кавычек и прерыванием запроса. Вместо этого он полностью связан с тем, как код Drupal обрабатывает массивы, передаваемые внутренним функциям. Это нелегко обнаружить с помощью чёрного ящика (где вы не взаимодействуете с кодом). Важный вывод здесь заключается в том, чтобы искать возможности для изменения формата ввода, отправляемого на сайт, поэтому при получении параметра
?name
попробуйте отправить массив, подобный?name[]
, чтобы посмотреть, как сайт обрабатывает его. Это также может не привести к SQLi, но может вызвать другое интересное поведение.
SQLi имеет огромное значение и опасность для сайтов. Обнаружение таких уязвимостей может привести к полному контролю над сайтом с точки зрения операций CURD. В некоторых случаях это может расшириться до удалённого выполнения кода. Пример Drupal фактически является одним из таких случаев, демонстрируя способность злоумышленников выполнять код через уязвимости. При поиске их следует обращать внимание не только на возможность передачи неэкранированных одинарных и двойных кавычек в запросах, но и на вероятность предоставления данных неожиданным образом, например, путём отправки массива параметров в POST-данных.
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )