IBM Rational AppScan: атаки на Web-приложения через подделку маркеров (cookie poisoning)

Источник: IBM
Амит Клейн, разработки по обеспечению безопасности, бывший директор компании Sanctum

Природа рисков, связанных с подделкой маркеров

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

Сизифов труд обслуживания сеансов собственными силами

Задача управления сеансами при программировании Web-приложений является сложной и трудоемкой. Программисту нужно учитывать многие аспекты управления сеансами, которые могут отвлечь его от основной цели - реализации бизнес-логики, которая делает сайт уникальным и прибыльным.

В числе этих задач:

  • Создание и идентификация сеанса: Как обеспечить, чтобы при возникновении необходимости в новом сеансе он действительно создавался? Программист должен выявить потребность клиента в сеансе, создать сеанс и выделить сеанс клиенту.
  • Проблемы одновременного доступа: Когда два клиента одновременно обращаются к одному сайту, для каждого из них требуется создать новый сеанс. Необходимо также убедиться, что процесс создания сеанса проходит корректно.
  • Завершение сеанса и ожидание: Что вызывает завершение сеанса? Как перераспределятся ресурсы при завершении сеанса? Что произойдет, если клиент обращается к сайту в тот момент, когда идет процесс завершения сеанса? Что произойдет, если клиент попытается обратиться к сайту при завершенном сеансе?
  • Хранение данных сеанса, множественные серверы, переключение на резерв. Где хранятся данные сеанса? На диске? В оперативной памяти? Как это сказывается на производительности? Что происходит на сайте с несколькими серверами, когда клиент обращается к первому серверу (и устанавливает сеанс с ним), а затем перенаправляется (системой перераспределения нагрузки) на второй сервер? Что происходит с данными сеанса клиента в случае выхода из строя исходного сервера?

Заботясь об обеспечении безопасности, важно учитывать следующие моменты:

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

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

