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

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

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

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

Файлы: 1 файл

ЯП.docx

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

       Ну, и как говорилось ранее, вместо нуля или единицы можно вставлять  произвольные булевы условия, значение которых MySQL приведет к целому.

       Примеры http://localhost/test2.php?order=(-id*(2=1)), или 

       http://localhost/test2.php?order=(-id*(‘abc’=’abc’))

       Эти булевы условия могут содержать  в том числе и значения других столбцов таблиц.

       http://localhost/test2.php?order=(-id*(pass+like+’a%’))

       http://localhost/test2.php?order=(-id*(pass+like+’b%’))

       и так далее.

       Теперь  осталось научиться различать, отгадали мы или нет. В этом случае, в случае, если пароль не удовлетворяет введенному условию, то значение функции по которой  делается упорядочивание будет равно  нулю для таких записей.

       В случае, если пароль для некоторых  записей удовлетворяет введенному условию, то для таких записей  упорядочивание произойдет по значению –id, которое всегда меньше нуля.

       Если  нет уверенности в том, что  значение id всегда больше нуля, то можно  поступить след образом:

       http://localhost/test2.php?order=(-(abs(id)+1)*(pass+like+’b%’))

       Теперь, функция, по которой происходит упорядочивание всегда меньше нуля для записей, для  которых пароль удовлетворяет условию, и равен нулю, для которых условие  для пароля неверно. Учитывая, что  упорядочивание происходит по возрастанию, то все записи, для которых условие  окажется верным, окажутся вверху списка.

       Если  нет гарантии, что упорядочивание действительно происходит по возрастанию, можно добавить ключевое слово ASK, и, возможно, обрезать оставшуюся часть  запроса, символом /*, или %00.

       Напомним, что /* обозначает открытие комментария. MySQL нормально реагирует на незакрытые комментарии в запросе. %00 же колирует символ с котом ноль, который в  Си подобных языках обозначает конец  строки, и функция MySQL API mysql_query(), посчитает  этот символ обычным концом строки, а, значит и запроса.

       Пример: http://localhost/test2.php?order=(-(abs(id)+1)*(pass+like+’b%’))+ASK+/*

       И так, допустим исходное упорядочивание, по –id, было таким:

       5 user5

       4 user4

       3 user3

       2 admin

       1 root

       и, после запроса http://localhost/test2.php?order=(-id*(pass+like+’b%’)) стало таким:

       4 user4

       2 admin

       1 root

       3 user3

       5 user5, то этот результат следует  интерпретировать, как то, что пароли  у user4 и admin начинаются на символ b.

       Аналогичным образом подбирается и весь пароль.

       Если  нас интересует пароль любого пользователя, то положительным результатом мы считаем, если в “вылезшем наверх”  списке пользователей присутствует хотя бы один пользователь. Если же нас  интересует пароль, какого то конкретного  пользователя, то положительным результатом  мы считаем то, что, этот пользователь присутствует в вылезшем наверх списке.

       В качестве основы этого метода лежит  упорядочивание по произведению двух функций – отрицательной для  всех записей основной функции, и  сигнальной булевой функции. Знак минус  взят для того, чтобы интересующие нас результаты появлялись в начале списка, а не в конце, те просто для  удобства.

       В большинстве случаев, в качестве основной функции можно взять (-id), или (-(abs(id)+1)), однако, это может быть и любая другая функция, возвращающая разные значения для разных записей  в таблице. Например, это может  быть длина некоторого текстового поля, или даже комбинации некоторых функций  от некоторых полей.

       В этом примере, аналогичным образом  можно использовать дихотомический поиск, и функцию char() вместо строк-констант.

       PHP SHELL, или инъекция после limit

       Действительно, почти безнадежным делом в  инъекции в MySQL 3.x может стать то, что инъекция возможна после ключевого  слова limit. Это вероятно в тех ситуациях, когда скрипт принимает и, не фильтруя, вставляет в запрос параметр, отвечающий за количество или смещение выведенных записей (например, номер страницы, количество записей на странице).

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

       Конструкция into outfile в руководстве MySQL описана  идущей сразу после select, однако, как  показывает практика, ее можно поставить  и в самый конец запроса, после limit. Таким образом, единственное, что  сможет сделать хакер в такой  ситуации, это попытаться сохранить  результаты запроса в файл с произвольным месторасположением и именем.

       Напомним, что имеется несколько ограничений.

       Файл  не должен существовать на диске 

       У пользователя MySQL должны быть права  на работу с файлами (file_priv)

       Целевая директория должна быть доступна на запись всем пользователям.

       Имя файла должно быть с полным путем.

       Имя файла должно быть строкой в кавычках. Использования выражений не допускается 

       Таким образом, если хакер знает полный путь до веб каталога на сервере, знает  имя папки, в которую разрешена  запись всем пользователям (такую папку  он сможет найти и перебором), то нападающий сможет вывести результаты запроса в файл, в том числе  с расширением, сопоставленным с  некоторым интерпретатором, например PHP.

       Однако, как внедрить в результат запроса  злонамеренные данные, например PHP Shell код? Ответ на этот вопрос не очевиден, и дать на него ответ должен сам  нападающий, исследуя конкретную систему.

       Так, например, если инъекция после limit возможна в скрипте, выводящем сообщения  на форуме, в параметре, отвечающим за номер страницы, то, вероятно, для  положительного результата следует  добавить сообщение на форуме, содержащее PHP Shell код, и затем произвести сохранение результатов запроса в файл.

       Запрос  может быть примерно таким http://localhost/test3?page=34+into+outfile+’/path/to/web/banners/cmd.php’, где на 34-ую страницу форума добавлено  сообщение типа <? System($_GET[‘cmd’]) ?>

       В случае, если, кроме того, на сервере  присутствует уязвимость типа local php source code injection, то практически в любом  случае таким образом можно создать  файл с PHP shell кодом в любой общедоступной  на запись директории, с последующем  подцеплением этого файла в уязвимости типа PHP инъекция. Например, директория /tmp/, обычно доступна на запись всем пользователям.

       Стоит еще раз заметить, что в качестве имени файла нельзя использовать выражения, а, значит, и привычный  фокус с char(), не пройдет в случае, если кавычки фильтруются.

       Стоит отметить, что фокус с into outfile будет  возможен и в других двух вышеописанных  случаях, и эксплуатироваться он будет примерно также.

       Внимание.

       Все приведенные HTTP запросы в статье – это всего лишь примеры, демонстрирующие  принцип. В реальных системах запросы  могут выглядеть иначе, иметь  более сложный вид, однако принцип  сохраниться тот же.

       Кроме того

       Я не стал описывать в статье подробно некоторые другие довольно часто  встречаемые ошибки в скриптах, которые  довольно подробно описаны и в  других источниках.

       Например, если при сравнении пароля с паролем  в БД используется функция like а не =, то значение % совпадет с любым  паролем.

       Кроме того, если инъекция происходит вследствие слабой фильтрации имени пользователя или пароля, то можно авторизоваться в системе под любым пользователем, введя примерно следующий пароль (или имя пользователя) ‘ OR 1 /*

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

       В первом случае результаты сервер будет  отдавать со значительной временной  задержкой, во втором, попытки новых  соединения с сервером будут отсекаться.

       Функция BenchMark в MySQL используется для того чтобы  вычислить заданное выражение заданное количество раз. Так например benchamrk(1000000, md5(current_time)) в зависимости от вычислительных мощностей сервера будет вычисляться  около 30-60 секунд. Если же функцию сделать  вложенной: benchamrk(1000000, benchamrk(1000000, md5(current_time))), то вычисление такой функции займет очень много времени на сервере  любой конфигурации.

       Теперь  осталось только внедрить эту функцию  в SQL запрос, так чтобы в нем  не произошло ошибки:

       http://localhost/test.php?id=1-benchamrk(1000000,benchamrk(1000000, md5(current_time))), или

       http://localhost/test2.php?order=(benchamrk(1000000,benchamrk(1000000, md5(current_time))))

       Теперь, для эффективной DoS атаки достаточно сделать серию таких HTTP запросов на сервер. Дожидаться ответа не обязательно, достаточно, чтобы запрос дошел до сервера. Серию таких запросов можно  организовать как вручную, через  броузер, так и скриптом.

       В зависимости от мощности сервера, будет  достаточно от нескольких десятков до нескольких сотен таких запросов.

       Следует учесть, что для эффективной атаки, результат запроса не должен нигшде кешироваться. Для того, чтобы предотвратить  кэширование на прокси сервер, в  каждый запрос можно добавлять случайную  величину:

       http://localhost/test.php?id=1-benchamrk(1000000,benchamrk(1000000, md5(current_time)))-46323279

       Заключение

       Многие  в настоящее время считают, что  если они используют MySQL сервер третей версии, то они защищены от уязвимости типа SQL инъекция. Я всего лишь показал, что это не так :)

       Что может сделать взломщик используя SQL injection 
 
С каждым днем все больше скриптов используют базы данных, все больше хостингов доверяют пароли своих клиентов SQL-базам, все больше популярных сайтов переходит на публичные форумы и движки, работающие с MySQL. Но далеко не все ясно представляют себе, насколько опасным может быть непродуманное использование MySQL в скриптах. 
 
Как это есть? 
 
Без знаний основ языка SQL трудно что-либо понять. Прежде всего разберемся, в чем заключается суть атаки типа SQL injection. К примеру, на атакуемом сервере стоит следующий PHP-скрипт, который на основе поля category_id делает выборку заголовков статей из таблицы articles и выводит их пользователю: 
 
//подключаемся к MySQL 
 
mysql_connect($dbhost, $dbuname, $dbpass) or die(mysql_error()); 
 
mysql_select_db($dbname) or die(mysql_error()); 
 
$cid=$_GET["cid"]; 
 
$result=mysql_query("SELECT article_id, article_title FROM articles where category_id=$cid"); // <- уязвимый запрос 
 
while( $out = mysql_fetch_array( $result)): 
 
echo "Статья: ".$out['article_id']." ".$out['article_title']."<br>"
 
endwhile; 
 
//выводим результат в виде списка 
 
В переводе с языка MySQL запрос звучит так: "ВЫБРАТЬ ид_статей, заголовки_статей ИЗ таблицы_статей ГДЕ ид_категории равно $cid". На первый взгляд все верно, по ссылке типа http://serv.com/read.php?cid=3 скрипт работает нормально и выводит пользователю список статей, принадлежащих категории 3. 
 
Но что если пользователь - никакой не пользователь, а обыкновенный хакер? Тогда он сделает запрос http://serv.com/read.php?cid=3' (именно с кавычкой) и получит что-то вроде: Warning: mysql_fetch_array(): supplied argument is not a valid MySQL result resource in /usr/local/apache/htdocs/read.php on line 14. 
 
Почему ошибка? Посмотрим, что запросил PHP у MySQL. Переменная $cid равна 1', тогда запрос принимает неверный с точки зрения MySQL вид: SELECT article_id, article_title FROM articles where category_id=1'. При синтаксической ошибке в запросе MySQL отвечает строкой "ERROR 1064: You have an error in your SQL syntax...". PHP не может распознать этот ответ и сообщает об ошибке, на основе которой хакер может судить о присутствии уязвимости типа SQL Injection. Очевидно, что злоумышленник получит возможность задавать переменной $cid любые значения ($cid=$_GET[cid]) и, следовательно, модифицировать запрос к MySQL. Например, если $cid будет равна "1 OR 1" (без кавычек в начале и в конце), то MySQL выдаст все записи, независимо от category_id, так как запрос будет иметь вид (..) where category_id=1 OR 1. То есть либо category_id = 1 (подойдут лишь записи с category_id, равными 1), либо 1 (подойдут все записи, так как число больше нуля - всегда истина). 
 
Только что описанные действия как раз и называются SQL Injection - иньекция SQL-кода в запрос скрипта к MySQL. С помощью SQL Injection злоумышленник может получить доступ к тем данным, к которым имеет доступ уязвимый скрипт: пароли к закрытой части сайта, информация о кредитных картах, пароль к админке и т.д. Хакер при удачном для него стечении обстоятельств получит возможность выполнять команды на сервере. 
 
Как атакуют? 
 
Классический пример уязвимости типа SQL Injection - следующий запрос: SELECT * FROM admins WHERE login='$login' AND password=MD5('$password'). 
 
Допустим, он будет проверять подлинность введенных реквизитов для входа в админскую часть какого-нибудь форума. Переменные $login и $password являются логином и паролем соответственно, и пользователь вводит их в HTML-форму. PHP посылает рассматриваемый запрос и проверяет: если количество возвращенных от MySQL записей больше нуля, то админ с такими реквизитами существует, а пользователь авторизуется, если иначе (таких записей нет и логин/пароль неверные) - пользователя направят на fsb.ru. 
 
Как взломщик использует SQL Injection в этом случае? Все элементарно. Злоумышленнику требуется, чтобы MySQL вернул PHP-скрипту хотя бы одну запись. Значит, необходимо модифицировать запрос так, чтобы выбирались все записи таблицы независимо от правильности введенных реквизитов. Вспоминаем фишку с "OR 1". Кроме того, в MySQL, как и в любом языке, существуют комментарии. Комментарии обозначаются либо --комментарий (комментарий в конце строки), либо /*комментарий*/ (комментарий где угодно). Причем если второй тип комментария стоит в конце строки, закрывающий знак '*/' необязателен. Итак, взломщик введет в качестве логина строку anyword' OR 1/*, а в качестве пароля - anyword2. Тогда запрос принимает такой вид: SELECT * FROM admins WHERE login='anyword' OR 1/* AND password=MD5('anyword2'). А в переводе на человеческий язык: ВЫБРАТЬ все ИЗ таблицы_admins ГДЕ логин равен 'anyword' ИЛИ 1, а остальное воспринимается как комментарий, что позволяет отсечь ненужную часть запроса. В результате MySQL вернет все записи из таблицы admins даже независимо от того, существует админ с логином anyword или нет, и скрипт пропустит хакера в админку. Такая уязвимость была обнаружена, например, в Advanced Guestbook. Она позволяла войти в администраторскую часть не зная пароля и внутри нее читать файлы. Но SQL Injection этого типа обычно не позволяют злоумышленнику получить данные из таблицы. 
 
