6.8. Защита от XSS атак

 

Для предотвращения атак XSS используется целый комплекс защитых мер. Самым простым и действенным способом является полностью запретить работу JavaScript в браузере. Однако в реальности это невозможно, так как многие приложения используют JavaScript для своей нормальной работы. Поэтому, отключая JS, лучше сразу отказаться от посещения веб сайтов.

 

Экранирование и кодирование специальных символов

Когда сервер вставляет введенное пользователем сообщение на страницу, то данное сообщение необходимо кодировать. Этим самым мы можем предотвратить выполнение JS кода. Исходя из особенностей приложений, динамический контент может использоваться в качестве атрибутов HTML элементов, свойств стилей CSS, переменных JavaScript и других. То есть практически в любом месте можно внедрить вредоносный код. Ниже даны эффективные и простые приемы, позволяющие обезопасить ваше приложение.

 

Кодирование HTML контекста

Представим себе такой код на сервере:

<div> Search for: $переменная </div>

Если хакер вставит вредоносный код, вроде <svg onload=alert(1)>, то после того, как браузер отрендерит его мы получим следущий код:

<div> Search for: <svg onload="alert(1)"> </svg> </div>

Однако, если мы проведем кодирование, то мы получим такой вид:

<div> Search for: &lt;svg onload=&guot;alert(1)&quot;&gt; &lt;/svg&gt; </div>

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

Рассмотрим простой пример. Откроем приложение Juice Shop и попробуем вставить следующий код в комментарии к товару: 

Внедрение JS эксплойта в комментарий к продукту

 На первый взгляд все выглядит хорошо:

JS эксплойт отображается, но он закодирован

Однако, если правой кнопкой мыши открыть контекстное меню и выбрать опцию “Edit as HTML”, то вы увидите, что HTML сущности были кодированы:

Отображение закодированных HTML сущностей

Кодирование осуществляет по следующей схеме:

&   =>  &amp;<   =>  &lt;>   =>  &gt;"   =>  &quot;'   =>  &#x27;

 

Кодирование контента в HTML атрибутах, JS скриптах и CSS стилях

Иногда приходится вставлять динамический контент внутри HTML тэгов в качестве атрибутов, в коде JS и стилях CSS. Если обернуть переменные в одинарные или двойные кавычки, то вставленный код будет восприниматься браузером, как обычный текст, а следовательно не будет выполнять введренный код. Сравните: 

<div data-content=$переменная> </div> - небезопасно<div data-content="$переменная"> </div> - безопасно

<style> selector { property : $переменная; } </style> - небезопасно<style> selector { property : "$переменная"; } </style> - безопасно

 

Применение политики контроля (защиты) содержимого (Content Security Policy - CSP)

CSP – эффективный механизм для предоствращения таких атак, как XSS, Clickjacking, внедрение сторонних ресурсов. Принцип работы очень простой. Сервер с каждой страницей отправляет предустановленный набор директив/указаний, которые указывают бразуеру, что можно делать, а что нельзя.

Директивы могут доставляться клиенту одним из двух способов:

Через HTTP заголовок:

Content-Security-Policy: список директив

 

Через мета тэг в HTML коде:

<meta http-equiv="Content-Security-Policy" content="список директив">

 

Приведем несколько примеров, чтобы понять, как работает CSP.

Пример 1. Запрет на встраивание и исполнение встроенных скриптов:

Content-Security-Policy: script-src 'none';

 

Пример 2. Разрешить только собственные скрипты и стили, а подгружаемые ресурсы из внешних источников запретить:

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

 

Пример 3. Разрешить загрузку и исполнение собственных и сторонних скриптов из определенного сервера (например, google.com). Все остальные скрипты запретить:

Content-Security-Policy: script-src 'self' https://google.com;

 

Пример 4. Разрешить загрузку фреймов (iframe) из внешнего сайта (google.com), а все остальные запретить:

Content-Security-Policy: frame-src 'self' https://google.com;

 

А теперь рассмотрим более сложный пример:

Content-Security-Policy: frame-src 'none'; img-src *; script-src google.com yandex.ru; style-src 'self'; connect-src 'self';

 

Эта политика CSP делает следующее:

frame-src 'none'; - Запрет загрузки фреймов (iframe) с любых источников.

img-src ; - Разрешает загрузку изображений из любых источников. Знак звездочки (*) означает "любой".

script-src google.com yandex.ru; - Разрешает загрузку скриптов только с доменов google.com и yandex.ru. Если какой-либо скрипт попытается выполниться с другого домена, он будет заблокирован.

style-src 'self'; - Разрешает использование только собственных стилей на странице, скрипты из других источников не будут выполнены.

connect-src 'self'; - Разрешает только AJAX запросы на собственный сервер. Все запросы к внешним ресурсам будут заблокированы.

 

Настройки Cookie

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

Set-Cookie: myCookie=myValue; HttpOnly

 

Когда установлен данный атрибут, то браузеры запрещают доступ к файлам cookie скриптам JavaScript. В этом легко убедиться, если открыть любой сайт, например Google,  и переключиться во вкладку Application (для Chrome). Для некоторых cookie уже установлен данный атрибут:

Отображение атрибутов cookie в Chrome

Если вы установите HttpOnly для всех cookie, кроме одного или двух, а затем в  консоли выполните команду document.cookie, то будут отображены только те значения cookie, в которых отсутствует HttpOnly:

Отображение cookie в зависимости от от флага HttpOnly

 

Список разрешенных символов - Whitelist

В многих приложениях приходится использовать определенные HTML тэги. Типичной ошибкой некоторых разработчиков является применение спика запрещенных символов/слов, так называемый черный список (Blacklist). Например, в приложении создали черный список, в который входят тэги <script> и <iframe>. Однако данное ограничение можно легко обойти, используя другие тэги и кодирование. К тому же черным списком невозможно охватить абсолютно весь список запрещенных и небезопасных символов/слов/комбинаций. Обязательно что-то будет упущено. К тому же, технологии постоянно развиваются и добавляются новые функции, а хакеры придумывают новые способы обхода.

Гораздо проще и эффективнее использовать списки разрешенных символов/слов, так называемый белый список (Whitelist). Например, разработчики решили разрешить пользователям применять курсив и жирный шрифт в водимых комментариях, что достигается с помощью тэгов <i> и <b> соответственно. В белый список достаточно внести данные теги, буквы алфавита и некоторые знаки пунктуации. Все, что не соответствует разрешенным символам будет блокироваться и удаляться.

 

WAF

Web Application Firewall (WAF) – это файрвол, который инспектирует веб трафик, проходящий через него. Устанавливается он как раз перед защищаемым веб сервером в качестве прокси-сервера и при наличии угрозы способен блокировать вредоносные запросы. Причем файрвол способен анализировать входящий и исходяший трафик. В основу анализа трафика положены специальные паттерны (сигнатуры). Если определенный паттерн был найден в запросе, то такой запрос будет заблокирован.

Любой WAF, в той или иной степени, можно обойти, а потому файрвол требует очень тщательной и индивидуальной настройки под конкретное приложение. Тем не менее WAF способен предотвратить большое количество XSS атак и создаст для хакера головную боль, чтобы обойти защиту.