Перевод неточен, оригинал http://www.contextis.com/files/Browser_ … ttacks.pdf

Специалисты из компании Context Information Security разработали весьма неординарную технику атаки с использованием новой функции requestAnimationFrame() в стандарте HTML5. Эта функция возвращает информацию о времени выполнения операций в браузере с точностью до миллионных долей секунды. Используя ее, можно определить цвет отдельных пикселов на экране жертвы и прочитать текст, что создает угрозу утечки приватной информации.

Новая функция создана для четкого контроля фреймрейта в браузере пользователя. Например, если отрисовка каждого кадра не превышает 16 миллисекунд, то мы может поддерживать четкий фреймрейт 60 кадров/с.

loop.png

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

Хакеры из Context Information Security описали целый класс «атак по времени» (timing attacks) с использованием этой новой функции. Например, ее можно использовать для детектирования события redraw в браузере, которое появляется при смене цвета посещенного URL. Если применить CSS-свойство text-shadow, то можно замедлить redraw до такой степени, что оно будет детектироваться с помощью requestAnimationFrame() при смене фреймов. Таким образом, мы получаем персональные сведения об истории серфинга пользователя.

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

Опять же, чтобы requestAnimationFrame() обеспечил достаточную точность распознавания, нужно максимально замедлить процесс выполнения фильтров. Для этого фрагмент оригинального фрейма (в левом верхнем углу) увеличивают в несколько раз (правый верхний угол), затем переводят в черно-белый режим (слева внизу), откуда берут каждый пиксел и обрабатывают его фильтром по отдельности как одноцветную картинку 100х100 пикселов.

filter1.png

Обработку черного и белого цвета фильтр осуществляет с большой разницей по времени, которая и детектируется с помощью requestAnimationFrame(). Ниже показан результат распознавания.

filter2.png

Если знать размер шрифта на странице, то можно совместить этот метод с работой системы OCR, и тогда техника позволит довольно быстро «просканировать» всю страницу. В противном случае, техника работает довольно медленно: прогон фильтра на каждом пикселе занимает около 0,1-0,2 с, то есть сканирование страницы 1024х768 «в лоб» займет 20-40 часов, что не очень приемлемо в реальных условиях.

Как вариант, можно сканировать не сам HTML, а исходный текст веб-страницы, который после аутентификации может содержать персональную информацию. В редакторе исходного кода используется стандартный шрифт, так что можно подключить систему OCR и ускоренное распознавание. Например, в Firefox под Windows используется шрифт Courier размером 13px, так что для распознавания каждого отдельного символа достаточно узнать значения буквально нескольких пикселов. Исследователям удалось добиться скорости распознавания 1 символ в секунду.

Разработчики браузеров уже уведомлены об уязвимостях

баг https://bugzilla.mozilla.org/show_bug.cgi?id=711043

Источник http://www.xakep.ru/post/61044/

okkamas_knife пишет

Canvas можно сделать сриншот текущей странички и дальше обрабатывай как пожелаешь

Вообще-то нельзя.

с точностью до миллионных долей секунды

Например, если отрисовка каждого кадра не превышает 16 миллисекунд

миллисекунда - 10-3
миллионная доля секунды - микросекунда (10-6)
Где-то что-то явно не стыкуется. Специфика источника?

okkamas_knife пишет

то есть в канвасе доступном странице нет никаких способов получить значения отрендеренного пикселя? точно-точно?
вроде гдето с полгодад назад была на форуме тема где один товарищ-извращенец пытался хранить данные в канвасе а они искажались изза сглаживания
там getImageData юзалось

Это легко проверить:

Выделить код

Код:

var canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
var w = canvas.width = content.innerWidth;
var h = canvas.height = content.innerHeight;
var ctx = canvas.getContext("2d");
ctx.drawWindow(content, 0, 0, w, h, "#fff");
content.open(canvas.toDataURL());

А в той теме на холст сначала выводились какие-то данные.
Так что рисовать обычные страницы могут, а вот делать скриншоты – нет.

hydrolizer
Добавил ссылку на оригинал.

okkamas_knife
Div и canvas это разные, не пересекающиеся слои. Нет, не будет ни дива, ни картинки. Работая с канвасом ты работаешь лишь с тем что внутри него, а не поверх него или под ним.

okkamas_knife
Lain_13
А я решил сначала пруф нарисовать:

canvas.html

Выделить код

Код:

<!DOCTYPE HTML>
<meta charset="utf-8" />
<title>Canvas test</title>
<script type="text/javascript">
function draw() {
    var canvas = document.getElementsByTagName("canvas")[0];
    var ctx = canvas.getContext("2d");
    ctx.fillStyle = "#aaa";
    ctx.fillRect(10, 10, 20, 20);
    
    var root = document.body || document.documentElement;
    var res = document.createElement("img");
    res.src = canvas.toDataURL();
    res.style.border = "1px solid";
    res.style.margin = "2px 2px 2px 0";
    res.title = "Image from canvas";
    root.appendChild(res);
}
</script>
<canvas width="100" height="100" style="border: 1px solid;" title="Canvas"></canvas>
<div style="position: absolute; top: 20px; left: 20px;">
    <a href="https://google.com/">Link</a>
</div>
<div>
    <button onclick="draw();">Draw and get result</button>
</div>

http://jsfiddle.net/b4f34/


:)

Infocatcher
Слушай, ты хоть трусы надень или крестик сними. Как можно написать doctype, но забыть добавить html, head и body?!
Кстати, для создания рабочих примеров кода рекомендую jsfiddle.net.