Union и MySQL версии 4 
 
Вернемся к скрипту получения заголовков статей. На самом деле он позволяет взломщику получить гораздо больше, чем список всех статей. Дело в том, что в MySQL версии 4 добавлен новый оператор - UNION, который используется для объединения результатов работы нескольких команд SELECT в один набор результатов. Например: SELECT article_id, article_title FROM articles UNION SELECT id, title FROM polls. В результате MySQL возвращает N записей, где N - количество записей из результата запроса слева плюс количество записей из результата запроса справа. И все это в том порядке, в каком идут запросы, отделяемые UNION. 
 
Но существуют некоторые ограничения по использованию UNION: 
 
1. число указываемых столбцов во всех запросах должно быть одинаковым: недопутимо, чтобы первый запрос выбирал, например, id, name, title, а второй только article_title; 
 
2. типы указываемых столбцов одного запроса должны соответствовать типам указываемых столбцов остальных запросов: если в одном запросе выбираются столбцы типа INT, TEXT, TEXT, TINYTEXT, то и в остальных запросах должны выбираться столбцы такого же типа и в таком же порядке; 
 
3. UNION не может идти после операторов LIMIT и ORDER. 
 
Так как же UNION может стать пособником злоумышленника? В нашем скрипте присутствует запрос "SELECT article_id, article_title FROM articles where category_id=$cid". Что мешает хакеру, используя SQL injection, вставить еще один SELECT-запрос и выбрать нужные ему данные? Правильно: ничего! 
 
