Защита веб-приложений

Защита веб-приложений #

Васильев Андрей Михайлович, 2024

Версии презентации


Виды информации #

В рамках веб-приложений приходится работать с разными видами информации:

  • Публичная: описание товаров, статьи и т.д.
  • Конфиденциальная: ФИО пользователей, пароли, банковские данные

Конфиденциальную информацию необходимо защищать:

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

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


Безопасность и конфиденциальность #

Данные концепции являются различными, но сильно связными

  • Безопасность — это процесс защиты личных данных и систем от несанкционированного доступа
  • Конфиденциальность — это предоставление пользователю возможность контролировать как его данные собираются, хранятся, используются и что они не используются безответственно

Хорошая безопасность является необходимой для обеспечения конфиденциальности

Обеспечение исключительно конфиденциальности может привести к краже или порче данных системы, т.к. небезопасная передача данных может привести к проблемам.


Функции безопасности веб-браузера #

Рассмотрим базовые возможности по обеспечению безопасности в веб-браузерах

  • Шифрование канала передачи данных
  • Контроль источника запроса, CORS
  • Контексты безопасности (важно для подключения JavaScript-документов)
  • . . .

Многие вопросы не будут рассмотрены в данной лекции, однако рекомендуется самостоятельно ознакомиться со всеми актуальными угрозами и способами их противодействия


Шифрование канала передачи данных #

Корректно зашифрованный поток передачи данных обеспечивает безопасную передачу данных между веб-браузером и сервером: если данные будут перехвачены третьей стороной, то они не смогут их проанализировать

На настоящий момент безопасным считается шифрование с помощью протокола TLS, лежащего в основе протокола HTTPS (HTTP Secure)

Для реализации шифрования необходимо:

  • Зафиксировать доменное имя сервера (получить доступ или приобрести)
  • Получить подписанный сертификат, являющийся основой для шифрования данных
    • Можно заплатить доверенному центру сертификации за выпуск сертификата
    • Можно обратиться к сервису автоматизированного управления сертификатами (Automated Certificate Management Environment, ACME), например Let’s Encrypt
  • Подключить сертификат к веб-серверу либо внутри веб-приложения, либо на уровне прокси-сервера

Без корректной реализации шифрования обеспечить безопасность невозможно


Особенности шифрования #

  • Веб-сервер может установить заголовок Strict-Transport-Security, чтобы указать необходимость использования HTTPS
  • Прозрачность сертификатов позволяет веб-браузеру отслеживать некорректно используемые сертификаты
  • Веб-браузер может отображать смешанное содержимое, т.е. когда часть данных получена по шифрованному каналу, а часть данных по незашифрованному каналу. Даже частичная передача данных по нешифрованному каналу может значительно снизить безопасность. По умолчанию такое поведение блокируется, что хорошо
  • Сервер может использовать устаревшие схемы шифрования, что значительно снижает безопасность пользователя, своевременно обновляйте настройки шифрования, которые устанавливает сервер

Контроль источника запроса #

Следующие технологии используются для реализации контроля источника запроса

  • Политика того же источника определяет как документ или скрипт, загруженный с одного источника может взаимодействовать с ресурсом из другого источника
  • Cross-Origin Resource Sharing (CORS) — механизм, использующий дополнительные заголовки, позволяющий агенту получить разрешение на доступ к ресурсам сервера

Первая технология запрещает доступ к ресурсам сервера, если запрос был сделан со страницы, загруженной с другого домена

diagram


Особенности работы с CORS #

  • При запросе дополнительных данных с того же источника они допускаются
  • При запросе данных с других источников клиент обязуется передать заголовок Origin, указывающий с какого домена выполняется запрос
    • При запросе данных с другого источника клиент должен выполнить предварительный OPTIONS-запрос, для получения политик доступа
    • Сервер должен ответить с заголовком Access-Control-Allow-Origin, указывающий политику разрешений доступа к ресурсу

Поддержка CORS в http4k #

В библиотеке http4k реализована поддержка CORS для серверных приложений

  • ServerFilters.Cors — фильтр, который необходимо настроить для всего приложения
  • CorsPolicy — параметры описания CORS-политики приложения
  • OriginPolicy — набор подходов для обработки источника: любой из, только, шаблон или разрешить все

