logo
Ещё

XSS-уязвимости

XSS-уязвимости – это ряд уязвимостей, при которых хакер может запускать вредоносные скрипты на стороне клиента (пользователя). И запускаются там, естественно, не безобидные скрипты: с помощью XSS атак злоумышленники «уводят» у пользователей как минимум – куки (после чего хакер может залогиниться под видом пользователя), как максимум – всю информацию о человеке и/или его банковской карте. Что еще хуже – XSS-уязвимости довольно сложно устраняются, потому что: а) очень легко пропустить «дыру»; б) некоторые виды атак завязаны на уязвимостях браузера пользователя. Ниже мы расскажем, как это все работает и где вы можете найти уязвимость на своем сайте/проекте.

Что такое XSS

XSS расшифровывается как Cross-Site Scripting, «C» заменили на «X» для того, чтобы не путать этот вид атак с технологией CSS. XSS – это вид вредоносной атаки, при которой злоумышленник запускает вредоносный код в браузере пользователя. Сайт в этом случае является промежуточным звеном атаки, отсюда и «Cross-Site». Общая схема атаки:


Как все работает:

  1. Хакер доставляет вредоносный скрипт в браузер клиента. Вариантов доставки есть несколько (ниже расскажем).
  2. Браузер, получает скрипт и выполняет его. Код выполняется автоматически и бесшумно – в этом и кроется одна из больших проблем XSS-атак. Да, современные браузеры имеют встроенные механизмы защиты, запрещающие выполнять вредоносный код, но чаще всего хакер может обойти эти механизмы при большом желании.
  3. Скрипт выполняет действие, вредящее пользователю. В подавляющем большинстве случаев выполняются скрипты, которые передают на сервер хакера куки и/или персональную информацию, включая информацию о платежных методах – то есть данные банковских карт.

15 лет назад на XSS приходилось 80% взломов и краж данных, сейчас он все еще входит в десятку самых опасных видов атак в мире. Обычно XSS-атаки – точечные, то есть взламывают тех, кто перешел по непроверенной ссылке; но если хакеры имеют доступ к крупному серверу, то XSS-атака может стать массовой и привести к утечке данных миллионов пользователей (хранимые XSS, о которых будет ниже).

Встроенные методы защиты

Поскольку проблеме – уже больше 20 лет, и основные ворота для атаки конечных пользователей – браузеры, разработчики последних разработали ряд методов, усложняющих XSS-атаки:

  • SOP. Политика, которая напрямую запрещает скрипту с «происхождением» от конкретного домена получать данные пользователя, если эти данные ассоциированы с другим доменом. Если упрощать, то скрипт, пришедший с сайта hacker.com, не может получить куки, пришедшие от сайта vk.com. Это защищает от самых банальных атак, но далеко не гарантирует полную безопасность.
  • CSP. Встроенная в любой браузер функция, позволяющая получать и исполнять скрипты только от проверенных сайтов, а все остальные – игнорировать. Поскольку база пополняется медленно, а сайтов в интернете – много, пользователи часто сами добавляют в доверенные источники вредоносные сайты. Кроме того, вполне обычный сайт вдруг может стать вредоносным, если его взломают. В общем – еще один инструмент, который немного повышает безопасность, но не гарантирует ее.
  • Проверка входных данных. Даже если сайт, на который вы заходите, не проверяет отправляемые ему данные (из-за этого XSS-атаки обычно и становятся возможными), это делает сам браузер. Механизм позволяет защититься от XSS-атак новичков, но вы без труда можете загуглить методы обхода встроенной проверки входных данных – там нет ничего сложного.

Типы XSS-атак

XSS-атака – вещь довольно креативная, поэтому строгую однозначную типизацию никто пока так и не вывел. В основном приводят 3 типа атак: хранимая, отраженная, через DOM.

Хранимая (постоянная) XSS-атака

Это – самая разрушительная XSS-атака из возможных. Ее суть – в том, что код попадает в базу данных сайта, и каждый пользователь, который запросит данные из базы, получит себе вредоносный скрипт. Понятно, что в этом случае количество пострадавших будет равно количеству людей, зашедших на сайт. Поскольку XSS-атаки – скрытные, проблему могут не замечать длительное время – именно таким образом и утекают данные тысяч или миллионов пользователей.

Самый просто пример – это комментарии на каком-либо сайте. Предположим, форма для комментария на странице описана следующим образом:

<form action="/submit_comment" method="post">

<label for="comment">Комментарий:</label>

<textarea id="comment" name="comment"></textarea>

<button type="submit">Отправить</button>

</form>

Когда пользователь вводит комментарий и жмет на «Отправить» – на сервере выполняется следующий код:

<?php

// Подключение к базе данных

$mysqli = new mysqli("localhost", "user", "password", "database");

// Проверка соединения

if ($mysqli->connect_error) {

die("Ошибка подключения: " . $mysqli->connect_error);

}