Допустим, цель хакера - получить логины и пароли всех авторов, которые могут добавлять статьи. Есть скрипт чтения списка статей http://serv.com/read.php?cid=1, подверженный SQL injection. Первым делом хакер узнает версию MySQL, с которой работает скрипт. Для этого он сделает следующий запрос: http://serv.com/read.php?cid=1+/*!40000+AND+0*/. Если скрипт вернет пустую страницу, значит, версия MySQL >= 4. Почему именно так? Число 40000 - версия MySQL, записанная без точек. Если версия, которая стоит на сервере, больше или равна этому числу, то заключенный в /**/ код выполнится как часть запроса. В результате ни одна запись не подойдет под запрос и скрипт не вернет ничего. Зная версию MySQL, хакер сделает вывод о том, сработает фишка с UNION или нет. В случае если MySQL третьей версии, фишка работать не будет. В нашем случае MySQL >= 4 и злоумышленник все-таки воспользуется UNION. 
 
Для начала взломщик составит верный UNION-запрос, то есть подберет действительное количество указываемых столбцов, которое бы совпало с количеством указываемых столбцов левого запроса (вспоминай правила работы с UNION). Хакер не имеет в распоряжении исходников скрипта (если, конечно, скрипт не публичный) и поэтому не знает, какой именно запрос шлет скрипт к MySQL. Придется подбирать вручную - модифицировать запрос вот таким образом: http://serv.com/read.php?cid=1+UNION+SELECT+1. И тут о своем присутствии объявит ошибка, так как количество запрашиваемых столбцов не совпадает. Хакер увеличивает количество столбцов еще на единицу: http://serv.com/read.php?cid=1+UNION+SELECT+1,2 - получает список статей из категории 1, а также в самом конце две цифры: 1 и 2. Следовательно, он верно подобрал запрос. 
 
