В Октябре 2005 года в
Сети появился первый червь, использующий Cross-Site Scripting (XSS) уязвимость для
распространения. За ночь червь Samy поразил
более миллиона аккаунтов на популярном сайте
Myspace.com, самой популярной социальной сети в
мире. Для исправления уязвимости и устранения
последствий сайт вынужден был прекратить свою
работу. Автор червя, к счастью, не планировал
нанесения особого вреда, единственным его
желанием было прославится — но что может
произойти получи менее положительный хакер
контроль над миллионом броузеров легко
представить… Итак, наш рассказ сегодня пойдет
о XSS червях, в частности о том самом черве Samy.

10 фактов о XSS червях и вирусах:

  1. Зародились на популярных комюнити
    сайтах, таких как социальные сети, блоги,
    сайты с обзорами пользователей, форумах,
    чатах, почте и пр.
  2. Могут возникнуть в любой момент, так как
    уязвимость такого рода существует примерно
    на 80% сайтов.
  3. Распространяются быстрее всех известных
    червей типа Slammer или Blaster.
  4. С их помощью возможно создание бот-сети
    с целью распределенной DoS атаки. Возможно
    так же распространение спама, обман
    пользователей, изменение данных.
  5. Независимы от операционных систем.
  6. Распространяются по клиент-серверной
    модели (сервер-веб броузер), а не по
    стандартной peer-to-peer вирусной модели.
  7. Не используют уязвимости операционной
    системы или броузера.
  8. Могут использовать для размножения
    виджеты сторонних сайтов — рекламные банеры,
    погодные и новостные блоки, RSS ленты,
    счетчики и т.д.
  9. Их трудно заметить, так как поведение
    "зараженного" броузера ничем не отличается
    от стандартного, а код JavaScript-а трудно
    отличить от стандартных скриптов
    веб-страниц.
  10. Их легко остановить, так как достаточно
    лишь исправить ошибку или закрыть доступ к
    пораженному веб-сайту.

Размножение

Очевидно, что успешному вирусу или червю
нужен механизм исполнения и размножения, XSS
черви
не исключение, но обладают своими
уникальными особенностями. Используя веб-сайт
для размещения вредоносного кода, XSS черви и
вирусы
перехватывают контроль над броузером и
размножаются за счет копирования кода в другое
место на сервере. Например, комментарий в блоге
может содержать злонамеренный код, который при
просмотре заставит броузер пользователей постить
зараженные комментарии в другие журналы и посты.
Код XSS вируса может так же отослать письма,
выполнить денежный перевод, в общем сделать все,
что способен сделать пользователь при помощи веб-броузера. Как возникают и распространяются
такие черви понятно, а как они общаются между
собой — за счет чего возможно размножение,
размещение своего кода в других местах сервера?

XSS эксплоиты, обычно HTML/JavaScript,
используют три пути для отправки HTTP запросов:
HTML теги, объекты JavaScript DOM,
XMLHTTPRequest (XHR).

Тэги

Очевидно, что они срабатывают сразу после
загрузки страницы. например Img с src атрибутом,
направленным на другой сервер, автоматически
запросит картинку послав соответствующий запрос.
Точно так же можно сконструировать форму с
атрибутом Action, указывающим на необходимую
страницу, и скриптом автомтически отправить ее.
Аналогичным способом можно передать серверу куки
пользователя, заставить перевести деньги,
оставить комментарий. Этот же механизм
соединения с другим сайтом может использоваться
червем для размножения.

Document Object Model

JavaScript изначально создавался, конечно, с
благими целями, однако на настоящий момент не
понятно, чего же больше от него — вреда или
пользы. При помощи JavaScript можно
манипулировать всем содержимым страницы —
изображениями, формами, окнами, текстом, куки и
прочим, все эти объекты являются частью Document
Object Model. Как и в случае с HTML тегами,
JavaScript может использоваться для
автоматической отсылки HTTP запросов.

Например:

var img = new Image();
img src = "http://server/path/";

будет аналогично такому запросу:

GET http://server/path HTTP/1.1
Host: server
User-Agent: Firefox/1.5.0.1
Content-length: 0

XHR

JavaScript API под названием XmlHttpRequest
является основой модной технологии AJAX, которая
позволяет обновлять содержимое веб-страниц без
их полной перезагрузки. XHR обеспечивает гибкий
механизм для работы с HTTP запросами, при помощи
него запросы можно отсылать незаметно, не
используя теги HTML или работу со скриптами.

Например:

var req = new XMLHttpRequest();
req.open('GET', 'http://server/path', true);
req.onreadystatechange = function () {
if (req.readyState ==4) {
alert(req.responseText);
}
} req.send(null);