// Обработка отправки формы

if ($_SERVER["REQUEST_METHOD"] == "POST") {

$comment = $_POST["comment"];

// Сохранение комментария в базе данных без фильтрации

$stmt = $mysqli->prepare("INSERT INTO comments (comment) VALUES (?)");

$stmt->bind_param("s", $comment);

$stmt->execute();

$stmt->close();

}

// Получение и отображение комментариев

$result = $mysqli->query("SELECT comment FROM comments");

while ($row = $result->fetch_assoc()) {

echo "<p>" . $row["comment"] . "</p>";

}

$mysqli->close();

?>

Самое важное здесь – то, что комментарий сохраняется в базе без какой-либо проверки на безопасность. Это значит, что когда какой-либо пользователь перейдет на страницу с комментариями – сервер отправит ему то же самое, что прислали на сервер, будь это текст с отзывом, картинка или взламывающий скрипт. Если мы добавим комментарий с текстом:

<script>alert('XSS');</script>

, то на странице будет отображаться пустой комментарий, при этом в момент загрузки страницы отработает скрипт, и у пользователя вылезет алерт «XSS». Если же в скрипте указано: «установить коннект с сервером ХХХ и загрузить туда куки», то это и произойдет – все, данные угнаны, при этом пользователь просто зашел на сайт.

Отраженная (непостоянная) XSS-атака

Отраженные атаки за редким исключением не оставляют следов на сервере – в случае с отраженной XSS-атаки пользователь сам посылает вредоносный запрос со скриптом на сервер, а сервер отправляет этот запрос обратно, после чего уже скрипт выполняется и наносит ущерб. Для того, чтобы атака сработала, должны совпасть 2 условия:

  1. Пользователь сам отправил вредоносный запрос на сервер. Делается это просто – пользователю присылают вредоносную ссылку, содержащую в себе код, вроде «vk.com/search?q=<script>alert()</script>». Если смотреть только на домен – ссылка ведет на защищенный ВКонтакте, то есть никакой угрозы нет. На самом же деле угроза кроется в параметрах запроса, то есть в правой его части, на которую мало кто смотрит.
  2. Сервер не проверяет запрос. Атака работает потому, что сервер отражает запрос в неизменном виде. Если сервер увидит вредоносный скрипт и обезвредит его – атаку удастся предотвратить.

Например, на сайте есть такая вот форма для поиска:

<form action="/search" method="get">

<label for="query">Поиск:</label>

<input type="text" id="query" name="query">

<button type="submit">Искать</button>

</form>

Когда данные передаются из формы на сервер – они вообще не проверяются, сервер просто дает то, что от него потребовали:

<?php

if (isset($_GET['query'])) {

$query = $_GET['query'];

echo "<p>Вы искали: " . $query . "</p>";

}

?>

В итоге если мы передадим ссылку с прописанным скриптом пользователю, он сам (через отраженный запрос от сервера) этот скрипт и запустит:

http://example.com/search?query=<script>alert('XSS');</script>

DOM XSS-атака

Эта атака, в отличие от двух предыдущих, вообще не касается сервера – она исполняется только на стороне клиента. «Ворота» для атаки здесь – тот факт, что с помощью JS можно изменять DOM (структуру документа); если фронтендер не позаботится о проверке входного значения в скрипте на клиентской стороне, атака будет возможна. Обычно атаку, как и в случае с отраженной, проводят через зараженную ссылку.

Например, на сайте есть страница поиска с таким кодом:

<!DOCTYPE html>

<html lang="ru">

<head>

<meta charset="UTF-8">

<title>Поиск</title>

</head>

<body>

<form id="searchForm">

<label for="query">Поиск:</label>

<input type="text" id="query" name="query">

<button type="submit">Искать</button>

</form>

<div id="results"></div>

<script>

document.getElementById('searchForm').onsubmit = function(e) {

e.preventDefault();

var query = document.getElementById('query').value;

document.getElementById('results').innerHTML = "Вы искали: " + query;

};

</script>

</body>

</html>

На странице есть скрипт, который выводит запрос на странице результатов, скрипт манипулирует DOM. Вредоносная ссылка будет выглядеть так:

http://example.com/?query=<script>alert('XSS');</script>

Как только человек перейдет по ней, скрипт на клиентской стороне исполнится, и данные уйдут хакеру.

Активная и пассивная атаки

Дополнительно к этим трем часто выделяют 2 вида XSS по способу воздействия – активные и пассивные. Пассивная XSS-атака требует от пользователя определенных действий – перейти по ссылке, навести курсор на определенный элемент страницы и так далее. Активная атака ничего этого не требует – она срабатывает автоматически при соблюдении определенных условий (пользователь зашел на страницу, например).

Каналы внедрения скриптов