Защита окружения исполнения сервера #

Доступ к данным должен осуществляться только уполномоченными лицами, чтобы исключить неправомерное использование, изменение, удаление данных или нарушение работы веб-приложения

Для обеспечения безопасности на стороне сервера необходимо выполнять работу систематически над:

  • Исходным кодом веб-приложения (ошибки должны остутствовать)
  • Обновлениями безопасности веб-сервера и другой инфраструктуры
  • Политикой хранения и обновления паролей (как приложения, так и инфраструктуры)
  • Настройками безопасности клиентского кода

Это комплексная задача, корректное решение которой требует детального понимания всех аспектов работы приложения и его окружения

diagram


Типичные проблемы сверверных веб-приложений #

Кратко рассмотрим проблемы, связанные с передачей данных от пользователя

  • Межсайтовый скриптинг (XSS)
  • SQL-инъекции
  • Подделка межсайтовых запросов (CSRF)
  • Перехват нажатий мышкой от пользователя (clickjaking)
  • Отказ в обслуживании (DoS)
  • Раскрытие доступа к файловой системе
  • Выполнение команд в рамках основной ОС

Список текущих актуальных угроз можно посмотреть на сайте OWASP


SQL-инъекция #

Уязвимости SQL-инъекций позволяют злоумышленникам выполнять произвольный SQL-код в базе данных, позволяя получать, изменять или удалять данные независимо от реализованной системы прав пользователя

Эта уязвимость присутствует, если пользовательский ввод, который передаётся в SQL-запрос, может изменить смысл оператора

Рассмотрим следующий код по подготовке SQL-запроса:

val statement = "SELECT * FROM users WHERE name = '$userName';"

Если переменная userName передаётся от пользователя (например в параметрах запроса), то пользователь может передать туда следующую строку:

a';DROP TABLE users; SELECT * FROM userinfo WHERE 't' = 't

В результате выполнится SQL-код:

SELECT * FROM users WHERE name = 'a';DROP TABLE users; SELECT * FROM
    userinfo WHERE 't' = 't';

Управление безопасностью #

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

Управление конфиденциальными данными #

После реализации системы безопасности приложения зачастую необходимо реализовать разделение полномочий пользователей для обеспечения конфиденциальности

Пример. Деление на читателей и администрацию #

  • Большинство пользователей может только просматривать информацию
  • Администрация может добавлять новые элементы на ресурс
  • Если пользователи могут добавлять данные, то администрация имеет возможность модерировать данные, введённые пользователем

Сложные системы разделения полномочий #

  • Пользователю может быть доступна только часть функций
  • Предоставление функций может определяться динамически приложением

Идентификация, аутентификация и авторизация #

  • Идентификация — процедура, в результате выполнения которой для субъекта идентификации выявляется его идентификатор, однозначно определяющий её в информационной системе, например имя пользователя
  • Аутентификация — это процедура проверки подлинности субъекта, например путём сравнения введённого им пароля с паролём, сохранённым в базе данных
  • Авторизация — предоставление субъекту прав на выполнение определённых действий, например на просмотр конфиденциальной информации

Пример процедуры аутентификации #

  1. Пользователь заходит на сайт и нажимает на кнопку «войти в систему»
  2. Система показывает экран для входа в систему
  3. Пользователь вводит имя пользователя, идентифицирует себя
  4. Пользователь вводит пароль, задаёт данные для аутентификации
  5. Пользователь нажимает на кнопку «Войти», начинает процедуру аутентификации
  6. Система получает введённые имя пользователя и пароль, выполняет их проверку и выполняет аутентификацию
  7. Если введённые данные верны, то аутентификационный токен передаётся пользователю в ответе
  8. При следующих обращениях к серверу браузер передаёт данный токен, сервер использует его для авторизации действий

Почему так сложно? #

  • Аутентификация без идентификации невозможна — нельзя определить субъекта, операцию выполнить невозможно
  • Авторизация без аутентификации невозможна — нельзя понять какие действия можно разрешать данному пользователю

Авторизация без идентификации возможна — публичная информация обычно доступна любому пользователю. Но даже в этом случае неявная авторизация выполняется

