Код:
select user,password,file_priv from user
user - имя пользователя,
passsword - 256 битный хеш пароля пользователя, начиная с версии 4.1 - хеш 640 битный. Столбец password, из соображений безопасности хранит ТОЛЬКО
хеш.
file_priv - опция отвечает за то, что пользователь имеет привелегию file.
Если это удастся, опять таки из-хза неправильной настройки сервера,
то помимо любых операций с доступной базой данных, взломщик получает возможность чтения любого файла в системе, доступного для самого mysql сервера.
Для этого можно использовать функцию load_file("ПОЛНОЕ ПУТЬ К ФАЙЛУ"). При достаточных правах она возвратит содержимое файла (если файл отсутствует,
или на его чтение у mysql нет прав, в ответе будет ошибка), в противном случае функция возвращает null. Если вывод сообщений об ошибках отсутствует,
то можно поступить так:
Код:
select if(load_file("blalala") is null,1,2);
Если в ответе будет 1, то это означает о невозможности использования load_file().
С ещё большим успехом можно применить конструкцию select * into outfile "ПОЛНЫЙ ПУТЬ К СОЗДАВАЕМОМУ ФАЙЛУ", которая срабатывает очень редко -
для этого нужно иметь привелегии root. Так можно получить например веб-шелл.
В отличии от других субд, MySQL, до версии 5, не позволяло получить доступ к именам таблиц и столбцов в определенной БД, тогда как в MS SQL,
например, это делалось возможным благодаря представлениям INFORMATION_SCHEMA.TABLES и INFORMATION_SCHEMA.COLUMNS.
В новой версии MySQL 5 появилась возможность доступа к системной базе INFORMATION_SCHEMA. Другими словами, теперь, определив версию sql сервера
с помощью функции version() или подключившись на 3306 порт (по-умолчанию), можно не подбирать имена таблиц/столбцов наугад, а с помощью таблицы
INFORMATION_SCHEMA.COLUMNS получить имена ВСЕХ доступных таблиц и соответствующих столбцов, так:
Код:
SELECT TABLE_SCHEMA,COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME="ИМЯ";
Далее, может оказаться, что таблица с интересующем нас именем находится в другой базе, имя которой мы не знаем, получить его можно так:
Код:
SELECT TABLE_SCHEMA FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME="ИМЯ";
Иногда, может оказаться так, что база данных использует не стандартную кодировку для хранения строк, для преобразования в нужный формат
используйте функцию cщтмуке(), для приведения кодировок и типов:
1) convert(lala,TYPE), TYPE - любой из стандартных типов MySQL : INTEGER, varchar и т.д.
2) convert("stroka" using cp1251) - возвратит строку "stroka" в нужно вам кодировке.
Если есть доступ к таблице mysql.user или взломщик уже имеет пароль (пароль к хешу востановлен) нужного ему пользователя он может подключиться
любым mysql клиентом к вашей базе, конечно если это позволяют привилегии. Самым главным препядствием к подключению является адрес клиента, маска
доступных к подключению адресов хранится в столбце таблицы mysql.user host. Символ % означает любую последовательность символов, то есть
host="%.mail.ru" позволит подключится к базе только если клиент находится на любом домене mail.ru, включая его самого. Таким образом чтобы иметь
полный доступ к базе с любого удаленного адреса поле host для данного пользователя должно иметь значение "%". В противном случае взломщику
потребуется доступ к серверу адрес которого удовлетворяет маске или же на уязвимом сервере должна быть утилита типа phpmyadmin.
2) MS SQL
Доступны представления INFORMATION_SCHEMA.COLUMNS и INFORMATION_SCHEMA.TABLES, про применения см 1
Поддержка раздленых запросов существенно упрощает жизнь взломщику, достаточно поставить ;КОД--
Имея определенные права вы можете выполнять команды на сервере так:
Код:
exec master..xp_cmd_shell "dir>ФАЙЛ"
Можно прочитать файл так:
Код:
create table test(lala varchar(3000));bulk insert test from "c:/windows/ФАЙЛ"
Затем, можно получить содержмое файла:
Код:
select lala from test;drop table test
Оператор drop уничтожит ранее созданную таблицу.
Бывает так, что веб программисты защищают сервер проверкой на наличие слов типа UNION, SELECT и т.п. Но выолнить комманду это не мешает:
Код:
;exec ("UPDA"+"TE users"+"SET password=123456")
Если уязвимый скрипт выводит сообщение об ошибке, то это сильно упрощает дело взломщику, например:
Код:
select news_id from news where id=333 union select name from users
Если news_id имеет тип INT, То это вызовет сообщение об ошибке т.к. name будет иметь другой тип, например varchar. Вследствии чего,
в ошибке будет содержаться информация о невозможности приведения строки "admin_login" к целому типу. Так, можно получить и пароль любого
пользователя. В противном случае, если вывод сообщений об ошибках отсутствует, придется перебирать коды символов имени администратора.
Допустимо применение функции convert().
3) Oracle
Конкатенцаия строк "stroka1"||"stroka2".
Во отличии от предыдущих серверов баз данных конструкция select columnname; недопустима - нужно обязательно укзаывать имя таблицы.
Существует метатаблица ALL_TAB_COLUMNS, в которой основные поля: owner, table_name, column_name, data_type.
Вместо TOP в MSSQL, и LIMIT в MySQL используется конструкция where rownum = 1 или in (1,2).
Обеспечение собственной безопасности
Теперь остался самый главный вопрос - как же защитить сервер от sql-injection? Ответ прост - фильтровать все переменные приходящие от клиента,
конкретнее - проверять все начиная от значений передаваемых по методу GET кончая проверкой cookies. Например, если пердается число, то мы никого
не обидем если сразу сделаем преобразование intval(), а если строка, то достаточно вырезать ' и " при обычном сравнении и дополнительно _,% при работе например с предложением Like или в любых других, использующих спец символы. Не следует забывать и про опасность нулевого байта в запросе - его так же нужно фильтровать. Ну и конечно не ставить простых администраторских
паролей, но это уже к теме не относится. Ставить привелегии только при необходимости, для каждой части выделять отдельную БД. Очень полезно хранить
пароли в зашифрованном виде, например в md5. Также правильная архитектура проекта поможет избежать взлома, сделайте отдельный модуль отвечающий за
безопасность, фильтруйте данные до того как они попадут в функцию отправки sql запроса и тогда 95% безопасности будет обеспечено.
Заключение
К сожалению в этой статье сожержится чрезвычайно мало информации, многое мыслей осталось у меня в голове, поэтому эта статья будет по мере
возможностей пополняться. Все свои замечания и предложения на
zaco@yandex.ru.
При подготовке статьи были использованны материалы :
http://mysql.ru
http://sql.ru
podkashey
(c) ZaCo