Есть ряд «входных ворот», по которым вредоносные скрипты могут попасть к пользователю:

  • Уязвимости браузера. ПО не совершенно, браузеры – тоже, поэтому время от времени в них находят ошибки. Если хакер находит ошибку в браузере раньше, чем ее исправят разработчики – будут проблемы. Обычно такие уязвимости очень быстро закрывают, но полностью защититься от них практически невозможно.
  • Нет экранирования. Экранирование – это добавление специсимволов, делающее потенциально опасный ввод безопасным. Например, часто экранируют скобки < и >, что не позволяет запустить скрипт.
  • Нет фильтрации атрибутов. В атрибутах должно фильтроваться все, что связано со скриптами, иначе какой-нибудь опытный хакер напишет скрипт в атрибуте ссылки или изображения.
  • Подмена кодировки. Если мета-теги расположены на странице неправильно (title идет раньше meta), хакер может «подсунуть» странице кодировку UTF-7 и таким образом обойти все остальные ограничения.
  • Социальная инженерия. Если кратко – пользователю скидывают зараженную ссылку, и он по ней переходит. Чтобы защититься от такого, нужно объяснять пользователям, как работают механизмы взлома – это существенно сложнее, чем подправить что-то в коде.
  • Уязвимости сервера. Обычно хранимая XSS-атака проводится через SQL-инъекцию – последнюю можно провести в том числе тогда, когда не проверяется ввод данных от пользователя.

Чем опасны XSS-атаки?

Тем, что персональные данные пользователей утекают в руки неизвестных лиц. Если эта атака направлена на похищение данных – в руках хакеров окажутся имена, фамилии, фото, данные банковских карт и любые другие данные, которые можно «угнать» с этой страницы (а в некоторых случаях – и с других страниц/сохраненных в браузере данных). Если же атака направлена на получение куки пользователя, то хакер на все время действия куки сможет получить доступ к личному кабинету пользователя – если, например, речь идет о сайте банка, то хакеры смогут переводить деньги на другие счета, если у пользователя не подключена двухфакторная аутентификация. А если хакер угонит куки администратора сайта, то получит вообще полный доступ ко всему, и тогда можно ожидать худшего.

Как защищаться от XSS-атак?

В основном «ворота» для XSS-атак создаются по невнимательности – где-то разработчик забыл проверить ввод, где-то проверил его плохо, где-то «костылями» обошел встроенные во фреймворк ограничения и так далее. Соответственно, лучший способ защиты – это проверить вообще все, что связано с обработкой вводимой пользователями информацией:

  • Валидация и санитизация всех вводимых данных. Проверка данных на скрипты и обезвреживание последних (удалением скрипта или заменой символов) должна происходить и на фронтенде, и на бэкенде.
  • Кодирование HTML. Если вы обрабатываете входящие данные на стороне клиента – проверяйте все, что хотя бы в теории может попасть в атрибуты HTML, именно через атрибуты DOM-атаки обычно и проводятся. Этот совет сам по себе не исключит возможность атаки, но существенно усложнит работу хакерам.
  • Использование библиотек безопасности. Это могут быть как сторонние библиотеки (при условии, что вы им доверяете), так и встроенные во фреймворк библиотеки.
  • Использование фаервола. Обычно фаерволы настроены на отражение XSS атак, поэтому их использование может быть разумным, если вы работаете с большим объемом личной критической информации пользователей. Но фаерволы сложно настраивать, поэтому данный способ далеко не всем будет выгоден.

Что НЕ защищает от атак?

Даже не пытайтесь написать собственный regex для санитизации инпута или написать скрипт, который будет отсекать «<», «>» или «<script></script>» – все это очень легко обходится за счет кодировки. Например, XSS-атака может выглядеть так:

<BODY onload!#$%&()*~+-_.,:;?@[/|\]^`=alert("атака")>

Обычно у людей, профессионально занимающихся взломом, есть инструменты для проверки «дыр» в самописных способах санитизации инпута – и поверьте, у вас этих дыр будет предостаточно.

Сторонние сервисы для проверки

В сети можно найти ряд бесплатных и платных инструментов для проверки сайта на уязвимости, этакие автоматизированные пентестеры. Если вы владеете небольшим сайтом, который хотите проверить – в теории такого инструмента может оказаться достаточно. Но эти инструменты обновляются довольно медленно, так что всегда будет шанс, что вы пропустите ошибку (или неправильно ее исправите) – живой пентестер будет лучше.

Кратко о главном

  • XSS-уязвимость – это уязвимость, позволяющая провести XSS-атаку и украсть данные и/или куки пользователя.
  • Обычно атаки бывают хранимыми, отраженными или построенными на DOM-модели.
  • Самые страшные атаки – хранимые, потому что они затрагивают всех пользователей, посещающих сайт.
  • Основной способ защиты – кропотливая проверка всех «точек входа» и санитизация инпута библиотеками безопасности и средствами фреймворков.
  • Для поверхностной проверки своего сайта на XSS-уязвимости можно использовать сторонние сервисы, для детальной проверки лучше нанять пентестера.