Как оно может стать ещё сложнее:

  • Вариантов решения задач идентификации, аутентификации и авторизации много
  • Зачастую требуется реализовать несколько вариантов аутентификации в рамках одного приложения

Самостоятельно придуманные процессы аутентификации могут быть небезопасны, в приложениях следует реализовывать сценарии, проверенные специалистами по безопасности


Варианты аутентификации пользователей #

  • Аутентификация согласно встроенным возможностям протокола HTTP
  • Аутентификация с сохранением сессии
  • Аутентификация с использованием сертификатов
  • Аутентификация по одноразовому паролю
  • Аутентификация по ключам доступа
  • Аутентификация по токенам
  • Стандарты аутентификации OAuth и OpenID Connect

Аутентификация по протоколу HTTP #

Задача аутентификации возникла давно и в рамках стандарта HTTP утверждено несколько способов аутентификации: IANA

diagram


  • Поддерживаемый способ аутентификации сервер передаёт в HTTP-заголовоке WWW-Authenticate
  • Данные на сервер передаются клиентом в заголовке Authorization
  • После успешной авторизации пользователя браузер сохраняет данные в своём кеше
    • При каждом следующем запросе они заголовк Authorization отправляется
    • При обработке каждого запроса сервер извлекает данные из заголовка и выполняет авторизацию

Базовая HTTP-аутентификация, RFC7617 #

diagram


Особенности базовой аутентификации #

  • Браузер сохраняет введённые данные и передаёт их ко всем последующим запросам серверу через заголовки
  • Для сброса введённых данных необходимо перезапустить браузер
  • Данные базовой аутентификации передаются в открытом виде и могут быть перехвачены. Необходимо использовать зашифрованное соединение
  • Данные базовой аутентификации можно передать в рамках URL-запроса
    https://username:password@example.com/

Имя пользователя и пароль передаются в формате имя:пароль и отделяются от пути символом @

Будьте аккураты с копированием ссылок — в них могут содержаться конфиденциальные данные


Куки в HTTP протоколе #

HTTP cookie — это небольшой фрагмент данных, отправляемый сервером на браузер пользователя, который может сохранить и отсылать обратно с новым запросом к серверу

Используются в веб-приложениями для:

  • Управления сеансами пользователя, аутентификации, паполнения корзины
  • Персонализации контента
  • Мониторинга поведения пользователя

diagram


Заголовки Set-Cookie и Cookie #

Заголовки Set-Cookie устанавливаются сервером в рамках своего ответа

Простой заголовок может выглядит так:

Set-Cookie: <имя cookie>=<значение cookie>

Таких заголовков в ответе сервера может быть несколько:

Set-Cookie: yummy_cookie=choco
Set-Cookie: tasty_cookie=strawberry

Браузер будет передавать их клиенту в рамках заголовка Cookie:

Cookie: yummy_cookie=choco; tasty_cookie=strawberry

От клиента на сервер будут переданы все куки, которые соответствуют пути запроса документа от веб-браузера


Время жизни куков #

  • Сессионные cookie удаляются при закрытии клиента, то есть существуют только на протяжении текущего сеанса
    • Правила завершения сеанса определяет разработчик веб-браузера
    • Сеанс может длится бесконечно (невообразимо долго)
  • Постоянные cookie удаляются не по завершении сессии, а при наступлении определённого интервала времени, например:
Set-Cookie: id=5aoeu; Expires=Wed, 20 Nov 2010 10:15:00 GMT;

Пользователь может удалить или установить куки на стороне клиента самостоятельно


Безопасность HTTP куков #

  • Данные передаются в открытом виде, для защиты нужно использовать SSL-шифрование
  • Для защиты данных куки от доступа из контекста кода на JavaScript, необходимо использовать атрибут HttpOnly
  • Можно явно указать доменные имена, с которых будет доступна информация с помощью атрибутов Domain и пути с помощью Path
  • «Раздражающее» сообщение о куках необходимо по законодательству стран сообщать пользователю об их использовании веб-приложением и их назначением
  • Многие JavaScript-библиотеки добавляют свои куки, чтобы следить за пользователем

Аутентификация по имени и паролю #

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

