-40%

Безопасность веб-приложений. Исчерпывающий гид для начинающих разработчиков

Matn
Parchani o`qish
O`qilgan deb belgilash
Shrift:Aa dan kamroqАа dan ortiq

Заголовки безопасности: ремни безопасности для веб-приложений

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

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

СОВЕТ. Узнать больше о заголовках безопасности можно на сайте OWASP.org или SecurityHeaders.com.

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

Для проекта OWASP DevSlop Project мы с моей подругой Франциской Бюлер создали несколько видеороликов и записей в блоге о добавлении заголовков безопасности на сайт. Вот пример кода, который можно было бы использовать для ASP.Net:

<! – Start ASP.Net Security Headers – >

<httpProtocol>

<customHeaders>

<add name="X–XSS-Protection" value="1; mode=block"/>

<add name="Content-Security-Policy" value="default-src 'self'"/>

<add name="X-frame-options" value="SAMEORIGIN"/>

<add name="X–Content-Type-Options" value="nosniff"/>

<add name="Referrer-Policy" value="strict-origin-when-cross-origin"/>

<remove name="X-Powered-By"/>

</customHeaders>

</httpProtocol>

<! – End Security Headers – >

Х-XSS-Protection

Данный заголовок устарел. Он не только не поддерживается современными браузерами, но и, по рекомендациям ряда экспертов, вообще не должен использоваться из-за уязвимостей, которые может создать. В отдельных случаях он может помочь некоторым очень старым браузерам, однако принесет больше вреда, чем пользы, и поэтому его не следует использовать.[14]

Content-Security-Policy (CSP)

Первое, что делает злоумышленник, когда понимает, что сайт уязвим для XSS, – вызывает расположенный в интернете собственный скрипт. Обычно этот скрипт значительно длиннее допустимого, что не позволяет уязвимому приложению обнаружить и заблокировать его. Большинство приложений разрешают ввод только 20–100 символов для большинства полей, то есть злоумышленник не сможет установить полноценный вирус или нанести запланированный ущерб, поэтому он обращается к другому месту в интернете, где его ждет уже готовый вредоносный код.

Заголовок Content-Security-Policy заставляет перечислять все источники содержимого (скрипты, изображения, фреймы, шрифты и т. д.), которые использует сайт и которые находятся за пределами домена, что не позволит уязвимому веб-приложению вызвать и запустить «вторую» ступень атаки. Таким образом значительно снижается риск и потенциальный ущерб от этого типа атак. Тем не менее разработчики склонны считать, что отслеживание источников отнимает много времени, поэтому данный заголовок не пользуется популярностью. По моему мнению, Content-Security-Policy использовался бы гораздо чаще, если бы разработчики понимали риски и осознавали, какую защиту он обеспечивает. Если разработчика трудно убедить применять этот заголовок, подумайте о том, чтобы одолжить ему эту книгу. Надеюсь, он отблагодарит вас в будущем.

ПРИМЕЧАНИЕ. Никогда не включайте CSP в код без согласия и помощи разработчика. Вообще не следует включать средства безопасности без согласования с командами, на работу которых они могут повлиять, но особенно это касается CSP. Этот заголовок почти наверняка нанесет ущерб внешнему виду сайта и некоторым его функциям, но, что более важно, его применение нанесет ущерб вашим доверительным отношениям с командой разработчиков. Не торопитесь: тщательно протестируйте его перед первым развертыванием.

Самая простая настройка – просто заблокировать все лишнее, если разрабатываемый сайт статичен или имеет примитивный вид (не обращается к стороннему контенту). Настройки в таком случае будут следующими:

Content-Security-Policy: default-src 'self'; block-all-mixed-content;

Но давайте будем честны: немногие современные сайты настолько просты. Ничего страшного, мы справимся.

OWASP любезно предоставил список различных источников, которые можно определить в политике безопасности.

• default-src: Как понятно из названия, это настройка по умолчанию, своего рода «поимка всего». При попытке загрузить то, что не имеет четкого определения в остальной части политики, будет применен этот параметр. Его часто устанавливают на self, чтобы запретить загрузку контента, не имеющего четко полученного разрешения в политике. Всегда устанавливайте значение self в случае неуверенности в возможном содержимом сайта.

