Главная / Пресс-центр / Статьи

Статьи

18 июня 2020

Заголовки HTTP и их роль в обеспечении безопасности

Автор статьи: Александр Венедюхин, ведущий аналитик ТЦИ


Заголовки HTTP и их роль в обеспечении безопасности

В рамках проекта «Домены России» публикуется ежемесячный отчёт о распространённости HTTP-заголовков безопасности. Эта статья рассказывает о том, что собой представляют эти заголовки и какова их роль в обеспечении безопасной работы пользователя с веб-сайтом.


Введение

HTTP (Hyper Text Transfer Protocol) - протокол Веба. Именно по HTTP браузер взаимодействует с веб-сервером, загружая тот или иной веб-ресурс. HTTP - старый протокол, и в своих классических версиях устроен очень просто - клиент и сервер, установив соединение, обмениваются текстовыми запросами и ответами: клиент запрашивает документы, расположенные по указанному адресу, а сервер - передаёт их в ответ на запрос. Документы - это исходные коды веб-страниц, представляющие собой HTML- и CSS-код, файлы скриптов (например, Javascript), а также файлы изображений (картинки форматов .PNG, .GIF, .JPEG) и другие данные. Отметим, что существует суперсовременный протокол под названием HTTP/2 - этот протокол существенно отличается от классического HTTP (версий 1.0 и 1.1 или просто HTTP/1). Далее мы обсуждаем только классический вариант HTTP, который повсеместно используется, более того, для целей настоящей статьи, посвящённой HTTP-заголовкам, отличия HTTP/1 и HTTP/2 — не являются определяющими.

В HTTP запросы клиента содержат идентификаторы методов, которые обозначают способы обработки на стороне сервера. Так, запрос с методом GET - соответствует извлечению полного документа, находящегося по указанному адресу на сервере. GET повсеместно используется для извлечения кода веб-страниц. Метод POST - напротив, позволяет клиенту загрузить на сервер некоторый блок данных в определённом протоколом формате. Типичный способ использования POST - передача на сервер данных веб-формы (например, запоненной на сайте анкеты). Методы обозначаются простыми текстовыми строками.


HTTP в практике веба

Поскольку сценарии использования протокола HTTP в современном вебе достаточно сложные, запросы и ответы HTTP содержат, кроме идентификаторов методов и адресов документов, много дополнительной служебной информации. Самым известным примером здесь является поле User-Agent, в котором клиент указывает свой тип, название, версию. В частности, поле User-Agent позволяет веб-серверу определить тип браузера, который отправил запрос. User-Agent в классическом HTTP представляет собой текстовую строку, состоящую из идентификатора (собственно, "User-Agent") и значения, разделённых символом ":" (двоеточие). Так же записываются и другие HTTP-заголовки.

Дополнительные поля передаются и клиентом, и севером. Все эти поля представляют собой сочетание текстового имени поля и текстового же значения. Именно эти дополнительные поля в HTTP-ответе сервера и принято называть HTTP-заголовками, а идентификаторы - используются в качестве имён, по которым на конкретный заголовок ссылаются. Так, о поле с описанием типа браузера говорят как об "HTTP-заголовке User-Agent".

Как уже упоминалось выше, протокол HTTP - это протокол типа "клиент-сервер": клиент отправляет запросы, а сервер выполняет их (при возможности) и отправляет ответы. Клиентом, в типичной ситуации, выступает браузер, а сервер - это веб-сервер. Сессия работы с современным веб-сайтом включает множество HTTP-запросов и HTTP-ответов, которые могут направляться как последовательно, так и параллельно.

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

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

Безопасная версия HTTP –  HTTPS – использует TLS (протокол Transport Layer Security) для защиты информации. HTTPS, с точки зрения части HTTP, работает полностью аналогично открытой версии, однако, так как канал защищён криптографическими методами, клиент и сервер получают механизмы проверки подлинности и целостности переданных данных. Такая проверка проводится за пределами HTTP. HTTPS существенно усиливает значение HTTP-заголовков, и многие из этих заголовков актуальны только в случае HTTPS.