Это породит такой же запрос, как и в предыдущем
примере.

Однако вернемся к нашему подопытному, первому
червю подобного рода Samy. Как уже было сказано,
возник он на сайте MySpace.com. Автор разметил
первую копию в свое профиле. Когда
зарегистрированный пользователь просматривал
его, червь за счет использования XHR добавлял
Samy в друзья ничего не знающего юзера, а так
же записывал его в личные кумиры несчастного,
делая запись "but most of all, samy is my hero".
Ну и, конечно, червь вставлял самого себя. Червь
установил рекорд по скорости распространения, за
первые 24 часа он заразил более миллиона
аккаунтов — это почти в три раза больше чем у
Code Red (359.000) или Blaster (336.000).

Очевидно так же, что XSS червь не принес с
собой и особой сетевой катастрофы — именно за
счет своей природы он не обрушил весь Интернет в
день своего появления. Центральной точкой
распространения является уязвимый веб-сервер и
выполнение червя идет только в веб-броузере, где
код передается только от сервера к броузеру и
наоборот.

Как же работал червь? Достаточно просто,
давайте разберем основные принципы:

  1. Myspace блокирует множество тегов,
    позволяя только a, img и div. Однако
    некоторые броузеры (IE в частности)
    позволяют использовать скрипты внутри CSS
    тегов.
    Например: <div
    style="background:url(‘javascript:alert(1)’)">
  2. Внутри div невозможно использовать
    кавычки, так как они уже открыты, но это
    можно обойти за счет использования выражений
    и вызова их по имени:
    <div id="mycode" expr="alert(‘hah!’)"
    style="background:url(‘javascript:eval(document.all.mycode.expr)’)">
  3. Но это не все трудности. Сервер вырезает
    выражение javascript отовсюду, не дозволяя
    его использование. Это можно обойти за счет
    вставки символа перевода строки используя
    java\nscript вместо javascript:
    <div id="mycode" expr="alert(‘hah!’)"
    style="background:url(‘java
    script:eval(document.all.mycode.expr)’)">
  4. Несмотря на то, что мы внедрили
    одинарные кавычки, нам по прежнему нужны
    двойные. Это легко можно реализовать вот
    так:
    <div id="mycode" expr="alert(‘double quote:
    ‘ + String.fromCharCode(34))"
    style="background:url(‘java
    script:eval(document.all.mycode.expr)’)">
  5. Для того, что бы узнать ID пользователя
    используем document.body.innerHTML. Однако и
    это режет Myspace. Тогда разбиваем на
    строки:
    alert(eval(‘document.body.inne’ + ‘rHTML’));
  6. Для создания HTTP GET запроса к POST
    странице используем XML-HTTP. Блокирование
    onreadystatechange обходим так же, как и в
    предыдущем случае:
    eval(‘xmlhttp.onread’ + ‘ystatechange =
    callback’);
  7. Делаем еще один GET запрос для получения
    списка "героев" пользователя, что бы
    сохранить его и забить потом заново. Для
    этого используем XML-HTTP, получаем исходник
    страницы:
    var index = html.indexOf(‘frien’ + ‘dID’);
  8. Получив список друзей добавляем себя
    через XML-HTTP POST в странице addFriends.
    Однако запрос не проходит. Почему? Потому
    что мы на profile.myspace.com, а XML-HTTP не
    позволяет делать POST к сайтам с другим
    доменным именем. Обойдем это так, Myspace
    позволяет просматривать профиль на своем
    сайте:
    if (location.hostname ==
    ‘profile.myspace.com’) document.location =
    ‘http://www.myspace.com’ + location.pathname
    + location.search;
  9. Вроде бы все сделано, но все равно не
    работает… Myspace генерирует случайный хеш
    на странице, предшествующей POST запросу,
    если этот хеш не поступает вместе с данными,
    то они и не добавляются. Поэтому подобно
    броузеру мы сперва делаем GET запрос к этой
    странице, парсим источник в поисках хеша и
    лишь затем отправляем данные.
  10. Закончив, прописываем код вируса. Для
    этого опять получаем страницу с кешем,
    подготавливаем текст вируса — это проще
    сделать получив код профиля текущего пользователя и пропарсить его.
    Выделив необходимое
    добавляем ключевую фразу "but most of all,
    samy is my hero" и все. Мы получили
    саморазмножающийся вирус.

В ходе создании червя был решен и еще ряд
технических проблем, но в основном все решения
описаны. Исходники вы можете найти в сети, они
доступны в открытом виде.

Оставить мнение

Check Also

Майнинг в браузерах набирает обороты: в популярное расширение SafeBrowse добавили скрытый майнер

Пока одни разработчики выпускают расширения для браузеров, блокирующие работу майнеров, в …