Есть множество примеров недостаточной защиты маркеров. Они были продемонстрированы лабораторией Laboratory for Computer Science Массачусетского технологического института (см. статьюDos and Don'ts of Client Authentication on the Web (Аутентификация клиента в Web: что можно и что нельзя), Кевин Фу (Kevin Fu), Эмил Сит (Emil Sit), Кендра Смит (Kendra Smith) и Ник Фимстер (Nick Feamster)). Таким образом, мы видим, что трудно создать хорошее решение для управления сеансами, не говоря уж о безопасном решении для управления сеансами. Это одна из причин, почему серверы приложений настолько популярны.

Серверы приложений и их механизмы: решение и проблема

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

Примеры серверов приложений:

  • Microsoft® ASP .NET, функционирует поверх IIS
  • Macromedia
  • ColdFusion
  • Apache Tomcat
  • Apache JServ
  • PHP
  • BEA WebLogic
  • IBM® WebSphere® Application Server.

На странице Internet Cookie Report Web-сайта Security Space представлен анализ повторяемости при соотнесении имен cookie с породившим их сервером. Разумеется, этот подход неточен, поскольку некоторые серверы и сайты используют маркеры в параметрах, а не в cookies.

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

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

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

Пример 1. Атака на маркер, построенный на базе системного времени

Мишенью для этой атаки является механизм очень популярного коммерческого сервера приложений. Этот продукт использует два cookies для идентификации сеанса. Пара, образуемая двумя cookies, определяет сеанс. Первый cookie является просто счетчиком, содержимое которого увеличивается при каждом новом сеансе. Он должен гарантировать отсутствие двух одинаковых пар. Второй cookie - это маркер, который должен обезопасить пару, сделав ее "непредсказуемой". Учитывая, что значение первого cookie легко предугадать, мы сосредоточимся на втором cookie, который будет называть TOKEN .

На первый взгляд TOKEN представляет собой последовательность из произвольных восьмизначных чисел. Энтропия (степень случайности) здесь составляет 108 = 226.57, что можно считать достаточным, поскольку трудно направить столь большое количество запросов (100 млн.) на сайт, чтобы это осталось без внимания. Однако при более детальном рассмотрении можно увидеть, что TOKEN описывается следующим уравнением:

Обозначим как  t  время по Гринвичу, выраженное в секундах, 
такое как 01/01/1970 00:00, установленное на сервере приложений.



Обозначим как m составляющую в миллисекундах счетчика синхроимпульсов на сервере приложений.
Тогда: TOKEN= ( 31415821 * ( t + m ) + 1 ) mod 100000000

Интересно отметить, что значение t можно получить из значения HTTP-заголовка Date, которое сервер посылает обратно клиенту вместе со временем первой установки cookies. Это означает, что значение cookie TOKEN является вполне предсказуемым. Фактически, если кому-либо известен интервал времени T </- t < T+ΔT (в секундах), на протяжении которого был сформирован cookie, то он может сделать вывод, что значение TOKEN лежит в пределахΔT+1000, а это не столь уж большой массив значений. Проверка немногим более тысячи значений на сервере может занять всего несколько минут, а за это время сеанс жертвы вероятнее всего будет оставаться активным. Вот схема алгоритма атаки:

Получаем первую пару (id1, TOKEN1). Записываем t1 - 
время сервера (извлекаем из
HTTP заголовка) 

Ждем ΔT секунд.

Получаем вторую пару (id22, TOKEN2). 

Записываем t2 - время сервера (извлекаем из HTTP-заголовка Date) 

if (id2 > id1 +1) 

begin // здесь мы используем предполагаемое время сеанса жертвы.
 for (x= t1 ; x < t2+1000 ; x++) // 
which is ΔT+1000 Итерации начинаем с

Пробуем пару (id1 +1, ( 31415821 * x + 1 ) mod 100000000) end end 

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

Описанный выше алгоритм позволяет атакующему определить маркер жертвы при условии, что cookie был назначен жертве в интервале между двумя попытками атакующего подобрать cookie сайта. Поскольку атакующий может сколь угодно много раз повторять алгоритм, он способен получить эти cookies для всех клиентов, периодически посылая запросы на сайт (скажем, один раз в минуту) и дополнительно выдавая по 1060 запросов для каждого из вновь обнаруженных клиентов. Опять же, как упоминалось выше, можно сократить интервалы между запросами (по одному в секунду) и воспользоваться меньшей дискретностью часов, что в ряде случаев позволяет добиваться цели с помощью 100 запросов на каждого нового клиента .

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

Пример 2. Когда Random() не обеспечивает случайность

В этом примере мы имеем дело со все еще популярным (хотя и несколько устаревшим) механизмом сервера приложений. Этот механизм генерирует один cookie для каждого нового сеанса. Этот cookie (здесь мы называем его ID ) содержит три обязательных поля (F1, F2 и F3) и одно дополнительное (в зависимости от конфигурации сервера) поле (F4, предваряемое точкой), объединенные в единое целое. Вот эти поля:

F1 = 6 символов (A-Z0-9) - число PRNG (генератор псевдослучайных чисел), 
представленное в системе счисления по основанию 36 с начальными нулями 
F2 = 3 символа (A-Z0-9) - 
серверное время (в миллисекундах), деленное на 2000, 
по модулю 363 (=46656), представленное в системе
 счисления по основанию 36 цифр с начальными нулями
F3 = 3 символа (A-Z0-9) - число сеансов за эти 2 секунды, 
представленное в системе счисления по основанию 36 цифр 
F4 = строковая константа (уникальная для сервера)


Как можно видеть, число F4 (если оно присутствует) является константой, а поэтому его вполне можно предугадать. F2 - это просто серверное время (в секундах), поделенное на 2, по модулю 46656, тоже вполне предсказуемое, а число F3 тоже вполне можно определить, так как оно последовательно увеличивается на единицу через каждые две секунды (всегда отсчитывается с единицы).

Таким образом, единственным интересным полем является F1. Казалось бы, оно обладает достаточной энтропией, чтобы обеспечить безопасность системы, поскольку может принимать 366 значений (=231.0). Но опять-таки, если провести полный анализ, то, что на первый взгляд представляется безопасным, на самом деле таковым не является. Пояснение, как и почему можно предугадать значение F1, приведено в Приложении А. Проблема с F1 состоит в том, что при его формировании используется генератор псевдослучайных чисел (PRNG), работа которого сама по себе предсказуема. Зная несколько значений F1, можно предугадать число, сгенерированное PRNG, и, таким образом, будущие (и прошлые) значения F1.

Вот схема такой атаки:

Подготовка: 

Получаем три значения ID через минимально возможные интервалы времени. 

Извлекаем внутренний статус PRNG (как поясняется в Приложении А). 

Через цикл перехвата получаем ID и записываем серверное время
,  t . 

Для простоты полагаем, что  t  четное число. 

Находим внутренний статус PRNG, 
который был использован для генерации этого ID 
(как - поясняется в Приложении) 
ждем
ΔT секунд (здесь ΔT четное число) 
Меняем PRNG и фиксируем все внутренние статусы между состоянием
 PRNG применительно к старому ID и состоянием PRNG 
 применительно к генерации этого ID (как - поясняется в Приложении). 
Назовем список внутренних состояний L 

// ΔT/2 итераций: 
for (T=t; T<t+ΔT; T+=2) 
begin 
каждого внутреннего статуса PRNG  L, i. 
begin 
Пробуем ID cookie состоящий из:  

F1=генерируется из выборки состояний PRNG  i  и i+1; 
F2=T; 
F3=1; // Первый сеанс в этом двухсекундном интервале времени
F4=F4 любой из вычисленных выше ID ; //серверная константа  

end 
end 

Как можно видеть, возможно, хотя и не без усилий, предугадать некоторые идентифицирующие cookies. Необходимо, чтобы интервал времени (ΔT) был коротким (по отношению к ожидаемому коэффициенту использованию сервера), чтобы минимизировать длину списка L (содержащего возможные внутренние статусы PRNG). Если эти интервалы действительно очень малы (менее двух секунд), есть шанс, при правильном выборе промежутков времени, определить, был ли на протяжении текущего 2-секундного интервала запущен новый сеанс, что делает атаку более эффективной (поскольку дополнительные запросы на сервер посылаются только тогда, когда становится известно о создании жертвой нового сеанса). Следует также отметить, что во избежание потери синхронизации (внутреннего статуса PRNG) с сайтом необходимо время от времени запрашивать новый ID, чтобы привести внутренний статус PRNG атакующего в соответствие с новым значением. Это означает, что сайт может интенсивно использовать PRNG, а это вызывает быструю потерю синхронизации (чтобы воспрепятствовать этому, нужно осуществлять ресинхронизацию через минимально возможные промежутки времени, например, каждые несколько минут). С другой стороны, можно получить более четкое представление о внутреннем статусе PRNG, просматривая другие случайные значения, которые могут быть использованы на этом сайте. Это позволит найти обходной путь и сэкономить массу вычислительных ресурсов.

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

Что говорят поставщики

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

Поставщик 2 подтвердил наличие слабости, но ответил нам: "Сеансовые cookies не заменяют маркеры аутентификации. Разумными механизмами являются сеансовые cookies в сочетании со случайно формируемым маркером аутентификации, или проверка логина при аутентификации. Это справедливо для разработки сценариев, основанных на сеансах - даже в ситуациях, когда сеансовые маркеры сегодня считаются 'заслуживающими доверия'." Таким образом, этот поставщик перекладывает ответственность на разработчика.

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

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

Выводы

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

Решение простое: мир Web-приложений должен включать три компонента:

  • Приложение (которое разрабатывается собственными силами и содержит бизнес-логику, а также оригинальные и специфичные для компании/сайта элементы).
  • Среда выполнения приложения (механизм выполнения приложения и Web-сервер, позволяющий упростить разработку приложений и сосредоточиться на приложении, а не на инфраструктуре).
  • Компонент защиты Web-приложения, который обеспечивает безопасность приложения и разгружает разработчиков приложений (а иногда и разработчиков механизмов приложений!), позволяя им не беспокоиться о реализации системы безопасности своего приложения.

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


Страница сайта http://test.interface.ru
Оригинал находится по адресу http://test.interface.ru/home.asp?artId=18952