В типичном межсайтовом скриптинге жертва просматривает веб-сайт, содержащий некий HTML-код, вставленный туда не владельцем сайта. Это позволяет обойти встроенные ограничения на чтение cookie (сессий, настроек и т.п.), привязанных к домену. В большинстве случаев жертва получает ссылку на страницу, расположенную на сервере, на котором у нее есть некий аккаунт, и при просмотре этой ссылки выполняется некий код, встроенный атакующим (как правило, код на javacscript, отсылающий cookie пользователя на посторонний сервер в целях кражи информации о сессии и аккаунте).
Это лишь краткой описание межсайтового скриптинга, для его использования необходима достаточно серьезная подготовка. Интересующиеся могут воспользоваться статьей iDefence, посвященной XSS (см. Google . Представленная далее атака в сочетании с методом автоматизации атак iDefence оказывается весьма мощным средством.
Замечание (октябрь 2003). Sverre Huseby сообщил, что обобщенная версия атаки была ранее представлена Джимом Фултоном.
Метод POST
Поскольку POST-переменные передаются не вместе с URL, а в теле HTTP-запроса, непосредственная атака с использованием простого перехода по ссылке на сервер, подверженный XSS, становится невозможной. В этом заключается отличие от метода GET, в котором все значения передаются непосредственно через URL - например, в случае http://www.google.com/search?hl=en&q=xss значения переменных hl и q в нем сразу видны.
Для атаки с использованием веб-страницы, подверженной XSS, достаточно передать жертве URL вида http://vulnerable.com/search?q=. В данном случае жертва получает ссылку на поисковый скрипт, который в итоге выводит окно, содержащие сессионные cookie.
Атака с использованием метода POST чуть сложнее. Она потребует создания промежуточной веб-страницы, содержащей код, который заставить броузер жертвы послеть POST-запрос на XSS-сервер. Это делается элементарно с помощью формы и кода на javascript, автоматически отправляющего форму сразу после загрузки страницы:
name="explForm">
value="">
В нашем случае форма отошлется через одну миллисекунду после загрузки страницы. Разумеется, данный код может быть легко модифицирован для использования метода GET, для чего достаточно заменить method="POST" на method="GET". Он может быть размещен на любой статической веб-странице, адрес которой атакующий затем пересылает жертве.
Другой способ доставки формы жертве - использование промежуточного сервера, подверженного XSS через GET, и создание этой формы на лету. В обоих случаях атакующий вынуждает жертву зайти на промежуточную страницу, формирующую запрос, который отсылается на сервер, подверженный XSS. Т.е. мы получаем двухэтапную схему атаки вместо простой классической XSS (жертва --> промежуточная страница, формирующая запрос --> страница на сайте с XSS, содержащая внедренный код).
Развитие POST: защищенные ресурсы
На многих сайтах, использующих запароленный доступ к своим ресурсам, cookie, хранящие информацию о сессии, часто делают временными, чтобы препятствовать их использованию другими пользователями данного компьютера.
Модифицировав приведенный выше код, мы по-прежнему можем украсть сессионные cookie для временных сессий. К сожалению, временное окно, в течение которого можно провести данную атаку, в большинстве случаев довольно невелико, но с помощью предложенной iDefence идеи автоматизированных атак, эту проблему можно обойти. Этого можно добиться, вставив в промежуточную веб-страницу код, открывающий новое окно, предлагающее пользователю авторизоваться для входа в защищенную область (не стоит забывать о методах социальной инженерии):
name="explForm">
value="">
Отличия
Промежуточная страница находится в фоне, а отправка формы отложена до тех пор, пока пользователь не залогинится (второй параметр функции setTimeout). После пользовательского логина (30 секунд для этого должно хватить), как и в прошлый раз отправляется форма на скрипт, позволяющий украсть пользовательские данные. Использование промежуточного сайта несколько усложняет возможность успешной атаки, но позволяет достичь высокой гибкости - любая переменная, используемая динамически создаваемой страницей без фильтрации HTML, может быть использована для XSS-атак.
Обобщение автоматизации клиентов
Обобщение описанных ранее подходов позволяет воспользоваться другими, во многих случаях более опасными уязвимостями. Предложенная техника позволяет атакующему заполнять формы произвольными данными и отправлять их автоматически их контекста клиента. Т.е. уязвимыми становятся все формы, полагающиеся на то, что данные, отправленные от пользователя, были введены именно им.
Данная проблема возникает, когда форма сама по себе зависит только от статической или предсказуемой информации (в предсказании может помочь информация, передаваемая сторонним сайтам, например, referrer). При использовании описанного метода, автоматизация заполнения форм становится тривиальной задачей:
action="http://vulnerable.com/changeMailSettings" name="f">
Достаточно интересным способом использования данного подхода является создание вируса для подписей веб-почт. Атакующий создает веб-страницу, которая при посещении автоматически заполняет форму, меняющую подпись для отправляемых писем таким образом, чтобы она содержала ссылку на атакующую страницу. И всякий раз, когда "зараженный" пользователь будет отправлять письмо, он будет отправлять эту ссылку очередной потенциальной жертве. Кстати, отличное средство для автоматизированного спама.
На предмет подверженности данной уязвимости были протестированы Hotmail и Yahoo! Mail, и обе оказались защищенными, хотя каждая служба боролась с этим по-своему. Hotmail использует простую проверку referrer, и если он не является авторизованной страницей Hotmail, пользователь перенаправляется на входную страницу. Yahoo использует достаточно нестандартный подход, вставляя в кажду форму спрятанное поле ".crumb", связанное с cookie. Если бы удалось предсказать значение, попадающее в crumb, Yahoo оказалась бы уязвимой.
Защита
Обобщенную атаку довольно легко организовать, но защититься от нее несколько сложнее.
Поскольку атака происходит при участии пользовательского броузера, можно вполне доверять значению заголовка Referer и использовать его для проверки того, что данные были сформированы нашим скриптом, а не атакующим. Проверка на Referer предполагает, что атакующий на мог встроить произвольный html-код в один из наших доверенных скриптов - впрочем, подобная атака уже выходит за границы XSS.
Минимальная необходимая защита от XSS-атак - очистка пользовательского ввода от любых потенциально опасных символов, таких как < > " &. Как и любой добросовестный специалист по безопасности, хочу отметить превосходство "белых списков" над "черными" (пропускать только разрешенные символы, а не блокировать только запрещенные).
Причина большинства уязвимостей - пользовательский ввод. Программу типа "Hello world!" просто не удастся атаковать. Это приводит нас к заключению о том, что в большинстве случаев для обеспечения безопасности достаточно добиться строгой фильтрации пользовательского ввода. В этих целях очень полезно использовать регулярные выражения, обеспечивающие проверку по "белому списку" и проверяющие данные на соответствие жестким рамкам (включая, кстати, и длину). Все, что после этого остается аналитику - исключительно креативные размышления о том, каким образом можно заставить данные фильтры пропускать то, что они не должны пропустить.
Другим подходом к предотвращению ошибок является проект с кодовым именем Nirvana, в котором принимаю участие. Этот проект посвящен созданию фильтров пользовательского ввода и проверочных функций, и позволяет разработчикам более быстро писать безопасный код. В настоящее время проект размещен на http://libox.net/sanitize.php, но в ближайшее время переедет на http://www.owasp.org/