понедельник, 21 января 2013 г.

Browser Security Handbook. Глава 1, пункт 5

Руководство по безопасности браузеров (Browser Security Handbook). Глава 1


5.         Протокол передачи гипертекста (HTTP)

Это протокол прикладного уровня, основанный на технологии «клиент-сервер»: клиент инициирует соединение и посылает запрос серверу, а сервер производит необходимые действия и возвращает обратно сообщение с результатом.
Первая версия протокола была разработана Тимом Бернерсом-Ли и называлась HTTP/0.9 (в настоящее время не используется браузерами, но поддерживается некоторыми серверами). HTTP/1.1- текущая версия протокола, которая описана в RFC 2616.
Каждое HTTP-сообщение состоит из трёх частей, которые передаются в указанном порядке:
1. Стартовая строка (Starting line) — определяет тип сообщения.
2. Заголовки (Headers) — характеризуют тело сообщения, параметры передачи и прочие сведения.
3. Тело сообщения (Message Body) — непосредственно данные сообщения.
Заголовки и тело сообщения могут отсутствовать, но стартовая строка является обязательным элементом, так как указывает на тип запроса/ответа. Исключением является версия HTTP/0.9, у которой сообщение запроса содержит только стартовую строку, а сообщения ответа - только тело сообщения.
Каждый запрос начинается с однострочного описания метода HTTP (GET- используется для запроса содержимого указанного ресурса, POST -  применяется для передачи пользовательских данных заданному ресурсу). В HTTP/1.0 и выше, за методом HTTP следует версия протокола. Ниже идут строки, содержащие разделённую двоеточием пару параметр-значение, называемые заголовками HTTP. Эти заголовки могут указывать различные мета-данные: имя хоста, информацию о клиенте, поддерживаемые типы MIME, параметры кэша, источник запроса и т. д. Заголовки должны отделяться от тела сообщения хотя бы одной пустой строкой. Тело HTTP сообщения, если оно присутствует, используется для передачи тела объекта, связанного с запросом или ответом. Присутствие тела сообщения в запросе отмечается добавлением к заголовкам запроса поля заголовка Content-Length или Transfer-Encoding.


Пример HTTP-запроса:
POST /fuzzy_bunnies/bunny_dispenser.php HTTP/1.1

  Host: www.fuzzybunnies.com

  User-Agent: Bunny-Browser/1.7

  Content-Type: text/plain

  Content-Length: 12

  Referer: http://www.fuzzybunnies.com/main.html
 
HELLO SERVER
Сервер отвечает в том же порядке: код состояния,  версия протокола и заголовки, если таковые имеются:
HTTP/1.1 200 OK

  Server: Bunny-Server/0.9.2

  Content-Type: text/plain

  Connection: close

HELLO CLIENT

     Сеанс связи завершается после того, как был получен ответ на отправленный запрос. Поскольку устанавливать связь для каждого запроса неудобно, ввели дополнение к протоколу - постоянное HTTP-соединение (keep-alive connection), которое использует одно соединение для отправки и получения множественных запросов и ответов вместо открытия нового соединения для каждой пары запрос-ответ.