ПРИМЕЧАНИЕ. Исключением из этого правила являются опции Frame Ancestors и Form Action. Они не возвращаются к default-src.

• script-src: Список доменов (местоположений скриптов) или точный URL-адрес скрипта, которые разрешено запускать как часть сайта. Любой другой скрипт из любого другого места в интернете, кроме тех, что находятся в вашем домене и были включены в перечень разрешенных ресурсов, не будет выполняться. Так осуществляется защита от XSS-атак.

ВНИМАНИЕ. Ключевое слово unsafe-inline может использоваться как часть конфигурации для отмены всех блокировок, произведенных в политике безопасности контента. Оно позволяет запустить любой скрипт из любого места. Нельзя оставлять unsafe-inline в приложениях на постоянной основе: данная опция должна быть лишь временной мерой для проведения тестирования по мере продвижения к зрелой и полной реализации CSP. Кроме того, обязательно проверяйте наличие этой настройки в производстве во время оценки безопасности.

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

– object-src = плагины (надежные источники элементов <object>, <embed> и <applet>);

– style-src = стили (каскадные таблицы стилей, или CSS);

– img-src = изображения;

– media-src = видео и аудио;

– frame-src = фреймы;

– font-src = шрифты;

– plugin-types = ограничивает типы запускаемых плагинов.

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

СОВЕТ. Строки nonce – сложная тема, так как реализация функции nonce в CSP менялась с течением времени. В связи с этим я рекомендую изучить памятку от OWASP по этой теме, которая содержит свежие сведения и более подробное объяснение: cheatsheetseries.owasp.org/cheatsheets/Content_Security_Policy_Cheat_Sheet.html.

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

ВНИМАНИЕ. URL-адрес отчетов находится в открытом доступе, то есть злоумышленник может просмотреть отчеты, а также провести атаку «отказ в обслуживании» (DoS или DDoS), чтобы скрыть свои злодеяния.

Content-Security-Policy, безусловно, является самым сложным из всех заголовков безопасности. Получить дополнительную информацию можно по адресам csp-evaluator.withgoogle.com (Google) и mscotthelme.co.uk.

Например,

Content-Security-Policy: default-src 'self'; img-src

 

https://*.wehackpurple.com; media-src https://*.wehackpurple.com;

позволяет браузеру загружать изображения, видео и аудио из *.wehackpurple.com.

Content-Security-Policy: default-src 'self'; style-src

https://*.jquery.com; script-src https://*.google.com;

позволяет браузеру загружать стили из jquery.com и скрипты из google.com.

СОВЕТ. Заголовками безопасности, которые предоставляют отчеты, являются CSP, Expect-CT, Public-Key-Pins и XSS-Protection. Они очень полезны!

ПРИМЕЧАНИЕ. DoS или DDoS означает «отказ в обслуживании» (от англ. denial of service), а дополнительная буква «D» означает «distributed», или «распределенная атака». Цель атаки DoS – перегрузить ресурсы жертвы так, чтобы никто не мог ими воспользоваться. Она может привести к прекращению работы веб-сайта, потере продаж в интернет-магазинах и другим формам блокировки доступа к онлайн-ресурсам. В самом начале DoS-атаки часто исходили из одного-единственного источника, таким образом, IP-адрес можно было заблокировать и сорвать атаку. Со временем злоумышленники поняли, что наличие большого количества (сотен или даже тысяч) различных IP-адресов, запускающих атаку, наносит гораздо больший ущерб и от них трудно защититься. На данный момент большинство DoS-атак являются распределенными (DDoS), часто с использованием взломанных IoT-устройств в качестве составной части атаки.

X-Frame-Options

