Хакер #305. Многошаговые SQL-инъекции
Недавно я решил подготовить очередную презентацию, посвященную 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 уязвимости были закрыты.