Посмотрим на модифицированный запрос от PHP к MySQL: SELECT article_id, article_title FROM articles where category_id=1 UNION SELECT 1,2. В ответ MySQL возвращает результат первого SELECT (список статей) и результат второго SELECT - число "1" в первом столбце и "2" во втором столбце (SELECT+1,2). Другими словами, теперь, подставляя вместо '1' и '2' реальные имена столбцов из любой таблицы, можно будет заполучить их значения. 
 
Составив верный SELECT+UNION запрос, хакер постарается подобрать название таблицы с нужными ему данными. Например, таблица с данными пользователей будет, скорее всего, называться users, Users, accounts, members, admins, а таблица с данными о кредитных картах - cc, orders, customers, orderlog и т.д. Для этого злоумышленник сделает следующий запрос: http://serv.com/read.php?cid=1+UNION+SELECT+1,2+FROM+users. И если таблица users существует, то PHP-скрипт выполнится без ошибок и выведет список статей плюс '1 2', иначе - выдаст ошибку. Так можно подбирать имена таблиц до тех пор, пока не будет найдена нужная. 
 
В нашем случае "нужная" таблица – это authors, в которой хранятся данные об авторе: имя автора, его логин и пароль. Теперь задача хакера - подобрать правильные имена столбцов с нужными ему данными, чаще всего с логином и паролем. Имена столбцов он станет подбирать по аналогии с именем таблицы, то есть для логина столбец, скорее всего, будет называться login или username, а для пароля - password, passw и т.д. Запрос будет выглядеть так: http://serv.com/read.php?cid=1+UNION+SELECT+1,login+from+authors. 
 
