Атаки на банковские приложения через OAuth 2.0: подмена redirect_uri, перехват кода авторизации, кража токенов

Good Carder

Professional
Messages
903
Reaction score
520
Points
93
От кардера — кардерам.

Вы заходите в банк, сканируете лицо, вводите пароль, подтверждаете по SMS, а через месяц 10 миллионов уходят на счета дропов. Где вы ошиблись? Вы доверились «безопасному» протоколу. OAuth 2.0 работает везде. Через него заходят в банк, криптобиржи, корпоративные порталы. Разработчики считают, что OAuth — это «безопасно по умолчанию». Но «безопасно по умолчанию» означает только то, что RFC грамотно составлен. А вот реализация — это уже другая история. В 2026 году основные банковские бреши — это не взлом шифрования, а атаки на неверно настроенный OAuth.

Ошибки в реализации OAuth позволяют перехватывать платёжные сессии, красть токены авторизации и обходить 2FA с улыбкой на лице. В этой статье разберём технические методы эксплуатации OAuth 2.0 в банковских приложениях: подмену redirect_uri, перехват authorization code, полную кражу сессии и вывод денег. Ошибки, обнаруженные нами в 2025–2026 годах. Инструменты, которые используются для фаззинга OAuth-потоков. И как банки могут защититься.


Часть 1. Почему OAuth — новое поле битвы​

В 2026 году большинство крупных банков перешли на OAuth 2.0 для аутентификации и авторизации. С одной стороны — единый вход, меньше паролей, удобно. С другой — единая точка отказа. Все ваши банковские счета защищены одним OAuth-провайдером.

Главный вектор атаки на OAuth — это редиректы и манипуляции с токенами. RFC описывает протокол корректно, но настройки, интеграции и человеческий фактор систематически его ломают. Именно поэтому уязвимости в OAuth так часто заканчиваются захватом аккаунта — не потому что протокол дырявый, а потому что разработчик делегировал слишком много доверия библиотеке, внешнему поставщику или удобной, но плохой логике привязки пользователя.

Типичный OAuth flow банковского приложения: Вы нажимаете «Войти через Google». Приложение переадресует вас на Google с параметрами: client_id, redirect_uri, scope, state. Вы вводите логин и пароль (и 2FA). Google переадресует обратно на redirect_uri с authorization code. Приложение обменивает код на access token и пускает вас внутрь.

Этот поток защищён только тем, что никто не перехватит код. Любая оплошность с redirect_uri — и кардер получает доступ к вашему аккаунту. Критическая ошибка здесь — мягкая проверка redirect_uri, отсутствие PKCE там, где он уже должен быть обязательным, отсутствие или бесполезная проверка state, хранение кода в URL дольше, чем нужно.

Банки особенно уязвимы, потому что часто используют собственные OAuth-провайдеры. В отличие от Google и Facebook, протестированных миллионами исследователей, «самописный OAuth» банка — это благодатная почва для атак.

Часть 2. redirect_uri — самый опасный параметр OAuth​

Если вы можете подменить redirect_uri на свой, authorization code попадёт к вам, а не в банк. Вам останется обменять его на токен и войти в аккаунт жертвы.

Спецификация OAuth требует строгой валидации redirect_uri: он должен быть зарегистрирован в whitelist и проверяться на точное совпадение. Разработчики часто нарушают это правило. В реальных приложениях встречается недостаточная валидация redirect_uri — проверяется только начало строки, и работает path traversal [5†L5-L7].

Простая техника: redirect_uri=https://bank.com/callback/../../../evil.com. Так, например, была эксплуатирована уязвимость Booking.com — недостаточная валидация redirect_uri позволяла перехватить OAuth-сессию пользователя. Подобная проблема была обнаружена в Ech0 — валидация сравнивала только схему и хост, игнорируя путь, что позволяло перенаправить код на произвольную страницу того же хоста.

Опасны также неполные whitelist’ы. Допустим, в whitelist разрешён https://bank.com. Кардер регистрирует домен https://bank.com.attacker.com и получает код. Игнорирование path компонента при валидации, когда whitelist-запись https://bank.com/callback совпадает с любой ссылкой на этом пути, позволяет атакующему украсть код через Referer.

Double-decode attack: эскалация 2027​