Данный заголовок помогает защититься от кликджекинга[15], когда вредоносный сайт «обрамляет» надежный сайт и тем самым может украсть информацию либо «клики». Бывают случаи, при которых сайт должен быть «обрамлен» одним или несколькими конкретными сайтами, однако в результате может сложиться ситуация, когда пользователь будет считать, что находится на вашем сайте, а на самом деле начнет кликать на невидимые элементы другого сайта, являющегося, скорее всего, вредоносным (вот что подразумевается под кликджекингом). Это может привести к перехвату нажатия клавиш клавиатуры и краже учетных данных пользователя. Для активации кликджегинга пользователь должен собственноручно нажать на фишинговую ссылку или ссылку на вредоносном сайте, то есть данная атака не происходит сама по себе, как некоторые другие, но потенциальный ущерб от нее очень велик.

ВНИМАНИЕ. Заголовок X-Frame-Options устарел, вместо него в современных браузерах используется Content-Security-Policy (CSP). X-Frame-Options нужен для обратной совместимости старых браузеров и, надеюсь, будет постепенно выводиться из активного пользования.

Разрешить сайту использовать фреймы из вашего домена можно, установив для X-Frame-Options значение sameorigin:

X-Frame-Options: SAMEORIGIN

Запретить любые фреймы можно через значение deny в X-Frame-Options:

X-Frame-Options: DENY

X–Content-Type-Options

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

Заголовок безопасности X–Content-Type-Options инструктирует браузер не «обнюхивать» (определять или угадывать) тип содержимого данных, используемого в веб-приложении, а полагаться исключительно на тип, который был указан приложением. Браузеры любят думать, что могут предвидеть тип обслуживаемого содержимого, пытаясь быть полезными, но, к сожалению, данная функция превратилась в известную уязвимость, которую можно использовать во вред сайту. У данного заголовка безопасности есть только одна возможная настройка:

X–Content-Type-Options: nosniff

Referrer-Policy

Когда пользователь переходит с сайта на сайт, каждый предыдущий сайт отправляет следующему значение referrer – ссылку на страницу, с которой был совершен переход. Это очень полезная функция для тех, кто анализирует свой трафик: с ее помощью можно узнать, откуда приходят люди. Однако, находясь на сайте личного характера (например, с заявкой на ипотеку или с подробным описанием конкретного медицинского заболевания), пользователь, вероятно, не захочет, чтобы эти данные были отправлены на следующую страницу, которую он посетит. Для защиты конфиденциальности пользователей разработчик сайта может установить значение referrer так, чтобы передавался только домен, а не конкретная страница, на которой находился пользователь (то есть только wehackpurple.com, а не wehackpurple.com/embarrassing-blog-post-title), или вообще не передавалось никакое значение. Можно также изменить значение referrer в зависимости от того, «переходит» ли пользователь с HTTPS на HTTP.

Чтобы передавать информацию только о протоколе и домене, установите для referrer значение origin. Никакое другое условие не сможет изменить эту настройку.

Referrer-Policy: origin

Например, документ по адресу https://wehackpurple.com/page.html отправит ссылку https://wehackpurple.com.

Если пользователь покинет ваш домен, дальше будут переданы только протокол и домен, а если он находится в пределах домена – весь путь, что подходит для нечувствительных веб-сайтов:

Referrer-Policy: strict-origin-when-cross-origin

При отсутствии значения в поле referrer условие не имеет значения:

Referrer-Policy: no-referrer

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

Mozilla является лидером в данной области и предлагает замечательное техническое руководство: developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy.

Бонусный ресурс: получить больше информации по этой теме можно на сайте scotthelme.co.uk. Скотт Хельме – исследователь безопасности, который делится большим количеством сведений и инструментов по заголовкам безопасности.

Strict-Transport-Security (HSTS)

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

ОПРЕДЕЛЕНИЯ

Платформа как услуга (англ. Platform as a Service, PaaS) – услуга облачных вычислений, в рамках которой в облаке размещается программное обеспечение (обычно веб-приложение). Обслуживание PaaS (исправления или обновления версии) производится поставщиком облачных услуг.

Центр сертификации, или ЦС (англ. Certification authority, CA), – доверенная компания или организация, которая проверяет личность того, кто приобретает сертификат.