Итак, HTTP-заголовки - это представленные в текстовом формате сведения о различных параметрах HTTP-сессии. Заголовки позволяют веб-серверу информировать браузер о настройках, которые следует применять для данного адреса и данного сайта. Эти настройки могут относиться как к текущей сессии, так и к последующим. Рассмотрим элементарный пример запроса и ответа HTTP (с заголовками):

Запрос (это GET-запрос, он отправляется клиентом в адрес сервера, в данном случае - обозначает извлечение индексного документа из корневой директории на сервере, "HTTP/1.1" - указывает на версию, используемую клиентом):

GET / HTTP/1.1
Host: www.google.com

(Здесь Host: - это служебный HTTP-заголовок _запроса_, обозначающий имя сервера, к которому обращается клиент: www.google.com, в данном случае.)

Ответ (HTTP-ответ с кодом статуса 200, обозначающим успешное выполнение - код статуса указан в первой строке):

HTTP/1.1 200 OK
Date: Fri, 24 Apr 2020 18:33:48 GMT
X-XSS-Protection: 0
X-Frame-Options: SAMEORIGIN

Здесь нужно обратить внимание на две нижних строки, которые начинаются с обозначений X-XSS-Protection и X-Frame-Options. Это примеры _серверных_ HTTP-заголовков безопасности.


Заголовки безопасности

Часть серверных заголовков HTTP предназначены для повышения безопасности сессий при работе браузера с веб-сайтами. Эти заголовки называются "заголовками безопасности". Исторически, они вводились в употребление постепенно, в качестве ответа на возникавшие новые направления атак. Заголовки безопасности позволяют администратору веб-ресурса передать браузеру сведения, которые описывают рекомендованные администратором правила и политики работы клиента (браузера) с веб-сайтом. Поддержка и интерпретация заголовков различаются в деталях от браузера к браузеру (а также в разных версиях браузеров одной линейки), но базовые принципы во всех современных браузерах общие.

Вернёмся к двум заголовкам из примера выше.

X-Frame-Options. Этот заголовок определяет то, как браузер должен показывать соответствующую страницу в контексте встраиваемого отображения. Например, в HTML существует понятие "фрейма" (теги <frame> и <iframe>). "Фрейм" позволяет прозрачно встроить веб-страницу, соответствующую одному серверу, в некоторую область видимости внутри страницы, относящейся к другому серверу. Так показывается реклама на веб-сайтах: на основной странице выделяется визуальный блок, - обычно, фиксированного размера, - и внутри этого блока браузер показывает контент, полученный с совсем другого сайта (и сервера). Однако, при помощи той же конструкции с "фреймами", контент некоторого веб-сайта может быть встроен в страницу другого вопреки желанию владельца первого сайта. Это не просто позволяет злоумышленникам выдать чужой контент за свой, прозрачно подменив видимый адрес страницы, но и ввести пользователя в заблуждение относительно того, на каком сайте в действительности выполняются те или иные действия - например, пользователь кликает на какое-то изображение. Заголовок X-Frame-Options, если он поддерживается браузером, противодействует всем этим неприятностям.

Для X-Frame-Options, в современной версии, допускаются два значения - DENY и SAMEORIGIN. Заголовок считывается браузером и, если в качестве значения указано DENY, то браузер не станет показывать данную страницу внутри "фрейма". SAMEORIGIN - более мягкий вариант правила, допускающий демонстрацию страниц во "фреймах", если "охватывающая" страница принадлежит тому же источнику (впрочем, подробные детали того, как определяется, что источник двух страниц общий - достаточно туманны, но для понимания принципа можно считать, что это определяется по совпадающему имени домена).