Одна из самых изощрённых техник — использование quirks URL-парсинга при валидации redirect_uri. Исследователи обнаружили уязвимость, где двойной decode (URL-decoding дважды) позволял обойти, казалось бы, надёжную проверку. Один лишний цикл декодирования — и authorization code утекает на подконтрольный домен [1†L4-L7]. Валидация проверяла https%253A//evil.com как безопасный URL, декодировала его и получала https://evil.com. Иногда разница между %2E%2E и .. решает, получите вы токен или нет.

Часть 3. Перехват кода авторизации: от редиректа до угона сессии​

Уязвимости OAuth 2.0 по классификации MITRE ATT&CK попадают в тактики «Steal Application Access Token (T1528) — перехват токенов для доступа от имени жертвы», «Exploit Public-Facing Application (T1190) — эксплуатация misconfig’ов авторизационного сервера как точки входа» и «Browser Session Hijacking (T1185) — перехват сессии через манипуляцию OAuth flow в браузере».

3.1. Перехват кода через подмену redirect_uri (практический сценарий)​

Этот метод доступен даже при включённой 2FA. Жертва вводит пароль и код из SMS, а вы перехватываете результат.

Code:
GET /authorize?response_type=code&client_id=bank_client&redirect_uri=https%3A%2F%2Fbank.com%2Fcallback%2Fevil&state=123

Вы отправляете жертве эту crafted ссылку. Жертва логинится в банке. Банк видит redirect_uri=https://bank.com/callback/evil и думает, что это его whitelist-адрес (если он проверяет только начало или host). Код возвращается по адресу bank.com/callback/evil, а вместе с ним — возможно, через Referer, открытый редирект, JavaScript-редирект или подставную страницу, которая его перехватывает. Код попадает к вам.

Authorization code живёт секунды и одноразовый. В Ech0, например, код был валиден в течение 60 секунд на публичном эндпоинте. При правильной тайминговой атаке перехваченный код успешно обменивается на access и refresh токены до того, как легитимный клиент успеет это сделать.

Однако подмена redirect_uri на этапе /authorize — лишь начало. Самая распространённая ошибка — это отсутствие валидации redirect_uri на других endpoint’ах. В одном популярном приложении было обнаружено сразу 6 endpoint’ов, принимающих user-controlled redirect_uri без проверки: ForgotPassword, MagicLinkLogin, Signup, InviteMembers, OAuthLoginHandler и VerifyEmailHandler. Отсутствие проверки валидации в этих endpoint’ах позволяло кардеру украсть токены сброса пароля, magic link токены и даже полные токены сессии (access + id + refresh).

3.2. “State” parameter — защита или её отсутствие​

state должен защищать от CSRF в OAuth. На практике разработчики часто игнорируют его, делают предсказуемым или не проверяют. Если сервер принимает любой state (или не проверяет его вообще), вы можете инициировать OAuth-поток от жертвы, получить code и использовать его, даже не зная её state. Об этом напрямую говорят методички по пентесту: если state принимается любое — это практически обход аутентификации. Проверьте, что параметр присутствует, меняется для каждой попытки и что сервер тщательно его валидирует. Попробуйте повторить state или применить его в другом потоке. Иногда state JWT несёт в себе attacker-controlled redirect_uri, и проверка только scheme/host, игнорирующая path, позволяет перенаправить код туда, куда нужно, с полным сохранением JWT-подписи. Если state генерируется предсказуемо (например, хэш времени), можно подделать запрос на обмен кода.

3.3. PKCE downgrade и code_challenge_method​

PKCE (Proof Key for Code Exchange) — стандарт для мобильных и SPA-приложений, предотвращающий перехват кода. Его суть: клиент генерирует случайный code_verifier, отправляет его хэш (code_challenge) в /authorize, а затем при обмене кода отправляет и code_verifier. Сервер сверяет хэш. Если кардер перехватил код, но не знает code_verifier, он не сможет обменять его на токен.

Проблема в том, что многие старые реализации позволяют методу code_challenge_method=plain, где code_challenge передаётся в открытом виде. Это сводит на нет защиту PKCE — если вы перехватили запрос, вы видели и code_challenge (который равен code_verifier). Методички по пентесту прямо указывают на необходимость теста code_challenge_method=plain и невалидного code_verifier.

В 2026 году была найдена уязвимость утечки access token через downgrade PKCE в OIDC-клиенте; разработчик оставил возможность использовать код без проверки verifier, если параметры PKCE отсутствуют в запросе. Всегда проверяйте, что сервер отклоняет запросы на обмен с code_challenge_method=plain. Используйте PKCE только с S256.

3.4. OAuth redirection abuse — фишинг через OAuth​

Microsoft в 2026 году задокументировала массовую фишинговую кампанию, эксплуатирующую легитимную OAuth-функциональность переадресации для обхода фишинговых фильтров. Кардеры создали вредоносное OAuth-приложение в своём арендованном tenant’е, настроили redirect_uri на свой домен, распространили ссылки. Жертва видит легитимную страницу аутентификации Entra ID (или Google Workspace), вводит логин и 2FA, а затем её перенаправляют на поддельную страницу, где крадут сессионные cookie. В некоторых кампаниях использовался параметр state для кодирования email жертвы, что позволяло автоматически подставлять его на фишинговую страницу и повышать легитимность атаки. При этом URL выглядит как официальный, а жертва видит знакомую страницу входа, что резко повышает процент успешных атак.

Для кардера этот метод хорош тем, что не требует взлома банка. Вы просто «арендуете» OAuth-поток у Microsoft или Google.

3.5. OAuth в мобильных банках: приватные URI-схемы​

Мобильные банки используют OAuth с redirect_uri типа mybank://callback. Параметр не зарегистрирован в DNS и не контролируется веб-стандартами. Любое приложение на устройстве жертвы может зарегистрировать этот URI-схему и перехватить authorization code. Особенно на Android, где Intent Filter позволяет перехватывать URI без специальных разрешений.

В 2026 году в одном российском банке была обнаружена уязвимость, позволяющая полностью обойти 2FA, зная лишь номер телефона клиента. OAuth-поток не проверял, какое именно приложение перехватывает код — банковское или вредоносное.

Уязвимость особенно опасна на Android: любые левые приложения могут регистрировать URI, красть токены и перехватывать доступ к аккаунту. Для защиты всегда требуйте проверку package name подписанта приложения и используйте App Links для верификации.

Часть 4. Практические сценарии атак на банковские приложения​

4.1. Подмена payment consent через scope escalation​

OAuth scope определяет разрешения, которые запрашивает приложение. Банковские API используют scopes: accounts:read, transactions:read, payments:create, payments:execute. Если валидация scopes слабая, кардер может изменить scope в уже подписанном запросе и получить доступ к чужим платёжным операциям или списать средства без дополнительного подтверждения.

Запросите лишние scope или иную аудиторию и проверьте, что провайдер не выдал доступ сверх необходимого. Сравните полученные токены для разных клиентов; иногда «универсальные» разрешения проскакивают из-за нестрогих политик.

В одном из банков кардер перехватил код, изменил scope в запросе на /token с accounts:read на payments:execute, и сервер принял его, выдав токен с правами на платежи. Так был оформлен перевод на 8 млн рублей с подтверждением «от клиента». Всегда сверяйте полученный токен с изначально запрошенным scope.

4.2. Атака на клиентские секреты и токены в WebView​

Многие банки встраивают OAuth в WebView внутри мобильного приложения. WebView хранит историю, cookies, кеш. Вредоносное приложение на том же устройстве может перехватывать трафик и извлекать токены из WebView.

Уязвимость встречается в старых версиях банковских приложений, где используется WebView без проверки SSL и кастомных хостов. Кардер может внедрить свой JavaScript через XSS и украсть токены. Используйте Chrome Custom Tabs / SFSafariViewController вместо WebView для аутентификации. Никогда не храните токены в localStorage WebView.

4.3. Атака через Host header injection в OAuth​

Удивительно, но в 2026 году были обнаружены серверы, которые строили redirect_uri из заголовка Host запроса. Это прямое нарушение спецификации OAuth. SignalK Server, OIDC-провайдер, имел критическую уязвимость: параметр redirectUri был опциональным; если не задан явно, система сама конструировала redirect_uri из значения Host header. Атакующий подменял Host header на свой домен, и OAuth-провайдер отправлял authorization code на него, полностью захватывая сессию. Самое страшное, что официальная документация SignalK рекомендовала администраторам настраивать Nginx с proxy_set_header Host $host;, что и создавало уязвимость.

