Георгий
Вот примеры, которые браузер будет интерпретировать как скрипты с одинаковым origin’ом. Если на открытой вкладке присутствует 3 скрипта, origin’ы которых отличаются подобным образом, то браузер будет воспринимать их как скрипты с одним origin’ом:
https://my-website.com/home
https://my-website.com/settings
https://my-website.com/profile
А такие origin’ы будут считаться разными:
http://my-website.com/home
https://melicious-website/home
https://my-website.com:444
Важная особенность SOP: скрипт с одним origin’ом может посылать запросы на другой origin. Однако не сможет прочитать ответ на него. Чтение ответа будет заблокировано на уровне браузера. Если требуется заблокировать в том числе отправку запросов (скажем, вы не хотите, чтобы скрипты, загруженные на вашем сайте с других origin’ов, могли делать запрос на origin сайта), это тоже возможно реализовать посредством указания Content Security Policy. Но дефолтная политика (SOP) работает именно так.
В Angular’е можно за’inject’ить санитайзер и выбрать тот уровень санитизации, который подходит под ситуацию. Например, можно разрешить чтение стилей, но при этом экранировать любые скрипты.
Выглядит это так:
this.safeString = this.domSanitizer.bypassSecurityTrustHtml(dangerousString);
Помимо санитизации существует Content Security Policy (CSP) Header. Через него можно явно задать, скрипты с каким origin’ом могут исполняться браузером на текущей странице. По дефолту Content Security Policy содержит значение *. То есть браузеру разрешено запускать скрипты с любым origin’ом, включая inline-скрипты без origin’а. Такие настройки считаются очень небезопасными, и рекомендуется всегда явно указывать, скрипты с каким origin’ом можно запустить на сайте. Явное указание ограниченного набора origin’ов заодно предотвращает исполнение inline-скриптов. Чтобы разрешить их исполнение, требуется явно это прописывать.
Пример того, как может выглядеть CSP Header:
Content-Security-Policy:
default-src 'self';
img-src *;
media-src media1.com media2.com;
script-src userscripts.example.com
Такие настройки означают, что изображения могут подгружаться с любого источника (*), media только с двух источников (media1.com & media2.com). А скриптам позволено запускаться, если они имеют только один origin (userscripts.example.com). default-src ‘self’ позволяет запускать скрипты с текущего origin’а, но не его поддоменов.
https://tproger.ru/jobs/web-dev-wordpress-node-js-tproger/?utm_source=in_text
Посредством CSP-заголовка можно очень тонко настраивать исполнение скриптов на сайте.
content-security-policy Header и access-control-allow-origin немного похожи. CSP позволяет обходить SOP, а access-control-allow-origin позволяет получать разрешение на CORS. То есть отвечать (response) на запросы скриптов с другим origin’ом.
В начале статьи я упоминал, что SOP позволяет скриптам с одним origin’ом делать запросы на другой origin, однако SOP заблокирует ответ. Посредством access-control-allow-origin можно получить доступ к этому ответу, если на сервере явно прописан origin, который имеет право получать ответы.
Если кратко и утрированно, то SCP — это про SOP и frontend-часть системы. А access-control-allow-otigin — про CORS и backend-часть.
Второй по распространённости тип уязвимости — это Cross-Site Request Forgery («Межсетевая подделка запроса»). Этот вектор атаки использует склонность браузера неявно добавлять куки к любому запросу. Например, вы авторизовались на сайте, где используются куки, и в какой-то момент некий скрипт делает запрос на origin этого банка — то есть открыли почтовый клиент и перешли по вредоносной ссылке. Браузер автоматически добавит куки к запросу, даже если сам запрос происходит с другой вкладки.
Из-за SOP этот скрипт не будет иметь доступа к response. Но он сможет выполнять запросы на правах авторизованного пользователя. Например, сделать запрос на перевод денег или просто на удаление любой возможной информации.
Для предотвращения этой атаки в первую очередь рекомендуется использовать явные системы аутентификации. Например, session token / jwt в header или session token в body param. Также, если на сайте используется какая-то форма, то рекомендуется реализовывать anti-csrf token’ы. Их суть в том, что сервер в response отдаёт два случайных токена. Один предназначен для куков, другой прячется в скрытом поле формы. Когда клиент submit’ит форму, то должен отправить оба токена обратно на сервер. В случае, если они отличаются от того, что сервер выпустил изначально, сервер блокирует запрос.
В контексте информационной безопасности существует понятие CIA triad, объединяющее три аспекта:
Предположим, что вы используете cdn (content delivery network) для оптимизации скорости доставки приложения, однако вы хотите быть уверены, что приложение, которое вы сбилдили сами, и то, которое получаете из cdn, — одно и то же. В этом случае можно в процессе прод-билда приложения сгенерировать integrity-хеш, который указывается следующим образом:
<script src="https://example.com/example-framework.js"
integrity=“sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC”>
И когда браузер попытается загрузить скрипт из cdn, то, используя указанный алгоритм (в данном примере sha384) сгенерирует новый хеш на основе загруженного скрипта, произведет сравнение и позволит его запустить только в том случае, если хеши не отличаются.
В случае Angular’а включить генерацию таких хешей можно с помощью флага
—subresource-integrity.
Noveo Developer
В контексте веб-безопасности есть два основных вектора атаки, которые необходимо учитывать: XSS и CSRF. Прежде чем рассказать о них, необходимо понимать дефолтную политику браузера насчёт взаимодействия между вкладками — точнее, взаимодействия между скриптами с разным origin’ами. Эта политика называется Same Origin Policy (SOP). Её центральное понятие — Origin (~ источник) скрипта/документа. Он определяется комбинацией трёх понятий: протокола (http/https, etc.), хоста (my-website.com) и порта (например, 443 для https и 80 для http).Вот примеры, которые браузер будет интерпретировать как скрипты с одинаковым origin’ом. Если на открытой вкладке присутствует 3 скрипта, origin’ы которых отличаются подобным образом, то браузер будет воспринимать их как скрипты с одним origin’ом:
https://my-website.com/home
https://my-website.com/settings
https://my-website.com/profile
А такие origin’ы будут считаться разными:
http://my-website.com/home
https://melicious-website/home
https://my-website.com:444
Важная особенность SOP: скрипт с одним origin’ом может посылать запросы на другой origin. Однако не сможет прочитать ответ на него. Чтение ответа будет заблокировано на уровне браузера. Если требуется заблокировать в том числе отправку запросов (скажем, вы не хотите, чтобы скрипты, загруженные на вашем сайте с других origin’ов, могли делать запрос на origin сайта), это тоже возможно реализовать посредством указания Content Security Policy. Но дефолтная политика (SOP) работает именно так.
XSS / JS-Injections
Наиболее часто встречающейся атакой является Cross-Site Scripting («Межсайтовый скриптинг»), или более удачное, на мой взгляд, название — JS-инъекции (по аналогии с SQL-инъекциями). Если в html-документ вставить строку, в которой будут использоваться элементы, похожие на html-теги, то браузер будет интерпретировать их как валидный html-код и исполнять его. Например, можно прописать <img> с пустым src и добавить onerror=“alert(‘hacked’)” (так как src пустой, то браузер сразу перейдет к вызову onerror), внутри которого выполнить любой JS-код (имея доступ к localStorage и так далее). Также можно поместить вредоносный скрипт внутрь запроса query params в следующем виде:Предотвращение JS-инъекций
В современных фреймворках (вроде Angular/React) изначально действует санитизация, которую в случае необходимости (если вы хотите запустить inline-скрипт из строки и уверены, что там не содержится ничего вредоносного) можно отключить. В React’е это делается посредством атрибута, подчеркивающего опасность вставки inline-скриптов:В Angular’е можно за’inject’ить санитайзер и выбрать тот уровень санитизации, который подходит под ситуацию. Например, можно разрешить чтение стилей, но при этом экранировать любые скрипты.
Выглядит это так:
this.safeString = this.domSanitizer.bypassSecurityTrustHtml(dangerousString);
Помимо санитизации существует Content Security Policy (CSP) Header. Через него можно явно задать, скрипты с каким origin’ом могут исполняться браузером на текущей странице. По дефолту Content Security Policy содержит значение *. То есть браузеру разрешено запускать скрипты с любым origin’ом, включая inline-скрипты без origin’а. Такие настройки считаются очень небезопасными, и рекомендуется всегда явно указывать, скрипты с каким origin’ом можно запустить на сайте. Явное указание ограниченного набора origin’ов заодно предотвращает исполнение inline-скриптов. Чтобы разрешить их исполнение, требуется явно это прописывать.
Пример того, как может выглядеть CSP Header:
Content-Security-Policy:
default-src 'self';
img-src *;
media-src media1.com media2.com;
script-src userscripts.example.com
Такие настройки означают, что изображения могут подгружаться с любого источника (*), media только с двух источников (media1.com & media2.com). А скриптам позволено запускаться, если они имеют только один origin (userscripts.example.com). default-src ‘self’ позволяет запускать скрипты с текущего origin’а, но не его поддоменов.
https://tproger.ru/jobs/web-dev-wordpress-node-js-tproger/?utm_source=in_text
Посредством CSP-заголовка можно очень тонко настраивать исполнение скриптов на сайте.
content-security-policy Header и access-control-allow-origin немного похожи. CSP позволяет обходить SOP, а access-control-allow-origin позволяет получать разрешение на CORS. То есть отвечать (response) на запросы скриптов с другим origin’ом.
В начале статьи я упоминал, что SOP позволяет скриптам с одним origin’ом делать запросы на другой origin, однако SOP заблокирует ответ. Посредством access-control-allow-origin можно получить доступ к этому ответу, если на сервере явно прописан origin, который имеет право получать ответы.
Если кратко и утрированно, то SCP — это про SOP и frontend-часть системы. А access-control-allow-otigin — про CORS и backend-часть.
CSRF (XSRF)
Второй по распространённости тип уязвимости — это Cross-Site Request Forgery («Межсетевая подделка запроса»). Этот вектор атаки использует склонность браузера неявно добавлять куки к любому запросу. Например, вы авторизовались на сайте, где используются куки, и в какой-то момент некий скрипт делает запрос на origin этого банка — то есть открыли почтовый клиент и перешли по вредоносной ссылке. Браузер автоматически добавит куки к запросу, даже если сам запрос происходит с другой вкладки.
Из-за SOP этот скрипт не будет иметь доступа к response. Но он сможет выполнять запросы на правах авторизованного пользователя. Например, сделать запрос на перевод денег или просто на удаление любой возможной информации.
Для предотвращения этой атаки в первую очередь рекомендуется использовать явные системы аутентификации. Например, session token / jwt в header или session token в body param. Также, если на сайте используется какая-то форма, то рекомендуется реализовывать anti-csrf token’ы. Их суть в том, что сервер в response отдаёт два случайных токена. Один предназначен для куков, другой прячется в скрытом поле формы. Когда клиент submit’ит форму, то должен отправить оба токена обратно на сервер. В случае, если они отличаются от того, что сервер выпустил изначально, сервер блокирует запрос.
Integrity
В контексте информационной безопасности существует понятие CIA triad, объединяющее три аспекта:
- конфиденциальность; доступ к информации должен иметь только тот, кому она предназначается;
- доступность: информация должна быть доступна в нужном объеме и в нужное время;
- связность: то, насколько части системы могут доверять передаваемым друг другу сообщениям, и не произошло ли в процессе передачи нарушения данных.
Предположим, что вы используете cdn (content delivery network) для оптимизации скорости доставки приложения, однако вы хотите быть уверены, что приложение, которое вы сбилдили сами, и то, которое получаете из cdn, — одно и то же. В этом случае можно в процессе прод-билда приложения сгенерировать integrity-хеш, который указывается следующим образом:
<script src="https://example.com/example-framework.js"
integrity=“sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC”>
И когда браузер попытается загрузить скрипт из cdn, то, используя указанный алгоритм (в данном примере sha384) сгенерирует новый хеш на основе загруженного скрипта, произведет сравнение и позволит его запустить только в том случае, если хеши не отличаются.
В случае Angular’а включить генерацию таких хешей можно с помощью флага
—subresource-integrity.
Tproger — всё о программировании
Программирование с нуля, разработка приложений на разных языках, гайды, видеоуроки, книги по программированию, вакансии для программистов и ответы экспертов.
tproger.ru