Фонд электронных рубежей (англ. Electronic Frontier Foundation, EFF) – международная некоммерческая организация, которая работает над защитой конфиденциальности и других прав в интернете.

Let’s Encrypt (букв. «Давайте зашифруем») – проект под управлением Фонда электронных рубежей (EFF), предлагающий бесплатные сертификаты шифрования. На момент написания книги Let’s Encrypt является единственным потребительским центром сертификации.

Wildcard-сертификат – сертификат, который распространяется на все поддомены, а не только на основной домен. При этом для всех поддоменов будет нужен один такой сертификат. Поддоменами является всё под знаком «*» в формуле: *.какой-угодно. домен.

Например, сертификат *.wehackpurple.com будет включать newsletter.wehackpurple.com, store.wehackpurple.com и www.wehackpurple.com.


Для правильной работы Strict-Transport-Security (HSTS) необходимо иметь выданный центром сертификации (ЦС) сертификат, установленный на веб-сервере, PaaS, контейнере или любом другом месте, где размещается приложение. Этот сертификат будет использоваться в процессе шифрования, и без него невозможно включить HSTS. При наличии поддоменов лучше получить сертификат под названием Wildcard. Желательно иметь сертификат с максимально возможным сроком действия (один год, а не три месяца), чтобы не тратить время на частую «ротацию сертификатов».

Необходимо также знать, сколько времени в секундах длится действие вашего сертификата. Нет, я не шучу, они решили измерять время в секундах. Подсказка: один год равняется 31 536 000 секундам:

Strict-Transport-Security: max-age=31536000; includeSubDomains

СОВЕТ. Вы можете отправить свой домен на hstspreload.org и добавить суффикс preload. Google будет предварительно загружать сайт, тем самым не давая никому подключиться к нему через незашифрованное соединение. Хотя основные браузеры объявили о своем намерении начать применять эту функциональную возможность, она не является частью официальной спецификации HSTS[16].

Скорректированный синтаксис предыдущего примера станет таким: Strict-Transport-Security: max-age=31536000; includeSubDomains; preload.

Feature-Policy

На момент написания книги Feature-Policy является самым новым заголовком безопасности, поддерживаемым современными браузерами. Он разрешает или запрещает веб-приложению использовать HTML 5 и многие другие новые возможности в более современных браузерах.

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

• none: ничего не разрешать;

• self: разрешить функцию, но пользоваться ею может только собственный домен;

• src (только iframes): документ, загружаемый в iframe, должен иметь тот же источник, что и URL-адрес в атрибуте src для iframe[17];

• *: любой домен может пользоваться функцией;

• <origin(s)>: функция разрешена для определенных URL[18].

 

Вот пример, позволяющий запускать на сайте только свой динамик и полный экран:

Feature-Policy: camera 'none'; microphone 'none'; speaker 'self';

vibrate 'none'; geolocation 'none'; accelerometer 'none';

ambient-light-sensor 'none'; autoplay 'none'; encrypted-media 'none';

gyroscope 'none'; magnetometer 'none'; midi 'none'; payment 'none';

picture-in-picture 'none'; usb 'none'; vr 'none'; fullscreen *

Эти настройки использовались для сайта проекта OWASP DevSlop. Мы запретили почти все функции. Разрешили использовать динамик только при вызове с нашего сайта. Мы также разрешили любому домену переключать браузер в полноэкранный режим. В сомнительных моментах лучше быть более строгим. Пользователи отблагодарят за это.

X-Permitted-Cross-Domain-Policies

Заголовок безопасности X-Permitted-Cross-Domain-Policies относится только к продуктам Adobe (Reader и Flash), являющимся частью приложения. Adobe Flash ужасно небезопасен и больше не поддерживается компанией Adobe, поэтому его не следует использовать в современных веб-сайтах или приложениях.

Цель данного заголовка – разрешить или запретить доступ файлам домена к продуктам Adobe с других сайтов. Если вы намерены разрешить Adobe Reader, размещенному вне вашего домена, доступ к документам на вашем сайте, нужно указать сторонние домены в данном заголовке. В противном случае, установив значение none, вы запретите любым сторонним доменам использовать продукты Adobe для доступа к вашим документам либо ресурсам:

