ANTICHAT.XYZ    VIDEO.ANTICHAT.XYZ    НОВЫЕ СООБЩЕНИЯ    ФОРУМ  
Баннер 1   Баннер 2
Antichat снова доступен.
Форум Antichat (Античат) возвращается и снова открыт для пользователей. Здесь обсуждаются безопасность, программирование, технологии и многое другое. Сообщество снова собирается вместе.
Новый адрес: forum.antichat.xyz
Вернуться   Форум АНТИЧАТ > ИНФО > Статьи > Чужие Статьи
   
 
 
Опции темы Поиск в этой теме Опции просмотра

Sql-инъекции: борьба в удовольствие
  #1  
Старый 11.01.2008, 22:08
Аватар для FraiDex
FraiDex
Участник форума
Регистрация: 16.06.2006
Сообщений: 179
Провел на форуме:
515368

Репутация: 135
Отправить сообщение для FraiDex с помощью ICQ
По умолчанию Sql-инъекции: борьба в удовольствие

Опасность SQL-инъекций зачастую недооценивают. А даже если и знают в них толк, то нередко оставляют мероприятия по защите «на потом». И напрасно, поскольку существует довольно простой способ защиты. Этот способ, помимо собственно защиты, позволяет чрезвычайно удобно собирать тексты SQL-запросов из констант и переменных, не прибегая ни к утомительной работе с одинарными и двойными кавычками, ни к объектным способам доступа к БД.
Если скрипты уже написаны, то ничего не стоит изменить в них глобальной автозаменой всего одну функцию (обратная совместимость сохраняется). Но лучше всё же использовать приведённую методику с самого начала, тем более. Что она ещё и существенно упрощает отладку кода.
В чём опасность?
SQL-инъекция - один из распространённых способов взлома сайтов, позволяющий злоумышленнику исполнить практически любой SQL-запрос. Например, если URL страницы имеет вид

http://life.screenshots.ru/index.php?login=vasja
то вместо vasja можно написать нечто вроде

Код:
vasja'; DELETE FROM SomeTable --
предварительно приведя спецсимволы к виду %xx. Тогда запрос, формирующий страницу, вида

PHP код:
$query="SELECT * FROM WebsiteUsers WHERE UserName='" $_GET["login"] . "'"
будет выглядеть как

Код:
SELECT * FROM WebsiteUsers WHERE ID='vasja'; DELETE FROM SomeTable --‘
что приведёт к очистке таблицы (последовательность -- позволяет игнорировать завершающую кавычку, поэтому синтаксической ошибки не возникает). Другое дело, что у логина, под которым PHP обращается к SQL-серверу, может не быть прав на очистку таблицы либо запись двух операторов может быть запрещён конкретным SQL-диалектом. Но сути это не меняет, поскольку это лишь один из множества возможных примеров SQL-инъекций.
Подробнее можно почитать на Wikipedia или любых хакерских сайтах.
Как люди борются?
Есть несколько типовых вариантов борьбы с инъекциями вредоносного кода. Простейший - стандартная функция mysql_escape_string и подобные ей, которые заэскейпливают символы-разделители вроде точки с запятой, кавычки и т.п. Но такой метод не спасает от вставки всяких управляющих слов вроде OR, AND и т.п. Более того, нет гарантии, что ваш сервер БД поддерживает эскейп-последовательности символов.
Второй способ заключается в отлавливании известных вариантов инъекций, например, тех же слов OR и AND. Но, во-первых, иногда требуется передать запросу как раз такую последовательность в штатном режиме (а отключать в таких случаях защиту - ещё больший повод для путаницы). А, во-вторых, перебирать сотню вариантов - тупиковый путь, поскольку всегда найдётся сто первый.
Третий способ - это использование объектных «обёрток», когда параметры запроса «скармливаются» объекту при помощи присваивания значений свойствам или вызовов отдельных методов. Этот путь хорош всем, за исключением его громоздкости (а классы работы с БД почти всегда слоноподобны).
Есть способ лучше
Собственно, основная проблема SQL, которая приводит к возможности SQL-инъекций, заключается в отсутствии контроля типов передаваемых значений параметров запроса. Поэтому решение очевидно - параметры нужно предварительно типизировать!
Мы предлагаем использовать одну-единственную короткую и несложную функцию, которой нужно заменить вызовы mysql_query. В принципе, вам не составит труда написать её самостоятельно, но свои варианты на PHP и ASP мы написали довольно давно и за время эксплуатации добавили немало удобств и поисправляли ошибок.
Формат вызова:

PHP код:
xquery(QueryTemplateStringParameter1Parameter2...); 
Функция возвращает то же, что и обычный mysql_query: в случае неудачного исполнения false, в случае удачного - recordset (для запросов, возвращающих наборы данных, например, SELECT-запросов) либо true (для запросов на изменение данных).
Сама строка шаблона - это обычная строка запроса, в которой, однако, в местах, где требуется вставить значение параметра, стоят специальные маркеры. Например:

PHP код:
$Rcs=mysql_query("SELECT * FROM WebsiteUsers WHERE Age>" $_GET["age"] . " OR UserName='" $_GET["login"]); 
заменяется на:

PHP код:
$Rcs=хquery("SELECT * FROM WebsiteUsers WHERE Age>^N OR UserName=^S"$_GET["age"], $_GET["login"]); 
При помощи маркеров мы установили, что возраст - это числовое значение (^N), а логин - строковое (^S).
Процедура проанализирует типы переданных параметров (поскольку и в PHP, и в JScript есть возможность доступа к переданным функции параметрам как к элементам предопределённого массива, мы можем указывать любое количество параметров).
Для первого тип будет приведён к числовому (и вставить управляющие символы или слова будет невозможно). Для второго просто будут заэскейплены (либо заменены на другие - зависит от диалекта SQL) кавычки, которые могли бы разорвать текст запроса, а также добавлены кавычки, обрамляющие полученную строковую константу. Полученная в итоге безопасная SQL-строка будет передана на обработку mysql_query.
Собственно, вот и вся идея. А дальше начинается хронический улучшай.
Поддержка нескольких соединений
В JScript, например, очень удобно сделать два синтаксиса:

PHP код:
xquery(QueryTemplateStringParameter1Parameter2...); 
PHP код:
xquery(ConnectionObjectQueryTemplateStringParameter1Parameter2...); 
Если тип первого параметра - object, то используется второй синтаксис, где функции передаётся объект соединения (нередка ситуация, когда работа ведётся с более чем одним сервером БД), в противном случае используется первый синтаксис и соединение берётся по умолчанию (например, из глобальных параметров сайта – opt_conn).
Поддержка префиксации таблиц
Нередка ситуация, когда необходимо в одной физической БД хранить таблицы, которые, по-хорошему, должны бы принадлежать разным БД. Например, это актуально, если хостинг-провайдер предоставляет ограниченное число БД (и требует деньги за возможность создания дополнительных БД). Или же иногда возникает возможность сделать один запрос к двум таблицам, принадлежащим разным БД – и сделать это технически непросто.
Поэтому большинство тиражируемых web-приложений (например, блоговый «движок» Wordpress) при установке запрашивает, какой префикс дописать к идентификаторам всех своих таблиц БД - и становится возможным установить на одной БД сколько угодно таких движков.
Решение снова лежит на поверхности. Вводим новый маркер ^@ и ещё один глобальный параметр сайта (напомним - первый был объектом соединения с БД) - префикс таблицы:

PHP код:
$Rcs=xquery("SELECT * FROM WebsiteUsers WHERE UserName=^S"); 
трансформируется в

PHP код:
$Rcs=xquery("SELECT * FROM ^@WebsiteUsers WHERE UserName=^S"); 
Функция заменит все маркеры ^@ на префикс, и реально обращение произойдёт уже не к WebsiteUsers, а к таблице someprefix_WebsiteUsers, где someprefix - значение того самого глобального параметра (opt_table_prefix). При этом имя таблицы для пишущего код программиста по-прежнему соответствует имени, указанном в его ER-диагрмме.
Поддержка отладки
Очень удобно, когда вы можете увидеть подробную отладочную информацию, включая собранный текст SQL-запроса, который потом можно вставить в консоль сервера.
Для этого достаточно ввести ещё один глобальный параметр (opt_debug_mode, а для PHP-реализации ещё и opt_debug_show_sql, в котором разрешать либо запрещать вывод на поток отладочной информации.
Поддержка дополнительных типов
Ничто не мешает добавить обработку дополнительных типов параметров (нам мешает нехватка времени - но как-нибудь обязательно надо будет сделать, а пока опишем идеи).
Помимо этого, можно ввести дополнительные ограничения типов, например, ^S[50], которое будет автоматически обрезать строковой параметр до длины в 50 символов (согласитесь, это удобнее, чем обрезать отдельным substr).
Подобным же образом (^D, ^D[hh-MM-yyyy] - в каком формате подаётся значение параметра) можно автоматизировать весьма утомительную работу с датами/временем.
При помощи ^0 можно удобно трансформировать значения переменных null, undefined и т.п. в IS NULL или IS NOT NULL
При помощи ^M[regexp] можно контролировать соответствие входного строкового параметра самым сложным правилам - тогда xquery будет возвращать false в случае несоответствия.
Ну, наверное, идею вы поняли.
Где взять исходники?
Нашими исходниками вы можете пользоваться по своему усмотрению, не забывая на нас ссылаться. Если у вас есть идеи по улучшению и исправлению, то присылайте их нам - будем весьма признательны.
В настоящее время PHP- и JScript-версии несколько различаются по функциональности, но мы надеемся, что через некоторое время их уравняем.
• Исходник xquery на JScript (IIS ASP) для MS SQLServer
• Исходник xquery на PHP для mySQL
Взято из life.screenshots.ru
 
Ответить с цитированием
 



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Обнаружение Sql инъекций в Oracle, часть вторая k00p3r Чужие Статьи 0 13.06.2005 11:26
SQL инъекция и Oracle, часть 2 k00p3r Чужие Статьи 0 13.06.2005 11:24
Sql инъекция и Oracle, часть первая k00p3r Чужие Статьи 0 13.06.2005 11:23
Внедрение Sql кода с завязанными глазами k00p3r Чужие Статьи 0 12.06.2005 20:48
SQL Injection в Oracle k00p3r Чужие Статьи 0 12.06.2005 12:41



Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
 


Быстрый переход




ANTICHAT.XYZ