Веб-безопасность: ввод в HTTP

1656533677 veb bezopasnost vvod v http

Алексей Надалин

U37eUZn1h-fJe5eI0uwZKBi0mrWpgIQpHfKj
Фото Джеймса Понда на Unsplash

Это часть 2 серии о веб-безопасности: часть 1 была «Понимание браузера»

HTTP – это отличная вещь: протокол, просуществовавший более 20 лет, не меняя значительных изменений.

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

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

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

Ключевую разницу между ними можно объяснить очень простой аналогией: 20 лет назад люди заботились о своих родственниках так же, как сейчас, хотя способ их взаимодействия существенно изменился. Наши родители, наверное, взяли бы машину и поехали к своей сестре, чтобы догнать и провести время с семьей вместе.

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

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

Обзор

Как мы видели ранее, HTTP придерживается модели запрос/ответ, когда клиент, подключенный к серверу, выдает запрос, а сервер отвечает на него.

Сообщение HTTP (запрос или ответ) содержит несколько частей:

  • «первая линия»
  • заголовки
  • тело

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

GET /players/lebron-james HTTP/1.1

В этом случае клиент пытается GET ресурс на /players/lebron-james через версию 1.1 протокола – ничего трудно понять.

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

GET /players/lebron-james HTTP/1.1Host: nba.comAccept: */*Coolness: 9000

В этом запросе, например, клиент добавил к запросу 3 дополнительных заголовка: Host, Accept и Coolness.

подожди, Coolness?!?!

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

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

Иногда, однако, может иметь смысл включить «пользовательский» заголовок в сообщение, поскольку вы можете добавить метаданные, которые на самом деле не являются частью спецификации HTTP: сервер может решить включить техническую информацию в свой ответ, чтобы клиент может одновременно выполнять запросы и получать важную информацию о статус сервера, который отвечает:

...X-Cpu-Usage: 40%X-Memory-Available: 1%...

Используя пользовательские заголовки, всегда желательно добавлять к ним ключ, чтобы они не конфликтовали с другими заголовками, которые могут стать стандартными в будущем: исторически это хорошо работало, пока все не начали использовать «нестандартные» X префиксы, которые, в свою очередь, стали нормой. The X-Forwarded-For и X-Forwarded-Proto заголовки — это примеры пользовательских заголовков, широко используемых и понимаемых балансировщиками нагрузки и прокси, даже если они не были частью стандарта HTTP.

Если вам нужно добавить свое собственное пользовательское название, сегодня, как правило, лучше использовать поставщик префикс, например Acme-Custom-Header или A-Custom-Header.

После заголовков запрос может содержать тело, отделяемое от заголовков пустой строкой:

POST /players/lebron-james/comments HTTP/1.1Host: nba.comAccept: */*Coolness: 9000
Best Player Ever

Наш запрос полон: первая строка (информация о местонахождении и протоколе), заголовки и тело. Заметьте, что тело полностью необязательно и, в большинстве случаев, оно используется только тогда, когда мы хотим отправить данные на сервер — поэтому в примере выше используется глагол POST.

Ответ не очень отличается:

HTTP/1.1 200 OKContent-Type: application/jsonCache-Control: private, max-age=3600
{"name": "Lebron James", "birthplace": "Akron, Ohio", ...}

Первой информацией, рекламирующей ответ, является версия протокола, который она использует, вместе со статусом этого ответа. Заголовки следуют за примером и, если нужно, разрыв строчки, а затем тело.

Как упоминалось, протокол претерпел многочисленные просмотры и со временем добавлял функции (новые заголовки, коды состояния и т.п.), но базовая структура почти не изменилась (первая строка, заголовки и тело). Что действительно изменилось, так это то, как клиент и серверы обмениваются этими сообщениями — давайте рассмотрим это ближе.

HTTP против HTTPS против H2

HTTP претерпел 2 значительных семантических изменения: HTTP/1.0 и HTTP/1.1.

«Где HTTPS и HTTP2?», — спросите вы.

HTTPS и HTTP2 (сокращенно H2) – это более технические изменения, поскольку они представили новые способы доставки сообщений через Интернет, не влияя на семантику протокола.

HTTPS — это «безопасное» расширение для HTTP, предусматривающее установление общего секрета между клиентом и сервером, убедившись, что мы общаемся с нужной стороной и шифруем сообщения, обмениваемые общим секретом (подробнее об этом позже). Хотя HTTPS был направлен на повышение безопасности протокола HTTP, H2 был направлен на обеспечение скорости света.

H2 использует двоичные, а не открытые текстовые сообщения, поддерживает мультиплексирование, использует алгоритм HPACK для сжатия заголовков… Короче говоря, H2 — это повышение производительности к HTTP/1.1.

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

HTTPS

HTTPS (HTTP Secure) имеет целью позволить клиентам и серверам безопасно общаться через TLS (Transport Layer Security), преемник SSL (Secure Socket Layer).

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

Теперь перед вами 2 проблемы:

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

Что ты делаешь? Это именно та проблема, которую пытается решить HTTPS.

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

Однако это не мешает «злоумышленникам» узнать номер социального страхования жертвы, похитить смартфон вашей второй половинки и позвонить по телефону вам. Как проверить личность абонента?

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

В терминах HTTPS ваша мама называется CA, сокращенно от Certificate Authority: работа CA состоит в том, чтобы проверить идентичность по определенному серверу и выпустить сертификат с собственной цифровой подписью: это означает, что когда я подключаюсь к определенному домену, я не будет представлен сертификат , созданный владельцем домена (так называемый самоподписанный сертификат), а скорее ЦС.

