Чудесный мир OAuth: Bug Bounty Edition
Если вы когда-либо были на веб-сайте, вы, вероятно, в тот или иной момент сталкивались с OAuth, даже если никогда о нем не слышали. Вы видели кнопку «Войти через Google»? Если да, то вы столкнулись с OAuth! В этой статье мы кратко обсудим, что такое OAuth (в частности, OAuth 2.0) и как его можно реализовать неправильно с точки зрения безопасности. В частности, в нем будут освещены многие проблемы, с которыми я столкнулся в реализациях во время поиска ошибок.
«Быстрая» грунтовка
Есть несколько разных версий, а также типы грантов, которые следует учитывать, когда мы говорим об OAuth. Чтобы прочитать об этом, я рекомендую прочитать https://oauth.net/2/ , чтобы получить базовое понимание. В этой статье мы сосредоточимся на наиболее распространенном потоке, с которым вы столкнетесь сегодня, а именно на типе предоставления кода авторизации OAuth 2.0 . По сути, OAuth предоставляет разработчикам механизм авторизации, позволяющий приложению получать доступ к данным или выполнять определенные действия с вашей учетной записью из другого приложения (сервера авторизации).
Например, предположим, что веб-сайт https://yourtweetreader.com имеет функцию отображения всех твитов, которые вы когда-либо отправляли, включая личные твиты. Для этого вводится OAuth 2.0. https://yourtweetreader.com попросит вас разрешить их приложению Twitter доступ ко всем вашим твитам. появится страница согласия, На https://twitter.com показывающая, какие разрешения запрашиваются, и кто разработчик, запрашивающий их. После того как вы разрешите запрос, https://yourtweetreader.com сможет получить доступ к вашим твитам от вашего имени. Так вот, это был очень высокий уровень, и здесь есть некоторая сложность. Взяв этот пример, вот немного больше деталей о конкретных элементах, которые важно понимать в контексте OAuth 2.0:
владелец ресурса : The resource owner
это пользователь/организация, предоставляющая доступ к своему защищенному ресурсу, например, к своей учетной записи в Твиттере.
сервер ресурсов : The resource server
сервер, обрабатывающий аутентифицированные запросы после того, как приложение получило access token
от имени resource owner
. В приведенном выше примере это будет https://twitter.com.
клиентское приложение : client application
приложение, запрашивающее авторизацию у resource owner
. В этом примере это будет https://yourtweetreader.com.
сервер авторизации : The authorization server
сервер выдает access tokens
к client application
после успешной аутентификации resource owner
и получение авторизации. В приведенном выше примере это будет https://twitter.com .
client_id : client_id
является идентификатором приложения. Это общедоступный, несекретный уникальный идентификатор.
client_secret : client_secret
является секретом, известным только приложению и серверу авторизации. Это используется для генерации access_tokens
ответ_тип : response_type
— это значение, указывающее, какой тип токена запрашивается, например code
область применения : scope
запрошенный уровень доступа client application
просит от resource owner
redirect_uri : redirect_uri
URL-адрес, на который перенаправляется пользователь после завершения авторизации. Обычно это должно соответствовать URL-адресу перенаправления, который вы ранее зарегистрировали в службе.
состояние : state
Параметр может сохранять данные между пользователем, направляемым на сервер авторизации, и обратно. Важно, чтобы это было уникальное значение, поскольку оно служит механизмом защиты CSRF, если оно содержит уникальное или случайное значение для каждого запроса.
Grant_type : grant_type
Параметр объясняет, что такое тип гранта и какой токен будет возвращен.
код : это code
код авторизации, полученный от authorization server
который будет в параметре строки запроса «код» в этом запросе. Этот код используется вместе с client_id
а также client_secret
клиентским приложением для получения access_token
access_token : access_token
— это токен, который клиентское приложение использует для выполнения запросов API от имени resource owner
refresh_token : refresh_token
позволяет приложению получить новый access_token
без запроса пользователя
Что ж, это должно было быть кратким введением, но, похоже, с OAuth вы не можете просто дать краткое описание. Собрав все это вместе, вот как выглядит реальный поток OAuth:
- Вы посещаете https://yourtweetreader.com и нажимаете кнопку «Интеграция с Twitter».
- https://yourtweetreader.com отправляет запрос на https://twitter.com и просит вас, владельца ресурса, разрешить приложению Twitter https://yourtweetreader.com доступ к вашим твитам. Запрос будет выглядеть так:
https://twitter.com/auth
? ответ_тип = код
&client_id=вашweetreader_clientId
&redirect_uri=https%3A%2F%2Fyourtweetreader.com%2Fобратный вызов
&scope=readTweets
&state=kasodk9d1jd992k9klaskdh123
3. Вам будет предложено перейти на страницу согласия:
4. После принятия Twitter отправит запрос обратно redirect_uri
с code
а также state
параметры:
https://yourweetreader.com?code=asd91j3jd91j92j1j9d1& состояние = kasodk9d1jd992k9klaskdh123
5. https://yourtweetreader.com примет это code
, и с помощью своего приложения client_id
а также client_secret
, сделает запрос с сервера на получение access_token
от вашего имени, что позволит им получить доступ к разрешениям, на которые вы согласились:
POST /oauth/access_token
Хост: twitter.com
... {"client_id": " yourtweetreader_clientId", "client_secret": "yourtweetreader_clientSecret", "code": " asd91j3jd91j92j1j9d1", "grant_type": "авторизация_код"}
6. Наконец, поток завершен, и https://yourtweetreader.com сделает вызов API к Twitter с вашим access_token
для доступа к вашим твитам.
Находки по программе Bug Bounty
Теперь самое интересное! Есть много вещей, которые могут пойти не так в реализации OAuth, вот различные категории ошибок, которые я часто вижу:
Слабая конфигурация redirect_uri
Вероятно, это одна из наиболее распространенных вещей, о которых все знают при поиске ошибок реализации OAuth. redirect_uri
очень важно, потому что конфиденциальные данные, такие как code
добавляется к этому URL-адресу после авторизации. Если redirect_uri
может быть перенаправлен на сервер, контролируемый злоумышленником, это означает, что злоумышленник потенциально может захватить учетную запись жертвы, используя code
себя и получить доступ к данным жертвы.
То, как это будет использоваться, будет зависеть от сервера авторизации. Некоторые примут только то же самое redirect_uri
путь, указанный в клиентском приложении, но некоторые принимают что угодно в том же домене или подкаталоге redirect_uri
.
В зависимости от логики, обрабатываемой сервером, существует ряд методов обхода redirect_uri
. В ситуации, когда redirect_uri
, https://yourtweetreader.com/callback к ним относятся:
- Открытые перенаправления:
https://yourtweetreader.com/callback?redirectUrl=https://evil.com
- Обход пути:
https://yourtweetreader.com/callback/../redirect?url=https://evil.com
- Слабый
redirect_uri
регулярные выражения:https://yourtweetreader.com.evil.com
- HTML-инъекция и кража токенов через заголовок реферера:
https://yourtweetreader.com/callback/home/attackerimg.jpg
Неправильная обработка параметра состояния
Это, безусловно, самая распространенная проблема, которую я вижу в реализациях OAuth. Очень часто, state
параметр полностью опущен или используется неправильно. Если параметр состояния не существует или является статическим значением, которое никогда не меняется, поток OAuth, скорее всего, будет уязвим для CSRF. Иногда, даже при наличии state
параметр, приложение может не выполнять проверку параметра, и атака сработает. Способ использовать это — пройти процесс авторизации под своей учетной записью и сделать паузу сразу после авторизации. Затем вы столкнетесь с запросом, например:
https://yourweetreader.com?code=asd91j3jd91j92j1j9d1
После того, как вы получите этот запрос, вы можете отказаться от него, поскольку эти коды обычно используются один раз. Затем вы можете отправить этот URL вошедшему в систему пользователю, и он добавит вашу учетную запись к их учетной записи. Поначалу это может показаться не очень важным, поскольку вы просто добавляете свою учетную запись к учетной записи жертвы. Однако многие реализации OAuth предназначены для входа в систему, поэтому, если вы можете добавить свою учетную запись Google, которая используется для входа в систему, вы потенциально можете выполнить захват учетной записи одним щелчком мыши, поскольку вход в систему с помощью вашей учетной записи Google даст вам доступ к аккаунт потерпевшего.
Я также несколько раз видел, как параметр состояния использовался в качестве дополнительного значения перенаправления. Приложение будет использовать redirect_uri
для первоначального перенаправления, но затем state
в качестве второго перенаправления, которое может содержать code
в параметрах запроса или заголовке реферера.
Важно отметить, что это относится не только к ситуациям входа в систему и захвату учетной записи. Я видел неверные настройки в:
- Интеграция Slack, позволяющая злоумышленнику добавить свою учетную запись Slack в качестве получателя всех уведомлений/сообщений.
- Интеграция Stripe, позволяющая злоумышленнику перезаписывать платежную информацию и принимать платежи от клиентов жертвы.
- Интеграция PayPal, позволяющая злоумышленнику добавить свою учетную запись PayPal к учетной записи жертвы, которая будет вносить деньги в PayPal злоумышленника.
Назначение учетных записей на основе адреса электронной почты
Одна из других наиболее распространенных проблем, которые я вижу, — это когда приложения разрешают «Войти с помощью X», но также и имя пользователя/пароль. Есть 2 разных способа атаковать это:
- Если приложение не требует проверки электронной почты при создании учетной записи, попробуйте создать учетную запись с адресом электронной почты жертвы и паролем злоумышленника до того, как жертва зарегистрируется. Если затем жертва попытается зарегистрироваться или войти в систему через третью сторону, например Google, возможно, приложение выполнит поиск, увидит, что электронная почта уже зарегистрирована, а затем свяжет свою учетную запись Google с учетной записью, созданной злоумышленником. Это «захват предварительной учетной записи», когда злоумышленник будет иметь доступ к учетной записи жертвы, если он создал ее до регистрации жертвы.
- Если приложение OAuth не требует проверки электронной почты, попробуйте зарегистрироваться в этом приложении OAuth, указав адрес электронной почты жертвы. Та же проблема, что и выше, может существовать, но вы атакуете ее с другого направления и получаете доступ к учетной записи жертвы для захвата учетной записи.
Раскрытие секретов
Очень важно определить, какие из множества параметров OAuth являются секретными, и защитить их. Например, утечка client_id
совершенно прекрасно и необходимо, но утечка client_secret
опасный. В случае утечки злоумышленник может потенциально использовать доверие и личность доверенного клиентского приложения для кражи данных пользователя. access_tokens
и личная информация/доступ к их интегрированным учетным записям. Возвращаясь к нашему предыдущему примеру, одна проблема, которую я видел, заключается в выполнении этого шага с клиента, а не с сервера:
5. https://yourtweetreader.com примет это code
, и с помощью своего приложения client_id
а также client_secret
, сделает запрос с сервера на получение access_token
от вашего имени, что позволит им получить доступ к разрешениям, на которые вы согласились.
Если это делается с клиента, client_secret
будут просочены, и пользователи смогут генерировать access_tokens
от имени приложения. С помощью некоторой социальной инженерии они также могут добавить больше областей авторизации OAuth, и все это будет выглядеть законным, поскольку запрос будет исходить от доверенного клиентского приложения.
Итого
Существует множество других атак и вещей, которые могут пойти не так при реализации OAuth, но это одни из наиболее распространенных, которые вы увидите. Эти неправильные конфигурации встречаются на удивление часто, и из-за них возникает очень большое количество ошибок. Я намеревался сделать «Краткий курс» довольно коротким, но быстро понял, что все знания необходимы для остальной части поста. Учитывая это, логично, что большинство разработчиков не будут знать всех деталей безопасной реализации. Чаще всего эти проблемы имеют высокую степень серьезности, поскольку они связаны с утечкой/манипулированием конфиденциальными данными и захватом учетных записей. В какой-то момент я хотел бы более подробно остановиться на каждой из этих категорий, но хотел, чтобы это послужило общим введением и дало идеи, на что обратить внимание!