Книги, научные публикации Pages:     | 1 |   ...   | 4 | 5 | 6 | 7 | 8 |   ...   | 10 |

Michael Howard David LeBlank WRITING SECURE CODE Second Edition Press Майкл Ховард Дэвид Лебланк ЗАЩИЩЕННЫЙ код 2-е издание, исправленное Москва 2004 УДК 004.45 ББК 32.973.26-018.2 Х68 ...

-- [ Страница 6 ] --

действительное в пределах домена независимо от того, какой это домен: Win dows NT 4, Windows 2000, Windows 2000 с Active Directory или Windows XP.

Для определения канонического имени пользователя можете вызывать функ цию как в этом фрагменте (см. папку ffinclude for (int i = NameUnknown ;

i <= NameServicePrincipal;

TCHAR DWORD dwLen = sizeof szName / sizeof TCHAR;

TCHAR = NULL;

case 0 enf = "NameUnknown";

break;

case 1 enf = break;

case 2 enf = break;

case 3 enf = break;

case 4 enf = break;

case 5 enf = break;

case 6 enf = break;

case 7 enf = case 8 enf = break;

default Х "Unknown";

break;

: enf BOOL fRet = if (fRet) { в формате szName, else сбой enf, 'Х He удивляйтесь, если увидите ошибки;

некоторые расширенные форматы имен не относятся к пользователям.

ГЛАВА 11 Недостатки канонического И воздержитесь от принятия решений о предоставлении доступа основании имени пользователя. Если возможно, используйте Резюме Могу итог всему сказанному в этой главе одной фразой: й те решений, связанных с безопасностью, на основании какого бы то ни имени. Если не послушаетесь, наделаете ошибок и создадите дыры в защите. Если без подобных решений никак не обойтись, будьте предусмотрительны: четко сформулируйте критерий правильности запроса и принимайте только те, го удовлетворяют шаблону, а все остальные с негодованием отметайте.

Вам никогда не перечислить все так что даже не пытайтесь их отслеживать.

И не говорите, что я вас не предупредил!

Ввод в базу данных приложения и Web-приложения в частности хранят постоянные дан ные в базах данных (БД). В таких Web-приложений и Web-серви сов так много, что практически невозможно говорить о них обособленно, не ка саясь баз данных. Поэтому в этой главе я расскажу о проблемах ввода данных в в основном на примере взаимодействующих с БД. (Глава полностью посвящена безопасности Web-приложений, не связанных с базами данных, но принимающих большие объемы данных.) Ключевой момент этой темы Ч доверие введенным данным и опасность атак с внедрением SQL-кода;

но прежде всего я расскажу историю.

В 2001 г. я делал две доклада на Microsoft Professional Developer's Con ference (Конференция профессиональных разработчиков на платформе Microsoft) в Лос-Анджелесе. Один из них был посвящен вопросам доверия в целом и про блемам ввода информации в БД и в в частности. Я обрадовал ся, обнаружив полную аудиторию уже за 15 минут до начала презентации. К на чалу выступления в аудитории яблоку негде было упасть, люди столпились в ко ридоре, пожарный их не разогнал, но сейчас не об этом. Полчаса спустя после начала доклада об атаках с внедрением SQL-кода, человек, сидящий в пер вом ряду, покинул аудиторию и вернулся минут через десять. По оконча нии он подошел ко мне и сказал, что работает в крупной страховой компании на Восточном побережье и отлучался, чтобы позвонить команде разработчиков баз данных и дать им указания немедленно внести исправления в код приложений.

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

Мораль проста: многие просто не догадываются, что их базы данных уязвимы для заключающихся в манипуляциях со структурой запросов. В этой главе я обрисую связанные с этим проблемы расскажу, как атакуют базы данных посредством казалось бы безобидных на первый взгляд входных а также опишу несколько способов устранения подобной опасности, ГЛАВА Ввод в базу данных Суть проблемы Проблема все в том же, о чем говорилось в двух предыдущих главах и о чем речь пойдет в следующей главе: излишняя доверчивость, слепая вера в то, что пользо ватель передает приложению только правильные данные, когда на самом деле все происходит с точностью до наоборот. Вот пример.

Многие приложения содержат код, который выглядит так тесь, вы сами писали подобное);

string = "select * client where name = + name + Значение name пользователь. в том, что он может подставить в переменную пате другое SQL-выражение. он в результате чего получилась вполне благопристойная SQL-команда:

select * from where name = А что, если ввести следующее: or 1 = 1 Ч ? Получится такая строка:

select * from client where name = 1=1 - Эта команда вернет все строки таблицы содержащие значение поле пате. Вдобавок будут возвращены все строки, удовлетворяющие условию а это уж кому как понравится: плохие новости для хороших парней и хорошие новости для плохих, поскольку 1=1 истинно для всех строк в таблице, так что хакер увидит строки. Вам кажется, в этом нет ничего плохого? Тогда представьте, что схема таблиц БД выглядит, как показано на рис. 12-1,.

SO f Type Number | Address Apartment City \ Рис. 12-1. Схема таблиц с данными о содержащая информацию о кредитных картах 344 Часть II Методы безопасного кодирования В конце запроса стоят символы Это оператор комментария, который уп рощает хакеру задачу построения корректного, но тем не менее злонамеренного SQL-оператора. Сделав свое черное дело, то есть соорудив хакер ставит в конце строки оператор чтобы ядро данных игнори ровало все, что по замыслу программиста должно добавляться к выражению.

Примечание Оператор комментария поддерживают многие в том числе Microsoft SQL Server, IBM DB2, Oracle, PostgreSQL и Описанная атака, называется внедрением SQL-кода (SQL injection). В подобной ситуации изменяется логика SQL-выражения, в данном случае раз ница в добавлении выражения, присоединенного оператором or. Подобным ме тодом удается изменять не только единичные SQL-выражения, но добавлять до полнительные вызывать функции и хранимые процедуры, По умолчанию некоторые СУБД позволяют клиентским приложениям выпол нять более одного SQL-выражения за раз. Например, разрешается направить на SQL Server такое выражение:

select * select * table и сервер выполнит оба SQL-оператора select.

Хакеры могут намного больше, чем просто запускать на исполнение подряд несколько SQL-запросов. Большинство ядер СУБД поддерживают операторы ма нипулирования данными, в частности создания, удаления и обновления объектов БД: хранимых процедур, правил и видов. Посмотрите на лимя, которое может ввести хакер:

table client Результат Ч SQL-запрос, возвращающий запись с именем Blake, а затем удаля таблицу клиентов.

Во время демонстрации манипуляций с базами данных методом внедрения SQL кода на Professional Developer's Conference в 2001 году я случайно удалил табли цу, на которой и происходила демонстрация. Хоть я и лишился демонстрацион ной но эффект, произведенный на того стоил!

Вы, наверное, недоумеваете, как простой смертный пользователь в Интерне те, подключаясь к СУБД через Web-приложение или Web-сервис, может удалить таблицу? Взгляните на этот код:

string Status = "No";

string sqlstring = try < SqlConnection sql= new SqlConnection( sql.0pen();

+ - detail + Id ;

= new if != 0} Status = "Yes";

ГЛАВА Ввод в базу данных } catch (SqlException se) { Status = + e in { Status += + } } catch (Exception e) { Status = Х Вы увидели дыры в этом отрезке кода на очевидна: SQL-выраже ния создаются за счет конкатенации строк, что приводит к атакам с внедрением SQL-кода. Но это еще не все. Имя пользователя в строке подключения са к данных Ч то есть учетная запись системного администратора Никогда не создавайте подключения к БД с использованием такой опасной учетной записи: sa для SQL Server то же самое, что SYSTEM для Windows NT и более поздних ОС. Обе учетные записи обладают максимально возможными полномочиями и способны принести непоправимый ущерб. в Oracle Ч учетная запись internal.

Следующая ошибка Ч пароль учетной записи sa. Скажем прямо: его может о мать шестилетний ребенок! И вдобавок ко всему, все это жестко прописано в коде.

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

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

Псевдосредство заключение вводимых данных в кавычки Этот метод часто предлагается как панацея, предотвращающая ввод опасных дан ных в БД, но он определенно не работает как надо. Посмотрим, как он исполь ется и почему он так плох, int age = // Возраст, введенный пользователем.

name = // Имя, введенное name =, );

sql= new + FROM client WHERE name= + name + + age;

= new Как видите, код удваивает все одинарные кавычки в данных, введенных пользо вателем. Таким образом, если хакер попытается в качестве имени ввести будь вроде or 1 одиночная кавычка (отделяющая имя) 346 Часть II Методы безопасного ется, лишив провести атаку, поскольку до оператора комментария получается некорректное select * client WHERE ID = 1=1 -- age= Но это не спугнет нашего коварного хакера Ч для атаки он воспользуется полем age, к которому одиночные кавычки не добавляются. Например, age по его мило сти может стать 35;

Никаких кавычек, и сервер остановится. Обрати те внимание, что точка с запятой (;

) не 35 shutdown даст тот же ре зультат, так что не думайте, что, выкидывая точки с запятыми, вы лишите осу ее жала!

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

подобная следующей:

declare char(20) select Будучи присоединенной к другому SQL-запросу, эта конструкция формирует команду Последовательность символов Ч это эк вивалент shutdown в ASCII.

К чему я веду? Простое добавление кавычек в SQL-операторы в по могает, но далеко не всегда!

Внимание! Удаление определенных символов (в том числе кавычек) не тит от атак с внедрением Псевдосредство №2: хранимые процедуры Многие разработчики наивно что, вызывая хранимые процедуры из приложения, они атаки с внедрением SQL. Чушь! Эта мера пре дотвращает лишь некоторые виды атак, но бессильна перед остальными. Перед вами пример вызывающий хранимую процедуру string name // Имя, пользователем.

SqlConnection new sql.0pen();

+ name + ;

= new Попытка ввести or закончится неудачей, поскольку нельзя выпол нять соединение (join) между вызовами хранимых процедур. Следующий SQL синтаксис некорректен:

exec 1=1 -- ' Однако вот такое манипулирование данными абсолютно легально:

exec insert into client Эта SQL-команда получит данные о клиенте с именем Blake и вставит новую запись в таблицу клиентов! Как хранимые процедуры не сделают ваш код неуязвимым для атак с внедрением SQL-кода.

ГЛАВА в базу данных Я должен признать, что самый ужасный пример хранимой процедуры, приме няемой в целях безопасности, таков:

CREATE PROCEDURE AS Поняли, что делает этот код? Он просто выполняет то, что ввел Вот вам и вызов хранимой процедуры. К счастью, такие перлы мне встречались всего несколько раз.

К чему я все это рассказал? Вам следует знать о псевдосредствах Ч они помогают, но ни одно не защищает на все сто. А теперь посмотрим гарантированные Средство никаких подключений к СУБД под учетной записью администратора Я уже указывал на ошибку создания подключения к SQL Server или любому друго му серверу БД от имени системного администратора из приложений вроде Web-сервисов или Web-страниц. Заметив такую строку подключения, д рапортуйте об ошибке и добивайтесь исправления. к из под администраторской учетной записью Ч вопиющее на рушение принципов наименьших привилегий и защиты на каждом этапе.

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

Х удаление любой базы данных или отдельной таблицы;

Х удаление любых данных из любых таблиц;

Х модификация любых данных из любых таблиц;

Х модификация любых хранимых процедур, триггеров или правил;

Х удаление журналов;

Х добавление новых пользователей базы данных;

Х вызов любых административных или расширенных хранимых процедур.

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

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

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

348 Часть II Методы безопасного кодирования Наверное, наибольшая опасность использования администраторской учетной записи заключается в возможности вызывать любые административные хранимые процедуры. Например, в SQL Server есть хранимая процедура позво ляющая хакеру запускать на исполнение команды оболочки. В Oracle имеется процедура предоставляющая возможность читать и писать в файловую систему, Примечание Создание подключения к БД от имени учетной записи Ч это не только ошибка. Это вопиющее нарушение принципа наименьших привилегий. Разработчики с удовольствием идут на это, так как при та ком подходе все работает само по себе и никаких дополнительных уси лий на конфигурирование сервера не требуется. Но не забывайте, что взламывается такая система тоже легко!

Теперь давайте посмотрим, как правильно строить SQL-выражения. Как этого делать нельзя, вы уже знаете.

Средство №2: построение безопасных SQL-выражений Построение SQL-выражений программным путем довольно проблематично, впро я уже это продемонстрировал. Самый простой способ избежать проблем Ч переложить построение SQL-выражений на базу данных и не пытаться конструи ровать их в коде приложения. Следует использовать символы подстановки (place holder), которые часто называют параметризованными командами command). При написании запроса вы сами определяете, какие части SQL-выраже должны быть параметрами. Вот параметризованная версия запроса:

SELECT FROM client AND Затем следует присвоить конкретные значения параметрам, которые переда ются в БД вместе с SQL-запросом. Следующая функция на VBScript демонстриру ет использование символов подстановки;

Function ' Обратите внимание, я создаю доверенное к SQL Server, ' Никогда не используйте = + + + Set = strConn Set = = = "select client where name=? and означает ГЛАВА Ввод в базу данных = true Комментарии к числовым параметрам:

' тип данных - 200 строка переменной длины);

' - 1 (входной параметр);

' длина строки - 32 символа.

Set = 200, 1, 32, parml Set = 200, 1, 32, cmd. Append = Set rs = false If = 1 Then = true Function прочего, параметризованные запросы выполняются быстрее, чем скон в коде приложения SQL-запросы. Это тот редкий случай, удастся убить зайцев за раз: такие запросы и быстрее, и безопаснее!

Еще одно преимущество параметров Ч возможность указать для них тип дан ных. Например, если вы определите числовой то строгий контроль типов пресечет на корню множество SQL-атак, поскольку они невозможны с использо ванием одних только чисел, нужен еще и текст. Если приложение интерфейс ODBC и требуются применяйте функции и При с OLE DB задействуйте интерфейс Parameters. А если вы пишете управляемый код, то используйте класс Создание безопасных хранимых процедур Только что параметризованные запросы пригодны для доступа к БД из внешних приложений, таких как Web-сервисы. Однако иногда требуется выполнять те же действия в хранимых процедурах. Вам следует о двух простых механизмах, помогающих создавать безопасные выражения.

Во-первых, применяйте к именам объектов функцию выражение select top 3 name from превратится в select top 3 [name] from если вы выделите квадратными скобками пате и mytable. quotename это очень полезная встроенная функция (подробнее см.

цию SQL Server Books Online). Она выделяет имена объектов разделителями, ;

I.H неправильные символы. Результат ее работы можно запустив в SQL Analyzer приведенный далее пример. В этом примере также демонст что запрос обрабатывает ASCII-коды, о которых я говорил ранее в этой главе.

350 Часть II Методы безопасного кодирования declare set select set select set select set select Обратите внимание на значение переменной во втором блоке кода Она превратилась в безопасную строку, выделенную символами и Во-вторых, используйте sp_executesql для исполнения динамически созданных SQL-выражений, вместо того чтобы просто склеивать строки. Это не даст нехо рошим* параметрам проникнуть в СУБД:

Попробуйте выполнить код с declare set = -- Выполняем работу.

exec sp_executesql N'select au_id where = Оба этих механизма поддерживаются в SQL Server, и разработчики, создающие хранимые процедуры, должны ими пользоваться, так как они обеспечивают до полнительный уровень защиты. Нельзя спрогнозировать, как ваши хранимые процедуры будут вызываться в будущем! Теперь по поводу защиты на всех уровнях:

давайте посмотрим, как следует писать код, удовлетворяющий этому принципу.

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

// // using System;

using using using using using ГЛАВА 12 Ввод в базу данных using using using static string Id) SqlCommand = null;