Рассмотрим механизм применения заголовков в подробностях, на примере обработки браузером X-Frame-Options. Предположим, что браузер загружает страницу с адресом http://test.ru/page/. В HTML-коде этой страницы содержится конструкция <iframe>, создающая "фрейм". Схема подразумевает указание адреса веб-ресурса, страница которого выводится внутри "фрейма". Пусть это адрес http://example.com/form/. Загрузив страницу с узла test.ru и обнаружив в её HTML-коде ссылку на http://example.com/form/, браузер выполнит соответствующий GET-запрос к серверу под доменом example.com и получит в составе ответа HTTP-заголовки. Если среди этих заголовков (которые формирует сервер example.com) обнаружится строка "X-Frame-Options: DENY", то браузер проигнорирует параметры <iframe> и не выведет страницу http://example.com/form/ внутри "фрейма". Значение SAMEORIGIN - используется в том случае, если механизм "фреймов" применяется разработчиком непосредственно в рамках конкретного веб-ресурса, но при этом требуется, чтобы возможность использования "фреймов" не распространялась за рамки этого ресурса. X-Frame-Options регулирует не только конструкции <iframe> и <frame>, но также <embed> и <object> - принципы применяются те же.

Заголовок X-XSS-Protection. Этот заголовок управляет включением фильтра "кросс-сайтового скриптинга" на стороне браузера (заголовок считается устаревшим, но всё ещё рекомендован к использованию, так как позволяет защитить устаревшие же браузеры). "Кросс-сайтовый скриптинг" (сross-site scripting - XSS) - это распространённый инструмент для построения атак, которые базируются на внедрении дополнительного кода и навязывании специально сгенерированных HTTP-запросов в браузерные сессии, относящиеся к другим веб-сайтам, а не к сайту-источнику. Базовая логика атак XSS состоит в том, что навязанный скрипт или запрос исполняется в контексте другой сессии. Так, пользователь открывает в браузере веб-страницу некоторого сайта P, которая содержит специально подготовленный скрипт, вынуждающий браузер совершить, в контексте сохранённой сессии, запрос к сайту Q; так как сохранённая сессия может содержать активную авторизацию для сайта Q - запрос будет выполнен с соответствующими правами на сайте Q, как если бы сам пользователь открыл этот сайт в браузере и, например, отправил какое-нибудь сообщение. Заголовок X-XSS-Protection поддерживается не всеми современными браузерами, на смену ему приходит другой заголовок, позволяющий решать те же задачи, но не только их. Это Content-Security-Policy.

Content-Security-Policy (CSP) - самый насыщенный директивами и опциями заголовок безопасности. Он позволяет администратору сервера задать политики, определяющие загрузку браузером различных ресурсов и объектов, относящихся к данному адресу (или к странице). Например, политики, задаваемые Content-Security-Policy, определяют как и с каких именно серверов браузер может загружать скрипты, файлы изображений, дополнительные шрифты, плагины и другие элементы страницы. Но CSP не ограничивается этим - опций и директив очень много. Они разделяются на пять наборов: загрузочные директивы, документальные директивы, навигационные директивы, информирующие директивы и прочие директивы. Сколь-нибудь подробное рассмотрение составляющих всех этих наборов потребует отдельной статьи, поэтому мы лишь кратко опишем наборы директив.

Директивы загрузки CSP определяют допустимые источники (по адресам) для тех или иных ресурсов, ссылки на которые возникают при интерпретации исходных кодов страницы браузером. Так, при помощи директивы script-src CSP определяются допустимые источники JavaScript-файлов, а также способы проверки и обработки содержимого этих файлов.

Документальные директивы CSP регулируют контекст, в котором интерпретируется веб-страница целиком. Например, директива plugin-types ограничивает набор типов плагинов, допустимых для данного контекста документа, в частности, с помощью этой директивы можно разрешить загрузку и исполнение объектов Flash.

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

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

К набору прочих директив относится несколько не попавших в другие наборы - например, директива upgrade-insecure-requests, которая предписывает браузеру автоматически заменять возникающие в контексте документа "небезопасные" запросы (то есть, те, для которых указан протокол HTTP) на безопасные (HTTPS).