Почему хакер не стал вставлять имя столбца вместо единицы? Ему нужна текстовая информация (логин, пароль), а в нашем случае в левом запросе SELECT на первом месте идет article_id, имеющий тип INT. Следовательно, в правом запросе хакер не может ставить на первое место имя столбца с текстовой информацией (правила UNION). 
 
Итак, выполнив запрос http://serv.com/read.php?cid=1+UNION+SELECT+1,login+from+authors, взломщик находит список логинов всех авторов, а подставив поле password - список паролей. И получает желанные логины и пароли авторов, а админ сервера – подмоченную репутацию. Но это только в нашем примере Фортуна улыбнулась злоумышленнику так широко: он быстро подобрал количество столбцов, а в реальной жизни количество столбцов может достигать 30-40. 
 
UNION и нюансы 
 
Теперь рассмотрим некоторые ситуации, в которых использование UNION затруднено по тем или иным причинам. 
 
Ситуация 1 
 
Левый запрос возвращает лишь числовое значение. Что-то вроде SELECT code FROM artciles WHERE id = $id. Что будет делать хакер? Средства MySQL позволяют проводить различные действия над строками, к примеру, выделение подстроки, склеивание нескольких строк в одну, перевод из CHAR в INT и т.п. Благодаря этим функциям хакер имеет возможность выудить интересующую его информацию по одному символу. К примеру, требуется достать пароль из таблицы admins, используя приведенный выше запрос. Чтобы получить ASCII-код первого символа пароля, сделаем следующий запрос к скрипту: http://127.0.0.1/read.php?cid=1+union+select+ASCII(SUBSTRING(password,1,1))+from+admins. Функция SUBSTRING(name,$a,$b) в MySQL выделяет $b символов из значения столбца name начиная с символа под номером $a. Функция ASCII($x) возвращает ASCII-код символа $x. Для получения последующих символов следует просто менять второй параметр функции SUBSTRING до тех пор, пока ответом не будет 0. Подобный способ был использован в эксплойте для одной из версий phpBB. 
 