X-Permitted-Cross-Domain-Policies: none

Expect-CT

CT (от англ. Certification Transparency) обозначает прозрачность сертификатов, то есть это фреймворк с открытым исходным кодом, который обеспечивает надзор за центрами сертификации (ЦС). Время от времени центры сертификации случайно выдают сертификаты далеко не идеальным, а иногда даже откровенно вредоносным сайтам. Вся система центров сертификации была разработана для того, чтобы обеспечить доверие и убедиться в том, что имеющий сертификат сайт безопасен для браузеров и пользователей. Недопустимо, чтобы ЦС предоставлял сертификаты вредоносным сайтам, будь то по ошибке, небрежности или специально. Система Certificate Transparency Framework регистрирует данные о различных операциях, отслеживая случаи некорректной выдачи сертификатов центром сертификации.

Если при выдаче сертификатов ЦС допустил несколько «ошибок», браузер или организация могут перестать «доверять» выданным им сертификатам.

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

При включенном заголовке безопасности Expect-CT:

1) так или иначе браузер пользователя будет проверять журналы CT на предмет наличия в нем вашего сертификата;

2) при установленном значении enforce браузер пользователя будет обеспечивать прозрачность сертификата: если сертификат отсутствует в реестре или «не одобрен CT», соединение между сайтом и пользователем будет прервано. Если режим enforce не установлен, отчет отправляется на соответствующий URL-адрес.

Рекомендуется сначала установить режим only reporting («только отчетность»), а после подтверждения того, что сертификаты соответствуют требованиям и были правильно зарегистрированы, перейти в режим enforce.

Поле max-age (измеряется в секундах) – это время применения настройки (то есть она будет кэшироваться в браузере в течение определенного времени).

ВНИМАНИЕ. Как и в случае с отчетами CSP, URL-адреса отчетов Expect-CT носят открытый характер. Информация из них может быть доступна любому человеку, в том числе тем, у кого не самые честные намерения.

Ниже приведены два примера реализации заголовка Expect-CT:

Только отчетность

Expect-CT: max-age=86400, report-uri="https://wehackpurple.com/report"

Отчетность и блокировка

Expect-CT: max-age=86400, enforce, report-uri="https://wehackpurple.com/report"

Ниже приведен еще один пример из проекта OWASP DevSlop, на этот раз для приложений. Net CORE. Как указано в первой строке, в нем требуется добавление дополнительного пакета Nuget («Nwebsec.AspNetCore.Middleware»)[19]:

<PackageReference Include="Nwebsec.AspNetCore.Middleware"

Version="2.0.0"/>


//Security headers.Net CORE, not the same as ASP.net

app.UseHsts(hsts => hsts.MaxAge(365).IncludeSubdomains());

app.UseXContentTypeOptions();

app.UseReferrerPolicy(opts => opts.NoReferrer());

app.UseXXssProtection(options => options.EnabledWithBlockMode());

app.UseXfo(options => options.Deny());

app.UseCsp(opts => opts

BlockAllMixedContent()

StyleSources(s => s.Self())

StyleSources(s => s.UnsafeInline())

FontSources(s => s.Self())

FormActions(s => s.Self())

FrameAncestors(s => s.Self())

ImageSources(s => s.Self())

ScriptSources(s => s.Self())

);

//End Security Headers

14Несмотря на высокую сложность эксплойта, POST-запросы по-прежнему уязвимы для данного типа атак: developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X–XSS-Protection. .
15Кликджекинг: portswigger.net/web-security/clickjacking. .
16Предзагрузка HSTS-суффикса: developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security#Preloading_Strict_Transport_Security. .
17Предзагрузка HSTS-суффикса: developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security#Preloading_Strict_Transport_Security. .
18Список разрешенных Feature Policy источников: developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Feature-Policy. .
19Пакет Nuget: www.nuget.org/packages/NWebsec.AspNetCore.Middleware. .