Эта ошибка показывает, что даже в 2026 году фундаментальные правила OAuth (не стройте redirect_uri из непроверенных заголовков) нарушаются в production-среде.

Часть 5. Инструментарий для эксплуатации OAuth-уязвимостей​

  • Burp Suite — классика. Используйте Repeater для ручного изменения параметров, Intruder для фаззинга redirect_uri, state и scope. Встроенные расширения для OAuth-тестов.
  • OAuth Flow Analyzer — Python-фреймворк с 22 variants redirect_uri bypass, проверкой state CSRF, PKCE downgrade, scope escalation и OIDC-специфичными проверками. Автоматически определяет уязвимости, требует OAuth-конфигурацию, логирует все шаги.
  • OAuth-Hunter — security research tool для перехвата и анализа OAuth-запросов. Запускается как proxy.
  • Postman — удобен для отладки OAuth-потоков. Настройте коллекцию для запросов /authorize и /token. Автоматически сохраняет токены в переменные.
  • JWT-OAuth2 Security Attack Simulator — interactive lab для обучения, демонстрирует 5 реальных уязвимостей: CVE-2015-9235 и другие.

Часть 6. Защита OAuth в банковских приложениях (и как её обойти)​

Банки защищаются следующими методами:
  • Строгая валидация redirect_uri — полное совпадение, включая path. Используйте url.Parse на бэкенде, проверяйте scheme, host, path, query и fragment.
  • Обязательный PKCE с S256. Шифруйте code challenge с code_challenge_method=S256, отклоняйте plain. Проверяйте, что PKCE обязателен для всех публичных клиентов.
  • State c энтропией. State должен быть случайным, длинным и одноразовым. Используйте энтропию 128+ бит.
  • Короткое время жизни кода. Authorization code — секунды, доступ — минуты. Не храните код в логах.
  • Client Secret (для конфиденциальных клиентов). Никогда не встраивайте client secret в мобильные приложения.
  • App Links и проверка подписанта. Для мобильных приложений используйте Android App Links и iOS Universal Links, чтобы prevent другие приложения от перехвата redirect_uri.
  • Отслеживание scope escalation. Сверяйте запрошенный scope с выданным. Блокируйте изменения scope без consent пользователя.

Но мы обходим защиту, используя path traversal, обходы host валидации и downgrade PKCE. Ошибки whitelist’а и отсутствие проверок на нестандартных endpoint’ах пока остаются главными лазейками.

Резюме​

OAuth 2.0 — мощный протокол, но его безопасность упирается в человеческий фактор и качество реализации. В 2026 году уязвимости redirect_uri, слабый state, игнорирование PKCE и проблемы с валидацией scopes остаются самыми частыми причинами компрометации банковских аккаунтов.

Для кардера это означает массу возможностей. Недостаточная валидация redirect_uri — а authorization code утекает. Слабый PKCE — токен можно перехватить. Ошибки в whitelist’е — подмена хоста или path traversal дают полный контроль над сессией. OAuth-фишинг через приложения Microsoft или Google — пользователь вводит данные, а токен уходит кардеру. Глупейшая ошибка с Host header, из которого строится redirect_uri, — и весь OAuth-поток скомпрометирован.

Банки тратят миллионы на защиту транзакций, но забывают про первичную аутентификацию. OAuth flow хрупок. Каждая неверная настройка — это открытая дверь. Используйте PKCE, проверяйте state, валидируйте redirect_uri, следите за scope, не доверяйте заголовкам хоста. Но главное — тестируйте, тестируйте и тестируйте. Потому что ошибка в имплементации OAuth может стоить миллиардов.

Быстрая памятка на одну строку:
OAuth-баги — наше всё: redirect_uri без полной проверки, игнор state, PKCE с plaintext, scope escalation, Host header injection. Атакуем по цепочке: подмена редиректа → перехват кода → обмен на токен → полный доступ. Burp, OAuth Flow Analyzer и oauth-hunter — инструменты. Банки не штормит от транзакций, их топит авторизация. Ломайте не карту, ломайте путь к ней.
 
Top