Ключевая задача — сформировать токен аутентификации и сохранить его в куки

diagram

Следующие запросы будут выполнять аутентификацю по токену из куков


Сложности аутентификации по паролю #

  • Что делать, если злоумышленник получил доступ к кукам?
  • Как упростить жинь пользователю корпоративных систем, чтобы он один вводил пароль один раз (и не записывал его на бумажке у компьютера)

Для решения этих задач процедуру аутентификации делегируют единой системе, а другие приложения интегрируются с ней с помощью протоколов OpenID Connect и OAuth 2.0

Реализация аутентификации по паролю #

Для решения задачи аутентификации своими силами необходимо:

  • Корректно сохранять данные для идентификации и аутентификации
  • Сохранять средства быстрой проверки аутентификации, токены

Хранение аутентификационных данных #

В рамках приложения необходимо организовать хранилище для зарегистрированных пользователей. Данное хранилище должно включать объекты с полями:

  • Имя пользователя
  • Зашифрованный пароль пользователя

Пароль пользователя нельзя хранить в открытом виде, т.к. при потере данных (которая точно случится) вся защищённая информация станет доступна

Для защиты пароля рекомендуется использовать схему с добавлением соли

diagram

Базы данных обычно предоставляют возможности по выполнению хеширования


Особенности использования соли #

  • Соль должна хранится отдельно от хеша пароля, иначе схема теряет смысл
  • Соль должна быть достаточно длинная, т.к. небольшую соль достаточно легко подобрать по таблицам
  • Соль должна обладать высоким уровнем энтропии
  • Соль нельзя хранить в исходном коде приложения, которое устанавливается на многих компьютерах, т.к. она может быть потеряна
  • Соль может создаваться динамически, например согласно стандарту PBKDF2

Хранение и проверка сессионных токенов #

Для верификации сессионных токенов необходимо:

  • доверять данным, пришедшим от пользователя, т.е. отказаться от проверки данных
  • хранить сессионный токен на стороне сервера для сверки
  • применять схемы с шифрованием данных или подписью данных внутри токена

Хранение сессионных токенов на стороне сервера несёт ряд сложностей:

  • сколько токенов может быть выдано конкретному пользователю?
  • сколько пространства потребуется для хранения всех выданных токенов?
  • сколько времени уйдёт на выявление их корректности?

Последняя схема имеет ряд проблем:

  • надо корректно реализовать криптографические схемы
  • сложно отозвать скомпрометированные токены

Настройки приложения #

Приложению для работы могут потребоваться настройки для встраивания в конкретную информационную систему:

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

Настройки приложения зачастую считываются при старте приложения, для их изменения приложение перезапускается


Источники настроек #

  • Настройки могут быть считаны из файлов на файловой системы
  • Настройки могут быть получены из сетевого хранилища (Infisical)
  • Настройки могут быть переданы через переменные окружения

В рамках курса будем использовать хранение настроек на файловой системе, а для промышленного использования рекомендуется использовать сетевое хранилище


Поддержка настроек в http4k #

Библиотека http4k изначально разрабатывалась для использования в облачных окружениях, в которых параметры передаются через переменные окружения

  • Источником настроек является окружение, описываемое классом Environment
  • Для считывания данных из окружения можно воспользоваться линзами EnvironmentKey

В текущей реализации окруежние может быть построено на основе разных источников:

  • Переменных окружения, Environment.ENV
  • Свойств JVM-окружения, Environment.JVM_PROPERTIES
  • Properties-файлов, Environment.fromConfigFile
  • Из YAML-файлов, Environment.fromYaml

Составление цепочки из источников #

В рамках приложения удобно иметь возможность получения настроек из множества источников одновременно:

  • Из файлов для продуктового использования
  • Из переменных окружения для тестирования работы приложения

Для формирования цепочки из источников предлагается инфиксная функция overrides:

val environmentSource = Environment.ENV
val fileSource = Environment.from("app.properties")
val source = evironmentSource overrides fileSource

Переменные окружения могут быть настроены как в Gradle, так и в параметрах запуска системы сборки Gradle

© A. M. Васильев, 2024, CC BY-SA 4.0, andrey@crafted.su