К сожалению, сам протокол неоднозначен и склонен к избыточности, что приводит к многочисленным проблемам и различиям между тем, как серверы, прокси-серверы, и клиенты могут интерпретировать ответы:
- Как и многие другие тексты протоколов того времени, HTTP не имел четкого определения текстового формата или формат полей. Из-за этого происходила обработка несовместимыми способами, что приводило к искажению вводимой информации, например, неверные символы новой строки (CR, LF, CR+LF, NEL) или другие искажения управляющих символов в тексте, ошибочное количество пробелов в разделителе полей и т.д.; различные реализации Head\0er: Value - может быть Head, Head: Value, Header: Value, или Head\0er: Value. В RFC 2616 в разделе 19.3 “Tolerant Applications” стандарт рекомендует анализировать определенные поля и неправильные значения. Один из наиболее ярких примеров ляпа в браузере Firefox - prtime.c - функция используется для HTTP-анализа поля «Date», которая указывает на сложности при решении простой задачи.
- Плохо задан набор символов старшего бита для HTTP-заголовков, поэтому символы старшего бита разрешены в HTTP/1.0 без дальнейших ограничений, разрешены они и в HTTP/1.1 (если не закодированы в соответствии с RFC 2047). На практике, подобные символы  допустимы в определенных полях (Cookie, Content-Disposition filenames), которые не поддерживаются RFC 2047 либо поддерживаются несовместимо с другими RFC (например, требования для заголовка "Cookie"). В некоторых реализациях это приводит к преобразованию данных в UTF-8, а в других - используется однобайтовое преобразование низкоуровневыми средствами операционной системы для работы со строками.
- Поведение, когда обязательные заголовки содержат дублирующие или противоречивые запросы; приоритет появление одного и того же параметра в HTTP-заголовках у различных клиентов (например, дублирование Content-Type) или наличие противоречивых сведений (например, Content-Length не соответствует длине полезной нагрузки). В случае если приоритет может определиться, но не наглядно - например, в разделе 5.2 стандарта RFC 2616 говорится, что абсолютные запросы URI-данных имеют приоритет выше, чем хост-заголовки.
- Когда новые функции, меняющие значения запросов, были введены в стандарт  HTTP/1.1, требований по маркировке их в запросах или ответах как HTTP/1.0 не было. В результате, смысл сообщения HTTP/1.0 может значительно отличаться между действующими агентами, например, некоторыми коммерческими веб-прокси и приложениями HTTP/1.1, такими, как современные браузеры (Connection: keep-alive, Transfer-Encoding: chunked, Accept-Encoding: ...).

Ниже приводится обзор общих отличий, относящихся к безопасности, введенных в http-протокол:
Описание теста
MSIE7
MSIE8
FF3
Сафари
Опера
Хром
Android
Поддерживаются ответы без заголовков (HTTP/0.9)?
Да
Да
Да
Да
Да
Да
Да
CR (0x0D) рассматривается в качестве разделителя строки заголовка?
Да
Да
Нет
Нет
Да
Да
Нет
Значение заголовка «Content-Length» превышает фактическую длину содержимого?
Да
Да
Нет
Да
Да
Нет
Да
Имеет ли преимущество первый HTTP-заголовок с таким же именем?
Да
Да
Нет
Да
Нет
Да
Нет
Первое значение поля в HTTP-заголовке имеет приоритет?
Да
Да
Да
Да
Да
Да
Да
Заголовок «Referer» отсылается на HTTPS → HTTPS переход?
Да
Да
Да
Да
Нет
Да
Да
Заголовок «Referer» отсылается на HTTPS → HTTP переход?
Нет
Нет
Нет
Нет
Нет
Нет
Нет
Заголовок «Referer» отсылается на HTTP → HTTPS → переадресация HTTP?
Да
Да
Да
Да
Да
Нет
Да
Заголовок «Referer» отсылается на псевдо-протокол → HTTP переход?
Нет
Нет
Нет
Нет
Нет
Нет
Нет
Фрагмент ID включен в заголовок «Referer» на обычный запрос?
Нет
Нет
Нет
Нет
Нет
Нет
Нет
Фрагмент ID включен в заголовок «Referer»  при XMLHttpRequest?
Да
Да
Нет
Нет
Нет
Нет
Нет
Тело ответа на недействительный 30х  redirect показывается  пользователю?
Нет
Нет
Да
Нет
Да
Да
Нет
Символы старшего бита обрабатываются в HTTP cookies?
перекодирование
в 7 бит
перекодирование
в 7 бит
искажение
UTF-8
UTF-8
UTF-8
UTF-8
Значения строк в кавычках поддерживаются для HTTP cookies?
Нет
Нет
Да
Нет
Да
Нет
Да
ПРИМЕЧАНИЕ 1: Referer всегда будет указывать на сайт, с которого был сделан переход, независимо от 30х redirect. Если нужно скрыть исходный URL от сайта-получателя, необходимо использовать переадресацию Refresh или переход с псевдо-протокола JavaScrip.
ПРИМЕЧАНИЕ 2: Разметка заголовка «Refresh»  в IE происходит странным образом, что делает невозможным переход к адресу, содержащему символ «, если этот параметр заключается в дополнительные кавычки. Разметка  также допускает проведение XSS-атаки через Url-адрес, например:

http://example.com;URL=javascript:alert(1)

В отличие от других браузеров, ранние версии Internet Explorer интерпретировали эту запись как два URL, причем последний адрес имел приоритет: 

Refresh: 0; URL=http://example.com;URL=javascript:alert(1)

Комментариев нет:

Отправить комментарий