Ситуация 2 
 
SQL Injection находится в середине SQL-запроса. Например: SELECT code FROM artciles WHERE id = $id AND blah='NO' AND active='Y' LIMIT 10. Для правильной эксплуатации хакер просто откомментирует идущий следом за Injection код, то есть к вставляемому коду добавит /* или --. Пробелы в запросе взломщик может заменить на /**/, что полезно в случае если скрипт фильтрует пробелы. 
 
Ситуация 3 
 
Случается и такое, что в PHP-коде подряд идет несколько SQL-запросов, подверженных Injection. И все они используют переменную, в которую злоумышленник вставляет SQL-код. Например (опускаю PHP): 
 
$result=mysql_query("SELECT article_id, article_title FROM articles where category_id=$cid"); 
 
//php code here 
 
$result=mysql_query("SELECT article_name FROM articles where category_id=$cid"); 
 
//тут вывод результата 
 
Это довольно неприятно для хакера, так как для первого запроса SQL Injection пройдет нормально, а для второго UNION - уже нет, так как количество запрашиваемых столбцов отличается. И если программист, писавший код, предусмотрел остановку скрипта в случае ошибки типа "... or die("Database error!")", то эксплуатация обычными методами невозможна, так как скрипт остановится раньше, чем будет выведет результат. 
 
Ситуация 4 
 
Скрипт выводит не весь результат запроса, а, например, только первую запись. И если хакер будет прямо пользоваться UNION, то скрипт выдаст только первую запись из ответа MySQL, а остальное отбросит, в том числе результат SQL Injection. Для того чтоб преодолеть все препятствия и на этом этапе, хакер передаст левому запросу такой параметр для WHERE, чтобы в ответ на него MySQL не вернул ни одной записи. 
 
Например, есть такой запрос: SELECT name FROM authors WHERE id=$id. После SQL Injection он будет выглядеть следующим образом: (..) id=1 UNION SELECT password FROM authors. Но PHP-скрипт выведет только первую запись, поэтому вставляемый код следует модифицировать: (..) id=-12345 UNION SELECT (..). Теперь в ответ на левый запрос MySQL не вернет ничего, а в ответ на правый - желанные для хакера данные. 
 
Ситуация 5 
 
Скрипт не выводит результат запроса. Например, есть скрипт, который выводит какие-либо статистические данные, например, количество авторов, принадлежащих к определенной группе. Причем количество записей он считает не с помощью MySQL-функции COUNT, а в самом скрипте. Скрипт шлет MySQL такой запрос: SELECT id FROM authors where category_id=$cid. 
 
Допустим, скрипт возвращает что-то вроде "Найдено десять авторов в данной категории". В этом случае злоумышленник будет эксплуатировать SQL injection, конечно же, методом перебора символов! Например, хакеру надо получить пароль автора с id = 1, для чего потребуется перебирать каждый символ пароля. Но как получить символ, если PHP не выводит ничего из того, что возвратил MySQL? 
 
Рассмотрим такой запрос: SELECT id FROM authors where category_id=-1 UNION SELECT 1,2 FROM authors WHERE id=1 AND ASCII(SUBSTRING(password,1,1))>109. Результатом запроса будет одна запись, если ASCII-код первого символа пароля больше 109, и ноль записей, если больше, либо равна. Итак, методом бинарного поиска нетрудно найти нужный символ. Почему хакер использует знаки "больше/меньше", а не "равно"? Если взломщику надо получить 32-символьный хэш пароля, ему придется делать примерно 32*25 запросов! Метод бинарного поиска позволяет сократить это число в два раза. Само собой, делать запросы хакер будет уже не руками, а с помощью скрипта, автоматизирующего перебор. 
 
