Недавно я решил подготовить очередную презентацию, посвященную web-уязвимостям, в частности, XSS-атакам. Для этого мне нужно было изучить некоторые особенности современных систем фильтрации.
В качестве целевого сайта для тестирования я выбрал самый посещаемый сайт Рунета – vkontakte.ru. Мое внимание привлекла обновленная система статусов.
Код HTML-странички в месте, где происходит редактирование статуса, выглядит следующим образом:
Как видно, фильтр расположен непосредственно в функции infoCheck().
Сам же статус располагается в этой строке:
В данном случае имеем двухступенчатую фильтрацию. Первая ступень – непосредственно фильтрация у пользователя при вводе статуса. Вторая – преобразование введенного статуса в текст и возвращение его на страницу в том виде, в котором статус увидят другие пользователи.
В то время как вторая ступень работает безусловно хорошо, и превратить введенное пользователем в активную XSS явно не удалось бы, с первой не все так гладко. Именно о первой ступени и пойдет речь.
Как и предполагалось, простой <script>alert()</script> не сработал, статус остался пустым. Вариации на «околоscript-ные» темы тоже не прошли – судя по всему, конкретно эта последовательность фильтруется явным образом.
Однако, для выполнения скрипта вовсе не обязательно наличие тега <script>. Первая уязвимость на пользовательской машине достигается использованием тега <img>: введя в статус строку <img src=1.gif onerror=some_function>, мы добьемся выполнения этой самой функции. Для наглядности можно вызвать функцию profile.infoSave(), вызываемую с пустым аргументом при очистке статуса, с нашим аргументом. Так, введя <img src=1.gif onerror=profile.infoSave(‘XSS’)>, получаем в статусе строчку “XSS”:
Вторая забавная уязвимость фильтра – в отсутствии фильтрования тега <A>. Вводим в статус <A HREF=»//www.google.com/»>XSS</A> и получаем… гиперссылку, по клику на которой открывается окно для редактирования статуса, а мгновением позже – сайт google.com!
Как мы помним, XSS = cross site scripting, поэтому в следующей уязвимости я решил использовать сторонний сайт с загруженным туда скриптом. Помимо отсутствия фильтрации вышеуказанных тегов, проходит фильтр и тег <iframe>. Таким образом, введя в статусную строку <iframe src=»yoursite.com» width=»100%» height=»300″>, получаем iframe с запуском того самого загруженного скрипта. Пример такого “айфрейма”:
Эта уязвимость является более серьезной, чем две предыдущие. Один из способов эксплуатации – составление URL для изменения статуса пользователя и последующий клик пользователя по этому URL жертвой. Еще до того, как статус будет опубликован, скрипт успеет выполниться на странице пользователя. Таким образом, получаем классическую пассивную XSS.
Уязвимости были актуальны с 01.08.2010 — с момента введения новой системы статусов. 01.03.2011 мы сообщили администрации сети ВКонтакте об обнаруженных уязвимостях, и 03.03.2011 уязвимости были закрыты.
XSS-уязвимости ВКонтакте