Распространенные уязвимости аутентификации и авторизации (и как их избежать)

Аутентификация и авторизация – это два значимых элемента безопасности современных веб-приложений, однако существует множество способов сделать в них ошибки. Эта статья освещает то, как выявлять такие недостатки безопасности и избегать уязвимостей, которые могут позволить злоумышленникам получить доступ к конфиденциальным данным и функциям, обходя аутентификацию, авторизацию или и то, и другое одновременно.

В чем разница между аутентификацией и авторизацией?

Аутентификация и авторизация не только звучат и выглядят подобно, но и тесно связаны между собой. Ниже наведены их определения:

  • Аутентификация – это подтверждение личности (идентичности). Это может быть ввод имени пользователя и пароля, использование системы единого входа или предоставление уникального ключа доступа.
  • Авторизация – это проверка прав доступа. После аутентификации приложение должно убедиться, что пользователь имеет разрешение на доступ к определенному ресурсу или операции, обычно на основе его роли.

Поскольку оба процесса обычно выполняются вместе, их часто обобщают термином “auth”. Так как современные корпоративные веб-приложения сильно зависят от правильного обеспечения контроля доступа для защиты конфиденциальных данных, уязвимости и атаки, связанные с аутентификаціией и авторизацией, особенно значимы для веб-безопасности.

Распространенные типы уязвимостей

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

Распределенные архитектуры программного обеспечения усложняют это еще больше: запросы часто проходят через несколько сервисов и интерфейсов. Обеспечить надлежащий контроль доступа в такой среде очень трудно, особенно когда разные модули создаются отдельными командами. Проблемы с передачей auth-данных через API, форматы данных, домены и физические системы только повышают вероятность ошибок. Вот несколько типичных примеров:

Небезопасные сравнения значений

Одной из проблем являются небезопасные сравнения значений, которых еще называют “type juggling” уязвимостями. Два из самых популярных языков программирования, а именно JavaScript и PHP, имеют нестрогую (слабую) типизацию. Это означает, что они по умолчанию очень снисходительны к типам принимаемых данных. Каждый из них имеет свои особенности в сравнении значений, поэтому без надлежащей проверки входящих данных злоумышленники могут ввести специальное значение, которое всегда принимается в определенном контексте.

Пример: форма входа, где значения имени пользователя и пароля отправляются непосредственно к уязвимому скрипту на основе PHP, который использует нестрогие сравнения с оператором ==. Сравнение любой строки с TRUE или 0 с помощью него (по умолчанию) даст результат TRUE. Достаточно просто включить в запрос на вход в формате JSON логическое значение (boolean) TRUE, чтобы обойти аутентификацию.

Использование строгих сравнений с оператором === или (еще лучше) специальной функции сравнения обычно достаточно, чтобы избежать этой уязвимости. Но в больших программных проектах даже такие, казалось бы, тривиальные ошибки иногда могут попасть в продакшн.

Подводные камни контроля через каталоги

Еще одной плохой практикой, которая может привести к атакам обхода аутентификации и авторизации, является внедрение контроля доступа путем проверки определенного каталога. К примеру, приложение может проверить, имеет ли пользователь право доступа к панели администратора, просто сравнивая каталог, запрашиваемый пользователем, с тем, что ведет к панели администратора. Без очистки входящих данных можно обойти аутентификацию и авторизацию, вставив строки (strings) обхода каталога, чтобы запросить тот, который выглядит иначе (т.е. не блокируется), но в конце концов ведет к тому же URL-адресу панели администратора.

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

Неоправданное доверие к источникам авторизации и аутентификации

В сложных архитектурах, развертываниях и потоках данных решения, связанные с аутентификацией и авторизацией, часто отходят на второй план. Это особенно актуально, например, при обработке запросов, полученных через API, а не от пользователей. В приложениях на основе сотен микросервисов аутентификация и авторизация часто осуществляются только через API во фронтенде, поэтому службы бэкенда не имеют представления, от кого этот запрос. Если фронтенд имеет уязвимость обхода каталога, то бэкенд выполнит запрос, потенциально раскрывая конфиденциальные данные.

Решение, кому и чему код должен доверять, может иметь плохие последствия. Один реальный недостаток (давно исправленный) был найден в 2017 году, когда веб-сайт Uber оказался уязвимым к краже аккаунта через захват поддомена. Исследователь безопасности Arne Swinnen заметил, что один из субдоменов Uber указывал на другой домен, который он смог занять. Процесс аутентификации включал установку токена сессии, действительного для всех поддоменов Uber, включая тот, на который претендовал специалист. Перенаправляя пользователей на этот домен, он мог бы считывать сетевые токены и перехватывать учетные записи. И все это благодаря доверию к аутентификации на уровне домена.

Отсутствие контроля доступа на уровне функций

Этот класс охватывает сбои в проверке, имеет ли пользователь право использовать определенную функцию. В кейсе уязвимости в Maian Support Helpdesk, юзеры могли вызвать некоторые API-интерфейсы, которые не были видны в пользовательском интерфейсе, но все еще были доступны, включая определенные операции администратора. Без систематического контроля доступа на уровне функций такие упущения могут легко позволить злоумышленникам получить несанкционированный доступ.

Реализация контроля доступа может быть особенно сложной для GraphQL API, где существует много способов доступа к одним и тем же данным через разные запросы. В идеале каждый запрос должен возвращать только те данные, к которым текущий пользователь имеет право доступа. Любая ошибка на этом этапе может позволить злоумышленникам получить конфиденциальную информацию. Это особенно актуально, например, при добавлении слоя GraphQL в существующий API REST.

Ненадлежащее управление токенами

На уровне HTTP-запросов контроль доступа зависит от безопасного создания правильных токенов доступа и их отправки в систему в нужное время. Каждый раз, когда злоумышленникам удается получить действительный токен доступа (например, cookie сессии), есть риск перехвата сессии. Угроза кражи токенов на стороне клиента особенно высока в сложных процессах систем единого входа (SSO), где неправильные конфигурации могут позволить злоумышленникам перехватывать токены доступа через перенаправление или считывать их из журналов сервера.

Токены сброса пароля – это еще один критический механизм безопасности, подверженный неправильному управлению. Например, приложение может раскрыть API-интерфейс для создания токенов сброса пароля. Любая уязвимость, позволяющая злоумышленникам вызывать этот API, также может позволить им сбрасывать пароли для аккаунтов пользователей, что приведет к их захвату. Такие недостатки могут быть вызваны путаницей авторизации во вторичных контекстах или просто предположением, что поскольку API-інтерфейс является приватным, его не могут вызвать неавторизованные пользователи.

Лучшие практики для внедрения аутентификации и авторизации

В OWASP Top 10 за 2021 год нарушение контроля доступа занимает первое место среди проблем безопасности веб-приложений. Обеспечение надежного доступа требует тщательного планирования, правильного написания кода и постоянной проверки.

Рекомендации:

  • Включать вопросы авторизации и аутентификации уже на этапах планирования и дизайна ПО.
  • Реализовывать контроль доступа на уровне приложения, а не только сервера.
  • Соблюдать практики написания безопасного кода, регулярно проводить его проверку.
  • Если возможно, использовать проверенные библиотеки для аутентификации и авторизации вместо создания собственных решений.
  • Проверять контроль доступа на всех этапах разработки, включая продакшн.
  • Контролировать стороннюю инфраструктуру, которая может использоваться для обхода механизмов аутентификации и авторизации.

Подписаться на новости