MySQL версии 3 
 
Несмотря на отсутствие в третьей версии оператора UNION, и из нее хакер сможет вытащить то, чем интересуется. В осуществлении этого замысла помогут подзапросы и перебор символов, но описание этого метода займет еще пару листов (которых мне не дали). Поэтому ищи статьи на эту тему на www.rst.void.ru (автор 1dt.w0lf) и www.securitylab.ru (автор Phoenix). 
 
Как защищаться? 
 
Правило №1. Фильтруй входные данные. Кавычку заменяй на слеш-кавычку('), слеш - на слеш-слеш. В PHP это делается или включением magic_quotes_gpc в php.ini, или функцией addslashes(). В Perl: $id=~s/(['])/$1/g;. И на всякий случай: $id=~s/[a-zA-z]//g; - для числовых параметров. 
 
Правило №2. Не дай кому не надо внедрить SQL-код! Заключай в кавычки все переменные в запросе. Например, SELECT * FROM users WHERE id='$id'. 
 
Правило №3. Отключи вывод сообщений об ошибках. Некоторые программисты, наоборот, делают так, что при ошибке скрипт выводит сообщение самого MySQL, или, еще ужасней, - ВЕСЬ SQL-запрос. Это предоставляет злодею дополнительную информацию о структуре базы и существенно облегчает эксплуатацию. 
 
Правило №4. Никогда не разрешай скриптам работать с MySQL от root. Ничего хорошего не выйдет, если хакер получит доступ ко всей базе. 
 
Правило №5. Запускай публичные скрипты от отдельного пользователя с отдельной базой. Неприятно будет, если какой-нибудь кидди, воспользовавшись 0day-дырой в форуме, получит доступ к базе с СС твоих клиентов. 
 
Правило №6. Отключи MySQL-пользователю привилегию FILE - не дай хакеру записать в файл что-то вроде <?system($_GET[cmd])?> через MySQL. 
 
Правило №7. Не называй таблицы и базы данных в соответствии с их назначением, чтоб утаить от чужих глаз настоящие названия. В публичных скриптах часто предоставляют возможность установить prefix для названия таблиц - устанавливай самый сложный. Если кто-нибудь и найдет SQL injection, то не сможет ее эксплуатировать. 
 
Чаще всего уязвимости оставляют в тех запросах, параметры которых передаются через hidden формы в HTML и через cookies, видимо, из-за того, что они не видны пользователю и не так привлекают внимание злодеев. 
 
Часто забывают про SQL Injection в функции Reply, о поиске сообщений пользователя в форумах, в репортах различных сервисов. В 80% WAP-сервисов SQL injection находят по десять штук в каждом скрипте (наверное, админы думают, что туда только через сотовые ходят). На самом деле многие недооценивают SQL Injection. Известен случай, когда обычная SQL injection в скрипте репорта привела к реальному руту на трех серверах и дампу гиговой базы. А всего-то SQL Injection… 
 
Статьи по теме 
 
inattack.ru/group_article/34.html 
www.rst.void.ru/papers/sql-inj.txt 
www.securitylab.ru/49424.html 
www.securitylab.ru/49660.html 
 
Все чаще администраторы получают возможности убедиться в том, что знания по безопасности запросов к MySQL не менее важны, чем эффективное использование этих запросов. 
 
Защитить свою базу от хакеров можно – нужно только грамотно следовать определенным правилам по нейтрализации подобных атак. 
 
С помощью UNION хакер может легко узнать пользователя, базу данных и версию MySQL, для чего используются функции user(), database() и version() соответственно. Взломщик просто сделает запрос типа SELECT user(). 
 
Даже если в обороне есть брешь, можно дезинформировать противника присваивая переменным нелогичные названия. Тогда их будет просто невозможно подобрать. 
 
Чем ты больше знаешь о том, как ломают, тем проще предотвратить взлом. 
 
Регулярно просматривай новостные сайты по безопасности, чтобы быть в курсе вновь изобретенных способов взлома и не допускать утечек ценной информации.

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