Новая фишка хтмл 5 с обратной совместимостью :) Шуткую, но, например, вместо <script type="text/javascript"> можно написать <script> и это валидно.

Lain_13 пишет

Слушай, ты хоть трусы надень или крестик сними. Как можно написать doctype, но забыть добавить html, head и body?!

А это валидно. :)

Lain_13 пишет

Кстати, для создания рабочих примеров кода рекомендую jsfiddle.net.

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

KooL пишет

Шуткую, но, например, вместо <script type="text/javascript"> можно написать <script> и это валидно.

Ага. :) А так-то у меня автодополнением набрало.

Infocatcher
> А это валидно. :)
Ага, а потом в коде появляются уродцы вроде document.body || document.documentElement так-как document.body возвращает null. -_-
Поправил. :)
http://jsfiddle.net/b4f34/1/

> Ну, в принципе, да. Убого только что для примеров на чистом CSS на подобных сайтах все равно нужны скрипты.
Почему? Ни кто там не заставляет заполнять блок со скриптами.

Это если доктайпа нет.

KooL
Document.body возвращает null когда нет элемента body, а не доктайпа.

С Ишаком попутал и там не нул, а координаты экрана\страницы.

Lain_13 пишет

Ага, а потом в коде появляются уродцы вроде document.body || document.documentElement так-как document.body возвращает null. -_-

document.body автоматически создается, просто я не знаю, обязан ли он всегда создаваться.

Lain_13 пишет

Почему? Ни кто там не заставляет заполнять блок со скриптами.

Да никто, но наглядности меньше – надо убедиться в отстутствии подключенных библиотек и что в HTML тоже нет скриптов.

Infocatcher
> document.body автоматически создается, просто я не знаю, обязан ли он всегда создаваться.
Я не случайно дал ссылку выше. Элемент body создаётся только если ты его создашь в документе или его создадут за тебя (случай jsFiddle), или имеешь дело с фреймсетами. document.documentElement же является ссылкой на корневой элемент документа и обычно это тэг html. Вот только в случае с jsFiddle он указывает вовсе не на корень твоего документа, а на корень самого jsFiddle. В первом твоём примере оно работало потому, что корнем был сам документ, а не какой-то конкретный тэг в нём.

> Да никто, но наглядности меньше – надо убедиться в отстутствии подключенных библиотек и что в HTML тоже нет скриптов.
А толку убеждаться в отсутствии библиотек? Главное убедиться в отсутствии скриптов в HTML и в этом убеждаться придётся в любом случае. Для создания примера на CSS этот CSS нужно к чему-то применить, а значит блок с HTML всё одно будут редактировать. :)
Кстати, для создания наглядных примеров с CSS скрипты нужны. Они позволят, например, изменять параметры ползунками в реальном времени на странице, а не в коде. А это куда нагляднее.

Lain_13 пишет

Элемент body создаётся только если ты его создашь в документе или его создадут за тебя (случай jsFiddle)

Ну а на деле он берет и создается:

Выделить код

Код:

<!DOCTYPE HTML>
<meta charset="utf-8" />
<title>document.body test</title>
<script>
window.onload = function() {
    alert(document.body);
};
</script>

Другое дело, что как раз <body> – полезный узел (в отличие от <html>, который только для XML-образности и <head>, который разве что для группировки и так невидимых узлов) – все равно у него отступы по умолчанию обычно, которые часто надо менять стилями, так что для наглядности его лучше оставлять.

Lain_13 пишет

Главное убедиться в отсутствии скриптов в HTML и в этом убеждаться придётся в любом случае.

Временно отключить скрипты лично мне гораздо удобнее. :) Заодно будет видно, что получит пользователь в случае проблем со скриптами (не загрузились/отключены/неподдерживаемый браузер).
А то больно много стало любителей цеплять кучу сторонних скриптов, причем половина из этой кучи обязательно тянет что-нибудь еще (и хорошо, если на этом заканчивается), как результат – в лучшем случае это все безобразно тормозит.

Lain_13 пишет

Кстати, для создания наглядных примеров с CSS скрипты нужны. Они позволят, например, изменять параметры ползунками в реальном времени на странице, а не в коде. А это куда нагляднее.

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


P.S. Что-то мы отдалились от темы. :)

trionZabilParol
Зато если бы в Гхостери использовалась эта функция, Вы бы убеждали всех, что она безопасна и ничего так не прочитаешь.

Infocatcher
> Ну а на деле он берет и создается:
Чем больше я имею дело с JS и DOM, тем меньше они мне нравятся.
То у них null это объект, то NaN === NaN возвращает false, а теперь ещё и это. Просто замечательно. -_-

Пандёнок
Ghostery мы обсуждаем в другой теме, к созданию расширения я не имею ни какого отношения.

Ни одного довода в пользу шпионства Ghostery не было. Не ссылок, не исследований кода. Пустые бездоказательные слова. Это называется "навет" и "поклеп".

Lain_13
Enough about languages that suck, let's talk about Javascript (-;E
(Видел этот ролик?)

Вебня давно чем только не обросла, куча препроцессоров, фреймворков, библиотек, сотней разных реализаций ООП у жабоскрипта... Всего не перечислить.

trionZabilParol пишет

к созданию расширения я не имею ни какого отношения.

Не сомневаюсь. Не тот интеллектуальный уровень.
Далее см.
http://forum.mozilla-russia.org/viewtop … 16#p623216