1. введение
OAuth – это отраслевая стандартная структура для делегированной авторизации. Много мыслей и забот было вложено в создание различных потоков, составляющих стандарт. Даже тогда это не лишено уязвимости.
В этой серии статей мы обсудим атаки на OAuth с теоретической точки зрения и опишем различные варианты защиты наших приложений.
2. Предоставление Кода Авторизации
Поток Предоставление кода авторизации – это поток по умолчанию, используемый большинством приложений, реализующих делегированную авторизацию.
Перед началом этого потока Клиент должен предварительно зарегистрироваться на Сервере авторизации, и во время этого процесса он также должен предоставить URL-адрес перенаправления, то есть URL — адрес, по которому Сервер авторизации может перезвонить Клиенту с Кодом авторизации.
Давайте подробнее рассмотрим, как это работает и что означают некоторые из этих терминов.
Во время Потока предоставления кода авторизации Клиент (приложение, запрашивающее делегированную авторизацию) перенаправляет Владельца ресурса (пользователя) на Сервер авторизации (например, Вход в систему с помощью Google ). После входа в систему Сервер авторизации перенаправляет обратно клиенту код авторизации.
Затем клиент обращается к конечной точке на Сервере авторизации, запрашивая Маркер доступа, предоставляя Код авторизации. На этом этапе поток завершается, и клиент может использовать токен для доступа к ресурсам, защищенным Сервером авторизации.
Теперь Платформа OAuth 2.0 позволяет этим клиентам быть общедоступными , скажем, в сценариях, когда Клиент не может безопасно хранить секрет Клиента. Давайте рассмотрим некоторые атаки перенаправления, которые возможны против публичных клиентов.
3. Атаки Перенаправления
3.1. Предпосылки атаки
Атаки перенаправления основаны на том факте, что стандарт OAuth не полностью описывает степень, в которой должен быть указан этот URL-адрес перенаправления. Это сделано специально.
Это позволяет некоторым реализациям протокола OAuth разрешить частичный URL-адрес перенаправления.
Например, если мы зарегистрируем Идентификатор клиента и URL-адрес перенаправления клиента со следующим совпадением на основе подстановочных знаков на сервере авторизации:
* . cloudapp.net
Это было бы справедливо для:
Это было бы справедливо для:
но и для:
но и для:
Мы выбрали cloudapp.net домен специально, так как это реальное место, где мы можем размещать приложения с поддержкой OAuth. Домен является частью платформы Microsoft Windows Azure и позволяет любому разработчику разместить под ним поддомен для тестирования приложения. Это само по себе не проблема, но это жизненно важная часть большого подвига.
Вторая часть этого эксплойта-это сервер авторизации, который позволяет сопоставлять подстановочные знаки в URL-адресах обратного вызова.
Наконец, чтобы реализовать этот эксплойт, разработчику приложения необходимо зарегистрироваться на сервере авторизации, чтобы принять любой URL-адрес в основном домене в форме *.cloudapp.net .
3.2. Нападение
При выполнении этих условий злоумышленнику необходимо обманом заставить пользователя запустить страницу из поддомена, находящегося под его контролем, например, отправив пользователю аутентичное электронное письмо с просьбой предпринять какие-либо действия в учетной записи, защищенной OAuth. Как правило, это будет выглядеть примерно так https://evil.cloudapp.net/login . Когда пользователь откроет эту ссылку и выберет логин, он будет перенаправлен на Сервер авторизации с запросом авторизации:
GET /authorize?response_type=code&client_id={apps-client-id}&state={state}&redirect_uri=https%3A%2F%2Fevil.cloudapp.net%2Fcb HTTP/1.1
Хотя это может выглядеть типично, этот URL-адрес является вредоносным. См., что в этом случае Сервер авторизации получает измененный URL-адрес с идентификатором клиента приложения и URL-адресом перенаправления, указывающим на приложение evil .
Затем Сервер авторизации проверит URL-адрес, который является поддоменом в указанном основном домене. Поскольку Сервер авторизации считает, что запрос исходил из действительного источника, он аутентифицирует пользователя, а затем запрашивает согласие, как обычно.
После этого он будет перенаправлен обратно в evil.cloudapp.net поддомен, передающий код авторизации злоумышленнику.
Поскольку у злоумышленника теперь есть Код авторизации, все, что ему нужно сделать, это вызвать конечную точку маркера Сервера авторизации с Кодом авторизации, чтобы получить маркер, который позволяет ему получить доступ к защищенным ресурсам Владельца Ресурса.
4. Оценка уязвимости сервера авторизации Spring OAuth
Давайте рассмотрим простую конфигурацию сервера авторизации Spring OAuth:
@Configuration public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.inMemory() .withClient("apricot-client-id") .authorizedGrantTypes("authorization_code") .scopes("scope1", "scope2") .redirectUris("https://app.cloudapp.net/oauth"); } // ... }
Здесь мы видим, что Сервер авторизации настраивает нового клиента с идентификатором “apricot-clientid” . Нет никакого секрета клиента, так что это публичный клиент.
Наши уши безопасности должны оживиться при этом , так как теперь у нас есть два из трех условий – злые люди могут регистрировать поддомены и мы используем публичного клиента.
Но обратите внимание, что мы также настраиваем URL-адрес перенаправления и что он является абсолютным . Таким образом, мы можем смягчить уязвимость.
4.1. Строгий
По умолчанию Spring OAuth обеспечивает определенную степень гибкости при сопоставлении URL-адресов перенаправления.
Например, Распознаватель перенаправлений По умолчанию поддерживает сопоставление поддоменов.
Давайте использовать только то, что нам нужно. И если мы можем точно соответствовать URL-адресу перенаправления, мы должны это сделать:
@Configuration public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { //... @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) { endpoints.redirectResolver(new ExactMatchRedirectResolver()); } }
В этом случае мы переключились на использование Exact Match RedirectResolver для URL-адресов перенаправления. Этот распознаватель выполняет точное совпадение строк, никак не анализируя URL-адрес перенаправления. Это делает его поведение гораздо более безопасным и уверенным.
4.2. Снисходительность
Мы можем найти код по умолчанию, который имеет дело с сопоставлением URL-адресов перенаправления, в источнике Spring Security OAuth :
/** Whether the requested redirect URI "matches" the specified redirect URI. For a URL, this implementation tests if the user requested redirect starts with the registered redirect, so it would have the same host and root path if it is an HTTP URL. The port, userinfo, query params also matched. Request redirect uri path can include additional parameters which are ignored for the matchFor other (non-URL) cases, such as for some implicit clients, the redirect_uri must be an exact match. @param requestedRedirect The requested redirect URI. @param redirectUri The registered redirect URI. @return Whether the requested redirect URI "matches" the specified redirect URI. */ protected boolean redirectMatches(String requestedRedirect, String redirectUri) { UriComponents requestedRedirectUri = UriComponentsBuilder.fromUriString(requestedRedirect).build(); UriComponents registeredRedirectUri = UriComponentsBuilder.fromUriString(redirectUri).build(); boolean schemeMatch = isEqual(registeredRedirectUri.getScheme(), requestedRedirectUri.getScheme()); boolean userInfoMatch = isEqual(registeredRedirectUri.getUserInfo(), requestedRedirectUri.getUserInfo()); boolean hostMatch = hostMatches(registeredRedirectUri.getHost(), requestedRedirectUri.getHost()); boolean portMatch = matchPorts ? registeredRedirectUri.getPort() == requestedRedirectUri.getPort() : true; boolean pathMatch = isEqual(registeredRedirectUri.getPath(), StringUtils.cleanPath(requestedRedirectUri.getPath())); boolean queryParamMatch = matchQueryParams(registeredRedirectUri.getQueryParams(), requestedRedirectUri.getQueryParams()); return schemeMatch && userInfoMatch && hostMatch && portMatch && pathMatch && queryParamMatch; }
Мы видим, что сопоставление URL-адресов выполняется путем разбора входящего URL-адреса перенаправления на его составные части. Это довольно сложно из-за нескольких особенностей, например, должны ли совпадать порт, поддомен и параметры запроса. И решение разрешить совпадения поддоменов – это то, о чем стоит подумать дважды.
Конечно, такая гибкость есть, если она нам нужна – давайте просто использовать ее с осторожностью.
5. Неявные Атаки Перенаправления Потока
Чтобы было ясно, Неявный поток не рекомендуется . Гораздо лучше использовать поток предоставления кода авторизации с дополнительной безопасностью, обеспечиваемой PKCE . Тем не менее, давайте посмотрим, как атака перенаправления проявляется с неявным потоком.
Атака перенаправления против неявного потока будет следовать той же основной схеме, что и выше. Основное отличие заключается в том, что злоумышленник получает токен немедленно, так как нет шага обмена кодом авторизации.
Как и прежде, абсолютное совпадение URL-адреса перенаправления также смягчит этот класс атак.
Кроме того, мы можем обнаружить, что неявный поток содержит еще одну связанную уязвимость. Злоумышленник может использовать клиент в качестве открытого перенаправителя и заставить его повторно присоединить фрагменты .
Атака начинается, как и раньше, с того, что злоумышленник заставляет пользователя посетить страницу, находящуюся под контролем злоумышленника, например, https://evil.cloudapp.net/info . Страница создается для инициирования запроса авторизации, как и раньше. Однако теперь он включает URL-адрес перенаправления:
GET /authorize?response_type=token&client_id=ABCD&state=xyz&redirect_uri=https%3A%2F%2Fapp.cloudapp.net%2Fcb%26redirect_to %253Dhttps%253A%252F%252Fevil.cloudapp.net%252Fcb HTTP/1.1
redirect_to https://evil.cloudapp.net настраивает конечную точку авторизации для перенаправления токена в домен, находящийся под контролем злоумышленника. Теперь сервер авторизации сначала перенаправит на фактический сайт приложения:
Location: https://app.cloudapp.net/cb?redirect_to%3Dhttps%3A%2F%2Fevil.cloudapp.net%2Fcb#access_token=LdKgJIfEWR34aslkf&...
Когда этот запрос поступит в открытый перенаправитель, он извлечет URL-адрес перенаправления evil.cloudapp.net а затем перенаправить на сайт злоумышленника:
https://evil.cloudapp.net/cb#access_token=LdKgJIfEWR34aslkf&...
Абсолютное сопоставление URL-адресов также смягчит эту атаку.
6. Резюме
В этой статье мы обсудили класс атак на протокол OAuth, основанных на URL-адресах перенаправления.
Хотя это имеет потенциально серьезные последствия, использование абсолютного сопоставления URL-адресов на сервере авторизации смягчает этот класс атак.