Заголовки Content-Security-Policy это хорошо развитый инструмент для управления поверхностью атаки на больших и сложно устроенных веб-проектах, которые, к тому же, используют контент, загружаемый пользователями. Например, средствами CSP можно запретить исполнение внешних скриптов для всех источников, кроме проверенных, при этом проверенные - остаются внешними: к ним могут относиться провайдеры контекстной рекламы или системы веб-аналитики.

Referrer-Policy - относится к другому типу заголовков безопасности: этот заголовок определяет, какие данные браузер может передать в HTTP-заголовке Referer, который используется, например, при обработке браузером "перехода по ссылке". Так, Referer может содержать адрес предыдущего ресурса, с которого пользователь перешёл на данный. То есть, сервер, обслуживающий целевой ресурс, видит, откуда пришёл пользователь. Чтобы сократить утечки информации, происходящие через этот заголовок, перечень данных, которые могут в нём передаваться, регулируется заголовком безопасности Referrer-Policy. Например, "Referrer-Policy: origin" - определяет, что в поле Referer браузер передаёт только часть полного адреса (URL), определяющую протокол и имя сервера: при переходе со страницы https://test.ru/from.html в Referer браузер запишет только https://test.ru/. (В браузерах есть и другие механизмы, ограничивающие Referer.)

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

Особенно важен заголовок безопасности Strict-Transport-Security. Оно сообщает браузеру, что при соединении с данным веб-ресурсом следует использовать только безопасный протокол HTTPS. Этот заголовок противодействует атакам, использующим понижение уровня защиты, а именно - замену указанного в адресе ресурса протокола с https:// на http://. Такую замену можно проделать различными способами, в том числе, прямым вмешательством в незащищённый HTTP-трафик. При этом, пользователь может не заметить разницы в типе соединения, а отсутствие TLS позволяет осуществить и подмену адреса, сохранив знакомое доменное имя в адресной строке браузера.

Заголовок Public-Key-Pins - это механизм, позволяющий передать клиенту отпечатки серверных криптографических ключей TLS, которые являются допустимыми для данного сервера. Это известный по другим безопасным протоколам (например, SSH) метод запоминания ключей "при первой встрече". Метод позволяет в дальнейшем обнаружить подмену, даже если такая подмена проводится при участии доверенного удостоверяющего центра. Данный заголовок ранее полностью поддерживался распространёнными браузерами, в частности, Mozilla Firefox, но, к сожалению, сейчас практически выведен из поддержки (в актуальных версиях Firefox требуется включать поддержку вручную, а корректная работа не гарантируется).

Два последних из упомянутых заголовков особенно чувствительны к используемому протоколу - HTTP или HTTPS. Дело в том, что в случае "небезопасной" версии HTTP активный атакующий может удалить или подменить любые заголовки, соответственно, теряется смысл в отправке заголовков, управляющих использованием TLS: они просто могут не дойти до клиента, а пользователь ничего не заметит. При этом однократная передача заголовка по доверенному каналу, через HTTPS, позволяет браузеру запомнить настройки - так как в этом случае сервер-источник аутентифицирован, то и содержимое заголовков оказывается доверенным. Это же наблюдение распространяется и на другие заголовки: если модель атаки подразумевает активную подмену любого трафика, то никакой из заголовков уже не может приниматься к сведению при передаче по HTTP. Тем не менее, чаще используется более слабая модель, в которой атакующий может подменять только какие-то фрагменты на веб-страницах (обычно, на сервере) и передавать произвольную информацию с контролируемого сервера в ответ на запросы браузера. В этой модели ряд HTTP-заголовков безопасности имеют смысл и для открытой версии (HTTP), например, Content-Security-Policy и X-Frame-Options.


Итог

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

Возврат к списку

Заголовки HTTP и их роль в обеспечении безопасности