string Status = "Name Unknown";

try { // Проверить корректность переданного идентификатора (ID).

Regex r = new if throw new // Считать строку реестра.

SqlConnection new SqlConnection(ConnectionString);

// Добавить переданный ID-параметр.

string cmd = new = Status = catch (Exception e) { if == "127.0.0.1") Status = e.ToString();

else Status = "При обработке запроса произошла ошибка } finally // Закрыть даже в случае сбоя.

if (cmd != null) return Status;

// Получить строку internal static string ConnectionString 352 Часть II Методы безопасного кодирования get { return В этом примере несколько уровней защиты Ч несколько слов о каждом в от дельности.

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

Х Приложению разрешено считывать только один определенный раздел реест ра;

другие операции с реестром запрещены.

Х Код очень избирателен ко входным данным: от 4 до 10 цифр, и точка. Все ос тальное Ч в помойку.

Х Строка подключения к БД хранится к реестре, а не в коде или в файлах Web сервиса (например, в файле конфигурации).

Х Хранимая процедура применяется в основном для сокрытия логики приложе ния, на случай компрометации кода.

Х Хоть это и не видно, но для создания подключения не используется учетная запись Напротив, применяется учетная с наименьшими привилеги ями, то есть с только на чтение и исполнение для соответству ющих таблиц.

Х Для построения запросов применяются а не конкатенация строк.

Х Вводимые данные записываются в 64-разрядные целочисленные переменные (контроль типов).

Х При сбое хакер не получает никакой информации кроме самого факта ошибки.

Х Подключение к БД всегда закрывается, даже при сбое программы, Этот код кажется сложнее, чем есть на самом деле. Позвольте мне объяснить, почему этот код безопаснее, чем приведенный в первом примере. Я пока отложу объяснение атрибутов перед вызовом функции, Во-первых, код требует, чтобы введенный идентификационный номер пользо вателя (ID) содержал от 4 до 10 цифр. Это обеспечивается регулярным выраже нием которое пропускает только числа с количеством цифр от 4 до между началом и концом данных. Жестко определив входные данные и отклоняя все остальное, мы сильно обезопасили себя: хакеру просто не удастся добавить в идентификатор никаких SQL-выраже ний. Регулярные выражения в управляемом коде представлены в пространстве имен Код содержит также дополнительную защиту. Обратите внимание, что строка передаваемая объекту хранится в реестре. Посмотрите также па функцию доступа Чтобы узнать эту строку, хакеру не достаточно получить доступ к исходному коду Web-сервиса Ч потребуется доступ к соответствующему разделу реестра.

ГЛАВА 12 Ввод базу данных Данные раздела реестра представляют собой строку data initial Заметьте: база данных расположена на другом компьютере Ч Если хакеру удастся скомпрометировать Web-сервис, то даже в этом случае он не получит к SQL-данным. В придачу ко всему этот код не создает подключение от учетной записи напротив, для этого предназначена специальная учетная за пись с надежным (и страшным на вид) паролем, которой только право на чтение и исполнение соответствующих SQL-объектов в базе дан ных client. В случае компрометации подключения Web-сервиса к БД хакер жет запускать лишь несколько хранимых процедур и выполнять запросы к ным таблицам, ему не удастся повредить базу данных master или атаковать, уда ляя, вставляя или изменяя данные.

SQL-выражения не строятся помощи небезопасной техники конкатенации строк Ч для этого служат параметризованные запросы с вызовами хранимых хранимой процедуры быстрее и безопаснее, чем конкатенации строк, поскольку имена базы данных и таблиц не выставляются на всеобщее обозрение, а хранимые процедуры оптимизированы для работы с яд ром СУБД, Когда возникает ошибка, пользователю (а возможно, хакеру) не сообщается ничего, кроме типа запроса Ч локальный или с компьютера с кодом Получив физический доступ к компьютеру, на котором работает Web-сервис, в любом случае можете делать с ним все, что угодно! Неплохо добавить код, доставляющий доступ к детальному описанию ошибки только user = if { // Пользователь администратор, // поэтому ему сообщать подробности.

Далее, подключение к БД всегда закрывается в блоке finally. Если в теле try/catch инициируется будет выполнено корректное закрытие что предотвратит угрозу атак отказа в обслуживании, обычная причина Ч слишком много открытых подключений.

Все приведенные в этой главе рекомендации являются общими и справедли вы практически для любого языка программирования. Теперь я хочу заострить ваше внимание на особой защите, имеющейся только в Framework Ч атрибуты В начале оператора вызова функции имеются два атрибута защиты. Первый, позволяет провайдеру SQL Server Provider убедиться, что уровень безопасности пользователя достаточный для к источнику данных Ч в данном случае это выполняется присваиванием свойс 354 Часть II Методы false, то запретом пустого пароля. Программа инициирует исключение при подключиться к SQL Server от имени учет ной записи с пустым паролем.

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

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

Резюме Приложения, взаимодействующие с базой данных, одни из распростра ненных видов прикладных программ, и, к сожалению, многие из них уязвимы для атак с внедрением SQL-кода. Следуя простым правилам, вы избавите свои прило жения от подобных брешей.

Х Никогда не доверяйте данным, которые ввел пользователь!

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

Х Для построения запросов применяйте параметризацию, а не строк.

Х с хакером, предоставляя ему слишком много информации.

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

Проблемы ввода в Web-среде теперь пришло обратить взор на, пожалуй, самую агрессивную среду Ч Я расскажу, как гарантировать защищенность приложений, использующих Web в качестве транспортного механизма. вы ознакомились с главами и а если в вашем Web-приложении используются базы данных, то следует про читать и главу Практически все Web-приложения выполняют определенные действия в ответ на запросы пользователей. Сказать по правде. Web-приложение, не принимающее пользовательских данных, попросту говоря, бесполезно. Не забывайте, что следу ет четко определиться с тем, что такое правильные входные и отвер гать все остальное. Я понимаю, что вам хочется сказать: смени пластинку, ничего не поделаешь Ч проверка данных является одной из важнейших лин, и ее понимание Ч ключ к успешной разработке защищенных Вы узнаете о проблеме сценариев (вам это пригодится, так сценарии весьма популярны) и проблемах доверия в HTTP, а также о том, от ких опасностей защищают протоколы SSL (Secure Sockets Layer) и TLS Layer Security). Итак, за работу!

сценарии: когда выходные данные превращаются в монстров Я часто что кросс-сайтовые сценарии (cross-site scripting, XSS) очень но объяснить и сравнительно просто реализовать. Думаю, что пользователи плохо понимают сам механизм взлома: клиент компрометируется из-за дефектов в од ной или нескольких Web-страницах. Года три назад о них никто и не а 356 Часть II Методы безопасного кодирования сегодня каждый день в Web появляются сообщения об одной-двух ках. Так в чем же проблема и почему она такая серьезная? Она зиждется на двух Х Web-сайт доверяет данным, поступившим из внешнего ненадежного источника;

Х полученные Web-сайтом данные попадают в информацию, которую он возвра щает клиенту.

Держу что вам видеть такое:

Hello, Этот код выведет в браузере все, что передано в поле пате в на пример На первый взгляд Ч ничего страш ного, но что, если хакеру удастся убедить пользователя щелкнуть эту ссылку, на пример, на Web-странице, в новостной группе или в теле сообщения электрон ной почты? Вроде тоже, кажется, ничего страшного, но лишь до момента, когда вы поймете, что ссылка может оказаться такой:

<а Выиграй 000 000 где блок такой:

Настоящий взломщик, скорее всего, замаскирует ссылку, чтобы пользователь не заподозрил неладного. Например, так:

Выиграй $1 000 000 Кажется, что ссылка ведет на сайт но это не так! Здесь ис пользуется малоизвестный, но тем не менее корректный формат Он определен в RFC 1738, Resource Locators Вот выдержка из раз дела л3.1. Common Internet Scheme (Общий синтаксис схемы Интернета):

В то время как синтаксис конца URL-адреса может в зависимости от выбранной схемы, в схемах напрямую зующих основанный на протокол для указания хоста в Интер нете, применяется общий синтаксис: <паролъ Заметьте: ни одна из частей URL-адреса не является обязательной. Вернемся к нашему URL-адресу: ссылка www.microsofl.com Ч обманка. Это вообще не ссылка, а имя пользователя, за которым следует настоящее имя Web-сайта, в шестнадцатеричном виде, чтобы жертва не узнала, куда на самом деле она ГЛАВА Проблемы ввода в Web-среде ОК, вернемся к нашим баранам (в смысле к XSS). Проблема в параметре пате Ч не в а том, что в него внедряется HTML-текст с JavaScript, позволяющий обратиться к данным пользователя, например к cookie-файлам, через объект Как вы наверное знаете, cookie-файлы привязываются к домену.

cookie-файлы, созданные сайтом в домене contoso.com, только Web-стра ницам этого домена, но никак не Web-страницам с microsoft.com. А теперь >с на засыпку: в какого домена исполнится сценарий, когда пользователь щелкнет ссылку? Для ответа достаточно выяснить, откуда, собствен но, пришла эта страница Ч из домена contoso.com, поэтому у нее есть доступ к cookie-файлам Проблема в том, что для небезопасной обработки данных на клиентском компьютере, относящихся к определенному домену, дос таточно, чтобы лишь одна страница в домене имела подобную брешь.

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

Позвольте мне привести пример. В конце 2001 г. на Web-странице passport.com была обнаружена очень хитрая брешь, по сути похожая на ный выше пример. Отправив абоненту Hotmail специально оформленное пись мо, хакер мог заставить выполниться сценарий в домене поскольку служба Hotmail располагается в домене hotmail.passport.com. А это значит, что код получал доступ к cookie-файлам, сгенерированным сервисом Passport и приме няемым для аутентификации клиента. Воспроизводя эти cookie-файлы Ч ведь э всего-навсего заголовки Ч хакер получал возможность выдавать себя за того самого абонента и получал доступ к его частным данным, сценарии позволяют читать или изменять cookie-файлы. Э го обычно отравлением (poisoning). Подключаемые модули бра узера или родной (native) код, связанный с доменом (например, использующий ActiveX-шаблон описанный в главе 16), можно загрузить и нариями со зловредными данными, а введенные пользователем данные Ч пере хватить. Короче говоря, хакер получает бесконтрольный доступ к объектной дели браузера в контексте безопасности скомпрометированного домена.

Атаки подмены сетевых объектов (spoofing) выполняются похитрее.

что новостной сайт имеет Воспользовавшись этим, хакер получит пол ный доступ к объектной модели браузера в контексте безопасности новостного сайта. И если он убедит жертву зайти на этот сайт, то сможет подсунуть под дом статей с новостного сайта свои собственные (рис. 13-1).

Примечание Подлинная причина существования XSS-атак Ч смешение кода и данных. Подробнее о неудачных проектах с подобными брешами рас сказывается в разделе Разделяйте код и данные главы 3.

Любой поддерживающий выполнение сценариев Web-браузер в принципе уяз вим. Более того Ч данные, собранные злонамеренным сценарием, попасть к хакеру. Например, если в сценарии задействована объектная модель Dynamic HTML (DHTML) для извлечения данных со страницы, то в результате с сценарием эти данные могут направляться хакеру. Вот нагляд ный пример.

Часть II Методы кодирования <а

> Щелкни здесь!

Имейте в виду, что в реальном HTML-коде обычно применяются управляющие символы. В целях удобочитаемости я оставил все, как есть. После щелчка ссылки cookie-файлы пользователя передаются на другой Web-сайт.

Внимание! Использование SSL/TLS не спасает от сценариев.

Защищенные брандмауэром компьютеры также уязвимы для XSS-атак. Большин ство корпоративных ЛВС сконфигурированы так, что клиентские компьютеры доверяют внутренним серверам сети и не доверяют (расположенным в Интернете). Тем не менее внешний сервер, находящийся по ту сторону брандма уэра и направивший клиенту запрос на исполнение программы, может ввести клиента в заблуждение и заставить поверить, что запрос поступил от доверенно го внутреннего сервера. Все, что хакеру нужно. Ч имя Web-сервера, расположен ного за и не проверяющего данные на Web-странице. (Этот сер вер может использовать поля формы или Отыскать такой сервер не просто, если только хакер не владеет внутренней но вполне ре ально.

Отправка по электронной почте сообщения со ссылкой на Х ссылку, которую подсунул хакер Пользователь переходит на Web-сайт Ответ сервера содержит злонамеренные данные, которые отображаются (и/или исполняются) Сценарий выполняется в браузере пользователя в контексте Web-сайта жертвы Рис. 13-1. Схема ГЛАВА 13 Проблемы ввода в Web-среде Благодаря cookie-файлам могут выполняться постоянно, если выводящий данные из имеет дефект. Хакер делает свое про сто инфицируя cookie-файлы злонамеренным сценарием, и всякий раз, когда жертва заходит на этот сайт, сценарий выполняется. Атака повторяется, пока пользователь не удалит cookie-файлы, Примечание Прекрасный обзор XSS-атак вы найдете статье Cross-Site Scripting Overview (Обзор сценариев) на странице за мечательный ресурс Ч посвященный безопасности сайт Open Web Appli cation Security Project Иногда взломщик обходится без тэга .

В некоторых случаях взломщик не закрывает тэг а расширяет его ства. Например. расширит тэг включив в него со бытие onclick, и когда пользователь щелкнет ссылку, исполнится exploit-код, Защититься от таких атак обрамив необязательными двойными кавыч ками каждый атрибут так:

<а Обратите внимание на кавычки, которыми выделено значение атри бута href. Если взломщик попытается подсунуть свое значение для id, то у него ничего не получится, страница рассматривает всю строку как значение id, а не только первое значение, которое и есть id. Например, превратится в:

<а Сильно сомневаюсь, что у Сотою наличествует продукт А почему двойные кавычки, а не одинарные? А потому, что в HTML одинарные не применяются для управляющих символов Ч только двойные.

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