Задача органа власти состоит в том, чтобы убедиться, что они проверяют личность по домену и выдают сертификат соответственно: когда вы заказываете сертификат (широко известный как SSL сертификатдаже несмотря на то, что сейчас вместо него используется TLS – имена действительно остаются!), представитель власти может позвонить вам или попросить изменить настройки DNS, чтобы подтвердить, что вы контролируете соответствующий домен. После завершения процесса проверки он выдаст сертификат, который можно будет установить на своих веб-серверах.

Клиенты, такие как браузеры, будут подключаться к вашим серверам и получат этот сертификат, чтобы они могли проверить, выглядит ли он настоящим: браузеры имеют какие-то «связи» с ЦС, в том смысле, что они отслеживают список доверенных ЦС в проверить, действительно ли сертификат заслуживает доверия. Если сертификат не подписан надежным органом, браузер отображает большое информативное предупреждение для пользователей:

vxE2LWkdevzR-B35YJBqF381QkimQkkZEh5n

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

Вы можете сделать это, установив общую тайну между вами двумя и зашифровав сообщение через эту тайну: можно, например, решить использовать вариант шифра Цезаря на основе даты вашей свадьбы.

HOZnZEwiFLgX3QOGG5LsEFLk8WBo-EZFL3Qw

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

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

0Q0PFXLZ4dGndARsBR83txIHHvafpPLSdEx7

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

Для получения дополнительной информации о HTTPS и Диффи-Хеллмане я бы рекомендовал прочитать «Как HTTPS защищает соединение» Хартли Броуди и «Как на самом деле работает HTTPS?» Роберт Хитон. Кроме того, «Девять алгоритмов, изменивших будущее» содержит удивительную главу, объясняющую шифрование с открытым ключом, и я настоятельно рекомендую ее фанатам компьютерных наук, интересующихся гениальными алгоритмами.

HTTPS везде

Все еще обсуждаете, следует ли поддерживать HTTPS на своем веб-сайте? У меня нет для вас хороших новостей: браузеры начали отталкивать пользователей от веб-сайтов, не поддерживающих HTTPS, чтобы «заставить» веб-разработчиков обеспечить полностью зашифрованный просмотр.

По девизу «HTTPS везде», браузеры начали выступать против незашифрованных соединений – Google был первым поставщиком браузеров, предоставившим веб-разработчикам термин, объявив, что, начиная с Chrome 68 (июль 2018 года), он будет обозначать веб-сайты HTTP как «опасные»:

QzUgTtBZOyCSZAFW6sMDvFvFDyIqNN65QMxW

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

Jj16doX7GMJBEyfPGCRfqhGw78cEXsgWy2kn

Сравните это с тем, как выглядит веб-сайт, работающий на HTTPS и имеющий действительный сертификат:

xku80KAGhMxG0HRmZICncR3d-MESnpw6PC8B

Теоретически, веб-сайт не обязательно должен быть безопасным, но на практике это отпугивает пользователей – и это справедливо. В то время, когда H2 не был реальностью, могло иметь смысл придерживаться незашифрованного простого HTTP-трафика. Сейчас для этого практически нет причин. Присоединяйтесь к HTTPS везде движение и помочь сделать Интернет более безопасным местом для серфингистов.

GET против POST

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

Прежде всего, клиент уведомляет сервера, какие глаголы он использует для выполнения запроса: распространенные глаголы HTTP включают GET, POST, PUT и DELETEно список можно продолжать менее распространенными (но все же стандартными) глаголами, такими как TRACE, OPTIONSили HEAD.

Теоретически, ни один метод не безопаснее других; на практике это не так-то просто.

GET запросы обычно не содержат тела, поэтому параметры включаются в URL-адрес (т.е. www.example.com/articles?article_id=1) тогда как POST Запросы, как правило, используются для отправки («публикации») данных, включенных в тело. Другое отличие заключается в побочных эффектах, которые несут с собой эти глаголы: GET является идемпотентным глаголом, что означает, сколько запросов вы не будете посылать, вы не изменяете состояние веб-сервера. POSTне является идемпотентным: для каждого отправленного вами запроса вы можете изменять состояние сервера (подумайте, например, о ПУБЛИКОВАНИИ нового платежа — теперь вы, наверное, понимаете, почему сайты просят вас не обновлять страницу во время выполнения транзакции ).

Чтобы проиллюстрировать важное различие между этими методами, нам нужно посмотреть журналы веб-серверов, с которыми вы, возможно, уже знакомы:

192.168.99.1 - [192.168.99.1] - - [29/Jul/2018:00:39:47 +0000] "GET /?token=1234 HTTP/1.1" 200 525 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36" 404 0.002 [example-local] 172.17.0.8:9090 525 0.002 200192.168.99.1 - [192.168.99.1] - - [29/Jul/2018:00:40:47 +0000] "GET / HTTP/1.1" 200 525 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36" 393 0.004 [example-local] 172.17.0.8:9090 525 0.004 200192.168.99.1 - [192.168.99.1] - - [29/Jul/2018:00:41:34 +0000] "PUT /users HTTP/1.1" 201 23 " "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36" 4878 0.016 [example-local] 172.17.0.8:9090 23 0.016 201

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

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

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

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

Первоначально опубликовано на odino.org (22 августа 2018 г.).
Вы можете следить за мной в Твиттере – разговоры приветствуются! ?

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *