SQL-инъекции ¶
Многие веб-разработчики даже не догадываются, что SQL-запросы могут быть подделаны, и считают, что SQL-запросы всегда достоверны. На самом деле поддельные запросы могут обойти ограничения доступа, стандартную проверку авторизации, а некоторые виды запросов могут дать возможность выполнять команды операционной системы.Прямое внедрение вредоносных инструкций в SQL-запросы - это методика, в которой взломщик создает или изменяет текущие SQL-запросы для отображения скрытых данных, их изменения или даже выполнения опасных команд операционной системы на сервере базы данных. Атака выполняется на базе приложения, строящего SQL-запросы из пользовательского ввода и статических параметров. Следующие примеры, к сожалению, построены на реальных фактах.
Благодаря отсутствию проверки пользовательского ввода и соединению с базой данных под учетной записью суперпользователя (или любого другого пользователя, наделенного соответствующими привилегиями), взломщик может создать еще одного пользователя БД с правами суперпользователя.
Пример #1
Постраничный вывод результата... и создание суперпользователя в PostgreSQL
Обычно пользователи кликают по ссылкам 'вперед' и 'назад', вследствие чего значение
переменной $offset заносится в
<?php
$offset
= $argv[0]; // внимание, нет проверки вводимых данных!$query = "SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET $offset;";$result = pg_query($conn, $query);?>
URL. Скрипт ожидает, что $offset - десятичное число. Однако, взломщик может попытаться взломать систему, присоединив к
URL дополнительную строку, обработанную функцией urlencode():
0; insert into pg_shadow(usename,usesysid,usesuper,usecatupd,passwd) select 'crack', usesysid, 't','t','crack' from pg_shadow where usename='postgres'; --
Замечание:Еще один вероятный способ получить пароли учетных записей в БД - атака страниц, предоставляющих поиск по базе. Взломщику нужно лишь проверить, используется ли в запросе передаваемая на сервер и необрабатываемая надлежащим образом переменная. Это может быть один из устанавливаемых на предыдущей странице фильтров, таких как WHERE, ORDER BY, LIMIT и OFFSET, используемых при построении запросов SELECT. В случае, если используемая вами база данных поддерживает конструкцию UNION, взломщик может присоединить к оригинальному запросу еще один дополнительный, для извлечения пользовательских паролей. Настоятельно рекомендуем использовать только зашифрованные пароли.
Часто используемой техникой для игнорирования SQL-парсером оставшейся части запроса является использование --, означающей комментарий.
Пример #2
Листинг статей... и некоторых паролей (для любой базы данных)
Статическая часть запроса может комбинироваться с другим
SELECT-запросом, который выведет все пароли:
<?php
$query
= "SELECT id, name, inserted, size FROM products
WHERE size = '$size'";$result = odbc_exec($conn, $query);?>
' union select '1', concat(uname||'-'||passwd) as name, '1971-01-01', '0' from usertable; --
Команды UPDATE также могут использоваться для атаки. Опять же, есть угроза разделения инструкции на несколько частей и присоединения дополнительного запроса. Также взломщик может видоизменить выражение SET. В этом случае потенциальному взломщику необходимо обладать некоторой дополнительной информацией о структуре базы данных для успешного манипулирования запросами. Эту информацию можно получить, проанализировав используемые в форме имена переменных, либо просто перебирая все наиболее распространенные варианты названия соответствующих полей (а их не так уж и много).
Пример #3
От восстановления пароля... до получения дополнительных привилегий (для любой базы данных)
Но злоумышленник может ввести значение
' or uid like'%admin%' для переменной $uid для
изменения пароля администратора или просто присвоить переменной $pwd значение
hehehe', trusted=100, admin='yes
для получения дополнительных привилегий. При выполнении запросы переплетаются:
<?php
$query = "UPDATE usertable SET pwd='$pwd' WHERE uid='$uid';";?>
<?php// $uid: ' or uid like '%admin%$query = "UPDATE usertable SET pwd='...' WHERE uid='' or uid like '%admin%';";// $pwd: hehehe', trusted=100, admin='yes$query = "UPDATE usertable SET pwd='hehehe', trusted=100, admin='yes' WHERE
...;";?>
Пример #4 Выполнение команд операционной системы на сервере (для базы MSSQL)
Если взломщик введет значение
a%' exec master..xp_cmdshell 'net user test testpass /ADD' --
для переменной $prod, тогда запрос $query
будет выглядеть так:
<?php
$query
= "SELECT * FROM products WHERE id LIKE '%$prod%'";$result = mssql_query($query);?>
<?php
$query
= "SELECT * FROM products
WHERE id LIKE '%a%'
exec master..xp_cmdshell 'net user test testpass /ADD' --%'";$result = mssql_query($query);?>
Замечание:Авторство изображения принадлежит » xkcd
Некоторые приведенные в этой главе примеры касаются конкретной базы данных. Это не означает, что аналогичные атаки на другие программные продукты невозможны. Работоспособность вашей базы данных может быть нарушена каким-либо другим способом.
Способы защиты ¶
Хотя по-прежнему очевидно, что взломщик должен обладать по крайней мере некоторыми знаниями о структуре базы данных чтобы провести успешную атаку, получить эту информацию зачастую очень просто. Например, если база данных является частью open-source или другого публично доступного программного пакета с инсталляцией по умолчанию, эта информация является полностью открытой и доступной. Эти данные также могут быть получены из закрытого проекта, даже если он закодирован, усложнен, или скомпилирован, и даже из вашего личного кода через отображение сообщений об ошибках. К другим методам относится использование распространенных (легко угадываемых) названий таблиц и столбцов. Например, форма логина, которая использует таблицу 'users' c названиями столбцов 'id', 'username' и 'password'.Большинство успешных атак основывается на коде, написанном без учета соответствующих требований безопасности. Не доверяйте никаким вводимым данным, особенно если они поступают со стороны клиента, даже если это списки в форме, скрытые поля или куки. Первый приведенный пример показывают, как подобные запросы могут привести к катастрофе.
- Никогда не соединяйтесь с базой данных, используя учетную запись владельца базы данных или суперпользователя. Всегда старайтесь использовать специально созданных пользователей с максимально ограниченными правами.
- используйте подготовленные выражения с привязанными переменными. Эта возможность предоставляется расширениями PDO, MySQLi и другими библиотеками.
- Всегда проверяйте введенные данные на соответствие ожидаемому типу. В PHP есть множество функций для проверки данных: начиная от простейших функций для работы с переменными и функций определения типа символов (таких как is_numeric() и ctype_digit() соответственно) и заканчивая Perl-совместимыми регулярными выражениями.
-
В случае, если приложение ожидает цифровой ввод, примените функцию
ctype_digit() для проверки введенных данных, или
принудительно укажите их тип при помощи settype(),
или просто используйте числовое представление при помощи функции
sprintf().
Пример #5 Более безопасная реализация постраничной навигации
<?php
settype
($offset, 'integer');$query = "SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET $offset;";// обратите внимание на формат %d, использование %s было бы бессмысленно$query = sprintf("SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET %d;",
$offset);?> - Если на уровне базы данных не поддерживаются привязанные переменные, то всегда экранируйте любые нечисловые данные, используемый в запросах к БД при помощи специальных экранирующих функций, специфичных для используемой вами базы данных (например, mysql_real_escape_string(), sqlite_escape_string() и т.д.). Общие функции такие как addslashes() полезны только в определенных случаях (например MySQL в однобайтной кодировке с отключенным NO_BACKSLASH_ESCAPES), поэтому лучше избегать их использование.
- Ни в коем случае не выводите никакой информации о БД, особенно о ее структуре. Также ознакомьтесь с соответствующими разделами документации: "Сообщения об ошибках" и "Функции обработки и логирования ошибок".
- Вы можете использовать хранимые процедуры и заранее определенные курсоры для абстрагированной работы с данными, не предоставляя пользователям прямого доступа к данным и представлениям, но это решение имеет свои особенности.
Комментариев нет:
Отправить комментарий