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

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

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

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


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

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

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

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

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

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


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

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

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

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


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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

flowchart LR subgraph Веб-браузер example_document[["HTML-документ с\nexample.com"]] end example_server("Сервер example.com") tracking_server("Сервер отслеживания пользователей") external_server("Сервер изображений private-pics.com") example_document -- CSS-документ --> example_server example_server -- 200 --> example_document example_document -- JS-скрипт\nOrigin:example.com --> tracking_server tracking_server -- 200 --> example_document example_document -- изображение\nOrigin:example.com --x external_server external_server -- 403 --> example_document

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

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

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

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

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

Защита веб-сервера #

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

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

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

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


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

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

  • Межсайтовый скриптинг (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

sequenceDiagram participant cli as Клиент participant serv as Сервер cli ->> serv : GET-запрос по пути PATH serv ->> cli : Ответ 401, Unauthorized, заголовок WWW-Authenticate cli ->> cli : Формирует ответ cli ->> serv : GET-запрос по пути PATH с заголовком Authorization alt Данные введены верно serv ->> cli : Ответ 200 с указанным документом else serv ->> cli : Ответ 403, Forbidden end

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

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

sequenceDiagram actor user as Пользователь participant brow as Браузер participant serv as Сервер user ->> brow : Открывает ссылку в интерфейса brow ->> serv : Посылает GET-запрос на ссылку serv ->> brow : Ответ с кодом 401, Unauthorized brow ->> user : Окно для ввода имени имени и пароля user ->> brow : Вводит имя пользователя и пароль brow ->> serv : Передаёт данные в заголовке Authorization serv ->> serv : Выполняет проверку введённых данных serv ->> brow : Возвращает результат запроса

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

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

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


Аутентификация с сохранением сессии #

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

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

  • Управления сеансами пользователя, аутентификации, корзины
  • Персонализации контента
  • Мониторинга поведения пользователя
sequenceDiagram participant cli as Браузер participant ser as Сервер cli ->> ser : Запрос данных ser ->> cli : Ответ с заголовком(ами) `Set-Cookie` cli ->> ser : Запрос с заголовком `Cookie`

Заголовки 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, который определял бы процедуру авторизации с помощью формы, каждый разработчик может реализовать логику самостоятельно

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

sequenceDiagram participant cli as Браузер participant ser as Сервер cli ->> ser : GET-запрос на аутентификацию ser ->> cli : 200, HTML-документ с формой cli ->> cli : Пользователь заполняет форму и нажимает кнопку «отправить» cli ->> ser : POST-запрос с данными формы, именем пользователя и паролём ser ->> cli : 302, с заголовком `Set-Cookie`, содержащим токен аутентификации cli ->> ser : GET-запрос с заголовком `Cookie` и токеном аутентификации

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

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

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

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

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

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

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

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

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

flowchart LR salt("Соль") pass("Пароль") com["Объединение"] full("Соль + пароль") hashing["Хеш-функция"] hashed("Хеш пароля") salt --> com pass --> com com --> full full --> hashing hashing --> hashed

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


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

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

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

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

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

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

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

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

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

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