previous up index search
Previous: 4.5.6.5 Протокол HTTP/2 (RFC-7540, Hypertext Transfer Protocol Version 2 (M. Belshe, R. Peon, M. Thomson, Ed.)    UP: 4.5.6 WWW

4.5.6.6 HTTP поверх TLS (RFC-2818)

Семенов Ю.А. (ИТЭФ-МФТИ)
Yu. Semenov (ITEP-MIPT)

1. Введение

В исходном виде протокол HTTP [RFC2616] был предназначен для работы в открытом Internet.

Использование HTTP для приложений, критических в отношении безопасности потребовало дополнительных средств. Новый протокол работал на базе SSL и его приемника TLS [RFC2246], что обеспечивало безопасность на канальном уровне.

2. HTTP поверх TLS

Работа HTTP поверх TLS сходна с функционированием HTTP поверх TCP.

2.1. Установленрие соединения

Агент, выполняющий функцию HTTP-клиента, должен быть также и TLS-клиентом. Он должен инициировать соединение с сервером через определенный порт и, далее послать TLS ClientHello, чтобы начать диалог TLS. Когда диалог TLS завершен, клиент может послать первый запрос HTTP. Все HTTP-данные должны посылаться в качестве прикладной информации. Далее следует обычное поведение HTTP, включая обслуживание установленных ранее соединений.

2.2. Закрытие содинения

TLS предусматривает безопасную процедуру разрыва соединения. Когда приходит коррекктное уведомление о разрыве соединения, реализация может считать, что через соединение уже не будет получено никаких данных. Приложения TLS должны инициировать обмен уведомлениями о закрытии соединения, прежде чем разорвать канал. Реализация TLS может, после посылки уведомления о закрытии, разорвать соединение, не дожидаясь посылки партнером своего уведомления о закрытии, генерируя тем самым "неполное закрытие". Заметим, что реализация, которая это делает, может пытаться перезапустить сессию. Это должно делаться, когда приложение знает (обычно за счет детектирования границы сообщения), что получено все сообщение.

Как специфицировано в [RFC2246], любая реализация, которая получает уведомление о закрытии, не получив корректного уведомления о закрытии ("преждевременное закрытие"),не должна повторно использовать данную сессию. Заметим, что преждевременное закрятие не ставит под сомнение безопасность уже полученных данных, а лишь указывает, что последующие данные могут быть укорочены. Так как TLS не обращает внимания на границы запросов/откликов HTTP, он обязательно просматривает сами HTTP данные (особенно заголовок Content-Length), чтобы определить, произошло ли укорочение в пределах сообщения или между сообщениями.

2.2.1. Поведение клиента

Так как HTTP использует закрытие соединения в качесте сигнала окончания потока данных от сервера, реализация клиента должна рассматривать любую попытку закрытия канала в качестве ошибки, а полученные данные как укороченные. В то время как протокол HTTP в подобном случае позволяет клиенту выяснять, произошло ли укорочение, так что, если получен полный отклик, он может терпеть такие ошибки, следуя принципу "быть строгим при посылке и терпимым при получении" [RFC1958], часто укорочение не отмечается в HTTP протокольных данных; два случая заслуживают специального внимания:

HTTP-отклик без заголовка Content-Length. Так как длина данных в этой ситуации задана неожиданным уведомлением о завершении, генерируемым сервером, данное положение невозможно отличить от случая прерывания, осуществляемого атакером.

HTTP-отклик с корректным заголовком Content-Length до того, как все данные считаны. Так как TLS не обеспечивает защиты, ориентированной на документ, невозможно определить, выполнено ли некорректно вычисление Content-Length сервером или атакер пытается прервать соединение.

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

Клиент, детектирующий незавершенное закрытие, должен корректно восстановиться. Он может возобновить только что закрытую TLS-сессию.

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

2.2.2. Поведение сервера

RFC-2616 разрешает HTTP-клиенту разорвать соединение в любое время, и требует, чтобы серверы корректно при этом восстанавливали свое состояние. В частности, серверы должны быть готовы получить не полное уведомление о закрытии от клиента, так как клиент может определить, когда кончаются данные сервера. Серверы должны быть готовы возобновить сессию прерванную подобным образом.

Замечание по поводу реализации: В реализациях HTTP, которые не используют постоянные соединения, предполагается, что сервер может уведомлять о конце передачи данных путем разрыва соединения. При использовании Content-Length, однако, клиент может уже послать уведомление о закрытии соединения и разорвать связь.

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

2.3. Номер порта

Первое, что ожидает получить HTTP-сервер от клиента - это идентификатор Request-Line. Первое, что ожидает получить TLS-сервер (и, следовательно, HTTP/TLS-сервер) - это ClientHello. В результате, обычной практикой при работе с HTTP/TLS является использование отдельного порта, для того чтобы определить, какой протокол используется. Когда HTTP/TLS-протокол работает через TCP/IP-соединение, номер порта по-умолчанию равен 443. Это не исключает возможность работы HTTP/TLS с привлечением другой транспортной среды. Протокол TLS предполагает использование надежного информационного обмена, ориентированного на соединение.

2.4. Формат URI

В HTTP/TLS URI отличаются от HTTP наличием протокольного идентификатора 'https' вместо 'http'. Например, URI, указывающиее на HTTP/TLS, выглядит как: https://www.example.com/~smith/home.html

3. Идентификация партнеров

3.1. Идентификация сервера

Вообще, HTTP/TLS запросы генерируются разыменованными URI. Как следствие, имя компьютера сервера известно клиенту. Если имя компьютера доступно, клиент должен проверить корректность идентификатора сервера на основе содержимого Certificate-сообщения, для того чтобы предотвратить атаку типа человек-по-середине.

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

Если присутствует расширение subjectAltName для типа dNSName оно должно использоваться в качестве идентификатора. В противном случае, служба сертификациии рекомендует использовать поле Subject сертификата. Хотя использование Common Name является обычной практикой, это не рекомендуется и служба сертификации советует использовать dNSName.

Проверка соответствия осуществляется посредством правил, описанных в [RFC2459]. Если в сертификате имеется более одного идентификатора данного типа (напр., более одного имени dNSName, соответствие любому из набора считается приемлемым). Имена могут содержать символы подмены wildcard *, которые рассматриваются соответствующими любому отдельному компоненту доменного имени или фрагменту компонента. Например, *.a.com соответствует foo.a.com, но не соответствует bar.foo.a.com. f*.com соответствует foo.com, но не соответствует bar.com.

В некоторых случаях, URI специфицируется IP-адресом, а не именем компьютера. В этом случае, в сертификате должен присутствовать iPAddress subjectAltName и он должен строго соответствовать IP в URI.

Если имя компьютера не соответствует идентификатору в сертификате, клиенты, ориентированные на пользователя, должны, либо извещать об этом пользователя (клиенты могут предоставить пользователю возможность сохранить соединение в любом случае), либо прервать соединение с ошибкой "bad certificate". Автоматизированные клиенты должны фиксировать ошибку в соответствующем журнальном файле (если таковой имеется) и завершить соединение (с ошибкой "bad certificate"). Автоматизированные клиенты могут предоставлять возможность конфигурации, где такая проверка может блокироваться, но должна существовать возможность восставления такой проверки.

Заметим, что во многих случаях само URI получается из источников, не достойных доверия. Выше описанная проверка не обеспечивает защиты от атак, где такой источник скомпрометирован. Например, если URI было получено в результате кликанья на HTML-странице, которая сама получена без использования HTTP/TLS, человек-по-середине может подменить URI. Для того чтобы предотвратить такого рода атаку пользователь должен тщательно рассмотреть сертификат, полученный сервером и определить, соответствует ли он его ожиданиям.

3.2. Идентификация клиента

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

Ссылки

Previous: 4.5.6.5 Протокол HTTP/2 (RFC-7540, Hypertext Transfer Protocol Version 2 (M. Belshe, R. Peon, M. Thomson, Ed.)    UP: 4.5.6 WWW