21 Августа, 2013

Browser Security Handbook. Глава 1, пункт 10

Сергей Сторчак
Руководство по безопасности браузеров (Browser Security Handbook). Глава 1

   CSS используется как средство оформления внешнего вида веб-страниц, например, часть текста может быть представлена в виде пронумерованного списка или написана шрифтом «Comic Sans» с размером 72 pt. Хотя это и удобно для использования на новых страницах, но сложно реализовать автоматическую настройку внешнего вида документа, не изменяя его структуры (например, сайт под мобильные устройства, версия для печати, требования доступности), или точно сохранить структуру документа при перемещении данных или смене макета сайта.
Несмотря на то, что идея таблиц стилей как таковых предшествует HTML, текущий вариант проекта был одобрен консорциумом W3C ближе к 1998 году: из-за сложных изменений, необходимых для визуализации, потребовалось несколько лет, чтобы технология обрела популярность.
Существует три способа встраивания CSS в HTML-документ:
1. Использование встроенного параметра STYLE="...", применяемого с HTML-тегами любого типа; атрибуты, указанные таким образом применяются только к данному и вложенным тегам (и в значительной степени поражают цели всей системы, когда речь заходит о смене внешнего вида документа).
2. Использование тега <STYLE>...</STYLE>в любой части документа. Он может изменить внешний вид, установленный по умолчанию другим тегом, либо установить правила для конкретных тегов с параметром CLASS="..." (т.к. данный стиль обладает более высоким приоритетом).
3. Подключение удаленных стилей с помощью <LINK REL="stylesheet" HREF="..."> с таким же глобальным эффектом, как  и блок <STYLE>[6].
В первых двух способах, таблица стилей, как правило, наследует набор правил документа и интерпретируется соответствующим образом, в последнем - набор символов может быть получен из заголовка Content-Type, конструкции @charset, или обнаружен автоматически, если не работают другие варианты .
Поскольку CSS предоставляет мощный и стандартизированный способ управления внешним видом блока HTML, многие приложения позволяют третьей стороне управлять подмножеством синтаксиса CSS, используемого в документах. К сожалению, задача довольно сложная.
Важнейшими последствиями безопасности, контролируемых злоумышленником таблиц стилей, являются:
- Риск выполнения JavaScript. Малоизвестно, что некоторые реализации CSS позволяют сценарию встраиваться в таблицы стилей. Есть, по крайней мере, три способа достижения этой цели: с помощью конструкции expression(), которая дает возможность вычислять произвольные операторы JavaScriptи использовать их в качестве CSS-параметра; с помощью конструкции url('javascript:...'); или вызывая конкретные для браузера свойства, такие как -moz-binding в Firefox.
- Возможность свободно располагать текст в определенном месте. Если на странице разрешены таблицы стилей управляемые пользователем, различные свойства позиционирования CSS могут быть использованы для перемещения текста за пределы текущего контейнера и воспроизведения доверенных элементов пользовательского интерфейса (или в точности им соответствующих). Примерами свойств абсолютного позиционирования являются: z-index, margin, padding, bottom, left, position, right, top, или text-indent (многие из них имеют  подварианты, такие, как margin-left).
- Возможность повторного использования доверенных классов.Если управляемые пользователем атрибуты CLASS="..."разрешены в синтаксисе HTML, атакующему может повезти в "заимствовании" класса, используемом для отображения элементов доверенных элементов пользовательского интерфейса, и выдавать себя за данный класс.
Подобно JavaScript, таблицы стилей сложно обезвредить, потому что они следуют за синтаксическим анализом CDATA-стиля: буквенная последовательность </STYLE>завершаеттаблицу стилянезависимо от её местоположениявсинтаксисеCSS. Например, следующая таблица стиля будет завершена досрочно и приведет к выполнению javascript-кода:

<STYLE>
body{ background-image: url('http://example.com/foo.jpg?</STYLE><SCRIPT>alert(1)</SCRIPT>'); }
</STYLE>

Другое интересное свойство, специфичное для обработки <STYLE>, заключается в получении некорректного результата при наложении двух подобных CDATA-типов друг на друга. Например, следующая запись может быть истолкована как сценарий или как пустая таблица стилей (в зависимости от браузера):

<STYLE>
<!-- </STYLE><SCRIPT>alert(1)</SCRIPT> -->
</STYLE>

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

<STYLE>
.example {
  content: '*** USER STRING START ***
  } .example { color: red; } .bar { *** USER STRING END ***';
}
</STYLE>
<SPAN CLASS="example">Hello world (in red)!</SPAN>

С дополнительными примерами данного направления можно ознакомиться на страницах Википедии .
Некоторые основные различия синтаксического анализа CSS в распространенных браузерах приведены в таблице № 11:
 Таблица № 11
Описание теста
MSIE6
MSIE7
MSIE8
FF2
FF3
Safari
Opera
Chrome
Android
Поддерживается конструкция expression(...)?
Да
Да
Да
Нет
Нет
Нет
Нет
Нет
Нет
Поддерживаются сценарии в url(...)?
Да
Нет
Нет
Нет
Нет
Нет
Нет
Нет
Нет
Поддерживается выполнение сценария в свойстве -moz-binding?
Нет
Нет
Нет
Да
Нет
Нет
Нет
Нет
Нет
</STYLE> приоритетнее анализатора блока комментариев?
Нет
Нет
Нет
Да
Да
Нет
Нет
Нет
Нет
Допустимые символы в CSSв качестве разделителя поле-значение (кроме t r n x20)
x0B x0C xA0
x0B x0C xA0
x0B x0C xA0
x0B x0C
x0C
x0C
x0C xA0
x0C xA0
x0C

Кодировка символов в CSS

Как и в случае с JavaScript, в интернет-приложениях строки таблицы стилей, управляемые пользователем, необходимо представлять безопасным способом. Для работы со спецсимволами требуются методы экранирования потенциально небезопасных значений. Странно, однако, что CSS формат не поддерживает ни кодирование HTML-объектов, ни любой другой метод кодирования символов, представленный в JavaScript. Вместо этого используется довольно необычная и несовместимая схема : отображения символа начинаются с обратного слеша, следом за которым идет шестнадцатеричное число. Например, слово "test" может быть закодировано как "t65st" или "t000065st", но не как "test", "tx65st", "tu0065st" или "t&#x65;st".
Очень важная и малоизвестная особенность, уникальная для синтаксического анализатора CSS, заключается в том, что управляющая последовательность также принимается за пределами строки, и может заменить некоторые синтаксические управляющие символы в таблице стилей. Так, например, color:expression(alert(1))и color:expression028 alert 028 1 029 029имеют одинаковый смысл, смешанный синтаксис вроде color:expression(alert 029 1) 029работать не будет. Отдельные многострочные строковые литералы не поддерживаются (исключение - Internet Explorer), но одинокий обратный слеш «», стоящий в конце строки, может быть использован для разбиения длинной строки.