дефектный замысел SPIDER_NET Хакер, номер #075, стр. 006 (SPIDER_NET@INBOX.RU) SQL INJECTION АТАКИ ТИПА SQL INJECTION — ЧАСТЫЕ ГОСТИ В ЛЕНТАХ BUGTRAQ. ФОРУМЫ, ГОСТЕВЫЕ КНИГИ И РАЗНООБРАЗНЫЕ СЦЕНАРИИ, КОТОРЫЕ ИСПОЛЬЗУЮТ ДЛЯ ХРАНЕНИЯ ИНФОРМАЦИИ БАЗЫ ДАННЫХ, РЕГУЛЯРНО ПОДВЕРГАЮТСЯ ЭТИМ АТАКАМ SQL Injection – внедрение произвольных sql-команд, в результате которого меняется логика оригинального запроса к базе данных. Это представляет серьезную угрозу, так как таким образом злоумышленник может утянуть из нее конфиденциальную информацию. Типичный пример — через ошибки в web-интерфейсе у разных провайдеров не раз крали базы с логинами и паролями пользователей. Успешность атаки SQL Injection не зависит от используемого для написания web-приложений языка программирования - будь то PHP, Perl или ASР. Если сценарий работает с базами данных, а проверка входных параметров отсутствует, то всегда есть возможность внедрения sql-кода. Это относится не только к web-приложениям, но и к обычным программам, которые работают с базами данных. [как это происходит.] Чтобы не грызть сухую теорию, давай рассмотрим небольшой пример. Допустим, у тебя на сервере баз данных есть своя база, а в ней - таблица Users, в которой хранится информация обо всех зарегистрированных пользователях. Как правило, такие таблицы имеют минимум три поля: id (идентификатор), UserName (имя пользователя) и Password (пароль). Допустим, для того чтобы посмотреть профиль пользователя, используется следующий запрос к базе данных: ЛИСТИНГ SELECT * FROM Users WHERE id = переменная В данном примере видно, что значение поля id будет сравниваться со значением переменной. Если в качестве значения переменной указать, например, 10, то честный пользователь увидит свой профиль. Вроде все хорошо и прекрасно, но что будет, если модифицировать запрос до такого вида: ЛИСТИНГ SELECT * FROM Users WHERE id = переменная OR UserName = “Администратор” После выполнения такого запроса отобразится запись не только с id = значению переменной, но и запись, в которой значение поля UserName = Администратор. То есть после такого запроса хакер увидит всю информацию об учетной записи «Администратор». ЛИСТИНГ www.site.ru/profile.php?id=10 OR UserName=’Администратор’ На этом примере видно, что после того, как мы дописали к URL дополнительные sql-команды (OR UserName=…), логика запроса изменилась. Отсутствие фильтрации входных параметров - вот причина, из-за которой появилась возможность воспользоваться SQL Injection! Чтобы этого не произошло, необходимо перед выполнением запроса в сценарии кое-что проверить. В данном случае достаточно просмотреть содержимое одной (это при условии, что остальные переменные нигде не видны, но лучше проверять все) переменной id: в ней не должно быть никаких символов, кроме цифр от 0 до 9. [проблема специальных символов.] Знатоки языка запросов SQL знают, что с помощью специальных символов можно полностью изменить логику запроса и обойти многие ограничения, которые изначально придумывал программист. [1 одинарные и двойные кавычки] Их используют для выделения значений. Предыдущий пример (UserName = 'Администратор') как раз об этом. Первое, с чего начинает хакер свое исследование, это попытка вставки одинарной кавычки вместе со значением переменной. Если отсутствует фильтрация на спецсимволы, то взломщик увидит ошибку, сгенерированную сервером БД. В результате он уже точно будет знать, что есть возможность внедрить свой sql-код. Значит, в своем сценарии надо отключить вывод любых ошибок. Лучше в момент возникновения ошибки вывести свой текст, чем текст, который сгенерирует сервер БД. [2 двойное тире] Два тире подряд в SQL означают начало комментария. То есть все, что будет после двух знаков тире, не будет восприниматься как часть запроса. Рассмотрим пример: ЛИСТИНГ SELECT * FROM Users WHERE UserName=root AND Password= переменная Это запрос должен выбрать запись, где поле UserName равно root (как правило, в основном это имя используется для обозначения супер-пользователя), а поле Password равно значению переменной. Имя мы знаем, а пароль, естественно, нет. Но это не повод отчаиваться - можно умудриться модифицировать запрос до такого вида: ЛИСТИНГ SELECT * FROM Users WHERE UserName=root--AND Password = переменная В результате, код, который стоит после двух знаков тире (AND Password = переменная), не будет выполнен, и, следовательно, мы успешно проходим данную проверку, зная одно лишь имя пользователя. В SQL есть еще пара символов, которые обозначают комментарий, — «/*». Если вдруг оказывается, что знак тире фильтруется, то можно воспользоваться «/*». Принцип действия тот же самый. Весь текст запроса, который стоит после этих символов, не будет выполняться, а значит, можно отбросить лишние проверки и обойти защиту. [3 знак равенства] Казалось бы, чем может грозить простой знак равенства (=)? Но при правильном подходе и отсутствии фильтрации этого символа знак равенства превращается в боевое оружие. Пример: ЛИСТИНГ SELECT * FROM Users WHERE id= переменная Взломщик может без проблем в качестве значения переменной подставить «1 OR UserName=Aдмин», и запрос легким движением руки превратится в: ЛИСТИНГ SELECT * FROM Users WHERE id = 1 OR UserName=Админ Результат этого запроса вернет запись, где поле id равно единице или поле UserName равно «Админ». Теперь представь, что было бы, если бы знак равенства всегда отрезался. Запрос уже выглядел бы следующим образом: ЛИСТИНГ SELECT * FROM Users WHERE id = 1 OR UserNameАдмин Этот запрос неверный, поэтому он не будет выполнен сервером БД, а значит, взломщик останется с носом. [4 точка с запятой] Знак «;» тоже относится к специальным символам, он используется для разделения запросов между собой. Любой сервер БД может выполнять несколько действий одним запросом, но для этого каждое действие в запросе должно быть отделено друг от друга точкой с запятой. Как этим можно воспользоваться? ЛИСТИНГ SELECT * FROM Users WHERE id = переменная Теперь, если представить, что в переменную, с которой сравнивается значение поля id, вписывается такое значение: ЛИСТИНГ 1; DELETE FROM Users Запрос будет выглядеть следующим образом: ЛИСТИНГ SELECT * FROM Users WHERE id = 1; DELETE FROM Users Сначала сервер выполнит выборку из таблицы Users — запись, в которой значение поля id равно единице. А затем полностью удалит все записи из таблицы Users. Конечно, в реальной ситуации очистить все содержимое таблицы непросто, так как необходимо знать ее имя, а получить имена таблиц бывает непросто... но возможно. [5 знак плюса] Знак плюса в SQL сопоставляется со знаком пробела. Допустим, что воспользоваться обычным символом пробела бывает невозможно (фильтруется он, и все тут), в этом случае можно воспользоваться знаком плюса. ЛИСТИНГ SELECT * FROM Users WHERE id = 1+OR+UserName=Администратор Такой запрос будет абсолютно корректен и успешно выполнится. [специальные операторы.] В языке SQL есть множество операторов, воспользовавшись которыми, можно получить гораздо больше возможностей, чем при использовании простых специальных символов. [1 INSERT] Этот оператор используется для вставки новых записей в таблицу. Бывает необходимо сделать себе аккаунт (допустим, на каком-нибудь интересном форуме, где просто так не зарегистрируешься). Тогда, найдя возможность внедрения, можно добавить в запрос этот оператор. ЛИСТИНГ SELECT * FROM Users WHERE UserName=root and Password=123; INSERT INTO Users values (“0”, “spider_net”, “qwerty”) После выполнения такого запроса в таблице UserName добавится новая запись, в которой будут содержаться данные нового пользователя с логином spider_net и паролем qwerty. [2 LIKE] Оператор LIKE идентичен знаку «=», только используется для сравнения строк. Но многие забывают об одном нюансе, который проще показать на примере: ЛИСТИНГ SELECT * FROM Users WHERE UserName LIKE переманная1 AND Password LIKE переменная2 Если для сравнения используется именно LIKE, то достаточно к значению переменной с паролем добавить символ «%». В результате запрос будет выполнен успешно, и если он используется для авторизации пользователей, то мы без проблем сможем залогинится под любым пользователем. ЛИСТИНГ SELECT * FROM Users WHERE UserName LIKE root AND Password LIKE % В SQL знак процента используется для сопоставления с любыми символами. Эта ошибка достаточно распространена, особенно в самописных сценариях. Если ты занимаешься исследованием подобного сценария, то первым делом имеет смысл проверять внедрение именно этого знака. [3 UNION] Оператор UNION служит для объединения запросов. Если удается внедрить этот оператор в запрос, то перед тобой открываются безграничные возможности. Допустим, ты нашел какой-нибудь уязвимый сценарий (например, раздел новостей), но издевательства над новостями тебя не интересует, а хочется всего лишь утянуть всю базу данных с логинами и паролями юзеров. Вот в этом случаем как нельзя кстати пригодится оператор UNION. ЛИСТИНГ SELECT * FROM News WHERE id=1 UNION SELECT Id, UserName, Password FROM Users После выполнения этого запроса помимо текста новости отобразится информация обо всех учетных записях из таблицы UserName. [4 OUTFILE] Думешь, что если ты нашел возможность внедрения, то единственное, чем можно управлять на атакуемом сайте, это база данных? Нет, это не так — с помощью SQL можно получить доступ и к файловой системе. Опять же, пример: ЛИСТИНГ SELECT ‘Мой текст’ INTO OUTFILE ‘text.txt’ Если запрос выполнился успешно, то будет создан файл text.txt с единственной фразой «Мой текст». Конечно, если записать простой текст в файл, то выгоды будет мало. Но что если записать в качестве текста свой сценарий, который будет выполнять какую-нибудь системную функцию... ЛИСТИНГ SELECT '<?php system($cmd) ?>' INTO OUTFILE 'cmd.php' Запрос создаст php-сценарий, который будет выполнять команду из переменной $cmd. Таким же способом можно без проблем дефейснуть сайт, перезаписав файл index (если для этого есть соответствующие права). КАК ИЩУТ УКРОМНОЕ МЕСТЕЧКО ДЛЯ SQL INJECTION Первым делом ищут любые сценарии на сайте. Бывает так, что весь сайт выполнен в виде статичного html, а какой-нибудь один раздел (например, новости) является сценарием. Вот в нем и ищут возможность внедрения SQL Injection. Пробуют подставлять свои SQL-команды к значению переменных, которые передаются сценарию. Если на атакуемом сайте есть поиск, то его тоже проверяют. На многих сайтах сценарии поиска — самописные, значит, всегда есть шанс, что неопытный программист где-то допустил ошибку. Форум и гостевые книги – отличное место для поиска уязвимостей. Стоит только узнать название и версию форума и, если он известный, можно попробовать найти уже готовый эксплойт в Сети. |